অ্যান্ড্রয়েড অটো এবং অ্যান্ড্রয়েড অটোমোটিভ ওএস (AAOS) কোন কন্টেন্ট উপলব্ধ আছে তা জানার জন্য আপনার অ্যাপের মিডিয়া ব্রাউজার সার্ভিসকে কল করে। এটিকে সমর্থন করার জন্য, আপনাকে আপনার মিডিয়া ব্রাউজার সার্ভিসে এই দুটি মেথড ইমপ্লিমেন্ট করতে হবে।
onGetRoot বাস্তবায়ন করুন
আপনার সার্ভিসের onGetRoot মেথডটি আপনার কন্টেন্ট হায়ারার্কির রুট নোড সম্পর্কে তথ্য রিটার্ন করে। Android Auto এবং AAOS, onLoadChildren মেথড ব্যবহার করে আপনার বাকি কন্টেন্ট রিকোয়েস্ট করার জন্য এই রুট নোডটি ব্যবহার করে। এই কোড স্নিপেটটি onGetRoot মেথডের একটি ইমপ্লিমেন্টেশন দেখাচ্ছে:
কোটলিন
override fun onGetRoot(
clientPackageName: String,
clientUid: Int,
rootHints: Bundle?
): BrowserRoot? =
// Verify that the specified package is allowed to access your
// content. You'll need to write your own logic to do this.
if (!isValid(clientPackageName, clientUid)) {
// If the request comes from an untrusted package, return null.
// No further calls will be made to other media browsing methods.
null
} else MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null)
জাভা
@Override
public BrowserRoot onGetRoot(String clientPackageName, int clientUid,
Bundle rootHints) {
// Verify that the specified package is allowed to access your
// content. You'll need to write your own logic to do this.
if (!isValid(clientPackageName, clientUid)) {
// If the request comes from an untrusted package, return null.
// No further calls will be made to other media browsing methods.
return null;
}
return new MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null);
}
এই পদ্ধতির একটি বিশদ উদাহরণের জন্য, গিটহাবে থাকা ইউনিভার্সাল অ্যান্ড্রয়েড মিউজিক প্লেয়ার স্যাম্পল অ্যাপের onGetRoot দেখুন।
প্যাকেজ যাচাইকরণ যোগ করুন
যখন আপনার সার্ভিসের onGetRoot মেথডে কল করা হয়, তখন কলকারী প্যাকেজটি আপনার সার্ভিসে শনাক্তকারী তথ্য প্রেরণ করে। আপনার সার্ভিস এই তথ্য ব্যবহার করে সিদ্ধান্ত নিতে পারে যে ওই প্যাকেজটি আপনার কন্টেন্ট অ্যাক্সেস করতে পারবে কি না।
উদাহরণস্বরূপ, আপনি আপনার অ্যাপের কন্টেন্টে অ্যাক্সেসকে অনুমোদিত প্যাকেজগুলির একটি তালিকার মধ্যে সীমাবদ্ধ করতে পারেন:
- আপনার allowlist-এর সাথে
clientPackageNameটি তুলনা করুন। - প্যাকেজের APK-টি সাইন করতে ব্যবহৃত সার্টিফিকেটটি যাচাই করুন।
প্যাকেজটি যাচাই করা না গেলে, আপনার কন্টেন্টে প্রবেশাধিকার অস্বীকার করতে null রিটার্ন করুন।
Android Auto এবং AAOS-এর মতো সিস্টেম অ্যাপগুলোকে আপনার কন্টেন্টে অ্যাক্সেস দেওয়ার জন্য, যখন এই সিস্টেম অ্যাপগুলো onGetRoot মেথড কল করে, তখন আপনার সার্ভিসকে অবশ্যই একটি নন-নাল BrowserRoot রিটার্ন করতে হবে।
গাড়ির ব্র্যান্ড ও মডেল অনুযায়ী AAOS সিস্টেম অ্যাপের সিগনেচার ভিন্ন হয়। AAOS সাপোর্ট করার জন্য সমস্ত সিস্টেম অ্যাপ থেকে কানেকশনের অনুমতি দেওয়া নিশ্চিত করুন।
এই কোড স্নিপেটটি দেখায় কিভাবে আপনার সার্ভিস যাচাই করতে পারে যে কলিং প্যাকেজটি একটি সিস্টেম অ্যাপ কিনা:
fun isKnownCaller(
callingPackage: String,
callingUid: Int
): Boolean {
...
val isCallerKnown = when {
// If the system is making the call, allow it.
callingUid == Process.SYSTEM_UID -> true
// If the app was signed by the same certificate as the platform
// itself, also allow it.
callerSignature == platformSignature -> true
// ... more cases
}
return isCallerKnown
}
এই কোড স্নিপেটটি গিটহাবে থাকা ইউনিভার্সাল অ্যান্ড্রয়েড মিউজিক প্লেয়ার স্যাম্পল অ্যাপের PackageValidator ক্লাস থেকে নেওয়া একটি অংশ। আপনার সার্ভিসের onGetRoot মেথডের জন্য কীভাবে প্যাকেজ ভ্যালিডেশন প্রয়োগ করতে হয়, তার আরও বিস্তারিত উদাহরণের জন্য ওই ক্লাসটি দেখুন।
সিস্টেম অ্যাপগুলোকে অনুমতি দেওয়ার পাশাপাশি, আপনাকে অবশ্যই গুগল অ্যাসিস্ট্যান্টকে আপনার MediaBrowserService সাথে সংযোগ করার অনুমতি দিতে হবে। গুগল অ্যাসিস্ট্যান্ট তার মোবাইল এবং AAOS অ্যাপের জন্য ভিন্ন ভিন্ন প্যাকেজ নাম ব্যবহার করে।
অনলোডচিলড্রেন বাস্তবায়ন করুন
আপনার রুট নোড অবজেক্টটি পাওয়ার পর, অ্যান্ড্রয়েড অটো এবং AAOS তার ডিসেন্ডেন্টদের পাওয়ার জন্য রুট নোড অবজেক্টের উপর onLoadChildren মেথডটি কল করে একটি টপ-লেভেল মেনু তৈরি করে। ক্লায়েন্ট অ্যাপগুলো ডিসেন্ডেন্ট নোড অবজেক্ট ব্যবহার করে এই একই মেথডটি কল করার মাধ্যমে সাবমেনু তৈরি করে।
আপনার কন্টেন্ট হায়ারার্কির প্রতিটি নোড একটি MediaBrowserCompat.MediaItem অবজেক্ট দ্বারা উপস্থাপিত হয়। এই মিডিয়া আইটেমগুলোর প্রত্যেকটি একটি অনন্য আইডি স্ট্রিং দ্বারা চিহ্নিত করা হয়। ক্লায়েন্ট অ্যাপগুলো এই আইডি স্ট্রিংগুলোকে অস্বচ্ছ টোকেন হিসেবে গণ্য করে।
যখন কোনো ক্লায়েন্ট অ্যাপ কোনো সাবমেনুতে যেতে বা কোনো মিডিয়া আইটেম চালাতে চায়, তখন এটি টোকেনটি প্রেরণ করে। টোকেনটিকে উপযুক্ত মিডিয়া আইটেমের সাথে যুক্ত করার দায়িত্ব আপনার অ্যাপের।
এই কোড স্নিপেটটি onLoadChildren এর একটি বাস্তবায়ন দেখায়।
কোটলিন
override fun onLoadChildren(
parentMediaId: String,
result: Result<List<MediaBrowserCompat.MediaItem>>
) {
// Assume for example that the music catalog is already loaded/cached.
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
// Check if this is the root menu:
if (MY_MEDIA_ROOT_ID == parentMediaId) {
// Build the MediaItem objects for the top level
// and put them in the mediaItems list.
} else {
// Examine the passed parentMediaId to see which submenu we're at
// and put the descendants of that menu in the mediaItems list.
}
result.sendResult(mediaItems)
}
জাভা
@Override
public void onLoadChildren(final String parentMediaId,
final Result<List<MediaBrowserCompat.MediaItem>> result) {
// Assume for example that the music catalog is already loaded/cached.
List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>();
// Check if this is the root menu:
if (MY_MEDIA_ROOT_ID.equals(parentMediaId)) {
// Build the MediaItem objects for the top level
// and put them in the mediaItems list.
} else {
// Examine the passed parentMediaId to see which submenu we're at
// and put the descendants of that menu in the mediaItems list.
}
result.sendResult(mediaItems);
}
এই পদ্ধতির একটি উদাহরণ দেখতে, গিটহাবে থাকা ইউনিভার্সাল অ্যান্ড্রয়েড মিউজিক প্লেয়ার স্যাম্পল অ্যাপের onLoadChildren দেখুন।
রুট মেনুর গঠন
অ্যান্ড্রয়েড অটো এবং অ্যান্ড্রয়েড অটোমোটিভ ওএস-এর রুট মেনুর গঠন সম্পর্কে নির্দিষ্ট কিছু সীমাবদ্ধতা রয়েছে। এই সীমাবদ্ধতাগুলো রুট হিন্টস-এর মাধ্যমে MediaBrowserService কে জানানো হয়, যা onGetRoot() ফাংশনে পাস করা Bundle আর্গুমেন্টের মাধ্যমে পড়া যায়। এই হিন্টসগুলো অনুসরণ করা হলে, সিস্টেম রুট কন্টেন্টকে নেভিগেশনাল ট্যাব হিসেবে প্রদর্শন করে। যদি এই হিন্টসগুলো অনুসরণ না করা হয়, তাহলে কিছু রুট কন্টেন্ট বাদ পড়ে যেতে পারে অথবা সিস্টেমের কাছে তা সহজে খুঁজে পাওয়া নাও যেতে পারে।

চিত্র ১. মূল বিষয়বস্তু নেভিগেশনাল ট্যাব হিসেবে প্রদর্শিত।
এই ইঙ্গিতগুলো প্রয়োগ করার মাধ্যমে, সিস্টেমটি মূল বিষয়বস্তুকে নেভিগেশনাল ট্যাব হিসেবে প্রদর্শন করে। এই ইঙ্গিতগুলো প্রয়োগ না করলে, কিছু মূল বিষয়বস্তু বাদ পড়ে যেতে পারে বা সহজে খুঁজে পাওয়া নাও যেতে পারে। এই ইঙ্গিতগুলো প্রেরণ করা হয়:
Limit on the number of root children : In most cases, expect this number to be four, meaning that only four (or fewer) tabs can be shown.
রুট চাইল্ড আইটেমগুলিতে সমর্থিত ফ্ল্যাগ : এই ফ্ল্যাগের মান
MediaItem#FLAG_BROWSABLEহবে বলে আশা করা হয়, যার অর্থ হলো শুধুমাত্র ব্রাউজযোগ্য আইটেমগুলোই (প্লে করা যায় এমন আইটেম নয়) ট্যাব হিসেবে দেখানো যাবে।কাস্টম ব্রাউজ অ্যাকশনের সংখ্যার সীমা : কতগুলো কাস্টম ব্রাউজ অ্যাকশন সমর্থিত তা পরীক্ষা করুন।
কোটলিন
import androidx.media.utils.MediaConstants
override fun onGetRoot(
clientPackageName: String,
clientUid: Int,
rootHints: Bundle
): BrowserRoot {
val maximumRootChildLimit = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT,
/* defaultValue= */ 4)
val supportedRootChildFlags = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS,
/* defaultValue= */ MediaItem.FLAG_BROWSABLE)
// Rest of method...
}
জাভা
import androidx.media.utils.MediaConstants;
// Later, in your MediaBrowserServiceCompat.
@Override
public BrowserRoot onGetRoot(
String clientPackageName, int clientUid, Bundle rootHints) {
int maximumRootChildLimit = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT,
/* defaultValue= */ 4);
int supportedRootChildFlags = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS,
/* defaultValue= */ MediaItem.FLAG_BROWSABLE);
// Rest of method...
}
এই ইঙ্গিতগুলোর মানের উপর ভিত্তি করে আপনি আপনার কন্টেন্ট হায়ারার্কির কাঠামোর লজিককে বিভিন্ন দিকে ভাগ করার বিকল্প বেছে নিতে পারেন, বিশেষ করে যদি অ্যান্ড্রয়েড অটো এবং AAOS-এর বাইরের MediaBrowser ইন্টিগ্রেশনগুলোর মধ্যে আপনার হায়ারার্কি ভিন্ন হয়।
উদাহরণস্বরূপ, যদি আপনি সাধারণত একটি রুট প্লেয়েবল আইটেম দেখান, তবে সাপোর্টেড ফ্ল্যাগস হিন্ট-এর মানের কারণে আপনি সেটিকে একটি রুট ব্রাউজেবল আইটেমের অধীনে নেস্ট করতে চাইতে পারেন।
রুট হিন্টস ছাড়াও, ট্যাবগুলো সর্বোত্তমভাবে রেন্ডার করতে এই নির্দেশিকাগুলো ব্যবহার করুন:
প্রতিটি ট্যাব আইটেমের জন্য একরঙা (বিশেষত সাদা) আইকন
প্রতিটি ট্যাব আইটেমের জন্য সংক্ষিপ্ত এবং অর্থপূর্ণ লেবেল (সংক্ষিপ্ত লেবেল লেবেলগুলি কেটে যাওয়ার সম্ভাবনা কমায়)