AAOS'de medya kartı uygulama

Medya kartı, başlık ve albüm resmi gibi medya meta verilerini gösteren ve Oynat, Duraklat, Atla gibi oynatma kontrollerinin yanı sıra üçüncü taraf medya uygulaması tarafından sağlanan özel işlemleri de sunan bağımsız bir ViewGroup'tur. Medya kartı, oynatma listesi gibi medya öğelerinin sırasını da gösterebilir.

Medya kartı

Medya kartı

Medya kartı

1. şekil. Medya Kartı örnek uygulamaları.

Medya kartları AAOS'te nasıl uygulanır?

Medya bilgilerini gösteren ViewGroups, ViewGroup'u doldurmak için car-media-common kitaplığındaki data modelinden (PlaybackViewModel) gelen LiveData güncellemelerini izler. Her LiveData güncellemesi, değişen medya bilgilerinin bir alt kümesine karşılık gelir. Örneğin, MediaItemMetadata, PlaybackStateWrapper ve MediaSource.

Bu yaklaşım, tekrarlanan koda yol açtığı için (her istemci uygulaması, her LiveData parçasına Gözlemciler ekler ve birçok benzer Görünüme güncellenen veriler atanır) PlaybackCardController oluşturduk.

PlaybackCardController

Medya kartı oluşturmaya yardımcı olmak için PlaybackCardController, car-media-common kitaplığına eklendi. Bu, ViewGroup (mView), PlaybackViewModel (mDataModel), PlaybackCardViewModel (mViewModel) ve MediaItemsRepository örneği (mItemsRepository) ile oluşturulmuş herkese açık bir sınıftır.

setupController işlevinde, ViewGroup, mView.findViewById(R.id.xxx) ile belirli görünümler için kimliğe göre ayrıştırılır ve korumalı View nesnelerine atanır.

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 kaynağından gelen her LiveData güncellemesi, korumalı bir yöntemde gözlemlenir ve alınan verilerle ilgili Görünümlerle etkileşimde bulunur. Örneğin, MediaItemMetadata üzerindeki bir gözlemci, mTitle TextView üzerinde başlığı ayarlar ve MediaItemMetadata.ArtworkRef öğesini albüm kapağına ImageBinder mAlbumArtBinder iletir. Meta veriler null ise görünümler gizlenir. Denetleyici'nin alt sınıfları gerekirse bu mantığı geçersiz kılabilir.

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);
        }
    }

Extend the PlaybackCardController

Medya kartı oluşturmak isteyen istemci uygulamaları, her LiveData güncellemesinde işlemek istedikleri ek özellikler varsa PlaybackCardController öğesini genişletmelidir. AAOS'taki mevcut istemciler bu kalıbı izler. Öncelikle PlaybackCardController gibi bir alt sınıf oluşturulmalıdır. MediaCardController. Ardından, MediaCardController, PlaybackCardController sınıfını genişleten statik bir iç Builder sınıfı eklemelidir.

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
    // ...

  }
}

PlaybackCardController'ı veya bir alt sınıfı başlatın.

Denetleyici sınıfı, LiveData gözlemcileri için bir LifecycleOwner'a sahip olmak üzere bir Parçadan veya Etkinlikten başlatılmalıdır.

mMediaCardController = (MediaCardController) new MediaCardController.Builder()
                    .setModels(mViewModel.getPlaybackViewModel(),
                            mViewModel,
                            mViewModel.getMediaItemsRepository())
                    .setViewGroup((ViewGroup) view)
                    .build();

mViewModel, PlaybackCardViewModel (veya alt sınıf) örneğidir.

Durumu Kaydetmek İçin PlaybackCardViewModel

PlaybackCardViewModel, bir Fragment veya Activity'ye bağlı, durumu kaydeden bir ViewModel'dir. Yapılandırma değişikliği (ör. kullanıcı tünelden geçerken açık temadan koyu temaya geçiş) meydana gelirse medya kartının içeriğini yeniden oluşturmak için kullanılmalıdır. Varsayılan PlaybackCardViewModel, oynatma için MediaModel örneklerinin depolanmasını sağlar. Bu örneklerden PlaybackViewModel ve MediaItemsRepository alınabilir. Kuyruğun durumunu, geçmişini ve taşma menüsünü sağlanan getter'lar ve setter'lar aracılığıyla izlemek için PlaybackCardViewModel kullanın.

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;
    }
}

Ek eyaletlerin izlenmesi gerekiyorsa bu sınıf genişletilebilir.

Medya kartında sırayı gösterme

PlaybackViewModel, MediaSource'un bir kuyruğu destekleyip desteklemediğini algılamak ve kuyruktaki MediaItemMetadata nesnelerinin listesini almak için LiveData API'leri sağlar. Bu API'ler, RecyclerView nesnesini sıra bilgileriyle doldurmak için doğrudan kullanılabilse de bu süreci kolaylaştırmak amacıyla car-media-common kitaplığına bir PlaybackQueueController sınıfı eklenmiştir. CarUiRecyclerView içindeki her öğenin düzeni, istemci uygulaması ve isteğe bağlı bir başlık düzeni tarafından belirtilir. İstemci uygulaması, sürüş durumunda kuyrukta gösterilen öğe sayısını özel UXR kısıtlamalarıyla sınırlamayı da seçebilir.

PlaybackQueueController oluşturucusu ve ayarlayıcıları aşağıdaki örnekte gösterilmektedir. queueResource ve headerResource düzen kaynakları, Resources.ID_NULL olarak iletilebilir. İlk durumda kapsayıcı zaten id queue_list ile CarUiRecyclerView içeriyorsa, ikinci durumda ise kuyrukta başlık yoksa bu işlem yapılabilir.

   /**
    * 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;
    }

Her kuyruk öğesinin düzeni, QueueViewHolder iç sınıfında kullanılanlarla eşleşen ve göstermek istediği Görünümlerin kimliklerini içermelidir.

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 ile oluşturulan bir medya kartında sıra göstermek için PlaybackCardController, PlaybackViewModel ve MediaItemsRepository örnekleri için sırasıyla mDataModel ve mItemsRepository kullanılarak PlaybackCardController oluşturucusunda oluşturulabilir.PlaybackQueueController

Daha önce oynatılan MediaSource'ların geçmişini göster

Bu bölümde, daha önce oynatılan medya kaynaklarının geçmişini nasıl göstereceğinizi ve ortaya çıkaracağınızı öğreneceksiniz.

PlaybackCardViewModel API ile geçmiş listesini alma

PlaybackCardViewModel, medya geçmişi listesini almak için getHistoryList() adlı bir LiveData API sağlar. Daha önce oynatılmış MediaSource'ların listesini içeren bir LiveData döndürür. Bu veriler, CarUiRecyclerView nesnesini doldurmak için kullanılabilir. PlaybackQueueController'ya benzer şekilde, süreci kolaylaştırmak için car-media-common kitaplığına PlaybackHistoryController adlı bir sınıf eklendi.

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 ile Surface geçmişi kullanıcı arayüzü

Geçmiş verilerini CarUiRecyclerView ile doldurmak için yeni PlaybackHistoryController özelliğini kullanın. Bu sınıfın oluşturucuları ve ana işlevleri aşağıda verilmiştir. İstemci uygulamasından geçirilen kapsayıcı, kimliği history_list olan bir CarUiRecyclerView içermelidir. CarUiRecyclerView liste öğelerini ve isteğe bağlı bir başlığı gösterir. Hem liste öğesi hem de başlık düzenleri istemci uygulamasından geçirilebilir. Resources.ID_NULL, headerResource olarak ayarlanırsa başlık gösterilmez. PlaybackCardViewModel denetleyiciye iletildikten sonra playbackCardViewModel.getHistoryList() kaynağından alınan LiveData<List<MediaSource>> izlenir.

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() {
    }
}

Her öğenin düzeni, ViewHolder iç sınıfında kullanılanlarla eşleşen ve göstermek istediği görünümlerin kimliklerini içermelidir.

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 (veya bir alt sınıf) ile oluşturulan bir medya kartında geçmiş listesi göstermek için PlaybackHistoryController, PlaybackCardController oluşturucusunda oluşturulabilir.