37

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

fawaad
  • 341
  • 6
  • 12
NitZRobotKoder
  • 1,046
  • 8
  • 44
  • 74
  • You can try asking for the permission that allows you to turn off WiFi and ask the user if it is ok to do so? – BVB Oct 07 '14 at 03:15
  • 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 Oct 07 '14 at 05:12
  • 1
    @BVB https://developer.android.com/preview/api-overview.html#Wireless – NitZRobotKoder Oct 07 '14 at 05:12
  • What happens if you add connectivityManager.setNetworkPreference(TYPE_MOBILE) before you requestNetwork? It's not depricated yet even tho it will be soon. – Adam Wigren Oct 07 '14 at 06:01
  • @AdamWigren didnt help.Still think API's are not stable yet. – NitZRobotKoder Oct 10 '14 at 14:06
  • 1
    @LOG_TAG thats my post but Google is yet to reply. – NitZRobotKoder Oct 10 '14 at 14:06
  • 2
    @NitZRobotKoder OMG :) – LOG_TAG Oct 13 '14 at 03:32
  • How are you initializing networkCallback? I was able to get a callback but my setProcessDefaultNetwork is not working once I get that network back. I am trying to do the opposite, ensure it routes through WiFi even when there is no connectivity. – Flyview Nov 18 '14 at 21:25
  • my phones have metered data and they default to wifi when it is available. – danny117 Dec 04 '14 at 20:46
  • @Flyview" it routes through WiFi even when there is no connectivity" wHAT DO YOU MEAN? – NitZRobotKoder Feb 02 '15 at 06:42
  • @CommonsWare any inputs here ? Google does not reply too https://mailqa-cn.ihg.com/over-code.google.com/p/android/issues/detail?id=100849 – NitZRobotKoder Feb 02 '15 at 06:57
  • What I mean is I was trying to make sure internet requests were going through the WiFi connection, even if Android decides there is no good internet connection. Starting with Lollipop, if this is the case, Lollipop will automatically route network traffic over the data connection, even if WiFi is connected. – Flyview Feb 05 '15 at 00:10
  • @Flyview AFAIK if wifi is connected and can send packets out, android system wont use Cellular data to send out any request.Assuming you have not done any network request like above. – NitZRobotKoder Feb 05 '15 at 10:02
  • @NitZRobotKoder try these threads: http://stackoverflow.com/questions/3841317/how-to-see-if-wifi-is-connected-in-android, http://stackoverflow.com/questions/16577939/how-to-check-if-wifi-is-really-connected-in-android to see if WIFI is on – Haring10 Feb 12 '15 at 05:33
  • I'm sure you have a reason for trying this out but the first thing that comes to my mind is WHY?! The opposite seems reasonable if you want to download larger files or provide better user experience through a faster connection. Besides the fact that an app in my opinion could never determain 'where' the data is coming from, a lot of times I use my phone as hotspot for phones, tablet and PC's. – Tom Hofman Feb 12 '15 at 09:30
  • 1
    You'll see _"No comment was entered for this change"_ if a change was made to the issue (for example: priority changed, owner changed, status changed) but no comment was left. – David Wasser Feb 12 '15 at 10:05
  • According to our tests, on some Sony Xperia devices (Android 4.0.3, 4.1.2) requestRouteToHost did not work. It was messing with routing table and broke internet connection in general - restart was required.. Eventually, we've given up this idea and returned back to popup solution. – Zbigniew Malinowski Feb 12 '15 at 13:52
  • @JoshHarington will not server my purpose, if wifi connected i cant get mobile data state. – NitZRobotKoder Feb 13 '15 at 06:17
  • 1
    @TomHofman take a scenario where you are connected to weak wifi connection, want user to have option to use cellular data always. – NitZRobotKoder Feb 13 '15 at 06:19
  • @ZbigniewMalinowski Well the design on 4.4 and below works well on Samsung, LG,Moto,HTC ,Kyocera and many more for us.Not tested on Sony :) – NitZRobotKoder Feb 13 '15 at 06:21
  • @NitZRobotKoder I thought of that scenario but: "How is an app going to figure out if a weak, unreliable wifi connection is worth the trouble vs. mobile data." Considerations: a user already used his data bundle and would be charged otherwise, a user does not even have a data bundle, the user is trying to test the apps low-connectivity performance. I'd rather see a notification/alert if you require a better connection, but what is the threshold? – Tom Hofman Feb 13 '15 at 14:16
  • If the user wants to use only mobile data because their WiFi signal is too weak they have the option of turning off WiFi. – Dave S Feb 24 '15 at 00:41
  • 2
    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 internets – EionRobb Mar 11 '15 at 20:26

2 Answers2

21

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

fawaad
  • 341
  • 6
  • 12
NitZRobotKoder
  • 1,046
  • 8
  • 44
  • 74
  • 1
    How can you rollback to the default mode after you finished transmitting your data? @NitZRobotKoder – lyc001 Oct 16 '15 at 09:24
  • 2
    @lyc001 My answer itself is deprecated..See setProcessDefaultNetwork http://developer.android.com/reference/android/net/ConnectivityManager.html#bindProcessToNetwork(android.net.Network) How i did rollback was using below. ConnectivityManager.setProcessDefaultNetwork(null); or releaseNetworkRequest http://developer.android.com/reference/android/net/ConnectivityManager.html#releaseNetworkRequest(android.app.PendingIntent) – NitZRobotKoder Oct 19 '15 at 06:51
  • How to release the preference once my work done in mobile data ? Is there way to reset ? – Vinoth K Jun 26 '18 at 10:19
2

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);
leggetter
  • 15,248
  • 1
  • 55
  • 61
eskimwier
  • 1,037
  • 13
  • 16