37
votes

SDK: Android 5.0.1.

Android build: LRX22C.

Device : Nexus 5.

Problem: KITKAT(4.4.4) and below API's

1) startUsingNetworkFeature(int networkType, String feature) This method is deprecated. Deprecated in favor of the cleaner requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback).

2) requestRouteToHost(int networkType, int hostAddress) This method is deprecated. Deprecated in favor of the requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback), setProcessDefaultNetwork(Network) and getSocketFactory().

were used to send request over Mobile Data Network when WIFI and mobile data were on.

Starting Android L the API's is deprecated and no longer work.

New API's/Classes NetworkRequest.Builder, NetworkRequest, ConnectivityManager.NetworkCallback, requestNetwork, registerNetworkCallback were used. Detail Here on API usage
Android L API's

Code:

ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

NetworkRequest.Builder builder = new NetworkRequest.Builder();

builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);

NetworkRequest networkRequest = builder.build();
connectivityManager.requestNetwork(networkRequest, networkCallback);
connectivityManager.registerNetworkCallback(networkRequest, networkCallback);

Working Scenario:

Only mobile data on onAvailable callback is received.

Not working Scenario: Both Mobile and Wifi is on and connected, onAvailable callback is not received from system. Hence not able to set setProcessDefaultNetwork, ConnectivityManager.setProcessDefaultNetwork(preferedNetwork);

Frequently: Always

Expected output: Get mobile network avaliabe callback when wifi is on.

Am I missing something here or the firmware has some issues here?

ADB Logs:

09-18 18:50:42.617: I/art(1339): Heap transition to ProcessStateJankImperceptible took 64.332086ms saved at least 225KB
09-18 18:50:43.060: I/auditd(16947): type=1400 audit(0.0:899): avc:  denied  { getattr } for  comm="ls" path="/persist" dev="mmcblk0p16" ino=2 scontext=u:r:shell:s0 tcontext=u:object_r:persist_file:s0 tclass=dir
09-18 18:50:43.422: I/ActivityManager(769): START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.networktest/.MainActivity (has extras)} from pid 1149 on display 0
09-18 18:50:43.423: I/am_create_task(769): [0,20]
09-18 18:50:43.423: I/am_create_activity(769): [0,145055245,20,com.example.networktest/.MainActivity,android.intent.action.MAIN,NULL,NULL,270532608]
09-18 18:50:43.424: I/wm_task_created(769): [20,1]
09-18 18:50:43.424: I/wm_task_moved(769): [20,1,2]
09-18 18:50:43.424: I/am_pause_activity(769): [0,613529891,com.google.android.googlequicksearchbox/com.google.android.launcher.GEL]
09-18 18:50:43.442: I/am_destroy_service(769): [0,453570950,2161]
09-18 18:50:43.444: D/audio_hw_primary(200): select_devices: out_snd_device(2: speaker) in_snd_device(0: )
09-18 18:50:43.447: I/am_on_paused_called(1149): [0,com.google.android.launcher.GEL]
09-18 18:50:43.492: I/am_proc_start(769): [0,16964,10091,com.example.networktest,activity,com.example.networktest/.MainActivity]
09-18 18:50:43.492: I/ActivityManager(769): Start proc com.example.networktest for activity com.example.networktest/.MainActivity: pid=16964 uid=10091 gids={50091, 3003}
09-18 18:50:43.497: I/am_create_service(769): [0,565414612,.LightweightIndexService,10009,1339]
09-18 18:50:43.501: I/art(16964): Late-enabling -Xcheck:jni
09-18 18:50:43.522: I/am_proc_bound(769): [0,16964,com.example.networktest]
09-18 18:50:43.524: I/am_restart_activity(769): [0,145055245,20,com.example.networktest/.MainActivity]
09-18 18:50:43.526: I/art(16964): Profiler disabled.  To enable setprop dalvik.vm.profiler 1
09-18 18:50:43.533: I/am_create_service(769): [0,28763261,.LightweightIndexService$LightweightWorkerService,10009,1339]
09-18 18:50:43.536: I/am_destroy_service(769): [0,28763261,1339]
09-18 18:50:43.575: D/ConnectivityService(769): requestNetwork for NetworkRequest [ id=18, legacyType=-1, [ Transports: CELLULAR Capabilities: NOT_RESTRICTED] ]
09-18 18:50:43.575: D/ConnectivityService(769): handleRegisterNetworkRequest checking NetworkAgentInfo [WIFI ()]
09-18 18:50:43.575: D/ConnectivityService(769): sending new NetworkRequest to factories
09-18 18:50:43.575: D/WIFI(769): got request NetworkRequest [ id=18, legacyType=-1, [ Transports: CELLULAR Capabilities: NOT_RESTRICTED] ] with score 0
09-18 18:50:43.575: D/WIFI(769):   my score=60, my filter=[ Transports: WIFI Capabilities: INTERNET&NOT_RESTRICTED LinkUpBandwidth>=1048576Kbps LinkDnBandwidth>=1048576Kbps]
09-18 18:50:43.575: D/Ethernet(769): got request NetworkRequest [ id=18, legacyType=-1, [ Transports: CELLULAR Capabilities: NOT_RESTRICTED] ] with score 0
09-18 18:50:43.575: D/Ethernet(769):   my score=-1, my filter=[ Transports: ETHERNET Capabilities: INTERNET&NOT_RESTRICTED LinkUpBandwidth>=100000Kbps LinkDnBandwidth>=100000Kbps]
09-18 18:50:43.575: D/TelephonyNetworkFactory(1113): got request NetworkRequest [ id=18, legacyType=-1, [ Transports: CELLULAR Capabilities: NOT_RESTRICTED] ] with score 0
09-18 18:50:43.575: D/TelephonyNetworkFactory(1113):   my score=50, my filter=[ Transports: CELLULAR Capabilities: MMS&SUPL&DUN&FOTA&IMS&CBS&IA&RCS&XCAP&EIMS&INTERNET&NOT_RESTRICTED]
09-18 18:50:43.576: D/TelephonyNetworkFactory(1113): Cellular needs Network for NetworkRequest [ id=18, legacyType=-1, [ Transports: CELLULAR Capabilities: NOT_RESTRICTED] ]
09-18 18:50:43.576: D/ConnectivityService(769): listenForNetwork for NetworkRequest [ id=19, legacyType=-1, [ Transports: CELLULAR Capabilities: NOT_RESTRICTED] ]
09-18 18:50:43.577: D/ConnectivityService(769): handleRegisterNetworkRequest checking NetworkAgentInfo [WIFI ()]
09-18 18:50:43.841: I/am_create_service(769): [0,510459843,.EventLoggerService,10022,2161]
09-18 18:50:43.855: I/am_create_service(769): [0,271933548,.GetToken,10009,1339]
09-18 18:50:43.899: I/am_create_service(769): [0,609002555,.GoogleAccountDataService,10009,1339]
09-18 18:50:43.902: W/GLSUser(1339): GoogleAccountDataService.getToken()
09-18 18:50:43.910: I/am_destroy_service(769): [0,609002555,1339]
09-18 18:50:43.914: I/am_destroy_service(769): [0,271933548,1339]
09-18 18:50:43.996: I/sf_frame_dur(197): [com.google.android.googlequicksearchbox/com.google.android.launcher.GEL,89,0,2,0,1,2,1]
09-18 18:50:44.299: I/am_destroy_service(769): [0,510459843,2161]
09-18 18:50:44.760: I/art(16309): Heap transition to ProcessStateJankImperceptible took 6.712188ms saved at least 830KB
09-18 18:50:48.070: I/auditd(17031): type=1400 audit(0.0:900): avc:  denied  { getattr } for  comm="ls" path="/persist" dev="mmcblk0p16" ino=2 scontext=u:r:shell:s0 tcontext=u:object_r:persist_file:s0 tclass=dir
09-18 18:50:48.579: I/am_on_resume_called(16964): [0,com.example.networktest.MainActivity]
09-18 18:50:48.587: D/CanvasContext(16964): Render dirty regions requested: true
09-18 18:50:48.592: I/am_destroy_service(769): [0,565414612,1339]
09-18 18:50:48.597: I/art(2161): Heap transition to ProcessStateJankImperceptible took 109.715785ms saved at least 2MB
09-18 18:50:48.626: W/Adreno-GSL(16964): <ioctl_kgsl_device_getproperty:663>: mmap failed: errno 22 Invalid argument
09-18 18:50:48.626: I/Adreno-EGL(16964): <qeglDrvAPI_eglInitialize:320>: EGL 1.4 QUALCOMM Build: I10246dbd022c719c705be805d5642cc8fdfbd2a2Date: 03/07/14
09-18 18:50:48.626: I/CanvasContext(16964): Initialized EGL, version 1.4
09-18 18:50:48.644: I/art(1149): Heap transition to ProcessStateJankImperceptible took 75.768178ms saved at least 2MB
09-18 18:50:48.644: D/OpenGLRenderer(16964): Enabling debug mode 0
09-18 18:50:48.650: I/art(1252): Heap transition to ProcessStateJankImperceptible took 92.615158ms saved at least 384KB
09-18 18:50:48.688: I/am_activity_launch_time(769): [0,145055245,com.example.networktest/.MainActivity,5230,5230]
09-18 18:50:48.688: I/ActivityManager(769): Displayed com.example.networktest/.MainActivity: +5s230ms
09-18 18:50:48.904: I/sf_frame_dur(197): [Starting com.example.networktest,1,0,0,0,0,0,0]

EDIT: Google bug raised 1 Google bug raised 2 What does "No comment was entered for this change" mean from google?

Thanks

Nithin

2
No,was able to do without that till kitkat.Android L has new API's introduced and it clearly says "You can use the android.net.Network object from the callback to get additional information about the network, or to direct traffic to use the selected network."NitZRobotKoder
@LOG_TAG thats my post but Google is yet to reply.NitZRobotKoder
@NitZRobotKoder OMG :)LOG_TAG
This is also important if the user is connected to a WiFi device (such as a printer) without an internet connection, and needing to use 3G to get to the internetsEionRobb

2 Answers

21
votes

Well finally found solution for this. Trick was to use capability as NET_CAPABILITY_INTERNET. Which is same as startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, FEATURE_ENABLE_HIPRI);

See the Firmware design here

builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);

After this I am able to get onAvailable callback from system and later I set my process default network as mobile data.

Hence all the request goes over mobile data even if wifi is on. WOW!

Note: This was not working in initial releases of Preview L.

Edit 19-10-2015: setProcessDefaultNetwork is now depcreated use bindProcessToNetwork

2
votes

Here's a function that can simplify the action of preferring certain types of networks for your application (should work for any current API level (26 as of writing):

private void alwaysPreferNetworksWith(@NonNull int[] capabilities, @NonNull int[] transportTypes) {

    NetworkRequest.Builder request = new NetworkRequest.Builder();

    // add capabilities
    for (int cap: capabilities) {
        request.addCapability(cap);
    }

    // add transport types
    for (int trans: transportTypes) {
        request.addTransportType(trans);
    }

    final ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(CONNECTIVITY_SERVICE);

    connectivityManager.registerNetworkCallback(request.build(), new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(Network network) {
            try {
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                    ConnectivityManager.setProcessDefaultNetwork(network);
                } else {
                    connectivityManager.bindProcessToNetwork(network);
                }
            } catch (IllegalStateException e) {
                Log.e(TAG, "ConnectivityManager.NetworkCallback.onAvailable: ", e);
            }
        }
    });
}

Usage:

// Add any NetworkCapabilities.NET_CAPABILITY_...
int[] capabilities = new int[]{ NetworkCapabilities.NET_CAPABILITY_INTERNET };

// Add any NetworkCapabilities.TRANSPORT_...
int[] transportTypes = new int[]{ NetworkCapabilities.TRANSPORT_CELLULAR };

alwaysPreferNetworksWith(capabilities, transportTypes);