Xamarin.Forms 不同设备上同一应用程序中两个页面之间的通信
Xamarin.Forms Communication Between Two Pages Within Same App on Different Devices
我正在使用的技术、框架和设备:
- 框架:Xamarin.Forms
- IDE: Visual Studio 2022
- 物理设备(智能手机):Zebra TC26 (Android 10)
- 物理设备(智能手表):Samsung Galaxy Watch4 (Android 11)
问题定义
目前我有一个测试 Xamarin.Forms 项目,它包含两个不同的 UI(XAML 文件):
- 用户界面 1:HomePage.XAML - 此屏幕应显示在 智能手机
- 用户界面 2:WatchScreen.XAML - 此屏幕应显示在 智能手表
上
使用下面的代码,我确保 HomePage.XAML 已部署到智能手机并且 watchscreen 已部署到智能手表:
Page homePage = new NavigationPage(new HomePage());
// BuildVersionCodes.R is a reference to Android version 11 (mostly now used by Wear OS 3.x)
if (Build.VERSION.SdkInt == BuildVersionCodes.R)
{
// SM-R870 is a reference to the Samsung Galaxy Watch4
// Note: This is needed to ensure the UI is specific to the UI of a smartwatch
if (Build.Model == "SM-R870")
{
Page watchScreen = new NavigationPage(new WatchScreen());
MainPage = watchScreen;
}
}
else
{
MainPage = homePage;
}
现在我想让这些页面在不同的设备上相互通信。 HomePage.xaml 存在于主 Xamarin.Forms 项目以及 WatchScreen.xaml 中。
我希望他们相互交流的方式是通过发送消息或其他方式。 Xamarin.Forms 项目还附带一个本地项目。在本机 Xamarin.Android 项目中,我尝试在 MainActivity.cs 中检索主项目中存在的按钮(在 WatchScreen.xaml 中存在此按钮,在 WatchScreen.xaml.cs 中我有一个返回此按钮的方法)。
WatchScreen.xaml.cs 中返回按钮的方法:
public Button GetSendButtonFromWearableUI() => btnSendMessage;
在 MainActivity.cs 中,我使用以下方法获得此方法:
Button button = (App.Current.MainPage.Navigation.NavigationStack.LastOrDefault() as WatchScreen)
.GetSendButtonFromWearableUI();
每当我通过这样做点击按钮时:
button.Clicked += delegate
{
SendData();
};
一些数据应该从 MainActivity.cs 发送并被 HomePage.xaml 捕获并显示在上面。我尝试了几种方法,但没有成功实现需要发生的事情。因此,我想知道你们是否可以帮助我解决这个问题,我将不胜感激。
与此同时,我一直在调查这个问题并提出了解决方案。按照以下步骤获得相同的结果。为了使这个解决方案起作用,我结合了 Google 的可穿戴数据层 API 和 Microsoft 的 MessagingCenter。
另外,下面的示例仅显示了从智能手表到智能手机的通信。为了逆转过程,您可以将发送按钮放在主页而不是智能手表屏幕上,并确保订阅正确的消息。
最后一点: 请记住下面使用的来自 Google 的代码已被弃用,但它仍然有效...
用于完成这项工作的参考资料:
Syncing Data Between Wearable and Handheld Devices Using Xamarin in Android
在 Xamarin.Forms 项目中安装了 Xamarin.Android 项目的依赖项:
- Xamarin.Android.Support.v4
- Xamarin.GooglePlayServices.Base
- Xamarin.GooglePlayServices.Wearable
MessageKeys.cs
此 class 用于声明用于在设备之间发送和接收消息的消息密钥。
public class MessageKeys
{
public const string Smartwatch = "Smartwatch";
public const string Smartphone = "Smartphone";
}
Xamarin.Forms(基础项目)- App.xaml.cs
在 App.xaml.cs 中,如前所述,我确保可穿戴设备 UI 显示 WatchScreen.xaml 并且任何其他设备显示正常 Android UI -> HomePage.xaml.
Xamarin.Forms(基础项目)- WatchScreen.xaml.cs
从可穿戴设备向 Android 智能手机发送消息。
private void btnSendMessage_Clicked(object sender, EventArgs e)
{
MessagingCenter.Send(Xamarin.Forms.Application.Current, MessageKeys.Smartwatch);
}
Xamarin.Forms(基础项目)- HomePage.xaml.cs
public HomePage()
{
InitializeComponent();
MessagingCenter.Subscribe<Xamarin.Forms.Application>(Xamarin.Forms.Application.Current, MessageKeys.Smartphone, (sender) =>
{
DisplayAlert("Message", "Wearable message received!", "OK");
});
}
Xamarin.Forms(本机 Android 项目)- MainActivity.cs
在 MainActivity.cs 中,我实现了以下接口:
public class MainActivity : WearableActivity, DataClient.IOnDataChangedListener,
GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener
变量:
private GoogleApiClient client;
const string syncPath = "/[project name]/[subdirectory for watch]";
内部class'MessageReceiver'接收广播消息:
[BroadcastReceiver]
public class MessageReciever : BroadcastReceiver
{
MainActivity main;
public MessageReciever() { }
public MessageReciever(MainActivity owner) { this.main = owner; }
public override void OnReceive(Context context, Intent intent)
{
main.ProcessMessage(intent);
}
}
注册接收器(通过可穿戴数据层 API 接收),创建 Google 客户端并订阅智能手表消息(通过 MessagingCenter 检索消息)
protected override void OnCreate(Bundle bundle)
{
IntentFilter filter = new IntentFilter(Intent.ActionSend);
MessageReciever receiver = new MessageReciever(this);
LocalBroadcastManager.GetInstance(this).RegisterReceiver(receiver, filter);
client = new GoogleApiClient.Builder(this, this, this)
.AddApi(WearableClass.Api)
.Build();
MessagingCenter.Subscribe<Xamarin.Forms.Application>(Xamarin.Forms.Application.Current, MessageKeys.Smartwatch, (sender) =>
{
SendData();
});
}
ProcessMessage 方法:将接收到的消息从可穿戴设备发送到智能手机
public void ProcessMessage(Intent intent)
{
// For now I'm not sending the payload...
string message = intent.GetStringExtra("WearMessage");
MessagingCenter.Send(Xamarin.Forms.Application.Current, MessageKeys.Smartphone);
}
SendData(), OnStart(), OnStop(), OnDataChanged(这部分没有做任何事情,因为这是在项目外接收消息,我不需要它现在)、OnConnected()、OnConnectionSuspended()、OnConnectionFailed():
查看参考以查看使用了哪些代码,因为代码完全相同...P.S.: SendData 的一件事已更改。如果您想继续发送数据,请在 try 和 catch 块之后从 finally 中删除 'client.Disconenct()'。
Xamarin.Forms(本机 Android 项目)- WearableService 继承自 WearableListenerService:
WearableService 是一个新的 class 并在本机项目中创建。对于这部分,请参阅参考资料,因为它与我的项目中使用的代码完全相同。
为了全面了解正在发生的事情,我在下图中将其可视化:(示例显示了从智能手表到智能手机的通信方式)
如果你想从智能手机到智能手表进行通信,你可以这样做:
伙计们,就是这样。现在,您将使用可穿戴数据层 API 和 MessagingCenter 在同一应用程序中接收消息。我们没有单独的项目,而是使用单独的 UI 来实现这一点...
我正在使用的技术、框架和设备:
- 框架:Xamarin.Forms
- IDE: Visual Studio 2022
- 物理设备(智能手机):Zebra TC26 (Android 10)
- 物理设备(智能手表):Samsung Galaxy Watch4 (Android 11)
问题定义
目前我有一个测试 Xamarin.Forms 项目,它包含两个不同的 UI(XAML 文件):
- 用户界面 1:HomePage.XAML - 此屏幕应显示在 智能手机
- 用户界面 2:WatchScreen.XAML - 此屏幕应显示在 智能手表 上
使用下面的代码,我确保 HomePage.XAML 已部署到智能手机并且 watchscreen 已部署到智能手表:
Page homePage = new NavigationPage(new HomePage());
// BuildVersionCodes.R is a reference to Android version 11 (mostly now used by Wear OS 3.x)
if (Build.VERSION.SdkInt == BuildVersionCodes.R)
{
// SM-R870 is a reference to the Samsung Galaxy Watch4
// Note: This is needed to ensure the UI is specific to the UI of a smartwatch
if (Build.Model == "SM-R870")
{
Page watchScreen = new NavigationPage(new WatchScreen());
MainPage = watchScreen;
}
}
else
{
MainPage = homePage;
}
现在我想让这些页面在不同的设备上相互通信。 HomePage.xaml 存在于主 Xamarin.Forms 项目以及 WatchScreen.xaml 中。 我希望他们相互交流的方式是通过发送消息或其他方式。 Xamarin.Forms 项目还附带一个本地项目。在本机 Xamarin.Android 项目中,我尝试在 MainActivity.cs 中检索主项目中存在的按钮(在 WatchScreen.xaml 中存在此按钮,在 WatchScreen.xaml.cs 中我有一个返回此按钮的方法)。
WatchScreen.xaml.cs 中返回按钮的方法:
public Button GetSendButtonFromWearableUI() => btnSendMessage;
在 MainActivity.cs 中,我使用以下方法获得此方法:
Button button = (App.Current.MainPage.Navigation.NavigationStack.LastOrDefault() as WatchScreen)
.GetSendButtonFromWearableUI();
每当我通过这样做点击按钮时:
button.Clicked += delegate
{
SendData();
};
一些数据应该从 MainActivity.cs 发送并被 HomePage.xaml 捕获并显示在上面。我尝试了几种方法,但没有成功实现需要发生的事情。因此,我想知道你们是否可以帮助我解决这个问题,我将不胜感激。
与此同时,我一直在调查这个问题并提出了解决方案。按照以下步骤获得相同的结果。为了使这个解决方案起作用,我结合了 Google 的可穿戴数据层 API 和 Microsoft 的 MessagingCenter。
另外,下面的示例仅显示了从智能手表到智能手机的通信。为了逆转过程,您可以将发送按钮放在主页而不是智能手表屏幕上,并确保订阅正确的消息。
最后一点: 请记住下面使用的来自 Google 的代码已被弃用,但它仍然有效...
用于完成这项工作的参考资料: Syncing Data Between Wearable and Handheld Devices Using Xamarin in Android
在 Xamarin.Forms 项目中安装了 Xamarin.Android 项目的依赖项:
- Xamarin.Android.Support.v4
- Xamarin.GooglePlayServices.Base
- Xamarin.GooglePlayServices.Wearable
MessageKeys.cs
此 class 用于声明用于在设备之间发送和接收消息的消息密钥。
public class MessageKeys
{
public const string Smartwatch = "Smartwatch";
public const string Smartphone = "Smartphone";
}
Xamarin.Forms(基础项目)- App.xaml.cs
在 App.xaml.cs 中,如前所述,我确保可穿戴设备 UI 显示 WatchScreen.xaml 并且任何其他设备显示正常 Android UI -> HomePage.xaml.
Xamarin.Forms(基础项目)- WatchScreen.xaml.cs
从可穿戴设备向 Android 智能手机发送消息。
private void btnSendMessage_Clicked(object sender, EventArgs e)
{
MessagingCenter.Send(Xamarin.Forms.Application.Current, MessageKeys.Smartwatch);
}
Xamarin.Forms(基础项目)- HomePage.xaml.cs
public HomePage()
{
InitializeComponent();
MessagingCenter.Subscribe<Xamarin.Forms.Application>(Xamarin.Forms.Application.Current, MessageKeys.Smartphone, (sender) =>
{
DisplayAlert("Message", "Wearable message received!", "OK");
});
}
Xamarin.Forms(本机 Android 项目)- MainActivity.cs
在 MainActivity.cs 中,我实现了以下接口:
public class MainActivity : WearableActivity, DataClient.IOnDataChangedListener,
GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener
变量:
private GoogleApiClient client;
const string syncPath = "/[project name]/[subdirectory for watch]";
内部class'MessageReceiver'接收广播消息:
[BroadcastReceiver]
public class MessageReciever : BroadcastReceiver
{
MainActivity main;
public MessageReciever() { }
public MessageReciever(MainActivity owner) { this.main = owner; }
public override void OnReceive(Context context, Intent intent)
{
main.ProcessMessage(intent);
}
}
注册接收器(通过可穿戴数据层 API 接收),创建 Google 客户端并订阅智能手表消息(通过 MessagingCenter 检索消息)
protected override void OnCreate(Bundle bundle)
{
IntentFilter filter = new IntentFilter(Intent.ActionSend);
MessageReciever receiver = new MessageReciever(this);
LocalBroadcastManager.GetInstance(this).RegisterReceiver(receiver, filter);
client = new GoogleApiClient.Builder(this, this, this)
.AddApi(WearableClass.Api)
.Build();
MessagingCenter.Subscribe<Xamarin.Forms.Application>(Xamarin.Forms.Application.Current, MessageKeys.Smartwatch, (sender) =>
{
SendData();
});
}
ProcessMessage 方法:将接收到的消息从可穿戴设备发送到智能手机
public void ProcessMessage(Intent intent)
{
// For now I'm not sending the payload...
string message = intent.GetStringExtra("WearMessage");
MessagingCenter.Send(Xamarin.Forms.Application.Current, MessageKeys.Smartphone);
}
SendData(), OnStart(), OnStop(), OnDataChanged(这部分没有做任何事情,因为这是在项目外接收消息,我不需要它现在)、OnConnected()、OnConnectionSuspended()、OnConnectionFailed():
查看参考以查看使用了哪些代码,因为代码完全相同...P.S.: SendData 的一件事已更改。如果您想继续发送数据,请在 try 和 catch 块之后从 finally 中删除 'client.Disconenct()'。
Xamarin.Forms(本机 Android 项目)- WearableService 继承自 WearableListenerService:
WearableService 是一个新的 class 并在本机项目中创建。对于这部分,请参阅参考资料,因为它与我的项目中使用的代码完全相同。
为了全面了解正在发生的事情,我在下图中将其可视化:(示例显示了从智能手表到智能手机的通信方式)
如果你想从智能手机到智能手表进行通信,你可以这样做:
伙计们,就是这样。现在,您将使用可穿戴数据层 API 和 MessagingCenter 在同一应用程序中接收消息。我们没有单独的项目,而是使用单独的 UI 来实现这一点...