Friday, July 4, 2014

Fancy Android - Deep look at Android Networking. Part 3 + 2 + 1

http://vnamashko.blogspot.com/2012/05/deep-look-at-android-networking-part-3.html

Deep look at Android Networking. Part 3. Mobile internet.

Mobile internet (GPRS, EDGE, etc) is typically more expensive and slower than internet provided by wlan access points (via wi-fi), but has much greater coverage. Most android devices have mobile internet. It's configured from Settings (Settings->Wireless and network->Mobile Networks):

Since as typical android device has possibility to establish connection to wlan access point (i.e. wi-fi internet connection) and use mobile operator internet (i.e. mobile internet) option to establish 2 internet connection simultaneously theoretical exists. But to dot the i's and cross the t's let's consider typical rules for internet connection, which inherent not just for Android OS, but for most mobile operation systems:
  1. Only one internet connection can be established.
  2. Wi-fi internet has higher priority than mobile internet. 
  3. If wi-fi internet connection is established you will not be able to establish mobile internet connection.
  4. If mobile internet connection is established and you will try establish wi-fi connection, mobile internet connection will be disabled.
This rules are quite logical and make sense. Only one internet connection can be established to save device battery. Wi-fi has higher priority because it's faster and cheaper than mobile internet. And since wi-fi connection has higher priority, points 3 and 4 are quite obvious too. But in case when you need to circumvent these rules you will be faced with serious problems (especially given the fact that the there is no public api in android sdk to manage mobile network connection) and all you remain to do is rely on funny tricks, some of which will be discussed below. But since all this tricks are based on reflection, dirty hacks and hidden api, there is no there is no guarantee, that this will works on your certain device (in my experience, it depends on vendor and device model). Furthermore, I don't recommend you to use this things in your production application, they are (this tricks) interesting only for experiments.

So, let's start from permissions essential for these experiments:
   <uses-permission android:name="android.permission.INTERNET"/>  
   <uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>  
   <uses-permission android:name="android.permission.WRITE_APN_SETTINGS"/>  
   <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>  
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
   <uses-permission android:name="android.permission.WRITE_SETTINGS"/>  

Next moment - we need to enable mobile data connection. It should be noted, that this operation a little bit differently performed for old and for new sdk version. For sdk 2.1 and earlier you should do something like this:
   private void setDataConnection(boolean dataConnection) {  
     Method dataConnSwitchMethod;  
     Class telephonyManagerClass;  
     Object ITelephonyStub;  
     Class ITelephonyClass;  
     TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);  
     try {  
       telephonyManagerClass = Class.forName(telephonyManager.getClass().getName());  
       Method getITelephonyMethod = telephonyManagerClass.getDeclaredMethod("getITelephony");  
       getITelephonyMethod.setAccessible(true);  
       ITelephonyStub = getITelephonyMethod.invoke(telephonyManager);  
       ITelephonyClass = Class.forName(ITelephonyStub.getClass().getName());  
       String invokeMethodName = dataConnection ? "enableDataConnectivity" : "disableDataConnectivity";  
       Log.d(TAG, invokeMethodName);  
       dataConnSwitchMethod = ITelephonyClass.getDeclaredMethod(invokeMethodName);  
       dataConnSwitchMethod.setAccessible(true);  
       dataConnSwitchMethod.invoke(ITelephonyStub);  
     } catch (Exception e) {  
       Log.e(TAG, e.getMessage());  
     }  
   }  

As you can see, we are getting ITelephony aidl interface to enable or disable mobile data connections:
   /**  
    * Allow mobile data connections.  
    */  
   boolean enableDataConnectivity();  
   /**  
    * Disallow mobile data connections.  
    */  
   boolean disableDataConnectivity();  

Starting from sdk 2.2 you can use the IConnectivityManager#setMobileDataEnabled method. It's hidden in API too, so we have to use reflection again:
   private void setMobileDataEnabled(boolean dataConnection) {  
     try {  
       final ConnectivityManager conman = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);  
       final Class conmanClass = Class.forName(conman.getClass().getName());  
       final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService");  
       iConnectivityManagerField.setAccessible(true);  
       final Object iConnectivityManager = iConnectivityManagerField.get(conman);  
       final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());  
       final Method setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);  
       setMobileDataEnabledMethod.setAccessible(true);  
       setMobileDataEnabledMethod.invoke(iConnectivityManager, dataConnection);  
     } catch (Exception e) {  
       ...  
     }  
   }  

On some devices this operation requires android.permission.WRITE_SECURE_SETTINGS, which maybe granted only for system applications, so for such cases all next tricks will have no any sense. Only thing you can do - root your device and install app to /system folder (using adb shell push app.apk /system command).

So, after mobile data connection is enabled, we will try add APN we want to use:
   private static final Uri APN_TABLE_URI = Uri.parse("content://telephony/carriers");  
   public static final String OPERATOR_NUMERIC_KEY = "gsm.sim.operator.numeric";  
   
   public int addAPN() {  
     int id = -1;  
     ContentResolver resolver = getContentResolver();  
     ContentValues values = new ContentValues();  
     values.put("name", appName);  
     values.put("apn", accessPointName);  
     values.put("user", userName);  
     values.put("password", password);  
     // read mobile operator numeric info using shell command getprop  
     String numeric = getSystemProperty(OPERATOR_NUMERIC_KEY);  
     String mcc = "";  
     String mnc = "";  
     try {  
       mcc = numeric.substring(0, 3);  
       mnc = numeric.substring(3, 5);  
     } catch (Exception e) {  
       ...  
     }  
     values.put("mcc", mcc);  
     values.put("mnc", mnc);  
     values.put("numeric", numeric);  
     Cursor cursor = null;  
     try {  
       // insert apn  
       Uri newRow = resolver.insert(APN_TABLE_URI, values);  
       if (null != newRow) {  
         cursor = resolver.query(newRow, null, null, null, null);  
         Log.d(TAG, "Newly added APN:");  
         // Obtain the apn id  
         int idIndex = cursor.getColumnIndex("_id");  
         cursor.moveToFirst();  
         id = cursor.getShort(idIndex);  
         Log.d(TAG, "New ID: " + id + ": Inserting new APN succeeded!");  
       }  
     }  
     catch (Exception e) {  
       Log.d(TAG, e.getMessage());  
     }  
     if (null != cursor) {  
       cursor.close();  
     }  
     return id;  
   }  
   
   ...
   public static String getSystemProperty(String key) {
        try {
            String line;
            String formattedKey = "[" + key + ']';
            java.lang.Process p = Runtime.getRuntime().exec("getprop");
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            while (null != (line = input.readLine())) {
                String[] property = line.split(":");
                if (formattedKey.equals(property[0].trim())) {
                    return property[1].trim().substring(1, property[1].length() - 2);
                }
            }
            input.close();
        }
        catch (Exception err) {
            err.printStackTrace();
        }

        return null;
    }

I think all is obvious here.  ContentResolver is used to access table of system APNs. The only thing that deserves attention here is 
            
     // read mobile operator numeric info using shell command getprop
     String numeric = getSystemProperty(OPERATOR_NUMERIC_KEY);  

We are extracting system property gsm.sim.operator.numeric and parsing result to get Mobile Network Code (mnc) and Mobile Country Code (mcc) - these values are essential for APN.

Now we need to set our inserted APN to be default. From user interface it's looks like to select appropriate radio button on list of available APNs.


Let's take a look how can we do this programmatically:

   private static final Uri PREFERRED_APN_URI = Uri.parse("content://telephony/carriers/preferapn");  

   public boolean setActiveAPN(int id) {  
     boolean result = false;  
     ContentResolver resolver = getContentResolver();  
     ContentValues values = new ContentValues();  
     values.put("apn_id", id);  
     try {  
       resolver.update(PREFERRED_APN_URI, values, null, null);  
       Cursor cursor = resolver.query(  
           PREFERRED_APN_URI,  
           new String[]{"name", "apn"},  
           "_id=" + id,  
           null,  
           null);  
       if (null != cursor) {  
         result = true;  
         cursor.close();  
       }  
     }  
     catch (Exception e) {  
       Log.d(TAG, e.getMessage());  
     }  
     return result;  
   }  

To setActiveAPN method we need to pass id. We can use identifier of APN, created by addAPN function or any other existed APN.

So, now, after mobile connection is enabled and you add APN and made it default you device will try to establish connection (of course, there should not be wi-fi connection). If you provide correct APN your device will have mobile internet after your credential will be verified.

But there is one more trick I want to show. It allow to raise mobile connection even with wifi connected. ConnectivityManager#startUsingNetworkFeature method is used to request network for you application. You need to specify which network the request pertains to (first param) and the name of the feature to be used (second param). Typical request will looks like:
    connectivityManager.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI");

This means, that you want to enable High Priority (HIPRI) Mobile data connection over mobile network. More about first argument you can read in documentation to ConnectivityManager. List of available features you can found in internal interface Phone:
   // "Features" accessible through the connectivity manager  
   static final String FEATURE_ENABLE_MMS = "enableMMS";  
   static final String FEATURE_ENABLE_SUPL = "enableSUPL";  
   static final String FEATURE_ENABLE_DUN = "enableDUN";  
   static final String FEATURE_ENABLE_HIPRI = "enableHIPRI";  
   static final String FEATURE_ENABLE_DUN_ALWAYS = "enableDUNAlways";  
   static final String FEATURE_ENABLE_FOTA = "enableFOTA";  
   static final String FEATURE_ENABLE_IMS = "enableIMS";  
   static final String FEATURE_ENABLE_CBS = "enableCBS";  

But you need to remember, that all requested network features are active only when your application is 'alive' (i.e. not stopped or killed by system). 

2 comments:

  1. This is great!

    I had a few question though
    1) do you know of a good link that describes what each of the different features do? such as "enableSUPL", "enableDUN", "enableDUNAlways", "enableFOTA", enableIMS", and "enableCBS" or could you explain?

    2) Also, I want to turn off (disable) wifi and turn on telephony. Would I use the setMobileDataEnabled function or startUsingNetworkFeature? if the second, i really don't know which feature to choose.

    Thanks for any advice!
    Reply
  2. Hi,

    1) I wasn't able to find detailed explanation of these features, so I have only intuitive understanding. For example, "enableSUPL": SUPL is Secure User-Plane Location, i.e. enable Assisted-GPS (A-GPS) capability for your device. "enableIMS": IMS means IP Multimedia Subsystem - a 3G and NGN (Next Generation Network) subsystem, which is used for several operators and services providers to bring IP multimedia services to your android device - such us VoIP (voice over ip), Presence, Push to Talk, etc. Android has basic support of these service (which can be extended by third party libs), etc. So, the goal of this features is to restrict allowed for transfer content.

    2) I guess you should 'setMobileDataEnabled' for true first and then use 'startUsingNetworkFeature'. At least I did so. For 'startUsingNetworkFeature' I reccomend you to use TYPE_MOBILE as network type and aneble high priority internet connection ("enableHIPRI") as network feature. Please, be aware, that 'startUsingNetworkFeature' request network feature for limited time (as far as i remember, default value is one minute). You can request feature again every 30 seconds (to avoid disconnects) or use http://developer.android.com/reference/java/lang/System.html#setProperty(java.lang.String,+java.lang.String): key name is "android.telephony.apn-restore" - timeout in ms.

    Hope this helps.
     ''''''''''''''''''''''''''''''''''

     http://vnamashko.blogspot.com/2012/05/deep-look-at-android-networking-part-2.html

    Deep look at Android Networking. Part 2. Wi-fi.

    Almost every android device has wi-fi module to exchange data wirelessly and provide quick and cheap internet. This technology is very popular nowadays so I think every internet user is superficially acquainted with it. We just need to remember, that all low-level wi-fi stuff is encapsulated to be accessed through supplicant. In Android SDK Wi-Fi API provides a facet' for applications to communicate with the lower-level wireless stack. With Wi-Fi API your application can get information about available networks (plus connected network speed), add wlan network description to the set of configured networks, terminate and initiate wi-fi connections and some other stuff.
    Let's start from simple example, which actually not used wi-fi api: define, is wi-fi network connected:
         public static boolean isWifiAvailable() {  
             ConnectivityManager mgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);  
             if(mgr == null) {  
                 return false;  
             }  
             NetworkInfo wifi = mgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);  
             return wifi != null && wifi.isConnected();  
       }  
    
    As you can see, we are using ConnectivityManager to get information about wi-fi network. Quite often (when your application downloads a lot of data from internet) it may be essential to perform network operations (such as downloading content) only through wlan networks. To do that we can simply use utility function to check is wlan network available:
         public static boolean canDownload() {  
             return !mIsWifiRequired || isWifiAvailable();  
         }  
    
    As for wi-fi api - key object here is WifiManager. It is well described in the documentation, so let's not pay much attention to it and focus on real problems.
    Android broadcasts a lot of information about changes of network state which may be interesting for our application. WifiManager has a few constants which represent intent actions related to network state events. For example, if we will 'subscribe' on WIFI_STATE_CHANGED_ACTION we will receive notifications when wi-fi has been enabled, disabled, enabling, disabling or unknown. Information about previous wi-fi state will be received too:
         NetworkStateBroadcastReciver networkStateBroadcastReciver = new NetworkStateBroadcastReciver();  
         IntentFilter networkStateFilter = new IntentFilter();  
         networkStateFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);  
         context.registerReceiver(networkStateBroadcastReciver, networkStateFilter);  
         
    
         class NetworkStateBroadcastReciver extends BroadcastReceiver {  
             public void onReceive(Context c, Intent intent) {  
                 int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);    
             
                 int wifiPrevState = intent.getIntExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);    
                 ...  
             }
         }  
    
    You can get much more notifications when 'subscribing' on SUPPLICANT_STATE_CHANGED_ACTION - start scanning for wi-fi networks, start authentication on wlan access point, etc. (for more information take a look on SupplicantState).
    'Subscribing' on SCAN_RESULTS_AVAILABLE_ACTION you will get list of available (found by WifiManager.html#startScan method) wlan access points.
    Another possible feature, which, I think, is rarely used - manually adding of access points (i.e. not using result of scanning). But those of you who needs to use this option will be disappointed due to serious limitation of this operation - you can only 'configure' access points WEP and WPA-PSK encryption scheme (and points w.o. encryption too), which is a little bit unpleasantly, since from Setting it's possible to add wi-fi networks with EAP authentication (such as EAP-TLS).
    Here is example how to configure Open, WEP and WPA-PSK points:
       WifiConfiguration wifiConfiguration = new WifiConfiguration();      
       wifiConfiguration.SSID = ssid;  
       wifiConfiguration.status = WifiConfiguration.Status.ENABLED;  
       wifiConfiguration.priority = 1;  
       
       ...  
    
       int addOpenNetwork(WifiConfiguration configuration) {  
         configureOpenNetwork(configuration);  
         return wifi.addNetwork(configuration);  
       }  
       
       private void configureOpenNetwork(WifiConfiguration configuration) {  
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);  
         configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);  
         configuration.allowedProtocols.set(WifiConfiguration.Protocol.WPA);  
         configuration.allowedAuthAlgorithms.clear();  
         configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);  
         configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);  
         configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);  
         configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);  
         configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);  
         configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);  
       }  
       
       int addWEPNetwork(WifiConfiguration configuration, String password) {  
         configureWEPNetwork(configuration, password);  
         return wifi.addNetwork(configuration);  
       }  
       
       private void configureWEPNetwork(WifiConfiguration configuration, String password) {  
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);  
         configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);  
         configuration.allowedProtocols.set(WifiConfiguration.Protocol.WPA);  
         configuration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);  
         configuration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);  
         configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);  
         configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);  
         configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);  
         configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);  
         configuration.wepKeys[0] = "\"".concat(password).concat("\"");  
         configuration.wepTxKeyIndex = 0;  
       }  
       
       int addWPANetwork(WifiConfiguration configuration, String password) {  
         configureWPANetwork(configuration, password);  
         return wifi.addNetwork(configuration);  
       }  
       
       private void configureWPANetwork(WifiConfiguration configuration, String password) {  
         configuration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);  
         configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);  
         configuration.allowedProtocols.set(WifiConfiguration.Protocol.WPA);  
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);  
         configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);  
         configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);  
         configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);  
         configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);  
         configuration.preSharedKey = "\"".concat(password).concat("\"");  
       }  
    
    After wi-fi networks were configured networks you need to call WifiManager#saveConfiguration. Sometimes this method will return false and in logs (logcat) you will see something like 'wpa supplicant is busy or not responding'. Don't worry, just call this method again after some timeout (you can use WifiManager#pingSupplicant to check supplicant availability). The last step in manual 'wi-fi configuration' is WifiManager#enableNetwork method, which you need to provide with identifier of network you want connect too.
     '''''''''''''''''''''''''''''''''''''''''''

     http://vnamashko.blogspot.com/2012/04/deep-look-at-android-networking-part-1.html

    Deep look at Android Networking. Part 1. Introduction.

    Most modern applications are actively using internet to interact with outer world. Internet has become an integral part of mobile development. Android OS is based on the Linux kernel and contains mighty set of networking capabilities inherent from it lower layer.
    This topic is not about application layer of network stack. Examples about how to get content of some url or download file can be easily found in internet (including android developers). Purpose of the topic is to consider basic points of network stack in context of android and java.
    Lets start from Network Interface - point of interconnection between a your device and a private or public network. It's generally a network interface card (NIC), but doesn't have to have a physical form - network interface can be implemented in software layer. For example, every android device (even when wifi is disabled and no mobile network configured) has the loopback interface (127.0.0.1 for IPv4 and ::1 for IPv6) - it's not a physical device but a piece of software which simulating a network interface.
    To get list of available interfaces use NetworkInterface#getNetworkInterfaces:
     NetworkInterface.getNetworkInterfaces()  
    
    Width disabled wifi and mobile connection you will typically get only one network interface - loopback interface lo0. NetworkInterface doesn't provide any particular information about network interface card (NIC) which it represents (however, it is worth noting that since sdk 9 a few additional method were added). Only things you can get - local name of interface and assigned ip address (like pdo0 and 46.133.18.123). Considering fact that only 'raised' interface will be found by NetworkInterface#getNetworkInterfaces it's hard to find any practical use of NetworkInterface (it can't be used to figure out connected or interface which performs data transmission or to check metric of interface) - it's interesting only in theoretical context (it's must less functional than NetworkInterface from java SE sdk).
    Unfortunately, android shell (adb shell) doen't provide all linux network commands (like ifconfig). But even supported commands, like, netcfg, not always works like expected. For example, with enabled (and connected wifi) we will see:
    $ netcfg
    lo       UP    127.0.0.1       255.0.0.0       0x00000049
    usb0     DOWN  0.0.0.0         0.0.0.0         0x00001002
    tunl0    DOWN  0.0.0.0         0.0.0.0         0x00000080
    gre0     DOWN  0.0.0.0         0.0.0.0         0x00000080
    sit0     DOWN  0.0.0.0         0.0.0.0         0x00000080
    svnet0   UP    0.0.0.0         0.0.0.0         0x000000d1
    eth0     UP    192.168.100.163 255.255.255.0   0x00001043
    
    while with wifi disabled:
    $ netcfg
    lo       UP    127.0.0.1       255.0.0.0       0x00000049
    usb0     DOWN  0.0.0.0         0.0.0.0         0x00001002
    tunl0    DOWN  0.0.0.0         0.0.0.0         0x00000080
    gre0     DOWN  0.0.0.0         0.0.0.0         0x00000080
    sit0     DOWN  0.0.0.0         0.0.0.0         0x00000080
    svnet0   UP    0.0.0.0         0.0.0.0         0x000000d1
    
    So, we can see the same problem that we had for NetworkInterface - disabled interface not found.
    Let's try to understand why.
    Here is what we can see (in logcat) when we try to enable wifi on device with wifi disabled:
    I/WifiHW  ( 3643): [WIFI] Load Driver
    I/WifiHW  ( 3643): [WiFi.c] insmod() Start!! 
    I/WifiHW  ( 3643): [WiFi.c] start init_module() Start!! 
    I/WifiHW  ( 3643): [WIFI] DRIVER OK
    I/WifiHW  ( 3643): wifi_start_supplicant: Enter
    D/WifiHW  ( 3643): /data/wifi/bcm_supp.conf exits
    E/WifiHW  ( 3643): wifi_start_supplicant: pi->serial=117440528, serial=0
    I/WifiHW  ( 3643): wifi_start_supplicant: Exit. supp_status=running
    ...
    
    end when wifi is enabled and connected and we are disabling it:
    I/WifiHW  ( 3643): wifi_stop_supplicant: Enter
    I/WifiHW  ( 3643): wifi_stop_supplicant: connecting supplicant is done
    I/WifiHW  ( 3643): wifi_stop_supplicant: status of  supplicant(connected), count(49) 
    I/wpa_supplicant( 5070): CTRL-EVENT-TERMINATING - signal 15 received
    I/wpa_supplicant( 5070): CTRL-EVENT-TERMINATING - signal 0 received
    I/WifiHW  ( 3643): wifi_stop_supplicant: exit normally
    D/WifiStateTracker( 3643): Reset connections and stopping DHCP
    I/WifiHW  ( 3643): wifi_close_supplicant_connection: enter
    I/WifiHW  ( 3643): wifi_close_supplicant_connection: exit
    ...
    I/WifiHW  ( 3643): wifi_unload_driver: enter
    ...
    E/WifiHW  ( 3643): [WIFI] Unload Driver
    I/WifiHW  ( 3643): wifi_unload_driver: exit
    
    What we have here? Assuming that WifiHW tag is used to mark operations related to wifi stuff (quite logical assumption) we can see, that in wifi disabled state not just supplicant is 'stopped', but even wifi driver is unloaded (insmod is used to load it). Otherwise, supplicant received signal 15 (termination signal) and then wifi driver is unloaded. Please note once again: all this assumptions are based on logs of devices.
    What does this tell us? This tells us, that Android is quite smart and economical (at least battery) system ... and that most like we not able to write application to monitor network interfaces (at least list all of them) of our device - when NIC is not used it's 'unloaded' from system. As far as you know, it's not possible to keep 2 network connections (wifi and mobile) raised in simultaneously (w.o. some funny tricks i'm going to show later in next topics) - system will disable mobile connection when wifi is connected. Obviously, this is correct behavior - save your battery and save your money (mobile internet sometimes very expensive). So that's why, apparently, we are not able to get all out network interfaces using sdk api.
    Also we are not able to manage our network interfaces with this basic api. Fortunately Android sdk provides WifiManager to help us with wifi stuff. A bit more complicated to work with mobile networks (but possible). And finally vpn api is introduced in sdk 14. I'm going to talk about these things in the next few chapters.


Programmatically Toggle Background Data

Not the auto sync but the background data altogether.

Optionally you can write your own code to do the same.

Either the same way as the "Settings" app (in ICS/JB) does it:

import android.app.Fragment
import android.content.Context;
import android.net.NetworkPolicyManager;
import android.os.Bundle;

public class MyClass extends Fragment {
    private NetworkPolicyManager mPolicyManager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Context context = getActivity();
        mPolicyManager = NetworkPolicyManager.from(context);
    }
   
    private void myFunction(boolean restrictBackground) {
        mPolicyManager.setRestrictBackground(restrictBackground);
    }
}
Or the way the "Secure Settings" plugin does it:

import android.net.IConnectivityManager;
import android.net.IConnectivityManager$Stub;
import android.net.INetworkPolicyManager;
import android.net.INetworkPolicyManager$Stub;
import android.os.IBinder;
import android.os.ServiceManager;

public class MyClass {

    // pre ICS method
    private void myFunction1() {
        IBinder svc = ServiceManager.getService("connectivity");
        IConnectivityManager connectivityManager = IConnectivityManager$Stub.asInterface(svc);
        connectivityManager.setBackgroundDataSetting(false);
    }
   
    // ICS+ method
    private void myFunction2() {
        IBinder svc = ServiceManager.getService("netpolicy");
        INetworkPolicyManager policyManager = INetworkPolicyManager$Stub.asInterface(svc);
        policyManager.setRestrictBackground(false);
    }
}

The latter is just a proof-of-concept, not working code. Since the two methods (myFunction1 and myFunction2) should be applied on an as-needed basis, you should wrap both with the Java Reflection API (ie. use extensive exception handling and call the respective methods dynamically ... and of course handle the case if the methods do not exist on the given Android device). Both approaches use undocumented functions (ie. not described in the official API documentation at https://developer.android.com/reference/ ), so your implementation might break in any future Android versions (but again ... using only public API functions does not guarantee backwards compatibility either ... they can and do change all the time :-) ).

source: https://groups.google.com/forum/#!msg/tasker/vBUNvqNhJeM/fxjq3VZraeAJ

Tuesday, December 10, 2013

How to access Learning Hub in Galaxy Note GT-N5100

After crawling the internet for hours, I choose these solutions that worked for me.

For Non-rooted Device

Cant open learning hub
http://forum.xda-developers.com/showthread.php?p=34841720


For Rooted Device

I found a way to make it work...
1 - Root.
2 - I used Triangle away.
3 - I installed superuser from the play store on my phone.
4 - Then, go to superSu app -> SETTINGS -> Switch superuser app.
5 - Try Learning hub and readers hub, it should work.
6 - If it works you can reinstall SuperSu (I had to wait around 20-25 minutes and then I was able to reinstall SuperSu from the play store) and uninstall superuser

source: http://forum.xda-developers.com/showthread.php?p=35910349

Saturday, August 17, 2013

Sims Freeplay stops working at startup

I downloaded Sims FreePlay (+307 MB) and tried to run for the first time.But the game never started successfully.
Here is how it happened in my Huawei U8825d Android phone.

Photo(a-d) - stages of game loading



Photo(1) - AIDE output of the game as much as it can capture in the game's process filter



Photo(2) - my Android device information