Wear-এ ডেটা লেয়ার ইভেন্টগুলি পরিচালনা করুন

আপনি যখন ডেটা লেয়ার এপিআই-তে একটি কল করেন, এটি সম্পূর্ণ হলে আপনি কলটির স্থিতি পেতে পারেন। এছাড়াও আপনি Wear OS by Google নেটওয়ার্কে আপনার অ্যাপ যেকোনও জায়গায় ডেটা পরিবর্তনের ফলে ডেটা ইভেন্ট শুনতে পারেন।

ডেটা লেয়ার API এর সাথে কার্যকরভাবে কাজ করার উদাহরণের জন্য, Android DataLayer নমুনা অ্যাপটি দেখুন।

ডেটা লেয়ার কলের স্থিতির জন্য অপেক্ষা করুন

ডেটা লেয়ার এপিআই-তে কল করা - যেমন DataClient ক্লাসের putDataItem পদ্ধতি ব্যবহার করে একটি কল—কখনও কখনও একটি Task<ResultType> অবজেক্ট ফেরত দেয়। Task অবজেক্ট তৈরি হওয়ার সাথে সাথে অপারেশনটি পটভূমিতে সারিবদ্ধ হয়। আপনি যদি এর পরে আর কিছু না করেন তবে অপারেশনটি শেষ পর্যন্ত নীরবে সম্পন্ন হয়।

যাইহোক, আপনি সাধারণত অপারেশন শেষ হওয়ার পরে ফলাফলের সাথে কিছু করতে চান, তাই Task অবজেক্ট আপনাকে ফলাফলের স্থিতির জন্য অপেক্ষা করতে দেয়, হয় অ্যাসিঙ্ক্রোনাস বা সিঙ্ক্রোনাসভাবে।

অ্যাসিঙ্ক্রোনাস কল

যদি আপনার কোড প্রধান UI থ্রেডে চলছে, তাহলে ডেটা লেয়ার API-এ ব্লকিং কল করবেন না। Task অবজেক্টে একটি কলব্যাক পদ্ধতি যোগ করে অ্যাসিঙ্ক্রোনাসভাবে কলগুলি চালান, যা অপারেশন শেষ হলে ফায়ার হয়:

কোটলিন

// Using Kotlin function references
task.addOnSuccessListener(::handleDataItem)
task.addOnFailureListener(::handleDataItemError)
task.addOnCompleteListener(::handleTaskComplete)
...
fun handleDataItem(dataItem: DataItem) { ... }
fun handleDataItemError(exception: Exception) { ... }
fun handleTaskComplete(task: Task<DataItem>) { ... }

জাভা

// Using Java 8 Lambdas.
task.addOnSuccessListener(dataItem -> handleDataItem(dataItem));
task.addOnFailureListener(exception -> handleDataItemError(exception));
task.addOnCompleteListener(task -> handleTaskComplete(task));

বিভিন্ন কার্য সম্পাদনের চেইনিং সহ অন্যান্য সম্ভাবনার জন্য টাস্ক API দেখুন।

সিঙ্ক্রোনাস কল

যদি আপনার কোড একটি ব্যাকগ্রাউন্ড পরিষেবাতে একটি পৃথক হ্যান্ডলার থ্রেডে চলছে, যেমন একটি WearableListenerService এ, তাহলে কলগুলি ব্লক করার জন্য এটি ঠিক আছে৷ এই ক্ষেত্রে, আপনি Task অবজেক্টে Tasks.await() কল করতে পারেন, যা অনুরোধটি সম্পূর্ণ না হওয়া পর্যন্ত ব্লক করে এবং একটি Result বস্তু ফেরত দেয়। এটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে।

দ্রষ্টব্য: মূল থ্রেডে থাকাকালীন এটিকে কল না করার বিষয়টি নিশ্চিত করুন।

কোটলিন

try {
    Tasks.await(dataItemTask).apply {
        Log.d(TAG, "Data item set: $uri")
    }
}
catch (e: ExecutionException) { ... }
catch (e: InterruptedException) { ... }

জাভা

try {
    DataItem item = Tasks.await(dataItemTask);
    Log.d(TAG, "Data item set: " + item.getUri());
} catch (ExecutionException | InterruptedException e) {
  ...
}

ডেটা লেয়ার ইভেন্টের জন্য শুনুন

যেহেতু ডেটা স্তরটি হ্যান্ডহেল্ড এবং পরিধানযোগ্য ডিভাইস জুড়ে ডেটা সিঙ্ক্রোনাইজ করে এবং পাঠায়, তাই আপনাকে সাধারণত ডেটা আইটেম তৈরি করা এবং বার্তাগুলি পাওয়ার মতো গুরুত্বপূর্ণ ইভেন্টগুলির জন্য শুনতে হবে৷

ডেটা লেয়ার ইভেন্টগুলি শুনতে, আপনার কাছে দুটি বিকল্প রয়েছে:

  • WearableListenerService প্রসারিত করে এমন একটি পরিষেবা তৈরি করুন।
  • একটি কার্যকলাপ বা ক্লাস তৈরি করুন যা DataClient.OnDataChangedListener ইন্টারফেস প্রয়োগ করে।

এই উভয় বিকল্পের সাথে, আপনি যে ইভেন্টগুলি পরিচালনা করতে আগ্রহী তার জন্য আপনি ডেটা ইভেন্ট কলব্যাক পদ্ধতিগুলিকে ওভাররাইড করেন৷

দ্রষ্টব্য: শ্রোতা বাস্তবায়ন নির্বাচন করার সময় আপনার অ্যাপের ব্যাটারি ব্যবহার বিবেচনা করুন। একটি WearableListenerService অ্যাপের ম্যানিফেস্টে নিবন্ধিত আছে এবং যদি এটি ইতিমধ্যে চালু না হয় তবে অ্যাপটি চালু করতে পারে। যদি আপনার অ্যাপটি ইতিমধ্যেই চলমান থাকাকালীন শুধুমাত্র ইভেন্টগুলি শুনতে হয়, যা প্রায়শই ইন্টারেক্টিভ অ্যাপ্লিকেশনগুলির ক্ষেত্রে হয়, তাহলে একটি WearableListenerService ব্যবহার করবেন না৷ পরিবর্তে, একটি লাইভ শ্রোতা নিবন্ধন. উদাহরণস্বরূপ, DataClient ক্লাসের addListener পদ্ধতি ব্যবহার করুন। এটি সিস্টেমে লোড কমাতে পারে এবং ব্যাটারি ব্যবহার কমাতে পারে।

একটি পরিধানযোগ্য লিসেনার সার্ভিস ব্যবহার করুন

আপনি সাধারণত আপনার পরিধানযোগ্য এবং হ্যান্ডহেল্ড উভয় অ্যাপেই WearableListenerService এর উদাহরণ তৈরি করেন। যাইহোক, আপনি যদি কোনো একটি অ্যাপে ডেটা ইভেন্টে আগ্রহী না হন, তাহলে আপনাকে সেই অ্যাপে পরিষেবাটি প্রয়োগ করতে হবে না।

উদাহরণস্বরূপ, আপনার কাছে একটি হ্যান্ডহেল্ড অ্যাপ থাকতে পারে যা ডেটা আইটেম অবজেক্টগুলি সেট করে এবং পায় এবং একটি পরিধানযোগ্য অ্যাপ যা এই আপডেটগুলির জন্য তার UI আপডেট করার জন্য শোনে। পরিধানযোগ্য অ্যাপ কখনোই কোনো ডেটা আইটেম আপডেট করে না, তাই হ্যান্ডহেল্ড অ্যাপ পরিধানযোগ্য অ্যাপ থেকে কোনো ডেটা ইভেন্টের জন্য শোনে না।

WearableListenerService ব্যবহার করে আপনি যে ইভেন্টগুলি শুনতে পারেন তার মধ্যে কয়েকটি হল নিম্নরূপ:

  • onDataChanged() : যখনই একটি ডেটা আইটেম অবজেক্ট তৈরি, মুছে ফেলা বা পরিবর্তিত হয়, সিস্টেমটি সমস্ত সংযুক্ত নোডগুলিতে এই কলব্যাকটিকে ট্রিগার করে।
  • onMessageReceived() : একটি নোড থেকে পাঠানো একটি বার্তা লক্ষ্য নোডে এই কলব্যাকটিকে ট্রিগার করে।
  • onCapabilityChanged() : যখন আপনার অ্যাপের বিজ্ঞাপনের একটি উদাহরণ নেটওয়ার্কে উপলব্ধ হয়ে যায়, সেই ইভেন্টটি এই কলব্যাকটিকে ট্রিগার করে। আপনি যদি কাছাকাছি কোনো নোড খুঁজছেন, তাহলে আপনি কলব্যাকে দেওয়া নোডগুলির isNearby() পদ্ধতিটি জিজ্ঞাসা করতে পারেন।

এছাড়াও আপনি ChannelClient.ChannelCallback থেকে ইভেন্ট শুনতে পারেন, যেমন onChannelOpened()

সমস্ত পূর্ববর্তী ঘটনাগুলি একটি পটভূমি থ্রেডে কার্যকর করা হয়, মূল থ্রেডে নয়।

একটি WearableListenerService তৈরি করতে, এই পদক্ষেপগুলি অনুসরণ করুন:

  1. WearableListenerService প্রসারিত করে এমন একটি ক্লাস তৈরি করুন।
  2. আপনি যে ইভেন্টগুলিতে আগ্রহী সেগুলি শুনুন, যেমন onDataChanged()
  3. আপনার WearableListenerService সম্পর্কে সিস্টেমকে অবহিত করতে আপনার Android ম্যানিফেস্টে একটি অভিপ্রায় ফিল্টার ঘোষণা করুন৷ এই ঘোষণাটি সিস্টেমকে আপনার পরিষেবাকে প্রয়োজন অনুসারে আবদ্ধ করতে দেয়।

নিম্নলিখিত উদাহরণটি দেখায় কিভাবে একটি সাধারণ WearableListenerService বাস্তবায়ন করতে হয়:

কোটলিন

private const val TAG = "DataLayerSample"
private const val START_ACTIVITY_PATH = "/start-activity"
private const val DATA_ITEM_RECEIVED_PATH = "/data-item-received"

class DataLayerListenerService : WearableListenerService() {

    override fun onDataChanged(dataEvents: DataEventBuffer) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onDataChanged: $dataEvents")
        }

        // Loop through the events and send a message
        // to the node that created the data item.
        dataEvents.map { it.dataItem.uri }
                .forEach { uri ->
                    // Get the node ID from the host value of the URI.
                    val nodeId: String = uri.host
                    // Set the data of the message to be the bytes of the URI.
                    val payload: ByteArray = uri.toString().toByteArray()

                    // Send the RPC.
                    Wearable.getMessageClient(this)
                            .sendMessage(nodeId, DATA_ITEM_RECEIVED_PATH, payload)
                }
    }
}

জাভা

public class DataLayerListenerService extends WearableListenerService {
    private static final String TAG = "DataLayerSample";
    private static final String START_ACTIVITY_PATH = "/start-activity";
    private static final String DATA_ITEM_RECEIVED_PATH = "/data-item-received";

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onDataChanged: " + dataEvents);
        }

        // Loop through the events and send a message
        // to the node that created the data item.
        for (DataEvent event : dataEvents) {
            Uri uri = event.getDataItem().getUri();

            // Get the node ID from the host value of the URI.
            String nodeId = uri.getHost();
            // Set the data of the message to be the bytes of the URI.
            byte[] payload = uri.toString().getBytes();

            // Send the RPC.
            Wearable.getMessageClient(this).sendMessage(
                  nodeId,  DATA_ITEM_RECEIVED_PATH, payload);
        }
    }
}

এই শ্রোতার সাথে কীভাবে একটি অভিপ্রায় ফিল্টার ব্যবহার করবেন তা নিম্নলিখিত বিভাগে ব্যাখ্যা করা হয়েছে।

WearableListenerService সহ ফিল্টার ব্যবহার করুন

পূর্ববর্তী বিভাগে দেখানো WearableListenerService উদাহরণের জন্য একটি অভিপ্রায় ফিল্টার দেখতে এইরকম হতে পারে:

<service android:name=".DataLayerListenerService" android:exported="true" tools:ignore="ExportedService" >
  <intent-filter>
      <action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
      <data android:scheme="wear" android:host="*"
               android:path="/start-activity" />
  </intent-filter>
</service>

এই ফিল্টারে, DATA_CHANGED অ্যাকশন পূর্বে প্রস্তাবিত BIND_LISTENER অ্যাকশনকে প্রতিস্থাপন করে যাতে শুধুমাত্র নির্দিষ্ট ইভেন্টগুলি আপনার অ্যাপকে জাগিয়ে তোলে বা লঞ্চ করে। এই পরিবর্তনটি সিস্টেমের কার্যকারিতা উন্নত করে এবং আপনার অ্যাপের সাথে যুক্ত ব্যাটারি খরচ এবং অন্যান্য ওভারহেড হ্রাস করে৷ এই উদাহরণে, ঘড়িটি /start-activity ডেটা আইটেম শোনে এবং ফোন /data-item-received বার্তার প্রতিক্রিয়া শোনে।

স্ট্যান্ডার্ড অ্যান্ড্রয়েড ফিল্টার ম্যাচিং নিয়ম প্রযোজ্য। আপনি প্রতি ম্যানিফেস্টে একাধিক পরিষেবা, পরিষেবা প্রতি একাধিক অভিপ্রায় ফিল্টার, ফিল্টার প্রতি একাধিক অ্যাকশন এবং ফিল্টার প্রতি একাধিক ডেটা স্তবক নির্দিষ্ট করতে পারেন। ফিল্টার একটি ওয়াইল্ডকার্ড হোস্ট বা একটি নির্দিষ্ট একটিতে মিলতে পারে। একটি ওয়াইল্ডকার্ড হোস্টে মেলানোর জন্য, host="*" ব্যবহার করুন। একটি নির্দিষ্ট হোস্টের সাথে মেলাতে, host=<node_id> উল্লেখ করুন।

আপনি একটি আক্ষরিক পথ বা পথ উপসর্গও মেলাতে পারেন। এটি করার জন্য, আপনাকে অবশ্যই একটি ওয়াইল্ডকার্ড বা নির্দিষ্ট হোস্ট উল্লেখ করতে হবে। অন্যথায়, সিস্টেম আপনার নির্দিষ্ট পথ উপেক্ষা করে।

Wear OS সমর্থন করে এমন ফিল্টার প্রকার সম্পর্কে আরও তথ্যের জন্য, WearableListenerService এর জন্য API রেফারেন্স ডকুমেন্টেশন দেখুন।

ডেটা ফিল্টার এবং ম্যাচিং নিয়ম সম্পর্কে আরও তথ্যের জন্য, <data> ম্যানিফেস্ট উপাদানের API রেফারেন্স ডকুমেন্টেশন দেখুন।

অভিপ্রায় ফিল্টার মেলে, দুটি গুরুত্বপূর্ণ নিয়ম মনে রাখবেন:

  • অভিপ্রায় ফিল্টারের জন্য কোনো স্কিম নির্দিষ্ট করা না থাকলে, সিস্টেমটি অন্যান্য সমস্ত URI গুণাবলী উপেক্ষা করে।
  • ফিল্টারের জন্য কোনো হোস্ট নির্দিষ্ট করা না থাকলে, সিস্টেম সমস্ত পাথ বৈশিষ্ট্য উপেক্ষা করে।

একটি লাইভ শ্রোতা ব্যবহার করুন

ব্যবহারকারী অ্যাপের সাথে ইন্টারঅ্যাক্ট করার সময় আপনার অ্যাপটি শুধুমাত্র ডেটা-লেয়ার ইভেন্টগুলির বিষয়ে চিন্তা করলে, প্রতিটি ডেটা পরিবর্তন পরিচালনা করার জন্য এটির দীর্ঘমেয়াদী পরিষেবার প্রয়োজন নাও হতে পারে। এই ধরনের ক্ষেত্রে, আপনি নিম্নলিখিত এক বা একাধিক ইন্টারফেস প্রয়োগ করে একটি কার্যকলাপের ইভেন্ট শুনতে পারেন:

ডেটা ইভেন্টের জন্য শোনে এমন একটি কার্যকলাপ তৈরি করতে, নিম্নলিখিতগুলি করুন:

  1. পছন্দসই ইন্টারফেস প্রয়োগ করুন।
  2. onCreate() বা onResume() পদ্ধতিতে, Wearable.getDataClient(this).addListener() , MessageClient.addListener() , CapabilityClient.addListener() , অথবা ChannelClient.registerChannelCallback() কল করুন যা আপনার Google Play পরিষেবাগুলি নয় ডেটা লেয়ার ইভেন্ট শুনতে আগ্রহী।
  3. onStop() বা onPause() এ, DataClient.removeListener() , MessageClient.removeListener() , CapabilityClient.removeListener() , বা ChannelClient.unregisterChannelCallback() এর সাথে যেকোনো শ্রোতাকে নিবন্ধনমুক্ত করুন।
  4. যদি একটি কার্যকলাপ শুধুমাত্র একটি নির্দিষ্ট পাথ উপসর্গ সহ ইভেন্টগুলিতে আগ্রহী হয়, আপনি শুধুমাত্র বর্তমান অ্যাপ্লিকেশন অবস্থার সাথে প্রাসঙ্গিক ডেটা পেতে একটি উপযুক্ত উপসর্গ ফিল্টার সহ একজন শ্রোতা যোগ করতে পারেন।
  5. আপনার প্রয়োগ করা ইন্টারফেসের উপর নির্ভর করে, onDataChanged() , onMessageReceived() , onCapabilityChanged() বা ChannelClient.ChannelCallback থেকে পদ্ধতি প্রয়োগ করুন। এই পদ্ধতিগুলিকে প্রধান থ্রেডে বলা হয়, অথবা আপনি WearableOptions ব্যবহার করে একটি কাস্টম Looper নির্দিষ্ট করতে পারেন।

এখানে একটি উদাহরণ যা DataClient.OnDataChangedListener প্রয়োগ করে:

কোটলিন

class MainActivity : Activity(), DataClient.OnDataChangedListener {

    public override fun onResume() {
        Wearable.getDataClient(this).addListener(this)
    }

    override fun onPause() {
        Wearable.getDataClient(this).removeListener(this)
    }

    override fun onDataChanged(dataEvents: DataEventBuffer) {
        dataEvents.forEach { event ->
            if (event.type == DataEvent.TYPE_DELETED) {
                Log.d(TAG, "DataItem deleted: " + event.dataItem.uri)
            } else if (event.type == DataEvent.TYPE_CHANGED) {
                Log.d(TAG, "DataItem changed: " + event.dataItem.uri)
            }
        }
    }
}

জাভা

public class MainActivity extends Activity implements DataClient.OnDataChangedListener {

    @Override
    public void onResume() {
        Wearable.getDataClient(this).addListener(this);
    }

    @Override
    protected void onPause() {
        Wearable.getDataClient(this).removeListener(this);
    }

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_DELETED) {
                Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
            } else if (event.getType() == DataEvent.TYPE_CHANGED) {
                Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
            }
        }
    }
}

লাইভ শ্রোতাদের সাথে ফিল্টার ব্যবহার করুন

পূর্বে উল্লিখিত হিসাবে, আপনি যেমন ম্যানিফেস্ট-ভিত্তিক WearableListenerService অবজেক্টের জন্য উদ্দেশ্য ফিল্টারগুলি নির্দিষ্ট করতে পারেন, আপনি পরিধানযোগ্য API এর মাধ্যমে একটি লাইভ শ্রোতা নিবন্ধন করার সময় অভিপ্রায় ফিল্টার ব্যবহার করতে পারেন। একই নিয়ম API-ভিত্তিক লাইভ শ্রোতা এবং ম্যানিফেস্ট-ভিত্তিক শ্রোতা উভয়ের ক্ষেত্রেই প্রযোজ্য।

একটি সাধারণ প্যাটার্ন হল একটি ক্রিয়াকলাপের onResume() পদ্ধতিতে একটি নির্দিষ্ট পথ বা পাথ উপসর্গের সাথে একজন শ্রোতাকে নিবন্ধন করা এবং তারপর কার্যকলাপের onPause() পদ্ধতিতে শ্রোতাকে সরিয়ে দেওয়া। এই ফ্যাশনে শ্রোতাদের প্রয়োগ করা আপনার অ্যাপটিকে আরও নির্বাচনীভাবে ইভেন্টগুলি গ্রহণ করতে দেয়, এর নকশা এবং দক্ষতা উন্নত করে৷