شروع دوره پایتون از پنجشنبه 1 خرداد ، مقدماتی تا پیشرفته، بدون پیش نیاز شروع دوره پایتون از پنجشنبه 1 خرداد ، مقدماتی تا پیشرفته، بدون پیش نیاز
🎯 ثبت نام

همگام سازی داده ها بین وسایل Wearable و Handheld

کلیه حقوق مادی و معنوی این مقاله متعلق به آموزشگاه تحلیل داده می باشد و هر گونه استفاده غیر قانونی از آن پیگرد قانونی دارد.

همگام سازی داده ها بین وسایل Wearable و Handheld با استفاده از Xamarin در اندروید

در این مقاله به شما نشان خواهم چطور می توانید داده ها را برنامه اندروید خود همگام سازی کنید.

ساخت پروژه Wear App

برای شروع، Visual Studio 2013 راباز کرده و به مسیر "File" -> "New" -> "Project..." بروید. از بین قالب های موجود C# > Android و در آخر Wear App (Android) Project را انتخاب کنید:

آموزش Xamarin

یک نام دلخواه برای پروژه خود انتخاب کنید و پس از آن یک نام برای آن انتخاب کنید و اجازه دهید Visual Studio فایل های لازم را برای شما ایجاد کند. در این مقاله نام  پروژه را WearDemo گذاشته ام.

آموزش Xamarin

قبل از تغییر کدهای موجود در پروژه، لازم است بدانید دو روش به نام های DataApi و MessageApi، برای تعامل بین وسایل Wearable و Handheld وجود دارد:

·         DataApi: یک API برای component هایی است که وظیفه خواندن و نوشتن داده ها (data items) و Assetها را بر عهده دارند. یک DataItem با همگام سازی خودکار بین handheld و wearable داده ها را ذخیره می کند. از Asset برای ارسال داده های BLOB نظیر عکس ها استفاده می شود. Assets ها به DataItem ها ملحق می شوند و سیستم به صورت خودکار مراقب فرآیند انتقال خواهد بود.

·         MessageApi: یک API برای ارسال پیغام به سایر nodeها (گره ها) است. این پیغام ها حاوی اطلاعات کوچکی هستند. می توانید با استفاده از Assetها به همراه DataApi داده های بزرگتر را ذخیره کنید.

در این مقاله از DataApi برای ارسال و همگام سازی داده ها بین وسایل استفاده کرده ام. از آنجا که DataApi بخشی از سرویس های Google Play Services است، لذا اولین چیزی که نیاز داریم این است که فضای نام های زیر را اضافه کنید:

  1. using Android.Gms.Common.Apis;  
  2. using Android.Gms.Wearable; 

·         Android.Gms.Common.Apis اجازه می دهد از GoogleApiClient استفاده کنیم. GoogleApiClient نقطه ورودی Google Play Services است.

·         Android.Gms.Wearable امکان استفاده از WearableClass را فراهم میکند. در مرحله بعد باید کلاس MainActivity را با ارث بری اینترفیس های زیر توسعه دهیم:

  • IDataApiDataListener.
  • IGoogleApiClientConnectionCallbacks
  • IGoogleApiClientOnConnectionFailedListener.

·         IDataApiDataListener برای دریافت رخدادهای داده استفاده می شود.

·         IGoogleApiClientConnectionCallbacks زمانی که client به سرویس متصل و یا اتصال آن با سرویس قطع می شود، فراخوانی می شود.

·         IGoogleApiClientOnConnectionFailedListener زمانی که client موفق به برقراری ارتباط با سرویس نشود، فراخوانی می شود.

با جمع بندی موارد گفته شده، از کد زیر برای ارسال داده به دستگاه handheld استفاده می شود.

using System;

using Android.Runtime;

using Android.Widget;

using Android.OS;

using Android.Support.Wearable.Views;

using Java.Interop;

using Android.Gms.Common.Apis;

using Android.Gms.Wearable;

using System.Linq;

 

namespace WearDemo

{

    [Activity(Label = "WearDemo", MainLauncher = true, Icon = "@drawable/icon")]

    public class MainActivity : Activity, IDataApiDataListener, IGoogleApiClientConnectionCallbacks, IGoogleApiClientOnConnectionFailedListener

    {

 

        private IGoogleApiClient _client;

        const string _syncPath = "/WearDemo/Data";

        protected override void OnCreate(Bundle bundle)

        {

            base.OnCreate(bundle);

 

            _client = new GoogleApiClientBuilder(this, this, this)

                             .AddApi(WearableClass.Api)

                             .Build();

 

            // Set our view from the "main" layout resource  

            SetContentView(Resource.Layout.Main);

            var v = FindViewById<WatchViewStub>(Resource.Id.watch_view_stub);

            v.LayoutInflated += delegate

            {

 

                // Get our button from the layout resource,  

                // and attach an event to it  

                Button button = FindViewById<Button>(Resource.Id.myButton);

 

                button.Click += delegate

                {

                    SendData();

                };

            };

        }

 

        public void SendData()

        {

            try

            {

                var request = PutDataMapRequest.Create(_syncPath);

                var map = request.DataMap;

                map.PutString("Message", "Vinz says Hello from Wearable!");

                map.PutLong("UpdatedAt", DateTime.UtcNow.Ticks);

                WearableClass.DataApi.PutDataItem(_client, request.AsPutDataRequest());

            }

            finally

            {

                _client.Disconnect();

            }

 

        }

        protected override void OnStart()

        {

            base.OnStart();

            _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 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  

        }

    }

}

اجازه دهید کد فوق را توضیح دهم . در رویداد OnCreate یک Google Play Services client ساخته می شود که Wearable API را include می کند. سپس در رویداد کلیک دکمه متد SendData() فراخوانی می شود تا داده ها ارسال شوند. منطق ارسال داده در متد SendData() وجود دارد. با ارسال مسیر شی داده، "/WearDemo/Data"، یک درخواست DataMapRequest ایجاد می شود. داده های واقعی، DataMap ای است که در آن مقادیر Message و UpdatedAt وجود دارد. در سمت گیرنده با استفاده از این مسیر منشاء داده را شناسایی می کند.

رخدادها

OnStart: زمانی که activity آغاز می شود، به لایه داده ها متصل می شود.

OnConnected: زمانی که برقراری اتصال با لایه داده ها موفقیت آمیز باشد، راه اندازی می شود.

OnStop: زمانی که Activity، OnConnectionSuspended و OnConnectionFailed (وقتی که نیاز به فراخوانی مجدد اتصال باشد- برای مثال زمانی که از خطاهای رخ داده log میگیریم و سرویس قطع می شود) را متوقف می کند، اتصال با لایه داده ها را قطع می کند.

OnDataChanged: زمانی که داده ها تغییر کنند، راه اندازی می شود.

همیشه به خاطر داشته باشید

مسیر همیشه با یک forward-slash (/) آغاز می شود.

زمانی که داده ها را ارسال می کنیم، استفاده از Timestamps ضروری است. چون رخداد OnDataChanged() فقط زمانی فراخوانی می شود که داد ها واقعاً تغییر  کرده باشند. با اضافه کردن Timastamp به داده ها مطمئن می شوید که متد فراخوانی می شود.

MetaData زیر را در فایل AndroidManifest.xml و پائین عنصر &lt;application> اضافه کنید.

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

ساخت پروژه Main App

برای بررسی همگام سازی و ارسال داده ها باید یک main Android app بسازیم تا شی داده ارسالی از wearable را دریافت کند. سپس برنامه اصلی (main app) روی دستگاه handheld (مانند موبایل یا تبلت) نصب می شود.

بر روی solution project راست کلیک کرده و ADD > NEW PROJECT را نتخاب کنید. در پنجره باز شده Visual C# > Android > Blank App (Android) را انتخاب کنید:

آموزش Xamarin

 

نام پروژه در این مثال MainAppDemo در نظر گرفته شده است. بر روی دکمه OK کلیک کنید تا فایل های لازم برای پروژه ساخته شوند:

آموزش Xamarin

قبل از شروع به نوشتن منطق Main app لازم است یکسری نکات را یادآور شوم:

·         فضای نام Wear app و Main app باید یکسان باشند. در این مثال از فضای نام WearDemo استفاده شده است. برای تغییر فضای نام پیش فرض می توانید هر یک از مراحل زیر را دنبال کنید:

o        به مسیر PROJECT > PROPERTIES > DEFAULT NAMESPACE بروید.

o        برای تغییر فضای نام در کل پروژه از کلید CTRL+H استفاده کنید و فضای نام پیش فرض را با مقدار مورد نظر، مثلاً WearDemo در اینجا، جایگزین کنید.

o        همچنین میتوانید با استفاده از Refactor کردن کد، فضای نام را تغییر دهید. برای انجام این کار بر روی فضای نام راست کلیک کرده و  REFACTOR > RENAME را انتخاب کنید.

·         نام Package، Wear app و Main app باید یکسان باشند. با کلیک راست بر روی پروژه و انتخاب PROPERTIES > ANDROID MANIFEST می توانید نام Package را مشاهده کنید:

آموزش Xamarin

در صورتی که دقیقاً مانند این مقاله پیش می روید، نام Package، WearDemo.WearDemo خواهد بود. با build کردن، مطمئن شوید با هیچ خطایی مواجه نمی شوید. هم اکنون می توانیم تغییرات لازم را در پروژه ایجاد کنیم. اول از همه مقدار Compile using Android version را به API Level 21 (Xamarin.Android v5.0 Support) تغییر دهید:

آموزش Xamarin

مطمئن شوید Xamarin.Android.Support.V4 در referenceها، موجود باشد. در غیر اینصورت می توانید بر روی Refrences راست کلیک کرده و MANAGE NUGET PACKAGES را انتخاب کنید. پس از انتخاب Online > Nuget.Org عبارت Xamarin.Android.Support.V4 را جستجو کنید:


آموزش Xamarin

بر روی Install کلیک کنید و صبر کنید تا فرایند نصب کامل شود. به همین ترتیب Xamarin.Android.Wear -Version 1.0.0 را نصب کنید.

افزودن WearableListenerService

با توسعه WearableListenerService می توانید از هر تغییری در لایه داده مطلع شوید. سیستم چرخه حیات سرویس را مدیریت می کند، زمانی که قرار است data itemها یا پیغامها ارسال شوند، با سرویس bind می شود (به سرویس وصل می شود) و وقتی کاری برای انجام نباشد، unbind می شود (ارتباط خود را با سرویس قطع می کند).

با داشتن چنین دستوراتی می توانیم از WearableListenerService از هر بروزرسانی در لایه داده مطلع شویم و داده ها را کنترل کنیم. بنابراین در مرحله بعد یک کلاس ایجاد خواهیم کرد که WearableListenerService را توسعه دهد. برای انجام این کار بر روی پروژه root راست کلیک کرده و ADD > Class و نام آن را WearService بگذارید. کل منطق کلاس به شکل زیر خواهد بود:

using System.Linq;

using Android.App;

using Android.Content;

using Android.Runtime;

using Android.Gms.Wearable;

using Android.Gms.Common.Apis;

using Android.Support.V4.Content;

 

namespace WearDemo

{

    [Service]

    [IntentFilter(new[] { "com.google.android.gms.wearable.BIND_LISTENER" })]

    public class WearService : WearableListenerService

    {

        const string _syncPath = "/WearDemo/Data";

        IGoogleApiClient _client;

 

        public override void OnCreate()

        {

            base.OnCreate();

            _client = new GoogleApiClientBuilder(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);

            LocalBroadcastManager.GetInstance(this).SendBroadcast(intent);

        }

    }

}

 

کد فوق رویداد OnDataChanged را پیاده سازی می کند و رویدادهای داده های دریافتی (incoming data events)  را که از نوع TypeChanged هستند را فیلتر می کند، مسیر شی داده، /WearDemo/Data، را بررسی می کند، سپس داده را به صورت محلی منتشر می کند.

Main Activity

قطعه کد زیر را به کلاس main activity اضافه کنید.

using Android.App;

using Android.Content;

using Android.Widget;

using Android.OS;

using Android.Support.V4.Content;

 

namespace WearDemo

{

    [Activity(Label = "MainAppDemo", MainLauncher = true, Icon = "@drawable/icon")]

    public class MainActivity : Activity

    {

        TextView _txtMsg;

 

        protected override void OnCreate(Bundle bundle)

        {

            base.OnCreate(bundle);

 

            // Set our view from the "main" layout resource  

            SetContentView(Resource.Layout.Main);

 

            // Get our TextBox from the layout resource,  

            _txtMsg = FindViewById<TextView>(Resource.Id.txtMessage);

 

 

            IntentFilter filter = new IntentFilter(Intent.ActionSend);

            MessageReciever receiver = new MessageReciever(this);

            LocalBroadcastManager.GetInstance(this).RegisterReceiver(receiver, filter);

        }

 

        public void ProcessMessage(Intent intent)

        {

            _txtMsg.Text = intent.GetStringExtra("WearMessage");

        }

 

        internal class MessageReciever : BroadcastReceiver

        {

            MainActivity _main;

            public MessageReciever(MainActivity owner) { this._main = owner; }

            public override void OnReceive(Context context, Intent intent)

            {

                _main.ProcessMessage(intent);

            }

        }

    }

}

 

در کد فوق، رویداد OnCreate()، داده های منتشر شده از ListenerService را دریافت می کند. سپس با تعریف یک کلاس تو در تو BroadcastReceiver را بسط می دهد، متد OnReceive() را پیاده ستزی کرده و داده ها را استخراج می کند. متد Process() داده ها را در سمت رابط کاربری نمایش می دهد.

Main layout

فایل Main.xaml را به شکل زیر تغییر دهید:

<?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">

  <TextView

      android:id="@+id/txtMessage"

      android:layout_width="fill_parent"

      android:layout_height="wrap_content"

      android:layout_marginTop="50dp"

      android:gravity="center"

      android:textColor="@android:color/white"

      android:textSize="80sp" />

</LinearLayout>

 

 

افزودن MetaData برای Google Play Services

در آخر MetaData زیر را در فایل AndroidManifest.xml و پائین عنصر &lt;application> اضافه کنید:

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

 

 

 

1394/10/07 2341 1159
رمز عبور : tahlildadeh.com یا www.tahlildadeh.com
نظرات شما

نظرات خود را ثبت کنید...