Mobile network switches for systems above android
I recently encountered a very interesting bug and posted it to share with you.
It was a warm morning, and the sun was quite pleasant. A bug email floated like a leaf to my mailbox.
After some discussion, I confirmed that the Widget switch in charge has no function in the system above Android5.0. I believe many of my friends who have made mobile network switches know that the traditional method is to use the setMobileDataEnabled and getMobileDataEnabled methods in ConnectivityManager to control the on and off of the mobile network.
/** * Gets the value of the setting for enabling Mobile data. * * @return Whether mobile data is enabled. * @hide */ public boolean getMobileDataEnabled() { try { return mService.getMobileDataEnabled(); } catch (RemoteException e) { return true; } } /** * Sets the persisted value for enabling/disabling Mobile data. * * @param enabled Whether the mobile data connection should be * used or not. * @hide */ public void setMobileDataEnabled(boolean enabled) { try { mService.setMobileDataEnabled(enabled); } catch (RemoteException e) { } }
But open the source code above 5.0, the two methods no longer exist.
We recommend a good website to view the source code online. Online source code URL.
At this time, the boss's reminder helped me. I opened the TelephonyMananger class of code above 5.0 and tried to get the setDataEnabled and getDataEnabled classes through reflection to complete the operation.
Source code
/** @hide */ @SystemApi public void setDataEnabled(boolean enable) { try { getITelephony().setDataEnabled(enable); } catch (RemoteException e) { Log.e(TAG, Error calling ITelephony#setDataEnabled, e); } } /** @hide */ @SystemApi public boolean getDataEnabled() { try { return getITelephony().getDataEnabled(); } catch (RemoteException e) { Log.e(TAG, Error calling ITelephony#getDataEnabled, e); } return false; }
My Reflection Method:
public void setMobileDataState(Context cxt, boolean mobileDataEnabled) { TelephonyManager telephonyService = (TelephonyManager) cxt.getSystemService(Context.TELEPHONY_SERVICE); try { Method setMobileDataEnabledMethod = telephonyService.getClass().getDeclaredMethod(setDataEnabled, boolean.class); if (null != setMobileDataEnabledMethod) { setMobileDataEnabledMethod.invoke(telephonyService, mobileDataEnabled); } } catch (Exception e) { LogHelper.v(TAG, Error setting + ((InvocationTargetException)e).getTargetException() + telephonyService); }}public boolean getMobileDataState(Context cxt) { TelephonyManager telephonyService = (TelephonyManager) cxt.getSystemService(Context.TELEPHONY_SERVICE); try { Method getMobileDataEnabledMethod = telephonyService.getClass().getDeclaredMethod(getDataEnabled); if (null != getMobileDataEnabledMethod) { boolean mobileDataEnabled = (Boolean) getMobileDataEnabledMethod.invoke(telephonyService); return mobileDataEnabled; } } catch (Exception e) { LogHelper.v(TAG, Error getting + ((InvocationTargetException)e).getTargetException() + telephonyService); } return false;}
However, the InvocationTargetException error is reported. Pass:
((InvocationTargetException)e).getTargetException()
The following error occurs when the reflection is executed:
Error settingjava.lang.SecurityException: Neither user 10240 nor current process has android.permission.MODIFY_PHONE_STATE.android.telephony.TelephonyManager
At this time, the boss reminded me to move the APP to system/app for a try.
After several attempts, the results are still the same.
At this time, I accidentally moved the APP to the system/priv-app, and it was actually successful. In this directory, the switch can work again.
Of course, our applications cannot be installed in this directory. We can only adopt a compromise solution. However, the whole process was very happy. This bug was the first time I found the differences between the source code of different Android versions and it was very interesting. I hope to inspire you.