use*_*866 2 c# android xamarin
我想将来自Android Wear设备的消息发送到连接的手机.Android智能手机应用程序是用本机Java编写的.Wear-Application是用C#用Xamarin编写的,不能正常工作.这是我到目前为止所得到的:
public class MainActivity : Activity, IMessageApiMessageListener,
IGoogleApiClientConnectionCallbacks, IResultCallback
{
private IGoogleApiClient mApiClient;
private SensorManager _SensorManager;
private Sensor _Gyroscop;
private static String WEAR_MESSAGE_PATH = "//message";
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
var v = FindViewById<WatchViewStub> (Resource.Id.watch_view_stub);
v.LayoutInflated += delegate {
};
if(_SensorManager == null) {
_SensorManager = (SensorManager)GetSystemService(SensorService);
}
SensorListener s = new SensorListener();
_Gyroscop = _SensorManager.GetDefaultSensor (SensorType.Gyroscope);
_SensorManager.RegisterListener (s, _Gyroscop,SensorDelay.Normal);
s.SensorChangedEvent += delegate(SensorEvent e) {
if(mApiClient.IsConnected ){
sendMessage(WEAR_MESSAGE_PATH,"Test");
}
};
initGoogleApiClient ();
}
private void initGoogleApiClient() {
mApiClient = new GoogleApiClientBuilder( this )
.AddApi( WearableClass.Api )
.AddConnectionCallbacks( this )
.Build();
if (mApiClient != null && !(mApiClient.IsConnected || mApiClient.IsConnecting)) {
mApiClient.Connect ();
}
}
private void sendMessage( String path, String text ) {
WearableClass.NodeApi
.GetConnectedNodes (mApiClient)
.SetResultCallback (this);
}
public void OnResult (Java.Lang.Object raw)
{
Exception nodeException, messageException;
try {
//send the message
var nodeResult = raw.JavaCast<INodeApiGetConnectedNodesResult> ();
foreach (var node in nodeResult.Nodes)
WearableClass.MessageApi.SendMessage (mApiClient, node.Id, WEAR_MESSAGE_PATH, StringToByteArray("Test")).SetResultCallback (this); //will go to second try/catch block
return;
} catch (Exception e) {
nodeException = e;
}
try {
//check that it worked correctly
var messageResult = raw.JavaCast<IMessageApiSendMessageResult> ();
if (!messageResult.Status.IsSuccess)
Console.WriteLine ("Problem");
return;
} catch (Exception e) {
messageException = e;
}
}
public void OnConnected (Bundle p0)
{
WearableClass.MessageApi.AddListener (mApiClient, this);
}
public void OnConnectionSuspended (int p0)
{
WearableClass.MessageApi.RemoveListener (mApiClient, this);
}
}
Run Code Online (Sandbox Code Playgroud)
问题是电话没有收到消息.
我终于完成了一个最小的工作实例,演示了手持设备和磨损之间的通信.它是纯Xamarin解决方案,允许在两个方向上发送消息和数据映射.
由于发送和接收信息对于手持设备和磨损的工作方式相同,因此我创建了一个名为"通信"的共享项目.它包含一个"Communicator"类,供两个应用程序使用.
此外,在这个简单的例子中,两个主要活动的AXML和C#实现是相同的.我们将在每个设备上看到两个按钮,允许发送新消息或某些数据.
将Communicator类从派生Java.Lang.Object并实现了两个侦听器接口.
public class Communicator: Java.Lang.Object, IMessageApiMessageListener, IDataApiDataListener
{
...
Run Code Online (Sandbox Code Playgroud)
它包含一个 IGoogleApiClient
readonly IGoogleApiClient client;
Run Code Online (Sandbox Code Playgroud)
并存储一个公共路径:
const string path = "/communicator";
Run Code Online (Sandbox Code Playgroud)
(API,消息API和数据API都需要"路径"作为一种通信通道标识符.对所有消息使用相同的路径是第一次尝试,但在更复杂的应用程序中增加流量时可能会产生噪音.)
的Communicator是使用Android构建的Context,并构建IGoogleApiClient.
public Communicator(Context context)
{
client = new GoogleApiClientBuilder(context)
.AddApi(WearableClass.Api)
.Build();
}
Run Code Online (Sandbox Code Playgroud)
恢复或暂停活动时将调用以下方法.它们连接或断开连接client并注册或取消注册Communicator为消息/数据侦听器:
public void Resume()
{
if (!client.IsConnected) {
client.Connect();
WearableClass.MessageApi.AddListener(client, this);
WearableClass.DataApi.AddListener(client, this);
}
}
public void Pause()
{
if (client != null && client.IsConnected) {
client.Disconnect();
WearableClass.MessageApi.RemoveListener(client, this);
WearableClass.DataApi.RemoveListener(client, this);
}
}
Run Code Online (Sandbox Code Playgroud)
有两种相似的发送信息的方法,一种用于消息,一种用于数据映射.为避免阻止UI,两个任务都在后台线程上执行.请注意,消息被发送到特定的"节点"(=设备),而数据没有特定的接收器.
public void SendMessage(string message)
{
Task.Run(() => {
foreach (var node in Nodes()) {
var bytes = Encoding.Default.GetBytes(message);
var result = WearableClass.MessageApi.SendMessage(client, node.Id, path, bytes).Await();
var success = result.JavaCast<IMessageApiSendMessageResult>().Status.IsSuccess ? "Ok." : "Failed!";
Console.WriteLine(string.Format("Communicator: Sending message {0}... {1}", message, success));
}
});
}
public void SendData(DataMap dataMap)
{
Task.Run(() => {
var request = PutDataMapRequest.Create(path);
request.DataMap.PutAll(dataMap);
var result = WearableClass.DataApi.PutDataItem(client, request.AsPutDataRequest()).Await();
var success = result.JavaCast<IDataApiDataItemResult>().Status.IsSuccess ? "Ok." : "Failed!";
Console.WriteLine(string.Format("Communicator: Sending data map {0}... {1}", dataMap, success));
});
}
Run Code Online (Sandbox Code Playgroud)
当然,我们需要接收数据的方法.它们实际上是由上面的两个接口定义的,需要实现.(OnDataChanged检查正确的路径,因为数据可能不专用于此应用程序.)
public void OnMessageReceived(IMessageEvent messageEvent)
{
var message = Encoding.Default.GetString(messageEvent.GetData());
Console.WriteLine(string.Format("Communicator: Message received \"{0}\"", message));
MessageReceived(message);
}
public void OnDataChanged(DataEventBuffer p0)
{
Console.WriteLine(string.Format("Communicator: Data changed ({0} data events)", p0.Count));
for (var i = 0; i < p0.Count; i++) {
var dataEvent = p0.Get(i).JavaCast<IDataEvent>();
if (dataEvent.Type == DataEvent.TypeChanged && dataEvent.DataItem.Uri.Path == path)
DataReceived(DataMapItem.FromDataItem(dataEvent.DataItem).DataMap);
}
}
Run Code Online (Sandbox Code Playgroud)
他们每个人都会调用以下事件之一.
public event Action<string> MessageReceived = delegate {};
public event Action<DataMap> DataReceived = delegate {};
Run Code Online (Sandbox Code Playgroud)
最后但并非最不重要的是,我们需要一种方法来检索所有连接的节点:
IList<INode> Nodes()
{
var result = WearableClass.NodeApi.GetConnectedNodes(client).Await();
return result.JavaCast<INodeApiGetConnectedNodesResult>().Nodes;
}
Run Code Online (Sandbox Code Playgroud)
为简单起见,两个应用程序使用相同的布局.它包含两个按钮,每个按钮占总屏幕大小的50%.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/messageButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Send message" />
<Button
android:id="@+id/dataButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Send data" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
这两个应用程序实现一个MainActivity源自Activity:
public class MainActivity : Activity
{
...
Run Code Online (Sandbox Code Playgroud)
每个活动都communicator封装了所有与通信相关的代码.
Communicator communicator;
Run Code Online (Sandbox Code Playgroud)
在OnCreate我们实例化的结束时communicator,
communicator = new Communicator(this);
Run Code Online (Sandbox Code Playgroud)
然后连线 messageButton
var messageButton = FindViewById<Button>(Resource.Id.messageButton);
messageButton.Click += (sender, e) => communicator.SendMessage("time: " + DateTime.Now.ToString("T"));
communicator.MessageReceived += message => RunOnUiThread(() => messageButton.Text = message);
Run Code Online (Sandbox Code Playgroud)
以及 dataButton
var dataButton = FindViewById<Button>(Resource.Id.dataButton);
dataButton.Click += delegate {
var dataMap = new DataMap();
dataMap.PutString("time", DateTime.Now.ToString("T"));
communicator.SendData(dataMap);
};
communicator.DataReceived += dataMap => RunOnUiThread(() => dataButton.Text = dataMap.ToString());
Run Code Online (Sandbox Code Playgroud)
(我们使用格式标识符"T"生成包含秒的"长时间"字符串.这样,在大多数情况下,字符串将从一次点击更改为另一次.这很重要,因为两次发送相同的数据映射不会触发OnDataChanged事件处理器!)
最后,我们Resume和Pause该communicator在正确的地方:
protected override void OnResume()
{
base.OnResume();
communicator.Resume();
}
protected override void OnPause()
{
communicator.Pause();
base.OnPause();
}
Run Code Online (Sandbox Code Playgroud)
由于我们使用的是Google移动服务,因此我们需要将以下行放入<application>两个AndroidManifest.xml文件的代码中:
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
Run Code Online (Sandbox Code Playgroud)
打开应用程序时,我们会看到以下屏幕.

点击几下,两个应用程序都会通过消息API或数据API将当前时间发送给对方.现在屏幕看起来如下.

请注意,某些数据映射的发件人也会收到它.因此,dataButton两个设备上的时间相同.相反,消息仅发送到所有其他节点,因此不会返回发送方.
| 归档时间: |
|
| 查看次数: |
1498 次 |
| 最近记录: |