গুগল অ্যাসিস্ট্যান্ট আপনাকে ভয়েস কমান্ড ব্যবহার করে গুগল হোম, আপনার ফোন এবং আরও অনেক ডিভাইস নিয়ন্ত্রণ করতে দেয়। এতে মিডিয়া কমান্ড ("বিয়ন্সের কিছু একটা চালাও") বোঝার অন্তর্নির্মিত ক্ষমতা রয়েছে এবং এটি মিডিয়া কন্ট্রোল (যেমন পজ, স্কিপ, ফাস্ট ফরোয়ার্ড, থাম্বস আপ) সমর্থন করে।
অ্যাসিস্ট্যান্ট একটি মিডিয়া সেশন ব্যবহার করে অ্যান্ড্রয়েড মিডিয়া অ্যাপগুলোর সাথে যোগাযোগ করে। এটি আপনার অ্যাপ চালু করতে এবং প্লেব্যাক শুরু করতে ইন্টেন্ট বা সার্ভিস ব্যবহার করতে পারে। সর্বোত্তম ফলাফলের জন্য, আপনার অ্যাপে এই পৃষ্ঠায় বর্ণিত সমস্ত বৈশিষ্ট্য বাস্তবায়ন করা উচিত।
একটি মিডিয়া সেশন ব্যবহার করুন
প্রতিটি অডিও এবং ভিডিও অ্যাপে অবশ্যই একটি মিডিয়া সেশন অন্তর্ভুক্ত থাকতে হবে, যাতে প্লেব্যাক শুরু হয়ে গেলে অ্যাসিস্ট্যান্ট ট্রান্সপোর্ট কন্ট্রোলগুলো পরিচালনা করতে পারে।
মনে রাখবেন যে, যদিও অ্যাসিস্ট্যান্ট শুধুমাত্র এই বিভাগে তালিকাভুক্ত অ্যাকশনগুলি ব্যবহার করে, অন্যান্য অ্যাপ্লিকেশনের সাথে সামঞ্জস্যতা নিশ্চিত করার জন্য সমস্ত প্রস্তুতি এবং প্লেব্যাক API প্রয়োগ করাই সর্বোত্তম অনুশীলন। যে সমস্ত অ্যাকশন আপনি সমর্থন করেন না, সেগুলির জন্য মিডিয়া সেশন কলব্যাকগুলি ERROR_CODE_NOT_SUPPORTED ব্যবহার করে একটি ত্রুটি ফেরত দিতে পারে।
আপনার অ্যাপের MediaSession অবজেক্টে এই ফ্ল্যাগগুলি সেট করে মিডিয়া এবং ট্রান্সপোর্ট কন্ট্রোলগুলি সক্রিয় করুন:
কোটলিন
session.setFlags( MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS )
জাভা
session.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
আপনার অ্যাপের মিডিয়া সেশনে এটি যে অ্যাকশনগুলো সমর্থন করে তা ঘোষণা করতে হবে এবং সংশ্লিষ্ট মিডিয়া সেশন কলব্যাকগুলো ইমপ্লিমেন্ট করতে হবে। setActions() -এ আপনার সমর্থিত অ্যাকশনগুলো ঘোষণা করুন।
ইউনিভার্সাল অ্যান্ড্রয়েড মিউজিক প্লেয়ার স্যাম্পল প্রজেক্টটি একটি মিডিয়া সেশন কীভাবে সেট আপ করতে হয় তার একটি ভালো উদাহরণ।
প্লেব্যাক অ্যাকশন
কোনো সার্ভিস থেকে প্লেব্যাক শুরু করার জন্য, একটি মিডিয়া সেশনে অবশ্যই এই PLAY অ্যাকশনগুলো এবং তাদের কলব্যাকগুলো থাকতে হবে:
| পদক্ষেপ | কলব্যাক |
|---|---|
ACTION_PLAY | onPlay() |
ACTION_PLAY_FROM_SEARCH | onPlayFromSearch() |
ACTION_PLAY_FROM_URI (*) | onPlayFromUri() |
আপনার সেশনে এই PREPARE অ্যাকশনগুলো এবং তাদের কলব্যাকগুলোও বাস্তবায়ন করা উচিত:
| পদক্ষেপ | কলব্যাক |
|---|---|
ACTION_PREPARE | onPrepare() |
ACTION_PREPARE_FROM_SEARCH | onPrepareFromSearch() |
ACTION_PREPARE_FROM_URI (*) | onPrepareFromUri() |
(*) গুগল অ্যাসিস্ট্যান্ট URI-ভিত্তিক অ্যাকশনগুলো শুধুমাত্র সেইসব কোম্পানির জন্য কাজ করে যারা গুগলকে URI প্রদান করে। গুগলের কাছে আপনার মিডিয়া কন্টেন্ট বর্ণনা করার বিষয়ে আরও জানতে মিডিয়া অ্যাকশনস দেখুন।
প্রিপারেশন এপিআইগুলো প্রয়োগ করার মাধ্যমে, ভয়েস কমান্ডের পরের প্লেব্যাক ল্যাটেন্সি কমানো যেতে পারে। যেসব মিডিয়া অ্যাপ প্লেব্যাক ল্যাটেন্সি উন্নত করতে চায়, তারা এই অতিরিক্ত সময়কে কন্টেন্ট ক্যাশ করা এবং মিডিয়া প্লেব্যাকের প্রস্তুতি শুরু করার জন্য ব্যবহার করতে পারে।
অনুসন্ধান প্রশ্নগুলি পার্স করুন
যখন কোনো ব্যবহারকারী কোনো নির্দিষ্ট মিডিয়া আইটেম অনুসন্ধান করেন, যেমন “[আপনার অ্যাপের নাম]-এ জ্যাজ বাজান” বা “[গানের শিরোনাম] শুনুন” , তখন onPrepareFromSearch() বা onPlayFromSearch() কলব্যাক মেথডটি একটি কোয়েরি প্যারামিটার এবং একটি এক্সট্রাস বান্ডেল গ্রহণ করে।
আপনার অ্যাপটি নিম্নলিখিত ধাপগুলো অনুসরণ করে ভয়েস সার্চ কোয়েরিটি পার্স করবে এবং প্লেব্যাক শুরু করবে:
- ফলাফল ফিল্টার করতে ভয়েস সার্চ থেকে প্রাপ্ত এক্সট্রাস বান্ডেল এবং সার্চ কোয়েরি স্ট্রিং ব্যবহার করুন।
- এই ফলাফলগুলোর উপর ভিত্তি করে একটি প্লেব্যাক কিউ তৈরি করুন।
- ফলাফল থেকে সবচেয়ে প্রাসঙ্গিক মিডিয়া আইটেমটি চালান।
onPlayFromSearch() মেথডটি একটি extras প্যারামিটার গ্রহণ করে, যাতে ভয়েস সার্চ থেকে প্রাপ্ত আরও বিস্তারিত তথ্য থাকে। এই extras আপনাকে আপনার অ্যাপে প্লেব্যাকের জন্য অডিও কন্টেন্ট খুঁজে পেতে সাহায্য করে। যদি সার্চ রেজাল্ট এই ডেটা সরবরাহ করতে না পারে, তবে আপনি র' সার্চ কোয়েরিটি পার্স করার এবং সেই কোয়েরির উপর ভিত্তি করে উপযুক্ত ট্র্যাকগুলি প্লে করার জন্য লজিক প্রয়োগ করতে পারেন।
অ্যান্ড্রয়েড অটোমোটিভ ওএস এবং অ্যান্ড্রয়েড অটো-তে নিম্নলিখিত অতিরিক্ত সুবিধাগুলো সমর্থিত:
নিম্নলিখিত কোড স্নিপেটটি দেখায় কিভাবে আপনার MediaSession.Callback ইমপ্লিমেন্টেশনে onPlayFromSearch() মেথডটি ওভাররাইড করে ভয়েস সার্চ কোয়েরি পার্স করতে এবং প্লেব্যাক শুরু করতে হয়:
কোটলিন
override fun onPlayFromSearch(query: String?, extras: Bundle?) { if (query.isNullOrEmpty()) { // The user provided generic string e.g. 'Play music' // Build appropriate playlist queue } else { // Build a queue based on songs that match "query" or "extras" param val mediaFocus: String? = extras?.getString(MediaStore.EXTRA_MEDIA_FOCUS) if (mediaFocus == MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE) { isArtistFocus = true artist = extras.getString(MediaStore.EXTRA_MEDIA_ARTIST) } else if (mediaFocus == MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE) { isAlbumFocus = true album = extras.getString(MediaStore.EXTRA_MEDIA_ALBUM) } // Implement additional "extras" param filtering } // Implement your logic to retrieve the queue var result: String? = when { isArtistFocus -> artist?.also { searchMusicByArtist(it) } isAlbumFocus -> album?.also { searchMusicByAlbum(it) } else -> null } result = result ?: run { // No focus found, search by query for song title query?.also { searchMusicBySongTitle(it) } } if (result?.isNotEmpty() == true) { // Immediately start playing from the beginning of the search results // Implement your logic to start playing music playMusic(result) } else { // Handle no queue found. Stop playing if the app // is currently playing a song } }
জাভা
@Override public void onPlayFromSearch(String query, Bundle extras) { if (TextUtils.isEmpty(query)) { // The user provided generic string e.g. 'Play music' // Build appropriate playlist queue } else { // Build a queue based on songs that match "query" or "extras" param String mediaFocus = extras.getString(MediaStore.EXTRA_MEDIA_FOCUS); if (TextUtils.equals(mediaFocus, MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE)) { isArtistFocus = true; artist = extras.getString(MediaStore.EXTRA_MEDIA_ARTIST); } else if (TextUtils.equals(mediaFocus, MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE)) { isAlbumFocus = true; album = extras.getString(MediaStore.EXTRA_MEDIA_ALBUM); } // Implement additional "extras" param filtering } // Implement your logic to retrieve the queue if (isArtistFocus) { result = searchMusicByArtist(artist); } else if (isAlbumFocus) { result = searchMusicByAlbum(album); } if (result == null) { // No focus found, search by query for song title result = searchMusicBySongTitle(query); } if (result != null && !result.isEmpty()) { // Immediately start playing from the beginning of the search results // Implement your logic to start playing music playMusic(result); } else { // Handle no queue found. Stop playing if the app // is currently playing a song } }
আপনার অ্যাপে অডিও কন্টেন্ট চালানোর জন্য ভয়েস সার্চ কীভাবে প্রয়োগ করবেন তার আরও বিস্তারিত উদাহরণের জন্য, ইউনিভার্সাল অ্যান্ড্রয়েড মিউজিক প্লেয়ার স্যাম্পলটি দেখুন।
খালি কোয়েরি পরিচালনা করুন
যদি কোনো সার্চ কোয়েরি ছাড়া onPrepare() , onPlay() , onPrepareFromSearch() , বা onPlayFromSearch() কল করা হয়, তাহলে আপনার মিডিয়া অ্যাপটি 'বর্তমান' মিডিয়াটি প্লে করবে। যদি কোনো বর্তমান মিডিয়া না থাকে, তাহলে অ্যাপটি সাম্প্রতিকতম প্লেলিস্ট বা র্যান্ডম কিউ থেকে কোনো গান প্লে করার চেষ্টা করবে। যখন কোনো ব্যবহারকারী অতিরিক্ত তথ্য ছাড়াই “[আপনার অ্যাপের নাম]-এ মিউজিক প্লে করুন” বলে, তখন অ্যাসিস্ট্যান্ট এই API-গুলো ব্যবহার করে।
যখন কোনো ব্যবহারকারী “[আপনার অ্যাপের নাম]-এ গান চালান” বলেন, তখন অ্যান্ড্রয়েড অটোমোটিভ ওএস বা অ্যান্ড্রয়েড অটো আপনার অ্যাপের onPlayFromSearch() মেথড কল করে অ্যাপটি চালু করার এবং অডিও চালানোর চেষ্টা করে। কিন্তু, যেহেতু ব্যবহারকারী মিডিয়া আইটেমের নাম বলেননি, onPlayFromSearch() মেথডটি একটি খালি কোয়েরি প্যারামিটার পায়। এই ধরনের ক্ষেত্রে, আপনার অ্যাপের উচিত অবিলম্বে অডিও চালানো, যেমন—সর্বশেষ প্লেলিস্ট বা র্যান্ডম কিউ থেকে কোনো গান চালানো।
ভয়েস অ্যাকশনের জন্য লিগ্যাসি সাপোর্ট ঘোষণা করুন
বেশিরভাগ ক্ষেত্রে, উপরে বর্ণিত প্লেব্যাক অ্যাকশনগুলো পরিচালনা করলেই আপনার অ্যাপের প্রয়োজনীয় সমস্ত প্লেব্যাক কার্যকারিতা পাওয়া যায়। তবে, কিছু সিস্টেমে অনুসন্ধানের জন্য আপনার অ্যাপে একটি ইন্টেন্ট ফিল্টার থাকা প্রয়োজন। আপনার অ্যাপের ম্যানিফেস্ট ফাইলগুলোতে এই ইন্টেন্ট ফিল্টারের জন্য সমর্থন ঘোষণা করা উচিত।
ফোন অ্যাপের ম্যানিফেস্ট ফাইলে এই কোডটি অন্তর্ভুক্ত করুন:
<activity>
<intent-filter>
<action android:name=
"android.media.action.MEDIA_PLAY_FROM_SEARCH" />
<category android:name=
"android.intent.category.DEFAULT" />
</intent-filter>
</activity>
পরিবহন নিয়ন্ত্রণ
আপনার অ্যাপের মিডিয়া সেশন সক্রিয় হওয়ার পরে, অ্যাসিস্ট্যান্ট প্লেব্যাক নিয়ন্ত্রণ করতে এবং মিডিয়া মেটাডেটা আপডেট করতে ভয়েস কমান্ড দিতে পারে। এটি কার্যকর করার জন্য, আপনার কোডে নিম্নলিখিত অ্যাকশনগুলি সক্ষম করতে হবে এবং সংশ্লিষ্ট কলব্যাকগুলি প্রয়োগ করতে হবে:
| পদক্ষেপ | কলব্যাক | বর্ণনা |
|---|---|---|
ACTION_SKIP_TO_NEXT | onSkipToNext() | পরবর্তী ভিডিও |
ACTION_SKIP_TO_PREVIOUS | onSkipToPrevious() | আগের গান |
ACTION_PAUSE, ACTION_PLAY_PAUSE | onPause() | বিরতি |
ACTION_STOP | onStop() | থামুন |
ACTION_PLAY | onPlay() | জীবনবৃত্তান্ত |
ACTION_SEEK_TO | onSeekTo() | ৩০ সেকেন্ড পিছনে যান |
ACTION_SET_RATING | onSetRating(android.support.v4.media.RatingCompat) | ভালো/খারাপ। |
ACTION_SET_CAPTIONING_ENABLED | onSetCaptioningEnabled(boolean) | ক্যাপশনিং চালু/বন্ধ করুন। |
অনুগ্রহ করে লক্ষ্য করুন:
- সিক কমান্ড কাজ করার জন্য,
PlaybackStateঅবশ্যইstate, position, playback speed, and update timeঅনুযায়ী হালনাগাদ থাকতে হবে। স্টেট পরিবর্তিত হলে অ্যাপটিকে অবশ্যইsetPlaybackState()কল করতে হবে। - মিডিয়া অ্যাপটিকে অবশ্যই মিডিয়া সেশন মেটাডেটা হালনাগাদ রাখতে হবে। এটি "কোন গান বাজছে?"-এর মতো প্রশ্নের উত্তর দিতে পারে। যখন প্রযোজ্য ফিল্ডগুলো (যেমন ট্র্যাকের শিরোনাম, শিল্পী এবং নাম) পরিবর্তিত হয়, তখন অ্যাপটিকে অবশ্যই
setMetadata()কল করতে হবে। - অ্যাপটি কোন ধরনের রেটিং সমর্থন করে তা নির্দেশ করার জন্য
MediaSession.setRatingType()অবশ্যই সেট করতে হবে এবং অ্যাপটিকে অবশ্যইonSetRating()ইমপ্লিমেন্ট করতে হবে। যদি অ্যাপটি রেটিং সমর্থন না করে, তবে রেটিং টাইপটিRATING_NONEএ সেট করা উচিত।
আপনি যে ভয়েস অ্যাকশনগুলো সমর্থন করেন, তা সম্ভবত কন্টেন্টের ধরন অনুযায়ী ভিন্ন হবে।
| বিষয়বস্তুর ধরণ | প্রয়োজনীয় পদক্ষেপ |
|---|---|
| সঙ্গীত | অবশ্যই সমর্থন করতে হবে : প্লে, পজ, স্টপ, পরবর্তী ধাপে যান এবং পূর্ববর্তী ধাপে যান। এর জন্য জোরালোভাবে সমর্থন সুপারিশ করছি : Seek To |
| পডকাস্ট | অবশ্যই সমর্থন করতে হবে : প্লে, পজ, স্টপ এবং সিক টু এর জন্য সমর্থন সুপারিশ করুন : পরবর্তীটিতে যান এবং পূর্ববর্তীটিতে যান |
| অডিওবুক | অবশ্যই সমর্থন করতে হবে : প্লে, পজ, স্টপ এবং সিক টু |
| রেডিও | প্লে, পজ এবং স্টপ অবশ্যই সমর্থন করতে হবে । |
| সংবাদ | অবশ্যই সমর্থন করতে হবে : প্লে, পজ, স্টপ, পরবর্তী ধাপে যান এবং পূর্ববর্তী ধাপে যান। |
| ভিডিও | অবশ্যই সমর্থন করতে হবে : প্লে, পজ, স্টপ, সিক টু, রিওয়াইন্ড এবং ফাস্ট ফরোয়ার্ড। 'Skip to Next' এবং 'Skip to Previous'- এর জন্য জোরালো সমর্থনের সুপারিশ করা হচ্ছে । |
আপনার প্রোডাক্ট অফারিং যতখানি সমর্থন করে, উপরে তালিকাভুক্ত অ্যাকশনগুলোর মধ্যে আপনাকে অবশ্যই ততগুলো সমর্থন করতে হবে, কিন্তু অন্য যেকোনো অ্যাকশনের ক্ষেত্রেও আপনাকে সাবলীলভাবে সাড়া দিতে হবে। উদাহরণস্বরূপ, যদি শুধুমাত্র প্রিমিয়াম ব্যবহারকারীদেরই আগের আইটেমে ফিরে যাওয়ার ক্ষমতা থাকে, তাহলে কোনো ফ্রি টিয়ার ব্যবহারকারী অ্যাসিস্ট্যান্টকে আগের আইটেমে ফিরে যেতে বললে আপনি একটি এরর দেখাতে পারেন। আরও নির্দেশনার জন্য এরর হ্যান্ডলিং সেকশনটি দেখুন।
চেষ্টা করার জন্য নমুনা ভয়েস কোয়েরি
নিম্নলিখিত সারণিতে কিছু নমুনা কোয়েরির রূপরেখা দেওয়া হলো যা আপনার ইমপ্লিমেন্টেশন পরীক্ষা করার সময় ব্যবহার করা উচিত:
| মিডিয়াসেশন কলব্যাক | “হে গুগল” বাক্যাংশটি ব্যবহার করতে | |
|---|---|---|
onPlay() | খেলুন। পুনরায় শুরু করুন। | |
onPlayFromSearch()onPlayFromUri() | সঙ্গীত | (অ্যাপের নাম) -এ গান বা মিউজিক চালান। এটি একটি খালি কোয়েরি। (অ্যাপের নাম) -এ (গান | শিল্পী | অ্যালবাম | ধরণ | প্লেলিস্ট) চালান। |
| রেডিও | (অ্যাপের নাম) -এ (ফ্রিকোয়েন্সি | স্টেশন) চালান। | |
| অডিওবুক | (অ্যাপের নাম) -এ আমার অডিওবুকটি পড়ুন। (অ্যাপের নাম) -এ (অডিওবুক) পড়ুন। | |
| পডকাস্ট | (অ্যাপের নামে) (পডকাস্ট) চালান। | |
onPause() | “থামুন।” | |
onStop() | থামুন। | |
onSkipToNext() | পরবর্তী (গান | পর্ব | ট্র্যাক) । | |
onSkipToPrevious() | পূর্ববর্তী (গান | পর্ব | ট্র্যাক) । | |
onSeekTo() | পুনরায় শুরু করুন। ## সেকেন্ড এগিয়ে যান। ## মিনিট পেছনে যান। | |
প্রযোজ্য নয় (আপনার MediaMetadata হালনাগাদ রাখুন) | কী চলছে? | |
ত্রুটি
মিডিয়া সেশনে কোনো ত্রুটি ঘটলে অ্যাসিস্ট্যান্ট তা পরিচালনা করে এবং ব্যবহারকারীদের কাছে রিপোর্ট করে। "একটি মিডিয়া সেশন নিয়ে কাজ করা " অংশে বর্ণিত পদ্ধতি অনুযায়ী, আপনার মিডিয়া সেশনটি যেন তার PlaybackState এ ট্রান্সপোর্ট স্টেট এবং এরর কোড সঠিকভাবে আপডেট করে, তা নিশ্চিত করুন। getErrorCode() দ্বারা ফেরত আসা সমস্ত এরর কোড অ্যাসিস্ট্যান্ট শনাক্ত করতে পারে।
সাধারণত ভুলভাবে পরিচালিত মামলা
এখানে কিছু ত্রুটির উদাহরণ দেওয়া হলো, যেগুলো আপনি সঠিকভাবে সামলাচ্ছেন কিনা তা নিশ্চিত করা উচিত:
- ব্যবহারকারীকে সাইন ইন করতে হবে
-
PlaybackStateএরর কোডটিERROR_CODE_AUTHENTICATION_EXPIREDএ সেট করুন। -
PlaybackStateত্রুটির বার্তা সেট করুন। - প্লেব্যাকের জন্য প্রয়োজন হলে
PlaybackStateঅবস্থাSTATE_ERRORএ সেট করুন, অন্যথায়PlaybackStateএর বাকি অংশ অপরিবর্তিত রাখুন।
-
- ব্যবহারকারী একটি অনুপলব্ধ কাজের জন্য অনুরোধ করেছেন
-
PlaybackStateএরর কোডটি যথাযথভাবে সেট করুন। উদাহরণস্বরূপ, যদি অ্যাকশনটি সমর্থিত না হয় তবেPlaybackStateERROR_CODE_NOT_SUPPORTEDএ সেট করুন, অথবা যদি অ্যাকশনটি সাইন-ইন দ্বারা সুরক্ষিত হয় তবেERROR_CODE_PREMIUM_ACCOUNT_REQUIREDএ সেট করুন। -
PlaybackStateত্রুটির বার্তা সেট করুন। -
PlaybackStateএর বাকি অংশ অপরিবর্তিত রাখুন।
-
- ব্যবহারকারী এমন কন্টেন্টের অনুরোধ করেছেন যা অ্যাপে উপলব্ধ নেই।
-
PlaybackStateএরর কোডটি যথাযথভাবে সেট করুন। উদাহরণস্বরূপ,ERROR_CODE_NOT_AVAILABLE_IN_REGIONব্যবহার করুন। -
PlaybackStateত্রুটির বার্তা সেট করুন। - প্লেব্যাক বন্ধ করতে
PlaybackSateস্টেটটিSTATE_ERRORএ সেট করুন, অন্যথায়PlaybackStateএর বাকি অংশ অপরিবর্তিত রাখুন।
-
- ব্যবহারকারী এমন কন্টেন্টের জন্য অনুরোধ করছেন যার হুবহু মিল পাওয়া যাচ্ছে না। উদাহরণস্বরূপ, একজন ফ্রি-টিয়ার ব্যবহারকারী এমন কন্টেন্ট চাইছেন যা শুধুমাত্র প্রিমিয়াম-টিয়ার ব্যবহারকারীদের জন্য উপলব্ধ।
- আমরা আপনাকে কোনো ত্রুটি না দেখানোর পরামর্শ দিচ্ছি, এবং এর পরিবর্তে প্লে করার জন্য অনুরূপ কিছু খুঁজে বের করাকে অগ্রাধিকার দিন। প্লেব্যাক শুরু হওয়ার আগে অ্যাসিস্ট্যান্ট সবচেয়ে প্রাসঙ্গিক ভয়েস রেসপন্সটি বলে দেবে।
একটি উদ্দেশ্য নিয়ে প্লেব্যাক
অ্যাসিস্ট্যান্ট একটি ডিপ লিঙ্কসহ ইন্টেন্ট পাঠিয়ে কোনো অডিও বা ভিডিও অ্যাপ চালু করতে এবং প্লেব্যাক শুরু করতে পারে।
অভিপ্রায় এবং এর গভীর সংযোগ বিভিন্ন উৎস থেকে আসতে পারে:
- যখন অ্যাসিস্ট্যান্ট কোনো মোবাইল অ্যাপ চালু করে, তখন এটি গুগল সার্চ ব্যবহার করে মার্ক-আপ করা কন্টেন্ট খুঁজে বের করতে পারে, যা কোনো ওয়াচ অ্যাকশনের জন্য একটি লিঙ্ক সরবরাহ করে।
- যখন অ্যাসিস্ট্যান্ট একটি টিভি অ্যাপ চালু করে, তখন মিডিয়া কন্টেন্টের জন্য URI প্রকাশ করতে আপনার অ্যাপে একটি টিভি সার্চ প্রোভাইডার অন্তর্ভুক্ত থাকা উচিত। অ্যাসিস্ট্যান্ট কন্টেন্ট প্রোভাইডারের কাছে একটি কোয়েরি পাঠায়, যা ডিপ লিঙ্কের জন্য একটি URI এবং একটি ঐচ্ছিক অ্যাকশন সম্বলিত একটি ইন্টেন্ট ফেরত দেবে। যদি কোয়েরিটি ইন্টেন্টে কোনো অ্যাকশন ফেরত দেয়, তবে অ্যাসিস্ট্যান্ট সেই অ্যাকশন এবং URI-টি আপনার অ্যাপে ফেরত পাঠায়। যদি প্রোভাইডার কোনো অ্যাকশন নির্দিষ্ট না করে, তবে অ্যাসিস্ট্যান্ট ইন্টেন্টটিতে
ACTION_VIEWযোগ করবে।
অ্যাসিস্ট্যান্ট আপনার অ্যাপে পাঠানো ইন্টেন্টে true ভ্যালু সহ অতিরিক্ত EXTRA_START_PLAYBACK যোগ করে। EXTRA_START_PLAYBACK সহ একটি ইন্টেন্ট পেলে আপনার অ্যাপের প্লেব্যাক শুরু করা উচিত।
সক্রিয় থাকা অবস্থায় ইনটেন্ট পরিচালনা করা
আপনার অ্যাপে আগের কোনো অনুরোধের কন্টেন্ট প্লে হতে থাকা অবস্থাতেও ব্যবহারকারীরা অ্যাসিস্ট্যান্টকে কিছু প্লে করতে বলতে পারেন। এর মানে হলো, আপনার অ্যাপের প্লেব্যাক অ্যাক্টিভিটি চালু ও সক্রিয় থাকা অবস্থাতেও অ্যাপটি প্লেব্যাক শুরু করার জন্য নতুন ইন্টেন্ট গ্রহণ করতে পারে।
যে অ্যাক্টিভিটিগুলো ডিপ লিঙ্কসহ ইনটেন্ট সমর্থন করে, তাদের নতুন অনুরোধগুলো পরিচালনা করার জন্য onNewIntent() ওভাররাইড করা উচিত।
প্লেব্যাক শুরু করার সময়, অ্যাসিস্ট্যান্ট আপনার অ্যাপে পাঠানো ইন্টেন্টে অতিরিক্ত ফ্ল্যাগ যোগ করতে পারে। বিশেষ করে, এটি FLAG_ACTIVITY_CLEAR_TOP অথবা FLAG_ACTIVITY_NEW_TASK অথবা উভয়ই যোগ করতে পারে। যদিও আপনার কোডের এই ফ্ল্যাগগুলো হ্যান্ডেল করার প্রয়োজন নেই, অ্যান্ড্রয়েড সিস্টেম সেগুলোতে সাড়া দেয়। যখন আগের URI-টি প্লে হতে থাকে এবং একটি নতুন URI সহ দ্বিতীয় প্লেব্যাক অনুরোধ আসে, তখন এটি আপনার অ্যাপের আচরণকে প্রভাবিত করতে পারে। এই ক্ষেত্রে আপনার অ্যাপ কীভাবে সাড়া দেয় তা পরীক্ষা করে দেখা ভালো। আপনি পরিস্থিতিটি অনুকরণ করতে adb কমান্ড লাইন টুল ব্যবহার করতে পারেন (ধ্রুবক 0x14000000 হলো দুটি ফ্ল্যাগের বুলিয়ান বিটওয়াইজ OR):
adb shell 'am start -a android.intent.action.VIEW --ez android.intent.extra.START_PLAYBACK true -d "<first_uri>"' -f 0x14000000
adb shell 'am start -a android.intent.action.VIEW --ez android.intent.extra.START_PLAYBACK true -d "<second_uri>"' -f 0x14000000
একটি পরিষেবা থেকে প্লেব্যাক
আপনার অ্যাপে যদি এমন কোনো media browser service থাকে যা অ্যাসিস্ট্যান্টকে কানেকশনের অনুমতি দেয়, তাহলে অ্যাসিস্ট্যান্ট সেই সার্ভিসের media session সাথে যোগাযোগ করে অ্যাপটি চালু করতে পারে। মিডিয়া ব্রাউজার সার্ভিস কখনোই কোনো অ্যাক্টিভিটি চালু করবে না। অ্যাসিস্ট্যান্ট আপনার setSessionActivity() দিয়ে সংজ্ঞায়িত করা PendingIntent উপর ভিত্তি করে আপনার অ্যাক্টিভিটি চালু করবে।
মিডিয়া ব্রাউজার সার্ভিসটি চালু করার সময় MediaSession.Token অবশ্যই সেট করুন। মনে রাখবেন, চালু করার সময়সহ সব সময় সমর্থিত প্লেব্যাক অ্যাকশনগুলো সেট করতে হবে। অ্যাসিস্ট্যান্ট আশা করে যে, প্রথম প্লেব্যাক কমান্ড পাঠানোর আগে আপনার মিডিয়া অ্যাপটি প্লেব্যাক অ্যাকশনগুলো সেট করে রাখবে।
কোনো সার্ভিস থেকে শুরু করার জন্য, অ্যাসিস্ট্যান্ট মিডিয়া ব্রাউজার ক্লায়েন্ট এপিআইগুলো প্রয়োগ করে। এটি TransportControls কলগুলো সম্পাদন করে, যা আপনার অ্যাপের মিডিয়া সেশনে PLAY অ্যাকশন কলব্যাকগুলোকে ট্রিগার করে।
নিম্নলিখিত ডায়াগ্রামটি অ্যাসিস্ট্যান্ট দ্বারা তৈরি কলগুলির ক্রম এবং সংশ্লিষ্ট মিডিয়া সেশন কলব্যাকগুলি দেখায়। (প্রস্তুতিমূলক কলব্যাকগুলি কেবল তখনই পাঠানো হয় যদি আপনার অ্যাপ সেগুলি সমর্থন করে।) সমস্ত কল অ্যাসিঙ্ক্রোনাস। অ্যাসিস্ট্যান্ট আপনার অ্যাপ থেকে কোনো প্রতিক্রিয়ার জন্য অপেক্ষা করে না।

যখন কোনো ব্যবহারকারী প্লে করার জন্য ভয়েস কমান্ড দেন, তখন অ্যাসিস্ট্যান্ট একটি সংক্ষিপ্ত ঘোষণার মাধ্যমে সাড়া দেয়। ঘোষণাটি শেষ হওয়া মাত্রই অ্যাসিস্ট্যান্ট প্লে অ্যাকশনটি সম্পাদন করে। এটি কোনো নির্দিষ্ট প্লেব্যাক অবস্থার জন্য অপেক্ষা করে না।
যদি আপনার অ্যাপ ACTION_PREPARE_* অ্যাকশনগুলো সমর্থন করে, তাহলে অ্যাসিস্ট্যান্ট ঘোষণা শুরু করার আগে PREPARE অ্যাকশনটি কল করে।
একটি মিডিয়া ব্রাউজার সার্ভিসের সাথে সংযোগ স্থাপন
আপনার অ্যাপ চালু করার জন্য কোনো সার্ভিস ব্যবহার করতে হলে, অ্যাসিস্ট্যান্টকে অবশ্যই অ্যাপটির MediaBrowserService-এর সাথে সংযোগ স্থাপন করতে এবং এর MediaSession.Token পুনরুদ্ধার করতে সক্ষম হতে হবে। সংযোগের অনুরোধগুলো সার্ভিসের onGetRoot() মেথডে পরিচালনা করা হয়। অনুরোধগুলো পরিচালনা করার দুটি উপায় আছে:
- সমস্ত সংযোগ অনুরোধ গ্রহণ করুন
- শুধুমাত্র অ্যাসিস্ট্যান্ট অ্যাপ থেকে সংযোগের অনুরোধ গ্রহণ করুন
সমস্ত সংযোগ অনুরোধ গ্রহণ করুন
আপনার মিডিয়া সেশনে অ্যাসিস্ট্যান্টকে কমান্ড পাঠানোর অনুমতি দেওয়ার জন্য আপনাকে অবশ্যই একটি BrowserRoot রিটার্ন করতে হবে। সবচেয়ে সহজ উপায় হলো সমস্ত MediaBrowser অ্যাপকে আপনার MediaBrowserService-এর সাথে সংযোগ করার অনুমতি দেওয়া। আপনাকে অবশ্যই একটি নন-নাল (non-null) BrowserRoot রিটার্ন করতে হবে। ইউনিভার্সাল মিউজিক প্লেয়ার থেকে প্রযোজ্য কোডটি নিচে দেওয়া হলো:
কোটলিন
override fun onGetRoot( clientPackageName: String, clientUid: Int, rootHints: Bundle? ): BrowserRoot? { // To ensure you are not allowing any arbitrary app to browse your app's contents, you // need to check the origin: if (!packageValidator.isCallerAllowed(this, clientPackageName, clientUid)) { // If the request comes from an untrusted package, return an empty browser root. // If you return null, then the media browser will not be able to connect and // no further calls will be made to other media browsing methods. Log.i(TAG, "OnGetRoot: Browsing NOT ALLOWED for unknown caller. Returning empty " + "browser root so all apps can use MediaController. $clientPackageName") return MediaBrowserServiceCompat.BrowserRoot(MEDIA_ID_EMPTY_ROOT, null) } // Return browser roots for browsing... }
জাভা
@Override public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) { // To ensure you are not allowing any arbitrary app to browse your app's contents, you // need to check the origin: if (!packageValidator.isCallerAllowed(this, clientPackageName, clientUid)) { // If the request comes from an untrusted package, return an empty browser root. // If you return null, then the media browser will not be able to connect and // no further calls will be made to other media browsing methods. LogHelper.i(TAG, "OnGetRoot: Browsing NOT ALLOWED for unknown caller. " + "Returning empty browser root so all apps can use MediaController." + clientPackageName); return new MediaBrowserServiceCompat.BrowserRoot(MEDIA_ID_EMPTY_ROOT, null); } // Return browser roots for browsing... }
অ্যাসিস্ট্যান্ট অ্যাপ প্যাকেজ এবং স্বাক্ষর গ্রহণ করুন।
আপনি আপনার মিডিয়া ব্রাউজার সার্ভিসের প্যাকেজ নেম এবং সিগনেচার যাচাই করে অ্যাসিস্ট্যান্টকে স্পষ্টভাবে সংযোগ করার অনুমতি দিতে পারেন। আপনার অ্যাপটি MediaBrowserService-এর onGetRoot মেথডে প্যাকেজ নেমটি গ্রহণ করবে। অ্যাসিস্ট্যান্টকে আপনার মিডিয়া সেশনে কমান্ড পাঠানোর অনুমতি দেওয়ার জন্য আপনাকে অবশ্যই একটি BrowserRoot রিটার্ন করতে হবে। ইউনিভার্সাল মিউজিক প্লেয়ার স্যাম্পলটি পরিচিত প্যাকেজ নেম এবং সিগনেচারের একটি তালিকা সংরক্ষণ করে। নিচে গুগল অ্যাসিস্ট্যান্ট দ্বারা ব্যবহৃত প্যাকেজ নেম এবং সিগনেচারগুলো দেওয়া হলো।
<signature name="Google" package="com.google.android.googlequicksearchbox">
<key release="false">19:75:b2:f1:71:77:bc:89:a5:df:f3:1f:9e:64:a6:ca:e2:81:a5:3d:c1:d1:d5:9b:1d:14:7f:e1:c8:2a:fa:00</key>
<key release="true">f0:fd:6c:5b:41:0f:25:cb:25:c3:b5:33:46:c8:97:2f:ae:30:f8:ee:74:11:df:91:04:80:ad:6b:2d:60:db:83</key>
</signature>
<signature name="Google Assistant on Android Automotive OS" package="com.google.android.carassistant">
<key release="false">17:E2:81:11:06:2F:97:A8:60:79:7A:83:70:5B:F8:2C:7C:C0:29:35:56:6D:46:22:BC:4E:CF:EE:1B:EB:F8:15</key>
<key release="true">74:B6:FB:F7:10:E8:D9:0D:44:D3:40:12:58:89:B4:23:06:A6:2C:43:79:D0:E5:A6:62:20:E3:A6:8A:BF:90:E2</key>
</signature>