如何 choose/enforce 在 Android 上使用移动数据(或 wifi)进行网络通话?

How to choose/enforce using mobile data (or wifi) for network calls on Android?

我有一个疯狂的用户案例,要求仅通过移动数据 (SIM) 调用某些 REST 服务。 我们想通过 wifi 发送其余数据。

是否可以在Android上强制通过哪种网络发送数据?

是否可以在同一个应用程序和同一个会话中通过移动数据发送一些数据并通过 wifi 发送其他数据?

此外,测试呼叫是否通过正确的网络类型发送的最佳方法是什么?

您可以使用 ConnectivityManager 检查可用的网络类型,如果 wifi 已连接,请调用您的 api 否则向用户显示对话框以通知他此 api 需要打开 wifi 或相反。 .

您可以使用连接 class 检查网络

public class Connectivity {

public static NetworkInfo getNetworkInfo(Context context){
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    return cm.getActiveNetworkInfo();
}


public static boolean isConnected(Context context){
    NetworkInfo info = Connectivity.getNetworkInfo(context);
    return (info != null && info.isConnected());
}

public static boolean isConnectedWifi(Context context){
    NetworkInfo info = Connectivity.getNetworkInfo(context);
    return (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_WIFI);
}

public static boolean isConnectedMobile(Context context){
    NetworkInfo info = Connectivity.getNetworkInfo(context);
    return (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_MOBILE);
}

public static boolean isConnectedFast(Context context){
    NetworkInfo info = Connectivity.getNetworkInfo(context);
    return (info != null && info.isConnected() && Connectivity.isConnectionFast(info.getType(),info.getSubtype()));
}

public static boolean isConnectionFast(int type, int subType){
    if(type==ConnectivityManager.TYPE_WIFI){
        return true;
    }else if(type==ConnectivityManager.TYPE_MOBILE){
        switch(subType){
        case TelephonyManager.NETWORK_TYPE_1xRTT:
            return false; // ~ 50-100 kbps
        case TelephonyManager.NETWORK_TYPE_CDMA:
            return false; // ~ 14-64 kbps
        case TelephonyManager.NETWORK_TYPE_EDGE:
            return false; // ~ 50-100 kbps
        case TelephonyManager.NETWORK_TYPE_EVDO_0:
            return true; // ~ 400-1000 kbps
        case TelephonyManager.NETWORK_TYPE_EVDO_A:
            return true; // ~ 600-1400 kbps
        case TelephonyManager.NETWORK_TYPE_GPRS:
            return false; // ~ 100 kbps
        case TelephonyManager.NETWORK_TYPE_HSDPA:
            return true; // ~ 2-14 Mbps
        case TelephonyManager.NETWORK_TYPE_HSPA:
            return true; // ~ 700-1700 kbps
        case TelephonyManager.NETWORK_TYPE_HSUPA:
            return true; // ~ 1-23 Mbps
        case TelephonyManager.NETWORK_TYPE_UMTS:
            return true; // ~ 400-7000 kbps
        /*
         * Above API level 7, make sure to set android:targetSdkVersion 
         * to appropriate level to use these
         */
        case TelephonyManager.NETWORK_TYPE_EHRPD: // API level 11 
            return true; // ~ 1-2 Mbps
        case TelephonyManager.NETWORK_TYPE_EVDO_B: // API level 9
            return true; // ~ 5 Mbps
        case TelephonyManager.NETWORK_TYPE_HSPAP: // API level 13
            return true; // ~ 10-20 Mbps
        case TelephonyManager.NETWORK_TYPE_IDEN: // API level 8
            return false; // ~25 kbps 
        case TelephonyManager.NETWORK_TYPE_LTE: // API level 11
            return true; // ~ 10+ Mbps
        // Unknown
        case TelephonyManager.NETWORK_TYPE_UNKNOWN:
        default:
            return false;
        }
    }else{
        return false;
    }
}

}

检查可用的网络类型

if (isConnectedWifi(ctx) {
        // Call api
    }else if (isConnectedMobile(ctx)){
       // Show dialog to user to inform him that this api required open wifi
    }else{
       //
    }

我的使用:

@TargetApi(21)
private fun getMobileNetWork() {
    connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val builder = NetworkRequest.Builder()
    builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)//TRANSPORT_WIFI
    val build = builder.build()
    connectivityManager!!.requestNetwork(build, networkCallback)
}


val networkCallback = object : ConnectivityManager.NetworkCallback() {
    override fun onAvailable(network: Network) {
        super.onAvailable(network)
        //Use the network to do your thing
    }

    override fun onLost(network: Network?) {
        super.onLost(network)
    }
    override fun onUnavailable() {
        super.onUnavailable()
    }
}

okhttp3中的网络使用情况:

    val builder = OkHttpClient.Builder()
            .connectTimeout(15L, TimeUnit.SECONDS)
            .readTimeout(20L, TimeUnit.SECONDS)
            .writeTimeout(15L, TimeUnit.SECONDS)
            .socketFactory(network.socketFactory)
            .dns {
                network.getAllByName(it).asList()
            }