Tạo ứng dụng đa phương tiện theo mẫu

Ứng dụng đa phương tiện theo mẫu đang ở giai đoạn thử nghiệm
Hiện tại, ai cũng có thể xuất bản ứng dụng truyền thông dựa trên mẫu lên các kênh kiểm thử nội bộ và kiểm thử khép kín trên Cửa hàng Google Play. Bạn sẽ được phép xuất bản lên kênh công khai và kênh phát hành công khai vào một thời điểm khác.

Các ứng dụng đa phương tiện sử dụng mẫu trong Thư viện ứng dụng dành cho ô tô có thể tuỳ chỉnh trải nghiệm duyệt xem và phát nội dung nghe nhìn, đồng thời đảm bảo trải nghiệm này được tối ưu hoá cho màn hình ô tô và giảm thiểu sự xao nhãng khi lái xe.

Hướng dẫn này giả định rằng bạn đã có một ứng dụng đa phương tiện phát âm thanh trên điện thoại và ứng dụng đa phương tiện đó phù hợp với cấu trúc ứng dụng đa phương tiện của Android. Car App Library cho phép bạn thay thế trải nghiệm trong ứng dụng bằng các mẫu thay vì những mẫu được tạo bằng cấu trúc dữ liệu MediaBrowser Tạo ứng dụng đa phương tiện cho ô tô. Bạn vẫn phải cung cấp một MediaSession cho các nút điều khiển phát và một MediaBrowserService hoặc MediaLibraryService, được dùng cho các đề xuất và trải nghiệm thông minh khác.

Định cấu hình tệp kê khai của ứng dụng

Ngoài các bước được mô tả trong bài viết Sử dụng Thư viện ứng dụng Android cho Ô tô, các ứng dụng đa phương tiện dựa trên mẫu phải đáp ứng những yêu cầu sau:

Khai báo tính năng hỗ trợ danh mục trong tệp kê khai của bạn

Ứng dụng của bạn cần khai báo androidx.car.app.category.MEDIA danh mục ứng dụng cho ô tô trong bộ lọc ý định của CarAppService:

<application>
    ...
   <service
       ...
        android:name=".MyCarAppService"
        android:exported="true">
      <intent-filter>
        <action android:name="androidx.car.app.CarAppService" />
        <category android:name="androidx.car.app.category.MEDIA"/>
      </intent-filter>
    </service>
    ...
<application>

Để có quyền truy cập vào MediaPlaybackTemplate, ứng dụng của bạn cũng cần khai báo quyền androidx.car.app.MEDIA_TEMPLATES trong tệp kê khai:

<manifest ...>
  ...
  <uses-permission android:name="androidx.car.app.MEDIA_TEMPLATES"/>
  ...
</manifest>

Đặt cấp độ API của ứng dụng trên ô tô tối thiểu

Các ứng dụng đa phương tiện sử dụng MediaPlaybackTemplate chỉ được hỗ trợ trong CAL API 8 trở lên, hãy đảm bảo rằng Car App API level tối thiểu được đặt thành 8.

<application ...>
  ...
  <meta-data
    android:name="androidx.car.app.minCarApiLevel"
    android:value="8"/>
  ...
</application>

Cung cấp biểu tượng ghi công

Hãy nhớ thêm một biểu tượng ghi nhận quyền tác giả cho các ứng dụng đa phương tiện được tạo bằng Thư viện ứng dụng cho ô tô.

Khai báo chức năng hỗ trợ Android Auto

Đảm bảo rằng tệp kê khai của ứng dụng có chứa những nội dung sau:

<application>
  ...
  <meta-data android:name="com.google.android.gms.car.application"
      android:resource="@xml/automotive_app_desc"/>
  ...
</application>

Sau đó, hãy thêm khai báo template vào automotive_app_desc.xml trong tài nguyên xml của bạn. Nội dung sẽ có dạng như sau:

<automotiveApp xmlns:android="http://schemas.android.com/apk/res/android">
 <uses name="media"/>
 <uses name="template"/>
</automotiveApp>

Khai báo tính năng hỗ trợ Android Automotive OS

Có 2 cách để phân phối một ứng dụng đa phương tiện có Car App Library trên Android Automotive OS: dưới dạng một APK hoặc dưới dạng 2 APK riêng biệt. Nếu bạn phân phối một APK duy nhất, thì APK đó sẽ hỗ trợ những xe có Android Automotive OS được bật với máy chủ Car App Library và quay lại ứng dụng MediaBrowserService hoặc MediaLibraryService nếu không, ngay cả đối với các phiên bản Android cũ (Android 10 – Android 13). Nếu chọn phân phối 2 APK riêng biệt, bạn có thể dễ dàng cập nhật các nội dung mới cho phiên bản Thư viện ứng dụng trên ô tô mà không lo ảnh hưởng đến phiên bản MediaBrowserService hoặc MediaLibraryService của ứng dụng.

Phân phối một APK duy nhất

Khi phân phối một APK duy nhất cho Thư viện ứng dụng cho ô tô và các phiên bản MediaBrowserService hoặc MediaLibraryService của ứng dụng, bạn cần phải đặt "" thành android:required="false".

<uses-feature android:name="android.software.car.templates_host.media" android:required="false"/>

Tiếp theo, hãy làm theo nguyên tắc về Thư viện ứng dụng dành cho ô tô cho AAOS và giới thiệu CarAppActivity có thể khởi chạy (hoặc hoạt động trampoline). Bạn phải đặt hoạt động thành android:enabled="false" trong tệp kê khai. Tiếp theo, hãy thêm thẻ siêu dữ liệu vào khai báo MediaBrowserService cho biết thành phần CarAppActivity là thành phần thay thế. Hãy xem tệp kê khai mẫu bên dưới:

<service android:name=".media.MyMediaService"
    android:exported="true"
    android:label="@string/app_name">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaLibraryService"/>
    </intent-filter>

    <!-- Link to Car App Library Activity -->
    <meta-data
        android:name="androidx.car.app.media.CalMediaActivityComponent" 
        android:value="com.example.mediaapp.LaunchableTrampoline"/>
</service>

<activity
    android:name=".LaunchableTrampoline"
    android:exported="true"
    android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
    android:launchMode="singleTask"
    android:label="@string/app_name_cal"
    android:enabled="false"> <!-- Set to false -->

    <meta-data android:name="distractionOptimized" android:value="true" />

    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <action android:name="androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

Phân phối trên Play

APK của bạn có Thư viện Car App và MediaBrowserService hoặc MediaLibraryService phải được bật bằng mã phiên bản cao hơn và minSdk nhắm đến Android 14 (34).

Phân phối bằng 2 tệp APK

Để phân phối 2 tệp APK riêng biệt, một tệp dùng Thư viện ứng dụng cho ô tô và một tệp dùng MediaBrowserService hoặc MediaLibraryService, hãy làm theo các bước sau để đảm bảo nhắm đến đúng các chức năng của xe.

Khi tạo một APK riêng cho phiên bản Thư viện Ứng dụng cho Ô tô của ứng dụng, bạn phải đặt android.software.car.templates_host.media thành android:required=true. Điều này đảm bảo ứng dụng chỉ được phân phối trên các bản dựng Android Automotive OS được chứng nhận có hỗ trợ máy chủ Car App Library.

<uses-feature android:name="android.software.car.templates_host.media" android:required="true"/>

Ngoài việc dùng android.software.car.templates_host.media và đặt thành android:required=true ở trên, hãy làm theo các bước sau để bật Android Automotive OS cho hoạt động có thể khởi chạy của Thư viện ứng dụng ô tô.

Play Distribution

APK sử dụng Car App Library phải được phân phối trong kênh chuyên biệt của Automotive OS.

Hỗ trợ thao tác bằng giọng nói

Bật tính năng giọng nói cho ứng dụng để người dùng có thể hoàn thành các thao tác thông thường mà không cần dùng tay. Hãy xem phần hỗ trợ thao tác bằng giọng nói cho nội dung nghe nhìn để biết hướng dẫn chi tiết hơn về cách triển khai. Với một ứng dụng đa phương tiện dựa trên mẫu, nếu nhận được lệnh thoại, bạn không cần cập nhật MediaBrowserService hoặc MediaLibraryService bằng kết quả tìm kiếm. Thay vào đó, hãy cân nhắc việc thêm một thao tác vào mẫu phát nội dung nghe nhìn để cho phép người dùng tìm thêm nội dung dựa trên truy vấn phát hoặc tìm kiếm đó. Bạn phải hỗ trợ lệnh thoại để đáp ứng nguyên tắc về chất lượng VC-1.

Tạo Mẫu phát

MediaPlaybackTemplate hiển thị thông tin phát nội dung nghe nhìn trong ứng dụng đa phương tiện của Thư viện ứng dụng cho ô tô. Mẫu này cho phép bạn đặt tiêu đề và các thao tác có thể tuỳ chỉnh, trong khi thông tin nội dung nghe nhìn và các nút điều khiển phát được máy chủ lưu trữ điền sẵn dựa trên trạng thái của MediaSession trong ứng dụng.

Một trình phát nhạc cho thấy bài hát Sounds of Spring của Summer Fielding, kèm theo ảnh chân dung vuông của một người phụ nữ đang chơi đàn guitar.

Hình 1: MediaPlaybackTemplate có thao tác trên tiêu đề để mở hàng đợi ở trên cùng.

Ví dụ về mã này cho biết cách tạo một mẫu phát ví dụ đặt thao tác tiêu đề cho phép người dùng điều hướng đến một màn hình có hàng đợi bài hát.

val playbackTemplate = MediaPlaybackTemplate.Builder()
      .setHeader(
        Header.Builder()
          .setStartHeaderAction(Action.BACK)
          .addEndHeaderAction(
                Action.Builder()
                  .setTitle(model.context.getString(R.string.queue_button_title))
                  .setIcon(
                    CarIcon.Builder(
                        IconCompat.createWithResource(
                          model.context,
                          R.drawable.gs_queue_music_vd_theme_24,
                        ))
                      .build())
                  .setOnClickListener(showQueueScreen())
                  .build())
          .setTitle(model.context.getString(R.string.media_playback_view_title))
          .build())
      .build()

Khi bạn sử dụng MediaPlaybackTemplate, hãy đăng ký mã thông báo MediaSession bằng MediaPlaybackManager trong CarAppService. Nếu không làm như vậy, lỗi sẽ xuất hiện khi MediaPlaybackTemplate được gửi đến máy chủ lưu trữ.

import androidx.car.app.media.MediaPlaybackManager


override fun onCreateSession(sessionInfo: SessionInfo): Session {
    return object : Session() {
        

        init {
          lifecycle.addObserver(
            LifecycleEventObserver { _, event ->
              if (event == ON_CREATE) {
                val token = ... // MediaSessionCompat.Token
                (carContext.getCarService(CarContext.MEDIA_PLAYBACK_SERVICE) as MediaPlaybackManager)
                  .registerMediaPlaybackToken(token)
              }
              ...
            }
          )
        }
    }
}

.registerMediaPlaybackToken là cần thiết để hiển thị thông tin và các chế độ kiểm soát chế độ phát nội dung nghe nhìn cho Android Auto. Điều này cũng quan trọng để máy chủ tạo thông báo dành riêng cho nội dung nghe nhìn.

Đối với các ứng dụng dùng thư viện Media3, sử dụng PlatformToken thay vì MediaSessionCompat.Token tiêu chuẩn, bạn sẽ cần triển khai SessionCommand tuỳ chỉnh trong MediaLibrarySession.Callback để trả về mã thông báo nền tảng cơ bản của phiên: session.platformToken. Trong CarAppService, hãy gửi lệnh tuỳ chỉnh này đến phiên. Sau khi nhận được mã thông báo nền tảng, hãy chuyển đổi mã thông báo đó bằng MediaSessionCompat.Token.fromToken(platformToken) và truyền mã thông báo tương thích này đến Thư viện ứng dụng ô tô trong .registerMediaPlaybackToken().

Sắp xếp nội dung nghe nhìn bằng mẫu

Để sắp xếp nội dung nghe nhìn để duyệt xem, chẳng hạn như bài hát hoặc album, bạn nên dùng SectionedItemTemplate. Lớp này cho phép bạn dùng GridSectionRowSection cùng nhau để tạo bố cục kết hợp danh sách hình ảnh và mục văn bản.

Giao diện của một ứng dụng âm nhạc hiển thị các bài hát và đĩa nhạc được phát gần đây, bao gồm 2 hàng dọc và 3 ảnh bìa đĩa nhạc theo chiều ngang.

Hình 2: SectionedItemTemplate chứa RowSection, sau đó là GridSection

Sử dụng SectionedItemTemplate bên trong TabTemplate

Một cách thuận tiện để phân loại nội dung nghe nhìn trong ứng dụng là sử dụng SectionedItemTemplate bên trong TabTemplate.

val template =
      SectionedItemTemplate.Builder()...build();
val tabTemplate = 
      TabTemplate.Builder(tabCallback)
          .setTabContents(TabContents.Builder(template).build)
          .setHeaderAction(Action.APP_ICON)
          
          .build();

Các thành phần và tính năng của Thư viện ứng dụng cho ô tô 1.9

Car App Library API Phiên bản 1.9 giới thiệu các thành phần tuỳ chỉnh cho các chức năng duyệt qua riêng biệt, chẳng hạn như Chips, Progress Bars, Condensed Items, Interactive and Expanded Header, Spotlight SectionsBanners.

Giao diện của một ứng dụng âm nhạc hiển thị các bài hát và đĩa nhạc được phát gần đây, bao gồm 2 hàng dọc và 3 ảnh bìa đĩa nhạc theo chiều ngang.

Hình 3: SectionedItemTemplate chứa Chips, Condensed Items, Interactive Header, Grid ItemsMinimized Control Panel

Giao diện của một ứng dụng âm nhạc hiển thị các bài hát và đĩa nhạc được phát gần đây, bao gồm 2 hàng dọc và 3 ảnh bìa đĩa nhạc theo chiều ngang.

Hình 4: Hai màn hình duyệt xem nội dung nghe nhìn có Expanded Header, Spotlight SectionsProgress Bars

Để biết thêm thông tin chi tiết về cách thiết kế giao diện người dùng của ứng dụng đa phương tiện bằng các mẫu này, hãy xem phần Ứng dụng đa phương tiện.

Khi duyệt qua nội dung nghe nhìn, người dùng phải có thể nhanh chóng chuyển đến MediaPlaybackTemplate mà không bị phân tâm.Để đáp ứng yêu cầu về chất lượng MFT-1, ứng dụng của bạn phải có cách truy cập vào MediaPlaybackTemplate từ tất cả các màn hình duyệt qua nội dung nghe nhìn.

Nếu đang dùng SectionedItemTemplate, bạn có thể thực hiện việc này bằng cách thêm một nút thao tác đưa bạn đến màn hình phát nội dung nghe nhìn. Sử dụng thao tác Action.MEDIA_PLAYBACK tiêu chuẩn của Thư viện ứng dụng cho ô tô. Ứng dụng đa phương tiện sẽ hiển thị thao tác này dưới dạng Bảng điều khiển thu nhỏ. Bạn phải sử dụng bảng điều khiển này để đáp ứng yêu cầu về chất lượng MFT-1 nếu đang dùng Car App Library API 1.9 trở lên. Đối với các mẫu khác, thao tác tiêu đề là một cách khác để đạt được điều này.

Xử lý ý định phát nội dung nghe nhìn của hệ thống

Bạn phải chuyển hướng người dùng đến MediaPlaybackTemplate khi một ứng dụng được khởi chạy từ một hệ thống phát nội dung nghe nhìn, chẳng hạn như thẻ nội dung nghe nhìn. Chúng tôi yêu cầu các ứng dụng đa phương tiện xử lý Intent Action này theo thứ tự để mang lại trải nghiệm liền mạch cho người dùng.

Thêm thao tác androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK vào intent-filter của thành phần Thư viện ứng dụng cho ô tô (CarAppActivity hoặc Activity).

Đảm bảo hoạt động của bạn sử dụng launchMode của singleTask hoặc singleTop để onNewIntent() được gọi.

<activity
    android:name=".LaunchableTrampoline"
    android:exported="true"
    android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
    android:launchMode="singleTask"
    android:label="@string/app_name_cal"
    android:enabled="false">

    <meta-data android:name="distractionOptimized" android:value="true" />

    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <action android:name="androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

Trong lớp Session, hãy ghi đè onNewIntent() để phân tích cú pháp ý định đến. Nếu thao tác theo ý định đến khớp với SHOW_MEDIA_PLAYBACK, hãy chuyển người dùng đến màn hình đang phát.

@Override
public void onNewIntent(@NonNull Intent intent) {
    super.onNewIntent(intent);
    if (SHOW_MEDIA_PLAYBACK.equals(intent.getAction())) {
        ScreenManager screenManager = getCarContext().getCarService(ScreenManager.class);
        // Avoid redundant navigation if already on the playing screen
        if (screenManager.getTop() instanceof MyMediaPlayScreen) {
            return;
        }
        screenManager.push(MyMediaPlayScreen.createScreenFromPlaying(
                getCarContext(), mMediaSessionController));
    }
}

Nếu bạn đang sử dụng một hoạt động trampoline, hãy kiểm tra thao tác theo ý định trong onCreate(). Truyền thao tác này đến ý định tạo CarAppActivity trước khi gọi finish().

public class LaunchableTrampoline extends AppCompatActivity {
    private static final String SHOW_MEDIA_PLAYBACK = "androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent receivedIntent = getIntent();
        String action;

        if (SHOW_MEDIA_PLAYBACK.equals(receivedIntent.getAction())) {
            action = SHOW_MEDIA_PLAYBACK;
        } else {
            action = Intent.ACTION_MAIN;
        }

        Intent intent = new Intent(action);
        intent.setClassName(getPackageName(), "androidx.car.app.activity.CarAppActivity");
        startActivity(intent);
        finish();
    }
}