采得百花成蜜后,为谁辛苦为谁甜。这篇文章主要讲述Android5.0以上系统的移动网络开关相关的知识,希望能为你提供帮助。
笔者近期遇到一个非常有意思的bug,贴出来和大家分享下。
那是一个温暖的早晨,阳光晒得人非常舒服。一封bug邮件像一片叶子飘到我的邮箱。
一番交流。笔者确认负责的Widget开关在android5.0以上系统没有作用。相信非常多做过移动网络开关的朋友都知道。传统的方法是在ConnectivityManager中通过反射两个方法setMobileDataEnabled和getMobileDataEnabled来控制移动网络开和关的。
/**
* 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) {
}
}
可是打开5.0以上的源代码,这两个方法已经不存在了。
推荐一个不错的在线看源代码的站点。在线源代码网址。
此时老大的提醒帮了我。我打开5.0以上代码的TelephonyMananger类尝试通过反射获取setDataEnabled和getDataEnabled类完毕操作。
源代码
/** @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;
}
我的反射方法:
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;
}
可是报了InvocationTargetException错误。
通过:
((InvocationTargetException)e).getTargetException()
方法得知是运行反射运行时发生例如以下错误:
Error settingjava.lang.SecurityException: Neither user 10240 nor current process has android.permission.MODIFY_PHONE_STATE.android.telephony.TelephonyManager
这个时候老大提醒我把APP移动到system/app下试试。
几番尝试。仍是相同的结果。
这个时候一个我无意的操作,将APP移动到system/priv-app,居然成功了。在这个文件夹下,开关又能够又一次工作了。
当然,我们的应用不可能装在这个文件夹下,仅仅能採取折中的方案。但整个过程还是非常开心的,这个bug算是我第一次发现了不同Android版本号之间源代码的差异,感觉非常有意思。希望对大家有所启示。
【Android5.0以上系统的移动网络开关】
推荐阅读
- elasticsearch index 之 put mapping
- 如何修复Windows 10未显示或无法识别的外置硬盘()
- 10大最佳数据恢复软件合集(哪个最适合你())
- Windows的5大最佳数据恢复软件(Stellar替代方案)
- Windows 10的10个最佳动态壁纸(你最喜欢哪个())
- 30多个Android最佳主屏幕启动器完整合集
- Windows 10的12款最佳免费媒体播放器合集
- Ghost Xp Sp3系统下的10项设置技巧你知道吗?
- 系统天地本文详解《重装电脑系统前的准备工作》