如何在 Android Wear 设备上运行 Xamarin.Forms 应用程序

2024-02-13

我怎样才能运行Xamarin.Forms.Platform.Android.FormsApplicationActivity在 Android Wear 设备上?电话base.OnCreate(bundle)在 - 的里面onCreate我的类的方法总是抛出 RuntimeException“您不能在手表上使用不确定的进度”。

这是我的代码:

namespace Test
{
    [Activity (Label = "Temp.Droid", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
    {
        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

            global::Xamarin.Forms.Forms.Init (this, bundle);

            LoadApplication (new App ());
        }
    }
}

实施App应该没关系,因为异常已经在调用 super 时抛出onCreate而不是通过调用LoadApplication (new App ())用于加载应用程序。然而,它是由项目向导为 Xamarin 移动应用程序生成的基本实现。


尽管 James Montemagno 给出了答案,但我发现可以在 Xamarin Forms 中同步数据。我用的方法是文森特·马弗里克 http://geekswithblogs.net/dotNETvinz/archive/2015/04/23/xamarin.android---syncing-data-between-wearable-and-handheld-devices.aspx并将其合并到 Xamarin Forms 中。首先,请确保您已安装正确的 Android SDK(Android Wear 教程 - 全面介绍 https://www.airpair.com/android-wear/posts/android-wear-tutorial-comprehensive-introduction)。 假设您有标准应用程序,建议在单独的 Xamarin Forms 跨平台应用程序中创建 Wear 应用程序。这是因为磨损尺寸与手机尺寸不同。

在 Wear 应用程序和手机应用程序中,右键单击 Android 项目的引用,然后选择管理 NUGET 包。浏览磨损并选择
Xamarin.GooglePlayServices.Wearable 版本 29.0.0(更高版本会出现问题)。

在两个应用程序中单击 Android 项目的属性。确保默认命名空间(应用程序选项卡)和包名称(Android 清单选项卡)相同。还要确保包名称不包含大写字母,这会导致将应用程序发布到 Android 商店时出现问题。 将“使用 Android 版本编译”的值更改为“API 级别 21(Xamarin.Android v5.0 支持)”。

在两个项目的 Android MainActivity 中添加 using

using Android.Gms.Wearable;
using Android.Gms.Common.Apis;
using Android.Support.V4.Content;

然后将两个应用程序的 MainActivity 更改为以下内容:

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IDataApiDataListener, IMessageApiMessageListener
{
    private static GoogleApiClient client;
    const string _syncPath = "/MySyncPath/Data";
    static string device = "Watch";
    static string text= "";

    protected override void OnCreate(Bundle bundle)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

        base.OnCreate(bundle);

        global::Xamarin.Forms.Forms.Init(this, bundle);
        LoadApplication(new App());

        client = new GoogleApiClient.Builder(this)
              .AddApi(WearableClass.API)
              .Build();
        IntentFilter filter = new IntentFilter(Intent.ActionSend);
        MessageReciever receiver = new MessageReciever(this);
        LocalBroadcastManager.GetInstance(this).RegisterReceiver(receiver, filter);
    }

    internal class MessageReciever : BroadcastReceiver
    {
        MainActivity _main;
        public MessageReciever(MainActivity owner) { this._main = owner; }
        public override void OnReceive(Context context, Intent intent)
        {
            _main.ProcessMessage(intent);
        }

    }

    public void OnDataChanged(DataEventBuffer dataEvents)
    {
        var dataEvent = Enumerable.Range(0, dataEvents.Count)
                                  .Select(i => dataEvents.Get(i).JavaCast<IDataEvent>())
                                  .FirstOrDefault(x => x.Type == DataEvent.TypeChanged && x.DataItem.Uri.Path.Equals(_syncPath));
        if (dataEvent == null)
            return;
        //do stuffs here
    }

    public override void OnBackPressed()
    {
           base.OnBackPressed();
    }

    protected override void OnStart()
    {
        base.OnStart();
        Android.Util.Log.Info("WearIntegration", "Received Message");

        client.Connect();
    }

    public void OnConnected(Bundle p0)
    {
        WearableClass.DataApi.AddListener(client, this);
    }

    public void OnConnectionSuspended(int reason)
    {
        Android.Util.Log.Error("GMSonnection suspended " + reason, "");
        WearableClass.DataApi.RemoveListener(client, this);
    }

    public void OnConnectionFailed(Android.Gms.Common.ConnectionResult result)
    {
        Android.Util.Log.Error("GMSonnection failed " + result.ErrorCode, "");
    }


    protected override void OnStop()
    {
        base.OnStop();
        client.Disconnect();
    }

    public void OnMessageReceived(IMessageEvent messageEvent)
    {
        if (messageEvent.Path.Equals(_syncPath))
        {
            var msg = System.Text.Encoding.UTF8.GetString(messageEvent.GetData());

            this.RunOnUiThread(() =>
                Android.Widget.Toast.MakeText(this, msg, ToastLength.Long).Show());
        }
    }

    public void ProcessMessage(Intent intent) 
    {
        if (intent.GetStringExtra("Device") != device)
        {
            text = intent.GetStringExtra("WearMessage");
            //do stuffs here

        }
    }

    public void SendData() {
        try {
            var request = PutDataMapRequest.Create(_syncPath);
            var map = request.DataMap;
            map.PutString("Device", device);
            map.PutString("Message", "Xamarin Forms says Hello from Wearable!");
            map.PutLong("UpdatedAt", DateTime.UtcNow.Ticks);
            WearableClass.DataApi.PutDataItem(_client, request.AsPutDataRequest());
        }
        finally {
            _client.Disconnect();
        }

}

在您的“电话”应用程序中,将静态字符串设备更改为“电话”,并更改消息文本(如果您愿意):

    static string device = "Phone";

            map.PutString("Message", "Xamarin Forms says Hello from Phone!");

然后将 WearService 类添加到您的两个 Android 项目中,添加与添加到 MAinActivity 中相同的用法,并更改 Wearservice,如下所示:

[Service]
[IntentFilter(new[] { "com.google.android.gms.wearable.BIND_LISTENER" })]
public class WearService : WearableListenerService
{
    const string _syncPath = "/KorfballTimer/Data";
    GoogleApiClient _client;

    public override void OnCreate()
    {
        base.OnCreate();
        _client = new GoogleApiClient.Builder(this.ApplicationContext)
                .AddApi(WearableClass.API)
                .Build();

        _client.Connect();

        Android.Util.Log.Info("WearIntegrationreated", "");
    }

    public override void OnDataChanged(DataEventBuffer dataEvents) 
    {
        var dataEvent = Enumerable.Range(0, dataEvents.Count)
                                  .Select(i => dataEvents.Get(i).JavaCast<IDataEvent)
                                  .FirstOrDefault(x => x.Type == DataEvent.TypeChanged && x.DataItem.Uri.Path.Equals(_syncPath));
        if (dataEvent == null)
            return;

        //get data from wearable
        var dataMapItem = DataMapItem.FromDataItem(dataEvent.DataItem);
        var map = dataMapItem.DataMap;
        string message = dataMapItem.DataMap.GetString("Message");

        Intent intent = new Intent();
        intent.SetAction(Intent.ActionSend);
        intent.PutExtra("WearMessage", message);
        intent.PutExtra("Device", map.GetString("Device"));
        LocalBroadcastManager.GetInstance(this).SendBroadcast(intent);
    }
}

最后,在 AndroidManifest.xml 元素下添加元数据:

    <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

如果您不想在 Wear 应用程序中使用 IOS 和 Windows 项目,只需删除它们即可。现在,您可以在 Xamarin Forms 中构建 Wear 应用程序,就像使用手机应用程序一样。快乐编码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Android Wear 设备上运行 Xamarin.Forms 应用程序 的相关文章

  • Parcelable 写入可序列化对象 getactivity() 时遇到 IOException

    所以我在 logcat 中得到了这个 java lang RuntimeException Parcelable encountered IOException writing serializable object name com re
  • GCM 通知的自定义 UI

    In GCM Docs http developer android com google gcm gcm html其给定 它不提供任何内置用户界面或其他处理 消息数据 GCM 只是将收到的原始消息数据直接传递给 Android 应用程序
  • 应用程序启动时立即隐藏导航栏

    基于以下代码片段 我能够隐藏状态栏当应用程序启动时 但不是导航栏 由后退 主页和任务管理器按钮组成的栏 因为它隐藏了稍后在 MainActivity 的线程完成加载后 这是清单
  • Android,无法从谷歌API获取天气

    以下代码之前运行良好 class RetreiveWeatherTask extends AsyncTask
  • Android 中的 XmlPullParser 陷入困境

    经过多个小时的搜索和调试后 我仍然停留在同一个地方 并且 Eclipse 没有帮助我 我试图解析这个 RSS 提要 http fr espnf1 com rss motorsport story feeds 0 xml type 2 这很简
  • 如何防止 Activity 在后退操作时重新加载

    我有连接到互联网以获取数据的应用程序 我可以多层次访问数据 假设我从第 3 级开始 在第 4 级我决定返回 每当我按回之前的活动时 就会从互联网重新加载数据 有可能阻止这种情况吗 我尝试以单顶模式运行该活动 将数据加载代码移至 single
  • 如何区分ActionBarSherlock中的两次菜单项点击?

    我最近一直在使用 ActionBarSherlock 并按照各种教程 我编写了这段代码来将项目添加到操作栏 Override public boolean onCreateOptionsMenu Menu menu menu add Ref
  • 在android中以编程方式创建布局 - 问题

    我正在使用以下代码动态创建 FrameLayout mylayout java FrameLayout layout new FrameLayout this FrameLayout LayoutParams layoutparams ne
  • GSON:自定义对象反序列化

    好吧 我编辑了这个问题 因为它不够清楚 Edit 2 更新了 JSON 文件 我在 Android 应用程序中使用 GSON 我需要解析来自服务器的 JSON 文件 而且有点太复杂了 我不想让我的对象结构太重 所以我想简化内容 所以我的对象
  • 适用于 Droid 手机的数学或 LaTeX 引擎 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 Android 手机有可用的数学或 LaTeX 引擎吗 我最喜欢的抽认卡应用程序 AnyMemo 似乎
  • SDK 管理器中缺少 Google Play 服务

    我想在我的应用程序中使用 Google 地图 我想在 SDK 管理器中安装 Google Play 服务 但是当我转到 SDK 管理器时 我没有看到 Google Play 服务 为什么 我该如何安装这个 我可以独立于 SDK Manage
  • Android 简单 TextView 动画

    我有一个 TextView 我想倒计时 3 2 1 发生了事情 为了使其更有趣 我希望每个数字都以完全不透明开始 然后淡出至透明 有没有一种简单的方法可以做到这一点 尝试这样的事情 private void countDown final
  • Android EditText 不起作用,android:imeOptions="actionNext" android:inputType="phone"

    我已经尝试过了 只有删除android inputType phone 键盘回车可以跳转到下一个EditText 不知道大家之间是否有过一些冲突android imeOptions actionNext and android inputT
  • Android Windows:它们何时以及如何创建?

    我已经阅读了标准的 Windows 相关文档并翻阅了 一堆源代码 试图理解 Android 如何以及何时 窗口已创建 我相信我已经拥抱它并愿意 对其进行验证或更正 据我所知 只有两种方法可以获得 Window 对象的句柄 1 Activit
  • Android 图标与徽标

    The
  • 动画结束后更改视图位置

    我开发了一个基于ViewGroup我的问题是我需要在动画结束后保存项目的位置 我打了电话setFillAfter true 在我创建的动画对象中AnimationListener并在其中onAnimationEnd方法调用View layo
  • RecyclerView 适配器的 Kotlin 泛型

    我正在尝试编写一个通用的 recyclerview 适配器 我找到了几个例子 然而 仍然无法弄清楚如何实现通用适配器 我写的代码是 open abstract class BaseAdapter
  • 如何为背景图像添加内边距

    我有一个LinearLayout其中有一个背景图像 一个 9 修补的 png 文件 如何向左和右添加填充 以使背景图像不占据整个宽度 我努力了android paddingLeft and android paddingRight 但这并没
  • Android 使用非公历

    我正在创建一个DatePickerDialogFragment用户将在其中选择出生日期 我想确保我可以处理非公历日期 我无法更改在我的设备上使用的日历类型 Android 是否允许用户切换日历类型 如果是的话 步骤是什么 到目前为止我还没有
  • 同时有两个操作栏(底部和向上)?

    我需要制作两个操作栏 顺便说一下我正在使用actionBarSherlock 所以我真正需要的是在正常操作栏上放置一个 欢迎屏幕 开关 并添加两个正常的 ActionBar 操作选项 与我需要的类似的是 Gmail 和地图 如下所示 htt

随机推荐

  • 使用 AudioWorklet 传输捕获的音频时如何防止中断/不稳定/故障?

    我们一直在开发基于 JavaScript 的音频聊天客户端 该客户端在浏览器中运行并通过 WebSocket 将音频样本发送到服务器 我们之前尝试使用 Web Audio API 的 ScriptProcessorNode 来获取样本值 这
  • 适用于使用 SSL Pinning 的移动应用程序的 Charles Proxy

    Charles Proxy 网站评论说 请注意 某些应用程序实施 SSL 证书固定 这意味着它们专门验证根证书 由于应用程序本身正在验证根证书 因此它不会接受 Charles 的证书 并且连接将失败 如果您已成功安装 Charles 根 S
  • 最终挂起后协程的状态

    协程具有初始挂起点和最终挂起点 Acoroutine handle is done https en cppreference com w cpp coroutine coroutine handle done当它在最终暂停点暂停时 然而
  • 如何在octobercms中过滤多个类别的博客文章?

    October CMS如何过滤多个类别的博文 我正在使用 RainLab 博客插件 该插件仅允许过滤一种类别 我想要一个综合结果 请帮忙 您将需要使用一些自定义代码来根据多个类别进行过滤 如果仍然使用 PostList 组件 请进行以下更改
  • iOS 编程中的中心地图

    我们如何在地图中关注用户 我想让蓝点 用户位置 位于地图的中心 但我还允许用户放大和缩小 然后在几秒钟后放大回用户位置 我对解决方案的有根据的猜测 我们检测用户是否正在放大或缩小 在没有放大或缩小检测的三秒后 我们开始跟随用户 你的帮助会很
  • IEnumerable 的性能比较和源中每个项目的引发事件?

    我想读取包含数百万条记录的大型二进制文件 并且我想获取一些记录报告 我用BinaryReader读取 我认为在读取器中具有最佳性能 并将读取的字节转换为数据模型 由于记录的数量 将模型传递到报表层是另一个问题 我更喜欢使用IEnumerab
  • 在 WSO2 ESB 中介期间修改配置注册表资源内容

    我有一个场景 我需要在配置注册表中存储简单计数器并在序列流结束时递增它 我们需要存储在配置注册表中的原因是 如果服务器重新启动 我们将保留最后的计数器值 有人可以建议如何增加配置注册表中的计数器吗 您可以在中介中使用示例 javascrip
  • “等待返回”有什么区别吗? [复制]

    这个问题在这里已经有答案了 有什么区别吗 const foo async gt some other code that uses await return await bar and const foo async gt some oth
  • Gradle - 仅执行单一构建类型

    我在 build gradle 中定义了多种构建类型 在变体窗口中 我选择了构建变体 例如 debugAPI23 我预计只会执行一种构建类型中的代码 但在 Gradle Console 中我可以看到所有构建类型的输出 正如您所看到的 我正在
  • 在同一地址多次放置 new 是否定义明确/合法?

    注意 这个问题的动机是试图提出预处理器黑客技术来生成无操作分配来回答另一个问题 接受新对象的宏 https stackoverflow com questions 7522949 c macro that accent new object
  • 路由的处理程序无效 - Wordpress

    我正在尝试使用类在 WordPress 中创建自定义 REST API 端点 我也用传统的方式做了同样的事情 效果很好 但是 使用类时我收到错误The handler for the route is invalid 代码 class CS
  • 谁能解释一下android中未绑定服务和绑定服务之间的区别

    任何人都可以解释一下android中未绑定服务和绑定服务之间的区别 并解释一下意图服务 Thanks 绑定服务 http developer android com guide components bound services html
  • 制作堆叠矩形而不是列的直方图

    使用以下代码 我得到如下的直方图 x lt rnorm 100 hist x col gray 我该怎么做才能将条形显示为堆叠矩形 通过其轮廓可见 而不是填充颜色的变化 而不是统一的列 每个矩形代表一个频率 例如 1 尽管我希望能够通过参数
  • 使用 dropzone.js 发送附加参数

    我正在尝试添加 dropzone js 并且想通过 file 传递另一个参数 因此我将隐藏输入放入 form 中 我可以上传文件并可以在Java部分读取它 但我无法读取type chooser WebKitFormBoundaryZxF6M
  • 我的上网IP是多少

    我的电脑上安装了两张网卡 一个用于互联网连接 另一个用于与客户端计算机共享互联网 我用这段代码获取我的IP IPHostEntry HosyEntry Dns GetHostEntry Dns GetHostName foreach IPA
  • Mustache Templates可以做模板扩展吗?

    我是小胡子的新手 许多模板语言 例如 Django Jinja 会让你像这样扩展 父 模板 基本 html block content endblock 首页 html extends base html block content h1
  • 如何从 mysql 数据库中删除重复的条目?

    我有一个包含一些 id 标题的表 我想让标题列唯一 但它已经有超过 600k 条记录 其中一些是重复的 有时是几十次 如何删除除一个之外的所有重复项 以便我可以在之后的标题列中添加一个 UNIQUE 键 此命令添加唯一键 并删除生成错误 由
  • Quarkus - SmallRye 反应式消息传递 - RabbitMQ:将消息发送到默认交换

    使用远程过程调用 https www rabbitmq com tutorials tutorial six java html模式 我需要将答案发送到回复队列 即我需要将消息发送到默认交换机 并以队列名称作为路由键 我在 Quarkus
  • JACOB 和 jre 1.7 出现 UnsatisfiedLinkError

    我编写了一个使用 JACOB 访问 iTunes 的程序 它在 Eclipse 中工作正常 但是当我导出它并在命令提示符中运行它时 我收到一个不满意的链接错误 告诉我 jacob 1 17 M2 x86 dll 是不在我的 java lib
  • 如何在 Android Wear 设备上运行 Xamarin.Forms 应用程序

    我怎样才能运行Xamarin Forms Platform Android FormsApplicationActivity在 Android Wear 设备上 电话base OnCreate bundle 在 的里面onCreate我的类