車模桌面加載成功後,需要各種交互
切換桌面處理
先補充如何切換桌面,初始化需要指定一個默認桌面,初始化其實兩個桌面都會一起加載,假設默認是車模桌面,地圖將不會初始化操作,但是地圖桌面會內嵌到Launcher中
兩個桌面是互斥的,基於這種模式下,就需要隱藏另一個桌面,因為切換動效的緣故,這裏直接使用setTranslationX移出屏幕外處理
為了讓兩個桌面互斥,需要通過 mActivityManager.moveTaskToFront(getTaskId(), 0) 方法讓兩個taskview內嵌的activity只能一個處於前台,另一個pause
public void maybeBringEmbeddedTaskToForeground(int taskId) { if (taskId > 0) { // The task in TaskView should be in top to make it visible. // NOTE: Tried setTaskAlwaysOnTop before, the flag has some side effect to hinder // AccessibilityService from finding the correct window geometry: b/197247311 mActivityManager.moveTaskToFront(taskId, /* flags= */ 0); } }
同時將兩個taskview內嵌後,又單獨處理了各自的生命週期,達到互斥效果
3D桌面跟Launcher通訊
這裏3D桌面需要額外處理,因為3D有個通訊進程,需要監聽底層信號對車模進行同步操作,而由於unity無法監聽到底層信號,所以需要跟launcher進行跨進程通訊
所以在3D處於pause時,需要將通訊進程也暫停,否則信號會一直髮送,並且3D也無法接受信號
override fun setUnityVisible(visible: Boolean) { Log.w(TAG, "setUnityVisible:${visible}") val fragment = UnityPlayerFragment.Current if (fragment != null && fragment.isLoadUnityFinish) { lastVisibleFromLauncher3 = visible Log.w(TAG, "setUnityVisible:setInteractionMsg $visible") if (visible) { fragment.resumeUnityPlayer() } else { fragment.pauseUnityPlayer() } } } }
跨進程通訊接口
package com.carlauncher; import android.os.Bundle; import com.carlauncher.IUnityBridgeCallback; interface UnityInterface { oneway void registerUnityBridgeCallback(IUnityBridgeCallback callback); oneway void unregisterUnityBridgeCallback(IUnityBridgeCallback callback); /** * 通知Unity 交互信息傳遞 * 交互信息傳輸專用,除Adapter都放這裏 EX:車衣按鈕被點擊 | 天氣信息傳遞(bx1e) | 其他 * * @param msgType 消息類型 * @param msgData 消息 */ oneway void setInteractionMsg(int msgType, in Bundle bundle); /** * 設置Unity是否處於顯示狀態 */ oneway void setUnityVisible(boolean visible); }
在service中實現接口,通過setInteractionMsg方法跟unity車模交互通訊
通訊隊列
信號不斷的上報,需要緩存信號然後實時發送同步到3D,這裏需要在子線程中不斷輪詢
public class AutoPullExecutor<K, E> extends Thread { private static final String TAG = "AutoPullExecutor"; private final FilterCache<K, E> mCache; private final List<FilterCacheHelper.OnPullCacheCallback<K, E>> mCallbacks; private boolean mIsRunning = false; public AutoPullExecutor(FilterCache<K, E> cache) { mCache = cache; mCallbacks = new ArrayList<>(); } @Override public void run() { Log.d(TAG, "AutoPullExecutor is start"); mIsRunning = true; while (mIsRunning) { FilterCache.Node<K, E> node = mCache.poll(); if (node == null) { continue; } autoPullCallback(node); } } private void autoPullCallback(FilterCache.Node<K, E> node) { for (FilterCacheHelper.OnPullCacheCallback<K, E> callback : mCallbacks) { callback.onCache(node.key, node.element); } } void addPullCallback(FilterCacheHelper.OnPullCacheCallback<K, E> callback) { mCallbacks.add(callback); } boolean isRunning() { return mIsRunning; } void exit() { mIsRunning = false; interrupt(); clear(); } void clear() { mCallbacks.clear(); } }
註冊好監聽,需要發送信號時添加到緩存隊列,輪詢判斷是否有需要發送的消息,發送完之後移除緩存