以下程序可讓您將 Android 寄件者應用程式從 將使用 CCL 的 SDK 第 2 版投放到 CAF。CCL 的所有功能 ,因此當您完成遷移後,您就不需要使用 CCL。
Cast CAF 傳送端 SDK 會使用 CastContext 代您管理 GoogleAPIClient。 CastContext 可為您管理生命週期、錯誤和回呼, 簡化投放應用程式的開發程序。
簡介
- 由於 CAF 寄件者設計受到 Cast 隨附程式庫影響,因此 從 CCL 遷移至 CAF 寄件者,大多是一對一的對應作業 類別及其方法
- CAF 寄件者仍是 Google Play 服務的一部分 Android SDK Manager
- 已更新的套件 (
com.google.android.gms.cast.framework.*
) 新增至 CAF 寄件者,具備類似 CCL 的功能 在任何情況下都能遵守 Google Cast 設計檢查清單。 - CAF 寄件者提供的小工具符合 Cast 使用者體驗規定。 這些小工具與 CCL 提供的小工具類似
- CAF 寄件者提供與 CCL 類似的非同步回呼,以便追蹤 狀態,並取得資料。與 CCL 不同,CAF 寄件者不提供任何免人工管理 各種介面方法的實作。
在後續章節中,我們會著重說明 使用 CCL 的 VideoCastManager 來顯示應用程式 概念也適用於 DataCastManager
依附元件
CCL 和 CAF 有相同的 AppCompat 支援資料庫依附元件, MediaRouter v7 支援資料庫和 Google Play 服務。不過 就是依賴 Google Play 新推出的 Cast 架構 9.2.0 以上版本。
在 build.gradle 檔案中,移除以下項目的依附元件:
「com.google.android.gms:play-services-cast
」和
com.google.android.libraries.cast.companionlibrary:ccl
,
然後加入新的 Cast 架構:
dependencies {
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:mediarouter-v7:23.4.0'
compile 'com.google.android.gms:play-services-cast-framework:9.4.0'
}
您也可以移除 Google Play 服務中繼資料:
<meta‐data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
屬於 CAF 的所有服務、活動和資源都會自動 與應用程式的資訊清單和資源合併
CAF 支援的最低 Android SDK 版本為 9 (Gingerbread);CCL 的最低 Android SDK 版本為 10。
CCL 提供了便利的方法
BaseCastManager.checkGooglePlayServices(activity)
,即可確認
版本的 Google Play 服務可取得。CAF 不含
作為 Cast SDK 的一部分按照程序操作
確保裝置已安裝 Google Play 服務 APK
確保使用者的
裝置,因為更新可能不會立即提供給所有使用者。
針對應用程式的 主題。
初始化
針對 CCL,VideoCastManager.initialize()
必須在
應用程式執行個體的 onCreate()
方法。這個邏輯應該是
從您的 Application 類別代碼中移除。
在 CAF 中,投放內容還必須要有明確的初始化步驟
這個架構的重點在於這包括初始化 CastContext
單例模式,方法是使用
適當的 OptionsProvider
來指定接收器應用程式 ID,以及
或使用其他全域選項CastContext
的作用與 CCL 的
VideoCastManager
,提供用戶端互動的單例模式。
OptionsProvider
類似於 CCL 的 CastConfiguration
,可讓您
來設定 Cast 架構功能
如果您目前的 CCL CastConfiguration.Builder
顯示如下:
VideoCastManager.initialize(
getApplicationContext(),
new CastConfiguration.Builder(context.getString(R.string.app_id))
.enableWifiReconnection()
.enableAutoReconnect()
.build());
接著在 CAF 中使用 CastOptions.Builder
,後續的 CastOptionsProvider
會類似於:
public class CastOptionsProvider implements OptionsProvider {
@Override
public CastOptions getCastOptions(Context context) {
return new CastOptions.Builder()
.setReceiverApplicationId(context.getString(R.string.app_id))
.build();
}
@Override
public List<SessionProvider> getAdditionalSessionProviders(
Context context) {
return null;
}
}
請參閱範例應用程式 完整實作 OptionsProvider。
在「application」中宣告 OptionsProvider元素的 AndroidManifest.xml 檔案:
<application>
...
<meta-data
android:name=
"com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="com.google.sample.cast.refplayer.CastOptionsProvider"
/>
</application>
延後初始化每個 Activity
的 onCreate
方法中的 CastContext
(而非 Application
例項):
private CastContext mCastContext;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.video_browser);
setupActionBar();
mCastContext = CastContext.getSharedInstance(this);
}
如要存取 CastContext
單例模式,請使用:
mCastContext = CastContext.getSharedInstance(this);
探索裝置
CCL 的 VideoCastManager
incrementUiCounter
和 decrementUiCounter
應該
會從 Activities
的 onResume
和 onPause
方法中移除。
在 CAF 中,探索程序會自動啟動及停止 當應用程式進入前景並進入背景時 。
投放按鈕和投放對話方塊
與 CCL 一樣,這些元件是由 MediaRouter v7 支援提供 資源庫。
MediaRouteButton
仍會實作「投放」按鈕,但您可以新增
使用 ActionBar
或 Toolbar
做為選單項目
。
選單 XML 中的 MediaRouteActionProvider
宣告與
與 CCL:
<item
android:id="@+id/media_route_menu_item"
android:title="@string/media_route_menu_title"
app:actionProviderClass="android.support.v7.app.MediaRouteActionProvider"
app:showAsAction="always"/>
與 CCL 類似,覆寫每個活動的 onCreateOptionMenu() 方法,但 請使用 CAF 的 CastButtonFactory 屬性,不要使用 CastManager.addMediaRouterButton 來連接 MediaRouteButton 與 Cast 架構:
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.browse, menu);
CastButtonFactory.setUpMediaRouteButton(getApplicationContext(),
menu,
R.id.media_route_menu_item);
return true;
}
裝置控制
與 CCL 類似,在 CAF 中,裝置控制功能通常由架構處理。
傳送者應用程式不需處理 (且不應嘗試處理)
連線至裝置並啟動接收端應用程式
GoogleApiClient
。
傳送者與接收者之間的互動現在以「工作階段」表示。
SessionManager
類別會處理工作階段的生命週期,並自動啟動
並停止工作階段,以回應使用者手勢:當工作階段
使用者在投放對話方塊中選取投放裝置,並在使用者輕觸裝置時結束
「停止投放」按鈕或傳送者應用程式本身
終止服務。
在 CCL 中,您必須擴充 VideoCastConsumerImpl
類別才能追蹤轉換
工作階段狀態:
private final VideoCastConsumer mCastConsumer = new VideoCastConsumerImpl() {
public void onApplicationConnected(ApplicationMetadata appMetadata,
String sessionId,
boolean wasLaunched) {}
public void onDisconnectionReason(int reason) {}
public void onDisconnected() {}
}
在 CAF 中,傳送端應用程式可透過下列方式接收工作階段生命週期事件的通知:
使用 SessionManager
註冊 SessionManagerListener
。
SessionManagerListener 回呼會定義所有工作階段的回呼方法
生命週期事件。
下列 SessionManagerListener
方法是從 CCL 的
VideoCastConsumer
介面:
VideoCastConsumer.onApplicationConnected
->SessionManagerListener.onSessionStarted
VideoCastConsumer.onDisconnected
->SessionManagerListener.onSessionEnded
宣告實作 SessionManagerListener
介面並移動的類別
將 VideoCastConsumerImpl
邏輯套用至相符方法:
private class CastSessionManagerListener implements SessionManagerListener<CastSession> {
public void onSessionEnded(CastSession session, int error) {}
public void onSessionStarted(CastSession session, String sessionId) {}
public void onSessionEnding(CastSession session) {}
...
}
CastSession
類別代表與投放裝置的工作階段。課程中有
控制裝置音量和靜音狀態的方法。
BaseCastManager
。
請勿使用 CCL VideoCastManager
新增消費者:
VideoCastManager.getInstance().addVideoCastConsumer(mCastConsumer);
立即註冊您的 SessionManagerListener
:
mCastSessionManager =
CastContext.getSharedInstance(this).getSessionManager();
mCastSessionManagerListener = new CastSessionManagerListener();
mCastSessionManager.addSessionManagerListener(mCastSessionManagerListener,
CastSession.class);
如要停止監聽 CCL 中的事件:
VideoCastManager.getInstance().removeVideoCastConsumer(mCastConsumer);
現在,請使用 SessionManager
停止監聽工作階段事件:
mCastSessionManager.removeSessionManagerListener(mCastSessionManagerListener,
CastSession.class);
為了明確中斷與投放裝置的連線,CCL 使用了:
VideoCastManager.disconnectDevice(boolean stopAppOnExit,
boolean clearPersistedConnectionData,
boolean setDefaultRoute)
如果是 CAF,請使用 SessionManager
:
CastContext.getSharedInstance(this).getSessionManager()
.endCurrentSession(true);
為了判斷傳送者是否已連線至接收器,CCL 可提供
VideoCastManager.getInstance().isConnected()
,但在 CAF 中使用
SessionManager
:
public boolean isConnected() {
CastSession castSession = CastContext.getSharedInstance(mAppContext)
.getSessionManager()
.getCurrentCastSession();
return (castSession != null && castSession.isConnected());
}
在 CAF 中,系統仍會透過回呼傳送音量/靜音狀態變更通知
Cast.Listener
中的方法;並向這些事件監聽器註冊
CastSession
。所有其他裝置狀態通知都會透過
CastStateListener
回呼;這些接聽程式註冊的
CastSession
。請務必取消註冊相關的
片段、活動或應用程式會移至背景。
重新連線邏輯
CAF 嘗試重新建立因故中斷的網路連線 Wi-Fi 訊號暫時中斷,或其他網路錯誤。這項程序是在 工作階段層級工作階段可能會在使用者進入「暫停」狀態時連線狀態 並且將切換回 「已連線」連線狀態 已還原。架構會負責重新連線至接收器應用程式 重新連結任何投放頻道
CAF 提供專屬的重新連線服務,因此您可以
資訊清單中的 CCL ReconnectionService
:
<service android:name="com.google.android.libraries.cast.companionlibrary.cast.reconnection.ReconnectionService"/>
您也不需要在資訊清單中使用以下權限: 重新連線邏輯:
<uses‐permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses‐permission android:name="android.permission.ACCESS_WIFI_STATE"/>
CAF 重新連線服務預設為啟用,但您可以使用
CastOptions
。
此外,CAF 也會加入自動恢復工作階段功能,方法是啟用
預設值 (並透過 CastOptions
停用)。如果匯款人應用程式
傳送至背景或終止運作 (透過滑動手勢或因當機而終止)
投放工作階段期間,架構會嘗試繼續執行
工作階段 (傳送者應用程式返回前景或重新啟動時) 的工作階段;
這是由 SessionManager
自動處理,因此發出
任何已註冊的 SessionManagerListener
執行個體上適用的回呼。
自訂管道註冊
CCL 提供兩種建立接收端自訂訊息管道的方法:
CastConfiguration
可讓您指定多個命名空間,CCL 將 然後為你建立頻道DataCastManager
和 VideoCastManager 相似,但著重於非媒體 具體來說,您可以設計提示來解決業務工作
兩種建立自訂頻道的方式都不在 CAF 支援範圍內 就必須按照 新增自訂管道 傳送給你的寄件人應用程式
與 CCL 類似,媒體應用程式不需要明確地 註冊媒體控制管道
媒體管理
在 CAF 中,RemoteMediaClient
類別相當於 VideoCastManager
媒體方法。RemoteMediaClient.Listener
相當於
VideoCastConsumer
方法。我們要用
「onRemoteMediaPlayerMetadataUpdated
」和「onRemoteMediaPlayerStatusUpdated
」
VideoCastConsumer
的方法會對應至 onMetadataUpdated
分別為 RemoteMediaClient.Listener
的 onStatusUpdated
方法:
private class CastMediaClientListener implements RemoteMediaClient.Listener {
@Override
public void onMetadataUpdated() {
setMetadataFromRemote();
}
@Override
public void onStatusUpdated() {
updatePlaybackState();
}
@Override
public void onSendingRemoteMediaRequest() {
}
@Override
public void onQueueStatusUpdated() {
}
@Override
public void onPreloadStatusUpdated() {
}
}
不需要明確初始化或註冊 RemoteMediaClient
object;架構就會自動將物件例項化,並註冊
工作階段啟動時的基本媒體管道 (如果接收端應用程式處於
已連結至媒體命名空間。
RemoteMediaClient
可以做為 getRemoteMediaClient
方法的
CastSession
物件。
CastSession castSession = CastContext.getSharedInstance(mAppContext)
.getSessionManager()
.getCurrentCastSession();
mRemoteMediaClient = castSession.getRemoteMediaClient();
mRemoteMediaClientListener = new CastMediaClientListener();
而不是 CCL 的:
VideoCastManager.getInstance().addVideoCastConsumer(mCastConsumer);
現在使用 CAF:
mRemoteMediaClient.addListener(mRemoteMediaClientListener);
任意數量的事件監聽器都能透過 RemoteMediaClient
註冊,
這可讓多個寄件者元件共用單一執行個體的
與工作階段相關聯的 RemoteMediaClient
。
CCL 的 VideoCastManager
提供處理媒體播放的方法:
VideoCastManager manager = VideoCastManager.getInstance();
if (manager.isRemoteMediaLoaded()) {
manager.pause();
mCurrentPosition = (int) manager.getCurrentMediaPosition();
}
這些項目現已由 CAF 中的 RemoteMediaClient 實作:
if (mRemoteMediaClient.hasMediaSession()) {
mRemoteMediaClient.pause();
mCurrentPosition =
(int)mRemoteMediaClient.getApproximateStreamPosition();
}
在 CAF 中,透過 RemoteMediaClient
發出的所有媒體要求都會傳回
透過 PendingResult
回呼 RemoteMediaClient.MediaChannelResult
狀態可用來追蹤要求進度和最終結果
CCL 和 CAF 都會使用 MediaInfo
和 MediaMetadata
類別來代表
媒體項目及載入媒體
如要在 CCL 中載入媒體,請使用 VideoCastManager
:
VideoCastManager.getInstance().loadMedia(media, autoPlay, mCurrentPosition, customData);
在 CAF 中,RemoteMediaClient
是用來載入媒體:
mRemoteMediaClient.load(media, autoPlay, mCurrentPosition, customData);
如要取得目前媒體工作階段的 Media
資訊和狀態,
接收端,CCL 會使用 VideoCastManager
:
MediaInfo mediaInfo = VideoCastManager.getInstance()
.getRemoteMediaInformation();
int status = VideoCastManager.getInstance().getPlaybackStatus();
int idleReason = VideoCastManager.getInstance().getIdleReason();
在 CAF 中,使用 RemoteMediaClient
取得相同的資訊:
MediaInfo mediaInfo = mRemoteMediaClient.getMediaInfo();
int status = mRemoteMediaClient.getPlayerState();
int idleReason = mRemoteMediaClient.getIdleReason();
簡介重疊
與 CCL 類似,CAF 提供自訂檢視畫面 IntroductoryOverlay
來醒目顯示
首次向使用者顯示的「投放」按鈕
不要使用 CCL 的 VideoCastConsumer
onCastAvailabilityChanged
方法
如要瞭解顯示疊加層的時機,請宣告 CastStateListener
來判斷
「投放」按鈕亮起後,
MediaRouter
設為區域網路:
private IntroductoryOverlay mIntroductoryOverlay;
private MenuItem mMediaRouteMenuItem;
protected void onCreate(Bundle savedInstanceState) {
...
mCastStateListener = new CastStateListener() {
@Override
public void onCastStateChanged(int newState) {
if (newState != CastState.NO_DEVICES_AVAILABLE) {
showIntroductoryOverlay();
}
}
};
mCastContext = CastContext.getSharedInstance(this);
mCastContext.registerLifecycleCallbacksBeforeIceCreamSandwich(this,
savedInstanceState);
}
protected void onResume() {
mCastContext.addCastStateListener(mCastStateListener);
...
}
protected void onPause() {
mCastContext.removeCastStateListener(mCastStateListener);
...
}
追蹤 MediaRouteMenuItem
例項:
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.browse, menu);
mMediaRouteMenuItem = CastButtonFactory.setUpMediaRouteButton(
getApplicationContext(), menu,
R.id.media_route_menu_item);
showIntroductoryOverlay();
return true;
}
檢查 MediaRouteButton
是否顯示,以便顯示簡介重疊元素
可顯示:
private void showIntroductoryOverlay() {
if (mIntroductoryOverlay != null) {
mIntroductoryOverlay.remove();
}
if ((mMediaRouteMenuItem != null) && mMediaRouteMenuItem.isVisible()) {
new Handler().post(new Runnable() {
@Override
public void run() {
mIntroductoryOverlay = new IntroductoryOverlay.Builder(
VideoBrowserActivity.this, mMediaRouteMenuItem)
.setTitleText(getString(R.string.introducing_cast))
.setOverlayColor(R.color.primary)
.setSingleTime()
.setOnOverlayDismissedListener(
new IntroductoryOverlay
.OnOverlayDismissedListener() {
@Override
public void onOverlayDismissed() {
mIntroductoryOverlay = null;
}
})
.build();
mIntroductoryOverlay.show();
}
});
}
}
請參閱 範例應用程式 ,找出顯示簡介疊加層的完整有效程式碼。
如要自訂簡介疊加層的樣式,請按照程序操作 自訂簡介疊加層。
迷你控制器
不要在 CCL 的 MiniController
中使用 CAF 的 MiniControllerFragment
您要顯示迷你活動的活動應用程式版面配置檔案
控制器:
<fragment
android:id="@+id/cast_mini_controller"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:castShowImageThumbnail="true"
android:visibility="gone"
class="com.google.android.gms.cast.framework.media.widget.MiniControllerFragment" />
CAF 不支援 CCL 的 MiniController
支援的手動設定
且不支援 Autoplay
功能
如要自訂迷你控制器的樣式和按鈕,請按照 療程 自訂迷你控制器。
通知和螢幕鎖定
與 CCL 的 VideoCastNotificationService
類似,CAF 提供了
MediaNotificationService
:管理媒體通知的顯示方式
。
您需要從資訊清單中移除以下項目:
VideoIntentReceiver
VideoCastNotificationService
CCL 支援透過
CastConfiguration.Builder
;並未受到 CAF 支援的
考慮使用 CCL 進行下列 CastManager
初始化:
VideoCastManager.initialize(
getApplicationContext(),
new CastConfiguration.Builder(
context.getString(R.string.app_id))
.addNotificationAction(
CastConfiguration.NOTIFICATION_ACTION_PLAY_PAUSE,true)
.addNotificationAction(
CastConfiguration.NOTIFICATION_ACTION_DISCONNECT,true)
.build());
針對 CAF 中的對等設定,SDK 提供
NotificationsOptions.Builder
可協助您建構媒體控制項
通知和螢幕鎖定畫面。通知和鎖定
初始化CastOptions
CastContext
。
public CastOptions getCastOptions(Context context) {
NotificationOptions notificationOptions =
new NotificationOptions.Builder()
.setActions(Arrays.asList(
MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK,
MediaIntentReceiver.ACTION_STOP_CASTING), new int[]{0, 1})
.build();
CastMediaOptions mediaOptions = new CastMediaOptions.Builder()
.setNotificationOptions(notificationOptions)
.build();
return new CastOptions.Builder()
.setReceiverApplicationId(context.getString(R.string.app_id))
.setCastMediaOptions(mediaOptions)
.build();
}
CAF 一律會啟用通知和螢幕鎖定控制項。另外請注意
系統預設會提供播放/暫停和停止投放按鈕。CAF
會自動追蹤活動的可見性,
何時顯示媒體通知 (Gingerbread 除外)。
(如果是 Gingerbread,請參閱先前說明,
使用 registerLifecycleCallbacksBeforeIceCreamSandwich()
;CCL
VideoCastManager
incrementUiCounter
和 decrementUiCounter
呼叫
)。
如要自訂通知中顯示的按鈕,請按照 療程 在通知和螢幕鎖定畫面中加入媒體控制項。
展開的控制器
CCL 提供 VideoCastControllerActivity
和 VideoCastControllerFragment
在投放媒體時顯示展開的控制器。
您可以移除資訊清單中的 VideoCastControllerActivity
宣告。
在 CAF 中 擴充 ExpandedControllerActivity 並新增「投放」按鈕。
如何自訂展開畫面中顯示的樣式和按鈕 請按照 自訂展開控制器。
音訊焦點
與 CCL 一樣,系統會自動管理音訊焦點。
音量控制項
以 Gingerbread 來說,dispatchKeyEvent
必須與 CCL 一樣。ICS 以上版本
,系統會自動處理 CCL 與 CAF 音量控制的設定。
可運用 CAF 的硬性音量按鈕 進入應用程式活動後,螢幕還會顯示音量列 投放。CAF 也會透過 強制調整音量,即使應用程式位於應用程式前方、處於鎖定狀態,或 關閉。
隱藏式輔助字幕
在 Android KitKat 以上版本裝置上,則可透過字幕自訂字幕 設定位於「設定」>「設定」無障礙設定。舊版 Android 但不具備這項功能CCL 會透過自訂 以及委派給 KitKat 系統設定 以上。
CAF 並未提供變更字幕偏好設定的自訂設定。個人中心
應從資訊清單中移除 CaptionsPreferenceActivity
參照
以及偏好設定 XML
由於變更關閉狀態,因此不再需要 CCL 的 TracksChooserDialog
字幕軌是由展開的控制器使用者介面所處理
隱藏式輔助字幕 API 與第 2 版相同
偵錯記錄功能
CAF 不提供偵錯記錄設定。
其他
CAF 不支援下列 CCL 功能:
- 在播放廣告前先透過提供
MediaAuthService
取得授權 - 可設定的 UI 訊息
範例應用程式
請參閱差異,瞭解如何將 Android 通用音樂播放器 (uamp) 範例應用程式從 CCL 遷移至 CAF。
我們也提供程式碼研究室教學課程,以及使用 CAF 的範例應用程式。