欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android 集成Google Cast 異常問題解析

 更新時(shí)間:2023年02月10日 09:58:04   作者:Dai_Dev  
這篇文章主要為大家介紹了Android 集成Google Cast 異常問題解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

GoogleCast 異常問題

項(xiàng)目中集成 Google Cast 功能時(shí), 部分機(jī)型遇到一些問題

需求

項(xiàng)目中Cast需求有點(diǎn)特別,默認(rèn)Cast Button處于不可見狀態(tài)。 APP進(jìn)入前臺(tái)時(shí),查詢周圍是否有可用Cast設(shè)備, 有才顯示Cast Button, 否則隱藏

根據(jù)流程, 我們有兩種情況需要處理

Fragment/Activity 啟動(dòng)時(shí)查詢Available Cast Devices

暫命名方法1

代碼實(shí)現(xiàn)如下: Fragment -> onResume(), checkCastDevices:

    public static boolean checkCastDevice(Context activity) {
        MediaRouter mediaRouter = MediaRouter.getInstance(activity);
        List<mediarouter.routeinfo> routes = mediaRouter.getRoutes();
        if (routes != null &amp;&amp; routes.size() != 0) {
            for (MediaRouter.RouteInfo info : routes) {
                if (info.getDeviceType() != MediaRouter.RouteInfo.CONNECTION_STATE_DISCONNECTED
                        && !info.isDefault() && !info.isBluetooth() && !info.isDeviceSpeaker()) {
                    return true;
                }
            }
        }
        return false;
    }

Fragment/Activity 處于前臺(tái)時(shí),動(dòng)態(tài)獲取Availabe Cast Devices

暫命名方法2

監(jiān)聽了addCastStateListener CastContext.addCastStateListener(this)

    @Override
    public void onCastStateChanged(int i) {
        stateListenerListTemp.clear();
        stateListenerListTemp.addAll(stateListenerList);
        switch (i) {
            case CastState.CONNECTED:
                for (CastStateListener listener : stateListenerListTemp) {
                    listener.connected();
                }
                break;
            case CastState.CONNECTING:
                for (CastStateListener listener : stateListenerListTemp) {
                    listener.connecting();
                }
                break;
            case CastState.NO_DEVICES_AVAILABLE:  //has not available devices
                for (CastStateListener listener : stateListenerListTemp) {
                    listener.noDevicesAvailable();  // hide cast button
                }
                break;
            case CastState.NOT_CONNECTED:  //has available devices, but not connect
                for (CastStateListener listener : stateListenerListTemp) {
                    listener.notConnected();  // show cast button
                }
                break;
        }
        stateListenerListTemp.clear();
    }

依據(jù)上述實(shí)現(xiàn), 可以即時(shí)監(jiān)聽Cast Devices的變化,動(dòng)態(tài)更新Cast Button的可見性

問題

新增了一個(gè)有個(gè)需求, Toolbar上新增了一個(gè)視圖,需要根據(jù)Cast Button的可見性來設(shè)置視圖可見性,即二者可見性互斥,但在測(cè)試中發(fā)現(xiàn)一些問題。

部分設(shè)備上,例如Remi Note 4, 上述兩個(gè)方法都無效

  • 問題1,方法1 只有在進(jìn)程銷毀后第一次啟動(dòng)可以獲取周圍Available Cast Devices,之后關(guān)閉APP重啟一直返回false
  • 問題2,方法2 APP處于前臺(tái)時(shí),斷開WIFI時(shí),Cast Button消失,重新連接WIFI,Cast Button可見,但代碼中并沒有收到Cast Devices 狀態(tài)更新的回調(diào), 設(shè)置Cast Button Visibility的代碼并未執(zhí)行,這就出現(xiàn)一種情況:雖然Cast Button不可見,但是新增的視圖卻并未顯示。

分析

  • 問題1

當(dāng)App進(jìn)程銷毀后重新啟動(dòng), 可以成功獲取Cast Devices, 說明初始化CastContext時(shí), 主動(dòng)掃描了周邊Routes, 而App關(guān)閉后重新打開, 部分設(shè)備未主動(dòng)掃描, 所以獲取狀態(tài)失敗。

  • 問題2

當(dāng)Cast Button可見時(shí),斷開WIFI連接, 因?yàn)闆]有收到onCastStateChanged的回調(diào),CastButton.SetVisibility(View.GONE)并未執(zhí)行, 但是Cast Button 卻不可見了, 打開Developers options--Show layouts bounds開關(guān), 發(fā)現(xiàn)Cast Button 在布局中存在,但是圖標(biāo)卻不可見,那么有兩種可能: - Cast Button的Drawable 被移除了 - Cast Button被設(shè)為View.INVISIBLE

但是onCastStateChanged的回調(diào)并未執(zhí)行, 但是Cast Button 狀態(tài)卻有變化,那只能說明Cast Button內(nèi)部監(jiān)聽了連接狀態(tài)的變化,并內(nèi)部處理了展示狀態(tài)。

項(xiàng)目中Cast Button是一個(gè)MediaRouteButton, 查詢?cè)创a

public class MediaRouteButton extends View {
    private static final String TAG = "MediaRouteButton";
    private static ConnectivityReceiver sConnectivityReceiver;
    private int mVisibility = VISIBLE;
    private boolean mAlwaysVisible;
    public MediaRouteButton(Context context) {
        this(context, null);
    }
    public MediaRouteButton(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.mediaRouteButtonStyle);
    }
    public MediaRouteButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(MediaRouterThemeHelper.createThemedButtonContext(context), attrs, defStyleAttr);
        if (sConnectivityReceiver == null) {
            sConnectivityReceiver = new ConnectivityReceiver(context.getApplicationContext());
        }
    }
    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        sConnectivityReceiver.registerReceiver(this);
    }
    @Override
    public void onDetachedFromWindow() {
        if (!isInEditMode()) {
            sConnectivityReceiver.unregisterReceiver(this);
        }
        super.onDetachedFromWindow();
    }
    void refreshVisibility() {
        //set VISIBLE or INVISIBLE
        super.setVisibility(mVisibility == VISIBLE
                && !(mAlwaysVisible || sConnectivityReceiver.isConnected())
                ? INVISIBLE : mVisibility);
    }
    /**
    * 監(jiān)聽連接狀態(tài)的變化,刷新MediaRouteButton可見性
    */
    private static final class ConnectivityReceiver extends BroadcastReceiver {
        private final Context mContext;
        // If we have no information, assume that the device is connected
        private boolean mIsConnected = true;
        private List<MediaRouteButton> mButtons;
        ConnectivityReceiver(Context context) {
            mContext = context;
            mButtons = new ArrayList<MediaRouteButton>();
        }
        public void registerReceiver(MediaRouteButton button) {
            if (mButtons.size() == 0) {
                IntentFilter intentFilter = new IntentFilter();
                intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
                mContext.registerReceiver(this, intentFilter);
            }
            mButtons.add(button);
        }
        public void unregisterReceiver(MediaRouteButton button) {
            mButtons.remove(button);
            if (mButtons.size() == 0) {
                mContext.unregisterReceiver(this);
            }
        }
        public boolean isConnected() {
            return mIsConnected;
        }
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
                boolean isConnected = !intent.getBooleanExtra(
                        ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
                if (mIsConnected != isConnected) {
                    mIsConnected = isConnected;
                    for (MediaRouteButton button: mButtons) {
                        button.refreshVisibility();
                    }
                }
            }
        }
    }
}

源碼中可見,內(nèi)部定義了ConnectivityReceiver來監(jiān)聽連接狀態(tài)的變化, 從而內(nèi)部控制MediaRouteButton的顯示。

解決

問題1

App啟動(dòng)時(shí),雖然主動(dòng)掃描周邊Routes,來更新可以Cast Devices狀態(tài)

    //Init Cast
    public static void initCast(Context context) {
        if (context == null)
            return;
        if (initialized) {
            CastContextManager.getInstance().addRouter(context);
            return;
        }
        initialized = true;
        //初始化CastContextManager
        ....
    }
    public void addRouter(Context context) {
        if(castContext !=null){
            MediaRouter mediaRouter = MediaRouter.getInstance(context);
            mediaRouter.removeCallback(callback);
            mediaRouter.addCallback(MediaRouteSelector.EMPTY, callback, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
        }
    }
    private final MediaRouter.Callback callback = new MediaRouter.Callback() {
        @Override
        public void onProviderAdded(MediaRouter router, MediaRouter.ProviderInfo provider) {
            super.onProviderAdded(router, provider);
            ZenLogger.dd("MXMediaRouter", () -> "onProviderAdded  " + provider.getRoutes());
        }
        @Override
        public void onProviderRemoved(MediaRouter router, MediaRouter.ProviderInfo provider) {
            super.onProviderRemoved(router, provider);
            ZenLogger.dd("MXMediaRouter", () -> "onProviderRemoved  " + provider.getRoutes());
        }
        @Override
        public void onProviderChanged(MediaRouter router, MediaRouter.ProviderInfo provider) {
            super.onProviderChanged(router, provider);
            ZenLogger.dd("MXMediaRouter", () -> "onProviderChanged  " + provider.getRoutes());
        }
    };

問題2

因?yàn)闊o法收到onCastStateChanged的回調(diào), 而且MediaRouteButton內(nèi)部監(jiān)聽了連接狀態(tài)的變化來更新顯示,那么我們也效仿相同的實(shí)現(xiàn),通過監(jiān)聽當(dāng)前連接狀態(tài),結(jié)合MediaRouteButton的可見性,來判斷Available Cast Devices

  • 當(dāng)前連接斷開, 直接隱藏MediaRouteButton
  • 當(dāng)前連接恢復(fù), 查詢是否有Available Cast Devices,來設(shè)置MediaRouteButton可見
  • 再判斷MediaRouteButton是否可見,來設(shè)置新視圖的可見性
    public static boolean checkCastDevice(Context activity) {
        //如果當(dāng)前無連接, 說明unavailable Cast devices
        if (!NetworkMonitor.isConnected(App.applicationContext())) return false;
        MediaRouter mediaRouter = MediaRouter.getInstance(activity);
        List<MediaRouter.RouteInfo> routes = mediaRouter.getRoutes();
        if (routes != null && routes.size() != 0) {
            for (MediaRouter.RouteInfo info : routes) {
                if (info.getDeviceType() != MediaRouter.RouteInfo.CONNECTION_STATE_DISCONNECTED
                        && !info.isDefault() && !info.isBluetooth() && !info.isDeviceSpeaker()) {
                    return true;
                }
            }
        }
        return false;
    }
    private NetworkMonitor.OnNetworkListener onNetWorkListener = (last, current) -> {
        showMediaRouteButton(CastHelper.checkCastDevice(getActivity()));
        //check MediaRouteButton isVisible
        ...
    };

總結(jié)

部分設(shè)備當(dāng)非殺進(jìn)程重新啟動(dòng)App,不能主動(dòng)掃描routes, 需要在添加主動(dòng)掃描,來獲取最新的Cast Devices

部分設(shè)備無法獲取onCastStateChanged回調(diào),且MediaRouteButton內(nèi)部會(huì)監(jiān)聽連接狀態(tài)設(shè)置顯隱性, 所以我們也同樣監(jiān)聽連接狀態(tài)的變化,來判斷Cast 是否可用

以上就是Android 集成Google Cast 異常問題解析的詳細(xì)內(nèi)容,更多關(guān)于Android集成Google Cast異常的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論