GoogleApi-এ Wear অ্যাপগুলি মাইগ্রেট করুন

Google Play পরিষেবাগুলির 11.8.0 সংস্করণ থেকে শুরু করে, Wear OS অ্যাপগুলিকে GoogleApiClient ক্লাস থেকে দূরে সরানো উচিত এবং পরিবর্তে GoogleApi ক্লাসের উপর ভিত্তি করে ক্লায়েন্ট অবজেক্টগুলি ব্যবহার করা উচিত৷

GoogleApi এর ব্যবহার অ্যাসিঙ্ক্রোনাস অপারেশন সেট আপ করা সহজ করে তোলে। উদাহরণস্বরূপ, Tasks API এর ভূমিকায় বর্ণিত হিসাবে, আপনি একটি PendingResult অবজেক্টের পরিবর্তে একটি Task অবজেক্ট পেতে পারেন।

এই পৃষ্ঠায় রয়েছে:

  • প্রতিস্থাপন উপাদান একটি টেবিল
  • টাস্ক API ব্যবহার করার জন্য একটি বিদ্যমান অ্যাপ আপডেট করার একটি উদাহরণ

দ্রষ্টব্য: এই আপডেটটি চীনের জন্য Wear OS অ্যাপগুলিতে প্রযোজ্য নয়, যা সাধারণত Google Play পরিষেবাগুলির 10.2.0 সংস্করণ ব্যবহার করে৷

দ্রষ্টব্য: এই APIটি বর্তমানে শুধুমাত্র Android ফোন এবং Wear OS ঘড়িগুলিতে উপলব্ধ যা Android ফোনের সাথে যুক্ত৷ iOS ফোনের সাথে যুক্ত Wear OS ঘড়িগুলির জন্য, ইন্টারনেট সংযোগ উপলব্ধ থাকলে অ্যাপগুলি অন্যান্য ক্লাউড-ভিত্তিক APIগুলিকে জিজ্ঞাসা করতে পারে।

অবচিত উপাদানের জন্য প্রতিস্থাপন

আপনি যখন GoogleApi ক্লাস প্রসারিত করে এমন ক্লাস ব্যবহার করেন, যেমন DataClient এবং MessageClient , তখন Google Play পরিষেবা SDK আপনার জন্য Google Play পরিষেবাগুলির সংযোগগুলি পরিচালনা করে৷

যে অ্যাপগুলি নীচের প্রতিস্থাপন ক্লাসগুলি ব্যবহার করে তাদের GoogleApiClient অবজেক্টগুলি তৈরি এবং পরিচালনা করার প্রয়োজন নেই৷ এছাড়াও পরিধানযোগ্য ক্লাসের জন্য Google API এবং রেফারেন্স পৃষ্ঠা অ্যাক্সেস করা দেখুন।

নিম্নোক্ত সারণীতে অপ্রচলিত উপাদান এবং তাদের প্রতিস্থাপন রয়েছে:

অবলুপ্ত উপাদান প্রতিস্থাপন উপাদান
CapabilityApi CapabilityClient
Channel ChannelClient.Channel
ChannelApi ChannelClient
DataApi DataClient
MessageApi MessageClient
NodeApi NodeClient

এছাড়াও নিম্নলিখিত নোট করুন:

একটি Wear অ্যাপের জন্য মাইগ্রেশনের উদাহরণ

মাইগ্রেশনের উদাহরণ হিসাবে, নীচের কোড স্নিপেটগুলি ব্যাখ্যা করে যে কীভাবে Wear ডেটা লেয়ার নমুনা , যা ডেটা লেয়ার API ব্যবহার করে, Google Play পরিষেবাগুলির 11.8.0 সংস্করণের জন্য আপডেট করা হয়েছিল৷ যদি আপনার অ্যাপে একটি ফোন মডিউল থাকে, তাহলে এর আপডেটগুলি পরিধান মডিউলের মতোই হতে পারে।

Google Play পরিষেবার উপর নির্ভরতা আপডেট করুন

যেহেতু আপনার অ্যাপ Google Play পরিষেবার আগের সংস্করণের উপর নির্ভর করতে পারে, তাই আপনার Wear মডিউলের build.gradle ফাইলে নিম্নলিখিত নির্ভরতা আপডেট করুন:

dependencies {
...
compile 'com.google.android.gms:play-services-wearable:11.8.0'
}

আপনার অ্যাপের আমদানি বিবৃতি আপডেট করুন

Tasks API- এ ক্লাস সহ প্রয়োজনীয় ক্লাস ইম্পোর্ট করুন।

উদাহরণ স্বরূপ, পূর্বে Wear Data Layer এর নমুনা MainActivity.java ফাইলে নিম্নলিখিত ইম্পোর্ট স্টেটমেন্ট অন্তর্ভুক্ত করত। এই import বিবৃতি মুছে ফেলা উচিত:

কোটলিন

...
import com.google.android.gms.common.api.GoogleApiClient
...

জাভা

...
import com.google.android.gms.common.api.GoogleApiClient;
...

Wear Data Layer এর নমুনায় , উপরের মত import বিবৃতিগুলি প্রতিস্থাপন করা হয়েছে, উদাহরণস্বরূপ, নিম্নলিখিতগুলি (দ্বিতীয়টি টাস্ক ব্যতিক্রমগুলি পরিচালনা করার জন্য):

কোটলিন

...
import com.google.android.gms.tasks.Tasks
import java.util.concurrent.ExecutionException
...

জাভা

...
import com.google.android.gms.tasks.Tasks;
import java.util.concurrent.ExecutionException;
...

নতুন ক্লায়েন্ট ইন্টারফেস প্রয়োগ করুন

GoogleApiClient ক্লাস এবং সংশ্লিষ্ট ইন্টারফেসের যেকোন ব্যবহার মুছে ফেলুন ( ConnectionCallbacks , OnConnectionFailedListener , ইত্যাদি) এবং অন্যান্য Listener বাস্তবায়নকে তাদের নতুন সংস্করণ দিয়ে প্রতিস্থাপন করুন। ওভাররাইড করার প্রকৃত পদ্ধতিগুলি সাধারণত আগের মতোই একই নাম থাকে, তাই মূল পরিবর্তনটি নীচের উদাহরণের মতো।

Wear Data Layer এর নমুনার প্রধান কার্যকলাপ (যেমন GitHub এ একটি পার্থক্যে নির্দেশিত) প্রয়োগ করা হয়েছে, উদাহরণস্বরূপ, CapabilityApi.CapabilityListener ইন্টারফেস। কিন্তু এখন, প্রধান কার্যকলাপ CapabilityClient.OnCapabilityChangedListener প্রয়োগ করে।

নীচে ক্লাস সংজ্ঞাগুলির একটি তুলনা।

Google Play পরিষেবাগুলির 11.8.0 সংস্করণ ব্যবহার করার আগে এখানে একটি স্নিপেট রয়েছে:

কোটলিন

class MainActivity :
        Activity(),
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        DataApi.DataListener,
        MessageApi.MessageListener,
        CapabilityApi.CapabilityListener

জাভা

public class MainActivity extends Activity implements
  ConnectionCallbacks,
  OnConnectionFailedListener,
  DataApi.DataListener,
  MessageApi.MessageListener,
  CapabilityApi.CapabilityListener

Google Play পরিষেবাগুলির 11.8.0 সংস্করণ ব্যবহার করার পরে এখানে একটি স্নিপেট রয়েছে:

কোটলিন

class MainActivity :
        Activity(),
        DataClient.OnDataChangedListener,
        MessageClient.OnMessageReceivedListener,
        CapabilityClient.OnCapabilityChangedListener

জাভা

public class MainActivity extends Activity implements
  DataClient.OnDataChangedListener,
  MessageClient.OnMessageReceivedListener,
  CapabilityClient.OnCapabilityChangedListener

সরান এবং শ্রোতা যোগ করুন

নতুন ক্লায়েন্ট অবজেক্টগুলি ক্যাশে করা হয় এবং GoogleApi দৃষ্টান্তগুলির মধ্যে ভাগ করা হয়, তাই সদস্য ভেরিয়েবলগুলি রাখা অপ্রয়োজনীয়; ক্লায়েন্ট তৈরি করতে সস্তা এবং তাদের শ্রোতা হারাবে না।

নীচে সংশোধিত পরিধান ডেটা লেয়ার নমুনা থেকে একটি স্নিপেট রয়েছে:

কোটলিন

override fun onResume() {
    super.onResume()
    Wearable.getDataClient(this).addListener(this)
    Wearable.getMessageClient(this).addListener(this)
    Wearable.getCapabilityClient(this)
            .addListener(
                    this,
                    Uri.parse("wear://"),
                    CapabilityClient.FILTER_REACHABLE
            )
}

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

জাভা

@Override
protected void onResume() {
  super.onResume();
  Wearable.getDataClient(this).addListener(this);
  Wearable.getMessageClient(this).addListener(this);
  Wearable.getCapabilityClient(this)
  .addListener(
    this, Uri.parse("wear://"), CapabilityClient.FILTER_REACHABLE);
}

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

টাস্ক API এর সাথে তথ্যের অনুরোধ করুন

আপনি শ্রোতাদের বাইরে তথ্যের জন্য অনুরোধ করতে চাইতে পারেন যা ডেটা পরিবর্তনের সময় আপনার অ্যাপ আপডেট করে। এই ধরনের ক্ষেত্রে, একটি ক্লায়েন্ট যেমন DataClient ব্যবহার করে একটি অনুরোধ করুন, Tasks API এবং একটি ফলাফল শ্রেণীর (যেমন, Task<ResultType> হিসাবে)।

উদাহরণ স্বরূপ, Wear Data Layer এর নমুনায় দেখানো হয়েছে, আপনি যে কোনো প্রদত্ত ক্ষমতা সহ সংযুক্ত নোডগুলি খুঁজে পেতে Tasks API ব্যবহার করতে পারেন:

কোটলিন

private fun showNodes(vararg capabilityNames: String) {
    Wearable.getCapabilityClient(this)
            .getAllCapabilities(CapabilityClient.FILTER_REACHABLE).apply {
                addOnSuccessListener { capabilityInfoMap ->
                    val nodes: Set<Node> = capabilityInfoMap
                            .filter { capabilityNames.contains(it.key) }
                            .flatMap { it.value.nodes }
                            .toSet()
                    showDiscoveredNodes(nodes)
                }
            }
}

private fun showDiscoveredNodes(nodes: Set<Node>) {
    val nodesList: Set<String> = nodes.map { it.displayName }.toSet()
    val msg: String = if (nodesList.isEmpty()) {
        Log.d(TAG, "Connected Nodes: No connected device was found for the given capabilities")
        getString(R.string.no_device)
    } else {
        Log.d(TAG, "Connected Nodes: ${nodesList.joinToString(separator = ", ")}")
        getString(R.string.connected_nodes, nodesList)
    }
    Toast.makeText(this@MainActivity, msg, Toast.LENGTH_LONG).show()
}

জাভা

private void showNodes(final String... capabilityNames) {
  Task<Map<String, CapabilityInfo>> capabilitiesTask =
    Wearable.getCapabilityClient(this)
            .getAllCapabilities(CapabilityClient.FILTER_REACHABLE);
  capabilitiesTask.addOnSuccessListener(new
    OnSuccessListener<Map<String, CapabilityInfo>>() {
      @Override
      public void onSuccess(Map<String, CapabilityInfo>
        capabilityInfoMap) {
          Set<Node> nodes = new HashSet<>();
          if (capabilityInfoMap.isEmpty()) {
            showDiscoveredNodes(nodes);
            return;
          }
          for (String capabilityName : capabilityNames) {
            CapabilityInfo capabilityInfo = capabilityInfoMap.get(capabilityName);
            if (capabilityInfo != null) {
              nodes.addAll(capabilityInfo.getNodes());
            }
          }
          showDiscoveredNodes(nodes);
      }
  });
}

private void showDiscoveredNodes(Set<Node> nodes) {
  List<String> nodesList = new ArrayList<>();
  for (Node node : nodes) {
    nodesList.add(node.getDisplayName());
  }
  LOGD(TAG, "Connected Nodes: " + (nodesList.isEmpty()
    ? "No connected device was found for the given capabilities"
    : TextUtils.join(",", nodesList)));
  String msg;
  if (!nodesList.isEmpty()) {
    msg = getString(R.string.connected_nodes, TextUtils.join(", ", nodesList));
  } else {
    msg = getString(R.string.no_device);
  }
  Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
}

পরিধানযোগ্য এবং টাস্ক API ব্যবহার করে এমন অতিরিক্ত কোডের জন্য, Wear Data Layer এর নমুনা দেখুন। এবং UI থ্রেডের বাইরে বা কোনও পরিষেবাতে ভারী কাজগুলি ব্যবহার করার উদাহরণ হিসাবে, আরেকটি বিকল্প উপলব্ধ রয়েছে। কিভাবে একটি টাস্ক ব্লক করতে হয় এবং সিঙ্ক্রোনাসভাবে ফলাফল পেতে হয় তার একটি উদাহরণ এখানে দেওয়া হল:

কোটলিন

override fun doInBackground(vararg params: Asset): Bitmap? {
    if (params.isNotEmpty()) {
        val asset = params[0]
        val getFdForAssetResponseTask: Task<DataClient.GetFdForAssetResponse> =
                Wearable.getDataClient(applicationContext).getFdForAsset(asset)
        return try {
            // Block on a task and get the result synchronously. This is generally done
            // when executing a task inside a separately managed background thread. Doing
            // this on the main (UI) thread can cause your application to become
            // unresponsive.
            val getFdForAssetResponse: DataClient.GetFdForAssetResponse =
                    Tasks.await(getFdForAssetResponseTask)
            getFdForAssetResponse.inputStream?.let { assetInputStream ->
                BitmapFactory.decodeStream(assetInputStream)
            } ?: run {
                Log.w(TAG, "Requested an unknown Asset.")
                null
            }

        } catch (exception: ExecutionException) {
            Log.e(TAG, "Failed retrieving asset, Task failed: $exception")
            return null
        } catch (exception: InterruptedException) {
            Log.e(TAG, "Failed retrieving asset, interrupt occurred: $exception")
            return null
        }

    } else {
        Log.e(TAG, "Asset must be non-null")
        return null
    }
}

override fun onPostExecute(bitmap: Bitmap?) {
    bitmap?.also {
        Log.d(TAG, "Setting background image on second page..")
        moveToPage(1)
        assetFragment.setBackgroundImage(it)
    }
}

জাভা

@Override
protected Bitmap doInBackground(Asset... params) {
  if (params.length > 0) {
    Asset asset = params[0];
    Task<DataClient.GetFdForAssetResponse> getFdForAssetResponseTask =
      Wearable.getDataClient(getApplicationContext()).getFdForAsset(asset);
    try {
      // Block on a task and get the result synchronously. This is generally done
      // when executing a task inside a separately managed background thread. Doing
      // this on the main (UI) thread can cause your application to become
      // unresponsive.
      DataClient.GetFdForAssetResponse getFdForAssetResponse =
        Tasks.await(getFdForAssetResponseTask);
      InputStream assetInputStream = getFdForAssetResponse.getInputStream();
      if (assetInputStream != null) {
        return BitmapFactory.decodeStream(assetInputStream);
      } else {
        Log.w(TAG, "Requested an unknown Asset.");
        return null;
      }

    } catch (ExecutionException exception) {
      Log.e(TAG, "Failed retrieving asset, Task failed: " + exception);
      return null;
    } catch (InterruptedException exception) {
      Log.e(TAG, "Failed retrieving asset, interrupt occurred: " + exception);
      return null;
    }
  } else {
    Log.e(TAG, "Asset must be non-null");
    return null;
  }
}

@Override
protected void onPostExecute(Bitmap bitmap) {
  if (bitmap != null) {
    LOGD(TAG, "Setting background image on second page..");
    moveToPage(1);
    assetFragment.setBackgroundImage(bitmap);
  }
}