接入 Android

移动调度中心在 10.1.68 及以上版本基线中提供支持。移动调度中心支持 原生 AAR 接入组件化(Portal&Bundle)接入 两种接入方式。

前置条件

添加移动调度 SDK 依赖

接入 mPaaS 支持以下两种接入方式,您可以根据实际情况进行选择。

  • 原生 AAR 方式

    参考 AAR 组件管理,通过 组件管理(AAR)在工程中安装 移动调度 组件。

  • 组件化(Portal&Bundle)方式

    在 Portal 和 Bundle 工程中通过 组件管理 安装 移动调度 组件。更多信息,请参考 接入流程

使用移动调度 SDK

添加 AndroidManifest 配置

使用 SDK 需要在 AndroidManifest 中添加移动调度中心的 dg 和 host 信息。

<!--配置移动调度中心分组名称-->
<meta-data
android:name="amdc.dg"
android:value="${MDC_DG}" />
<!--host配置为业务的移动调度中心服务域名-->
<meta-data
android:name="amdc.host"
android:value="${IP}" />
<!--可选,用于第一次本地dns缓存被污染情况下的备选IP-->
<meta-data android:name="amdc.backup"
android:value="${IP}" />

调用移动调度中心接口

MPMDC 类提供了所有移动调度中心相关 API,调用移动调度中心接口的操作步骤如下:

  1. mPaaS 框架初始化完成后,在 Application.onCreate 中调用 init 方法初始化 DMC。

    void init(Context context);

    示例如下:

    @Override
    public void onCreate() {
        super.onCreate();
        
        MP.init(this,
            MPInitParam.obtain().setCallback(new MPInitParam.MPCallback() {
                @Override
                public void onInit() {
                    MPMDC.init(App.this);
                }
            })
        );
    }
  2. 获取 IP 信息。

    MPHttpIp getIpsByHost(String host); // 获取对应host的IP信息
    List<MPHttpIp> getAll(); // 获取所有移动调度中心的IP配置信息
    class MPHttpIp {
        public MPHttpIpEntry[] ipEntries; // IP列表
        public String host; // host
        public String ip; //本地IP
    }
    class MPHttpIpEntry {
        public static final int IP_TYPE_V4 = 4;
        public static final int IP_TYPE_V6 = 6;
        public String ip; // IP
        public int port; // 端口
        public int ipType; // IP类型,v4/v6
    }
  3. 设置 UID。移动调度中心内部会根据 UID 来区分数据,提供用户灰度功能。

    MPLogger.setUserId(xxxx);

RPC 开启 MDC 功能

RPC 内部会使用移动调度中心相关配置,并提供 API。业务方基于 RPC 使用 RPC 提供的接口。业务方可以使用 mPaaS 的开关配置动态控制移动调度中心和 IPv6 的开关。

  • 开启移动调度中心开关,RPC 使用移动调度中心配置;关闭移动调度中心开关,RPC 不使用移动调度中心配置。开关默认开启。

    MPRpc.openMGDC(isOpen);

  • 关闭 IPv6 开关,RPC 会过滤掉移动调度中心 IPv6 的 IP,只使用移动调度中心 IPv4 的 IP;开启 IPv6 开关,则 IPv6 和 IPv4 IP 均使用。开关默认关闭。

    MPRpc.openIPV6(isOpen);

单独接入 MDC 示例

通过 IP 完成 Socket 建连

MPHttpIp httpIp = MPHttpIp.getIpsByHost(String host);
MPHttpIpEntry[] ipEntries = httpdnsIP.ipEntries;
String ips = new String[ipEntries.length];
for (int i = 0; i < httpdnsIPEntries.length; i++) {
	ipArr[i] = httpdnsIPEntries[i].ip;
}
//使用socket建连,
//selectAddressIndex 可以根据请求失败情况自行设置index
Socket newSocket = new Socket(Proxy.NO_PROXY);
newSocket.connect(new InetSocketAddress(ips[selectAddressIndex], port));

//通过ip建连后,如果访问https,还需进行ssl建连
//ssl建连,可以参考下方ssl建连参考代码,
//httpUrlConnection和okhttp同样需要设置sslSocketFactory来解决https问题
//获取socketFactory同样可以参考下面代码,均为标准模版代码,可以结合自己项目的情况

//使用httpUrlConnection
URL url = new URL("http://ips[selectAddressIndex]/index.jsp");
//如果是https,需要设置
HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();

//使用okhttp
Request request = new Request.Builder()
                .get()
                .url("http://ips[selectAddressIndex]/index.jsp")
                .build();
OkHttpClient client = new OkHttpClient.Builder()
        	//如果是https,需要设置
            .sslSocketFactory(sslSocketFactory).build();
Call call = client.newCall(request);

通过 SSL 建连

//获取socketFactory
	SSLSocketFactory sslSocketFactory = createZSSLContext().getSocketFactory();

	//ssl握手
	if (sslSocketFactory != null) {
        SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(socket, host, port, true);
        sslSocket.setUseClientMode(true);
        sslSocket.startHandshake();
        Log.d(LOGTAG, "tls socket ssl handshake suc");
        sslSocket.setSoTimeout(0);
        return sslSocket;
	}

	public static final SSLContext createZSSLContext() throws NoSuchAlgorithmException, KeyManagementException {
        final SSLContext sslContext = SSLContext.getInstance("TLS");
        final X509KeyManager x509KeyManagers[] = {createDefaultKeyManager()};
        final X509TrustManager x509TrustManagers[] = {new X509TrustManagerWrapper(createDefaultTrustManager())};
        sslContext.init(x509KeyManagers, x509TrustManagers, new SecureRandom());
        return sslContext;
    }

    public static final X509KeyManager createDefaultKeyManager() throws KeyManagementException {
        try {
            String defaultAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(defaultAlgorithm);
            kmf.init(null, null);
            return findX509KeyManager(kmf.getKeyManagers());
        } catch (NoSuchAlgorithmException e) {
            throw new KeyManagementException(e);
        } catch (UnrecoverableKeyException e) {
            throw new KeyManagementException(e);
        } catch (KeyStoreException e) {
            throw new KeyManagementException(e);
        }
    }

    private static final X509KeyManager findX509KeyManager(KeyManager[] kms) throws KeyManagementException {
        for (KeyManager km : kms) {
            if (km instanceof X509KeyManager) {
                return (X509KeyManager)km;
            }
        }
        throw new KeyManagementException("Failed to find an X509KeyManager in "+ Arrays.toString(kms));
    }


    public static final X509TrustManager createDefaultTrustManager() throws KeyManagementException {
        try {
            String defaultAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(defaultAlgorithm);
            tmf.init((KeyStore)null);
            return findX509TrustManager(tmf.getTrustManagers());
        } catch (NoSuchAlgorithmException e) {
            throw new KeyManagementException(e);
        } catch (KeyStoreException e) {
            throw new KeyManagementException(e);
        }
    }

    private static final X509TrustManager findX509TrustManager(TrustManager tms[]) throws KeyManagementException {
        for (TrustManager tm : tms) {
            if (tm instanceof X509TrustManager) {
                return (X509TrustManager) tm;
            }
        }
        throw new KeyManagementException("Failed to find an X509TrustManager in "+Arrays.toString(tms));
    }

    private static final class X509TrustManagerWrapper implements X509TrustManager {

        private final X509TrustManager x509TrustManager;

        public X509TrustManagerWrapper(X509TrustManager x509TrustManager) {
            this.x509TrustManager = x509TrustManager;
        }

        @Override
        public final void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            x509TrustManager.checkClientTrusted(chain, authType);
        }

        @Override
        public final void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            int size = 0;
            if (chain != null) {
                size = chain.length;
            }
            try {
                x509TrustManager.checkServerTrusted(chain, authType);
            } catch (Throwable e) {
                if (e instanceof CertificateException) {
                    throw (CertificateException) e;
                } else {
                    throw new CertificateException(e);
                }
            }
        }

        @Override
        public final X509Certificate[] getAcceptedIssuers() {
            X509Certificate[] acceptedIssuers = x509TrustManager.getAcceptedIssuers();
            return acceptedIssuers;
        }

    }