Monday, February 27, 2012

Android: Enable/Disable 3G programmatically


Here we go again,

Hint: this post will be just a wrap up to what you can find here.

Unfortunately, the data-connection enable/disable APIs are not exposed to the user, So we'll access them using JAVA reflection.

Starting from API level 8 (platform 2.2) we can use the following snippet:

 final ConnectivityManager conman =   
    (ConnectivityManager) context.getSystemService(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);   
      
 // (true) to enable 3G; (false) to disable it.   
 setMobileDataEnabledMethod.invoke(iConnectivityManager, true);   

We need to add the following permission to the manifest file

 <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>  

Hint: the previous piece of code was tested on SAMSUNG GALAXY SII API level 9(platform 2.3).

Ok, now I'll post another snippet that I got it working on the emulator for APIs levels prior to (8):

 Method dataConnSwitchmethod;  
 Class telephonyManagerClass;  
 Object ITelephonyStub;  
 Class ITelephonyClass;  
    
 TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);  
    
 if(telephonyManager.getDataState() == TelephonyManager.DATA_CONNECTED){  
    isEnabled = true;  
 }else{  
    isEnabled = false;  
 }  
    
 telephonyManagerClass = Class.forName(telephonyManager.getClass().getName());  
    
 Method getITelephonyMethod = telephonyManagerClass.getDeclaredMethod("getITelephony");  
    
 getITelephonyMethod.setAccessible(true);  
 ITelephonyStub = getITelephonyMethod.invoke(telephonyManager);  
 ITelephonyClass = Class.forName(ITelephonyStub.getClass().getName());  
    
 if (isEnabled) {  
    // if you want to disable it.  
    dataConnSwitchmethod =  ITelephonyClass.getDeclaredMethod("disableDataConnectivity");  
 } else {  
    // if you want to enable it.  
    dataConnSwitchmethod = ITelephonyClass.getDeclaredMethod("enableDataConnectivity");  
 }  
    
 dataConnSwitchmethod.setAccessible(true);  
 dataConnSwitchmethod.invoke(ITelephonyStub);  

That's it, don't hesitate to comment, to share your knowledge and to correct me.

Thursday, February 9, 2012

Hello World !

This is my first blogging activity ever and I feel so excited about it.

So, as a warm up, let's get our hands dirty in some ANDROID issue that confused me for a while.

SlidingDrawer is a very interesting and useful tool that acts the same as a desk drawer.

It contains a layout but the layout, and of course its contents, can't be seen except if the drawer is openned/dragged.

well, what I found out was that :

animateOpen() behaves the same as animateClose() and both behave the same as animateToggle(), meaning, for example, that if the drawer is already opened and animateOpen() is executed then the drawer will be closed and so on which is not supposed to be done.

the only difference that I could notice was the speed of the animation:

animateOpen(), the animation while opening is faster than the animation while closing.
animateClose(), the animation while closing is faster than the animation while opening.
animateToggle(), both speeds are equal.

So, to solve this, just check the state of the drawer using (isOpened()) before each animation.

That's it, don't hesitate to comment, to share your knowledge and to correct me.