একটি মিডিয়া কার্ড হল একটি স্বয়ংসম্পূর্ণ ভিউগ্রুপ যা মিডিয়া মেটাডেটা যেমন শিরোনাম, অ্যালবাম আর্ট এবং আরও অনেক কিছু প্রদর্শন করে এবং প্লেব্যাক নিয়ন্ত্রণ যেমন প্লে এবং পজ , স্কিপ এবং এমনকি তৃতীয় পক্ষের মিডিয়া অ্যাপ দ্বারা প্রদত্ত কাস্টম অ্যাকশনগুলি প্রদর্শন করে৷ একটি মিডিয়া কার্ড মিডিয়া আইটেমগুলির একটি সারি দেখাতে পারে, যেমন একটি প্লেলিস্ট৷
চিত্র 1. মিডিয়া কার্ডের নমুনা বাস্তবায়ন।
AAOS-এ মিডিয়া কার্ডগুলি কীভাবে প্রয়োগ করা হয়?
ভিউগ্রুপগুলি যেগুলি মিডিয়া তথ্য দেখায় তারা ভিউগ্রুপকে পপুলেট করতে car-media-common
লাইব্রেরি ডেটা মডেল, PlaybackViewModel
থেকে লাইভডেটা আপডেটগুলি পর্যবেক্ষণ করে৷ প্রতিটি লাইভডেটা আপডেট MediaItemMetadata
, PlaybackStateWrapper
, এবং MediaSource
মতো পরিবর্তিত মিডিয়া তথ্যের একটি উপসেটের সাথে মিলে যায়৷
যেহেতু এই পদ্ধতিটি বারবার কোডের দিকে নিয়ে যায় (প্রতিটি ক্লায়েন্ট অ্যাপ লাইভডেটার প্রতিটি অংশে পর্যবেক্ষকদের যোগ করে এবং অনেক অনুরূপ ভিউ আপডেট করা ডেটা বরাদ্দ করা হয়), আমরা PlaybackCardController
তৈরি করেছি।
প্লেব্যাককার্ড কন্ট্রোলার
PlaybackCardController
একটি মিডিয়া কার্ড তৈরিতে সহায়তা করার জন্য car-media-common
লাইব্রেরিতে যোগ করা হয়েছে। এটি একটি পাবলিক ক্লাস যা একটি ViewGroup ( mView
), PlaybackViewModel ( mDataModel
), PlaybackCardViewModel ( mViewModel
), এবং MediaItemsRepository
ইনস্ট্যান্স ( mItemsRepository
) দিয়ে নির্মিত।
setupController
ফাংশনে, ViewGroup-কে কিছু নির্দিষ্ট ভিউয়ের জন্য ID দ্বারা পার্স করা হয়, mView.findViewById(R.id.xxx)
দিয়ে এবং সুরক্ষিত ভিউ অবজেক্টে বরাদ্দ করা হয়।
private void getViewsFromWidget() {
mTitle = mView.findViewById(R.id.title);
mAlbumCover = mView.findViewById(R.id.album_art);
mDescription = mView.findViewById(R.id.album_title);
mLogo = mView.findViewById(R.id.content_format);
mAppIcon = mView.findViewById(R.id.media_widget_app_icon);
mAppName = mView.findViewById(R.id.media_widget_app_name);
// ...
}
PlaybackViewModel
থেকে প্রতিটি LiveData আপডেট একটি সুরক্ষিত পদ্ধতিতে পর্যবেক্ষণ করা হয় এবং প্রাপ্ত ডেটার সাথে প্রাসঙ্গিক ভিউগুলির সাথে মিথস্ক্রিয়া সম্পাদন করে। উদাহরণস্বরূপ, MediaItemMetadata
এর একজন পর্যবেক্ষক mTitle
TextView
এ শিরোনাম সেট করে এবং MediaItemMetadata.ArtworkRef
অ্যালবাম আর্ট ImageBinder
mAlbumArtBinder
এ পাস করে। মেটাডেটা শূন্য হলে, ভিউ লুকানো হয়। প্রয়োজনে কন্ট্রোলারের উপশ্রেণীগুলি এই যুক্তিটিকে ওভাররাইড করতে পারে।
mDataModel.getMetadata().observe(mViewLifecycle, this::updateMetadata);
// ...
/** Update views with {@link MediaItemMetadata} */
protected void updateMetadata(MediaItemMetadata metadata) {
if (metadata != null) {
String defaultTitle = mView.getContext().getString(
R.string.metadata_default_title);
updateTextViewAndVisibility(mTitle, metadata.getTitle(), defaultTitle);
updateTextViewAndVisibility(mSubtitle, metadata.getSubtitle());
updateMediaLink(mSubtitleLinker,metadata.getSubtitleLinkMediaId());
updateTextViewAndVisibility(mDescription, metadata.getDescription());
updateMediaLink(mDescriptionLinker, metadata.getDescriptionLinkMediaId());
updateMetadataAlbumCoverArtworkRef(metadata.getArtworkKey());
updateMetadataLogoWithUri(metadata);
} else {
ViewUtils.setVisible(mTitle, false);
ViewUtils.setVisible(mSubtitle, false);
ViewUtils.setVisible(mAlbumCover, false);
ViewUtils.setVisible(mDescription, false);
ViewUtils.setVisible(mLogo, false);
}
}
প্লেব্যাককার্ড কন্ট্রোলার প্রসারিত করুন
যে ক্লায়েন্ট অ্যাপগুলি একটি মিডিয়া কার্ড তৈরি করতে চায় তাদের PlaybackCardController
প্রসারিত করা উচিত যদি তাদের অতিরিক্ত ক্ষমতা থাকে তবে তারা প্রতিটি LiveData আপডেটে পরিচালনা করতে চায়। AAOS-এ বিদ্যমান ক্লায়েন্টরা এই প্যাটার্ন অনুসরণ করে। প্রথমে, একটি PlaybackCardController
সাবক্লাস তৈরি করা উচিত, যেমন MediaCardController
। এরপরে, MediaCardController
একটি স্ট্যাটিক ইনার বিল্ডার ক্লাস যোগ করা উচিত যা PlaybackCardController
প্রসারিত করে।
public class MediaCardController extends PlaybackCardController {
// extra fields specific to MediaCardController
/** Builder for {@link MediaCardController}. Overrides build() method to
* return NowPlayingController rather than base {@link PlaybackCardController}
*/
public static class Builder extends PlaybackCardController.Builder {
@Override
public MediaCardController build() {
MediaCardController controller = new MediaCardController(this);
controller.setupController();
return controller;
}
}
public MediaCardController(Builder builder) {
super(builder);
// any other function calls needed in constructor
// ...
}
}
প্লেব্যাককার্ড কন্ট্রোলার বা একটি সাবক্লাস ইনস্ট্যান্টিয়েট করুন
লাইভডেটা পর্যবেক্ষকদের জন্য একটি লাইফসাইকেল মালিক পেতে কন্ট্রোলার ক্লাসটি একটি ফ্র্যাগমেন্ট বা ক্রিয়াকলাপ থেকে তাত্ক্ষণিক হওয়া উচিত।
mMediaCardController = (MediaCardController) new MediaCardController.Builder()
.setModels(mViewModel.getPlaybackViewModel(),
mViewModel,
mViewModel.getMediaItemsRepository())
.setViewGroup((ViewGroup) view)
.build();
mViewModel
হল PlaybackCardViewModel
(বা সাবক্লাস) এর একটি উদাহরণ।
স্টেট সেভ করতে প্লেব্যাককার্ডভিউ মডেল
PlaybackCardViewModel
হল একটি রাষ্ট্র-সংরক্ষণকারী ViewModel যা একটি ফ্র্যাগমেন্ট বা ক্রিয়াকলাপের সাথে আবদ্ধ যা মিডিয়া কার্ডের বিষয়বস্তু পুনর্গঠন করতে ব্যবহার করা উচিত যদি কনফিগারেশন পরিবর্তন ঘটে (যেমন একজন ব্যবহারকারী যখন একটি টানেলের মধ্য দিয়ে ড্রাইভ করে তখন আলো থেকে অন্ধকার থিমে স্যুইচ করা)। ডিফল্ট PlaybackCardViewModel
প্লেব্যাকের জন্য MediaModel
-এর দৃষ্টান্ত সংরক্ষণ করে, যেখান থেকে PlaybackViewModel
এবং MediaItemsRepository
পুনরুদ্ধার করা যেতে পারে। প্রদত্ত গেটার এবং সেটারের মাধ্যমে সারি, ইতিহাস এবং ওভারফ্লো মেনুর অবস্থা ট্র্যাক করতে PlaybackCardViewModel
ব্যবহার করুন।
public class PlaybackCardViewModel extends AndroidViewModel {
private MediaModels mModels;
private boolean mNeedsInitialization = true;
private boolean mQueueVisible = false;
private boolean mHistoryVisible = false;
private boolean mOverflowExpanded = false;
public PlaybackCardViewModel(@NonNull Application application) {
super(application);
}
/** Initialize the PlaybackCardViewModel */
public void init(MediaModels models) {
mModels = models;
mNeedsInitialization = false;
}
/**
* Returns whether the ViewModel needs to be initialized. The ViewModel may
* need re-initialization if a config change occurs or if the system kills
* the Fragment.
*/
public boolean needsInitialization() {
return mNeedsInitialization;
}
public MediaItemsRepository getMediaItemsRepository() {
return mModels.getMediaItemsRepository();
}
public PlaybackViewModel getPlaybackViewModel() {
return mModels.getPlaybackViewModel();
}
public MediaSourceViewModel getMediaSourceViewModel() {
return mModels.getMediaSourceViewModel();
}
public void setQueueVisible(boolean visible) {
mQueueVisible = visible;
}
public boolean getQueueVisible() {
return mQueueVisible;
}
public void setHistoryVisible(boolean visible) {
mHistoryVisible = visible;
}
public boolean getHistoryVisible() {
return mHistoryVisible;
}
public void setOverflowExpanded(boolean expanded) {
mOverflowExpanded = expanded;
}
public boolean getOverflowExpanded() {
return mOverflowExpanded;
}
}
অতিরিক্ত রাজ্য ট্র্যাক করা প্রয়োজন হলে এই শ্রেণী বাড়ানো যেতে পারে।
একটি মিডিয়া কার্ডে একটি সারি দেখান৷
PlaybackViewModel
লাইভডেটা এপিআই সরবরাহ করে যে মিডিয়াসোর্স একটি সারি সমর্থন করে কিনা তা সনাক্ত করতে এবং সারিতে থাকা MediaItemMetadata
অবজেক্টের তালিকা পুনরুদ্ধার করতে। যদিও এই API গুলি সরাসরি সারি তথ্যের সাথে একটি RecyclerView
অবজেক্টকে পপুলেট করতে ব্যবহার করা যেতে পারে, এই প্রক্রিয়াটিকে স্ট্রিমলাইন করার জন্য একটি PlaybackQueueController
ক্লাস car-media-common
লাইব্রেরিতে যোগ করা হয়েছে। CarUiRecyclerView
এ প্রতিটি আইটেমের লেআউট ক্লায়েন্ট অ্যাপের পাশাপাশি একটি ঐচ্ছিক হেডার লেআউট দ্বারা নির্দিষ্ট করা হয়। ক্লায়েন্ট অ্যাপটি কাস্টম UXR বিধিনিষেধ সহ ড্রাইভ অবস্থার সময় সারিতে দেখানো আইটেমের সংখ্যা সীমিত করতেও বেছে নিতে পারে।
PlaybackQueueController
কনস্ট্রাক্টর এবং সেটার্স নিম্নলিখিত নমুনায় দেখানো হয়েছে। queueResource
এবং headerResource
লেআউট রিসোর্স Resources.ID_NULL
হিসাবে পাস করা যেতে পারে যদি, পূর্বের ক্ষেত্রে, কন্টেইনারে ইতিমধ্যে id queue_list
সহ একটি CarUiRecyclerView
থাকে এবং পরবর্তী ক্ষেত্রে, সারিতে একটি হেডার না থাকে।
/**
* Construct a PlaybackQueueController. If clients don't have a separate
* layout for the queue, where the queue is already inflated within the
* container, they should pass {@link Resources.ID_NULL} as the LayoutRes
* resource. If clients don't require a UxrContentLimiter, they should pass
* null for uxrContentLimiter and the int passed for uxrConfigurationId will
* be ignored.
*/
public PlaybackQueueController(
ViewGroup container,
@LayoutRes int queueResource,
@LayoutRes int queueItemResource,
@LayoutRes int headerResource,
LifecycleOwner lifecycleOwner,
PlaybackViewModel playbackViewModel,
MediaItemsRepository itemsRepository,
@Nullable LifeCycleObserverUxrContentLimiter uxrContentLimiter,
int uxrConfigurationId) {
// ...
}
public void setShowTimeForActiveQueueItem(boolean show) {
mShowTimeForActiveQueueItem = show;
}
public void setShowIconForActiveQueueItem(boolean show) {
mShowIconForActiveQueueItem = show;
}
public void setShowThumbnailForQueueItem(boolean show) {
mShowThumbnailForQueueItem = show;
}
public void setShowSubtitleForQueueItem(boolean show) {
mShowSubtitleForQueueItem = show;
}
/** Calls {@link RecyclerView#setVerticalFadingEdgeEnabled(boolean)} */
public void setVerticalFadingEdgeLengthEnabled(boolean enabled) {
mQueue.setVerticalFadingEdgeEnabled(enabled);
}
public void setCallback(PlaybackQueueCallback callback) {
mPlaybackQueueCallback = callback;
}
প্রতিটি সারি আইটেমের বিন্যাসে এমন ভিউগুলির আইডি থাকা উচিত যা এটি দেখাতে চায় যেগুলি QueueViewHolder
অভ্যন্তরীণ শ্রেণীতে ব্যবহৃত হয়।
QueueViewHolder(View itemView) {
super(itemView);
mView = itemView;
mThumbnailContainer = itemView.findViewById(R.id.thumbnail_container);
mThumbnail = itemView.findViewById(R.id.thumbnail);
mSpacer = itemView.findViewById(R.id.spacer);
mTitle = itemView.findViewById(R.id.queue_list_item_title);
mSubtitle = itemView.findViewById(R.id.queue_list_item_subtitle);
mCurrentTime = itemView.findViewById(R.id.current_time);
mMaxTime = itemView.findViewById(R.id.max_time);
mTimeSeparator = itemView.findViewById(R.id.separator);
mActiveIcon = itemView.findViewById(R.id.now_playing_icon);
// ...
}
PlaybackCardController
(বা একটি সাবক্লাস) দিয়ে তৈরি একটি মিডিয়া কার্ডে একটি সারি দেখানোর জন্য, PlaybackQueueController
PlaybackCardController
কন্ট্রোলারে যথাক্রমে PlaybackViewModel
এবং MediaItemsRepository
উদাহরণগুলির জন্য mDataModel
এবং mItemsRepository
ব্যবহার করে তৈরি করা যেতে পারে।
পূর্বে চালানো মিডিয়াসোর্সের ইতিহাস দেখান
এই বিভাগে, আপনি শিখবেন কিভাবে পূর্বে প্লে করা মিডিয়া সোর্সগুলির ইতিহাস দেখাতে হয় এবং সারফেস করতে হয়।
PlaybackCardViewModel API দিয়ে ইতিহাসের তালিকা পান
PlaybackCardViewModel
মিডিয়া ইতিহাসের তালিকা পুনরুদ্ধার করতে getHistoryList()
নামে একটি LiveData API প্রদান করে। এটি একটি লাইভডেটা প্রদান করে যার মধ্যে মিডিয়াসোর্সের একটি তালিকা রয়েছে যা আগে চালানো হয়েছে। এই ডেটা একটি CarUiRecyclerView
অবজেক্ট তৈরি করতে ব্যবহার করা যেতে পারে। PlaybackQueueController
এর মতোই, প্রক্রিয়াটিকে স্ট্রিমলাইন করতে car-media-common
লাইব্রেরিতে PlaybackHistoryController
নামে একটি ক্লাস যুক্ত করা হয়েছে।
public class PlaybackCardViewModel extends AndroidViewModel {
public PlaybackCardViewModel(@NonNull Application application) {
}
/** Initialize the PlaybackCardViewModel */
public void init(MediaModels models) {
}
public LiveData<List<MediaSource>> getHistoryList() {
return mHistoryListData;
}
}
PlaybackHistoryController সহ সারফেস হিস্ট্রি UI
একটি CarUiRecyclerView
এ ইতিহাসের ডেটা পূরণ করতে সাহায্য করতে নতুন PlaybackHistoryController
ব্যবহার করুন। এই শ্রেণীর কনস্ট্রাক্টর এবং প্রধান কাজগুলি নিম্নরূপ। ক্লায়েন্ট অ্যাপ থেকে পাস করা ধারকটিতে ID history_list
সহ একটি CarUiRecyclerView
থাকা উচিত। CarUiRecyclerView
তালিকা আইটেম এবং একটি ঐচ্ছিক শিরোনাম প্রদর্শন করে। তালিকা আইটেম এবং শিরোনাম উভয় লেআউট ক্লায়েন্ট অ্যাপ্লিকেশন থেকে পাস করা যেতে পারে. Resources.ID_NULL
হেডার রিসোর্স হিসেবে সেট করা থাকলে, হেডার দেখানো হয় না। PlaybackCardViewModel
কন্ট্রোলারে পাস করার পরে, এটি playbackCardViewModel.getHistoryList()
থেকে পুনরুদ্ধার করা LiveData<List<MediaSource>>
নিরীক্ষণ করে।
public class PlaybackHistoryController {
public PlaybackHistoryController(
LifecycleOwner lifecycleOwner,
PlaybackCardViewModel playbackCardViewModel,
ViewGroup container,
@LayoutRes int itemResource,
@LayoutRes int headerResource,
int uxrConfigurationId) {
}
/**
* Renders the view.
*/
public void setupView() {
}
}
প্রতিটি আইটেমের লেআউটে ViewHolder
অভ্যন্তরীণ শ্রেণীতে ব্যবহৃত ভিউগুলির সাথে সামঞ্জস্যপূর্ণ যেগুলি দেখাতে চায় তার আইডি থাকা উচিত৷
HistoryItemViewHolder(View itemView) {
super(itemView);
mContext = itemView.getContext();
mActiveView = itemView.findViewById(R.id.history_card_container_active);
mInactiveView = itemView.findViewById(R.id.history_card_container_inactive);
mMetadataTitleView = itemView.findViewById(R.id.history_card_title_active);
mAdditionalInfo = itemView.findViewById(R.id.history_card_subtitle_active);
mAppIcon = itemView.findViewById(R.id.history_card_app_thumbnail);
mAlbumArt = itemView.findViewById(R.id.history_card_album_art);
mAppTitleInactive = itemView.findViewById(R.id.history_card_app_title_inactive);
mAppIconInactive = itemView.findViewById(R.id.history_item_app_icon_inactive);
// ...
}
PlaybackCardController
(বা একটি সাবক্লাস) দিয়ে তৈরি একটি মিডিয়া কার্ডে একটি ইতিহাসের তালিকা দেখানোর জন্য, PlaybackHistoryController
PlaybackCardController
এর কনস্ট্রাক্টরে তৈরি করা যেতে পারে।