Android 多端互動實現方案

網絡發現

網絡發現中有主控設備(一般是移動端)與被控設備(一般是TV或者PC端)兩種角色。

方案一(局域網發現)

採用mDns(組播DNS)相對更獨立靈活一些,Android原生有API(NSD)。

在Windows上需要應用自己集成mDns開發。

爲防止主控設備與錯誤的被控設備綁定,採用隨機碼輔助選擇。被控設備會一直顯示一個連接碼。

在異構網絡拓撲中,因爲組播轉發受限,該方案不可行,需要下面兩個輔助方案。

Android NSD 使用:

public class ServiceDiscovery {

    public interface IServiceListener {
        void onServiceFound(NsdServiceInfo serviceInfo);
        void onServiceLost(NsdServiceInfo serviceInfo);
    }

    private static final String TAG = "ServiceDiscovery";
    private final String mServerType = "_board._tcp.";

    private NsdManager mNsdManager = null;
    private NsdManager.DiscoveryListener mDiscoveryListener = null;
    private NsdManager.ResolveListener mResolveListener = null;
    private IServiceListener mServiceListener;

    ServiceDiscovery(Context context, IServiceListener mServiceListener) {
        this.mServiceListener = mServiceListener;
        mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
        mDiscoveryListener = new MyDiscoveryListener();
        mResolveListener = new MyResolveListener();
    }

    public void startDiscover() {
        mNsdManager.discoverServices(mServerType,
                NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
    }

    public void resoleServer(NsdServiceInfo nsdServiceInfo){
        mNsdManager.resolveService(nsdServiceInfo, mResolveListener);
    }

    private class MyResolveListener implements NsdManager.ResolveListener {
        @Override
        public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
        }
        @Override
        public void onServiceResolved(NsdServiceInfo serviceInfo) {
            Log.i(TAG, "resolution : " + serviceInfo.getServiceName()
                    + " \n host_from_server: " + serviceInfo.getHost() +
                    "\n port from server: " + serviceInfo.getPort());
            String hostAddress = serviceInfo.getHost().getHostAddress();
            Log.i(TAG, "hostAddress ip--> " + hostAddress );
            mServiceListener.onServiceFound(serviceInfo);
        }
    }

    private class MyDiscoveryListener implements NsdManager.DiscoveryListener {
        @Override
        public void onStartDiscoveryFailed(String serviceType, int errorCode) {
            Log.i(TAG, "onStartDiscoveryFailed--> " + serviceType + ":" + errorCode);
        }
        @Override
        public void onStopDiscoveryFailed(String serviceType, int errorCode) {
            Log.i(TAG, "onStopDiscoveryFailed--> " + serviceType + ":" + errorCode);
        }
        @Override
        public void onDiscoveryStarted(String serviceType) {
            Log.i(TAG, "onDiscoveryStarted--> " + serviceType );
        }
        @Override
        public void onDiscoveryStopped(String serviceType) {
            Log.i(TAG, "onDiscoveryStopped--> " + serviceType );
        }
        @Override
        public void onServiceFound(NsdServiceInfo serviceInfo) {//關鍵的回調方法
            Log.i(TAG, "onServiceFound Info:  " + serviceInfo);
            resoleServer(serviceInfo);
        }
        @Override
        public void onServiceLost(NsdServiceInfo serviceInfo) {
            Log.i(TAG, "onServiceLost--> " + serviceInfo);
            mServiceListener.onServiceLost(serviceInfo);
        }
    }
}

方案二(後臺輔助)

用後臺輔助設備綁定,被控設備向後臺註冊,後臺負責維護設備編號與網絡地址的對應關係,主控設備通過某種途徑獲取到設備編號,然後到後臺查詢其最新的地址。

被控設備的網絡地址端口可能每次啓動不一樣,最新的地址會同步到後臺。

爲防止IP地址變化引起的衝突,被控設備需要增加校驗機制(比如校驗編號),拒絕信息不匹配的請求。

方案三(二維碼輔助)

被控設備顯示二維碼,包含網絡地址信息,主控設備通過掃碼獲取這些信息。

可選的,主控設備主動把設備編號推給被控設備,被控設備立即並且以後每次啓動都用新的編號更新地址。

使用zxing-android-embedded,啓動掃碼:

                IntentIntegrator intentIntegrator = new IntentIntegrator(MainActivity.this);
                intentIntegrator.setCaptureActivity(CaptureActivity.class);
                intentIntegrator.setBeepEnabled(false);
                intentIntegrator.initiateScan();

獲取結果:

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
            IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
            if (result != null) {
                Log.d(TAG, "", result.getContents());
            }
    }

 

服務請求

採用定製推送協議,基於HTTP。

主控設備能夠通過被控設備的地址主動連接被控設備。主控設備可能處於NAT內網,被控設備如果反向連接,需要在路由器上配置端口映射,基於UPNP/IGD可以自動配置端口映射,Android平臺Upnp實現一般基於Cling庫。

 

爲解決 NAT 網絡穿透問題,多端互動傳輸協議的設計要儘量避免反向連接,減少對網絡拓撲的依賴。比如:投屏功能實現中視頻數據的傳輸需要支持推流模式。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章