使用root访问禁用/启用Android L上的移动数据

使用root访问禁用/启用Android L上的移动数据,android,android-5.0-lollipop,Android,Android 5.0 Lollipop,我正在编写一个只有我自己才会使用的小应用程序,我想在一个有根的安卓4.5设备上实际启用/禁用我的移动数据(我正在运行一个针对Nexus 4的定制安卓L) 我已经寻找了一段时间,找到了在android 4.3之前一直有效的反射方法。 我在这篇文章中也看到了这种方法,但这需要氰莫德 从我在互联网上发现的情况来看,这对于非根应用程序是不可能的,但我的问题是: 是否可以使用root权限来完成此任务?使用此功能 TelephonyManager tm = (TelephonyManager)getSyst

我正在编写一个只有我自己才会使用的小应用程序,我想在一个有根的安卓4.5设备上实际启用/禁用我的移动数据(我正在运行一个针对Nexus 4的定制安卓L)

我已经寻找了一段时间,找到了在android 4.3之前一直有效的反射方法。 我在这篇文章中也看到了这种方法,但这需要氰莫德

从我在互联网上发现的情况来看,这对于非根应用程序是不可能的,但我的问题是:

是否可以使用root权限来完成此任务?

使用此功能

TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
Method methodSet = tm.class.getDeclaredMethod( "setDataEnabled", boolean.class);
methodSet.invoke(tm, true); 
编辑: 这需要权限
修改\u PHONE\u STATE
,这是系统或签名级别的权限

理想情况下,您可以使用此代码创建一个可运行的jar文件,并使用

export CLASSPATH=<jar path>
exec app_process <jar-dir-path> your.package.name.classname "$@"
导出类路径=
exec app_处理您的.package.name.classname“$@”

苏壳公司

我在互联网上创建了这个方法;它在android 5.0.1上运行良好
void turnData(boolean ON) throws Exception
{

    int currentapiVersion = android.os.Build.VERSION.SDK_INT;
    if(currentapiVersion == Build.VERSION_CODES.FROYO)
    {

        Log.i("version:", "Found Froyo");
        try{ 
            Method dataConnSwitchmethod;
            Class telephonyManagerClass;
            Object ITelephonyStub;
            Class ITelephonyClass;
            TelephonyManager telephonyManager = (TelephonyManager) cx.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);

            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 (ON) {
             dataConnSwitchmethod = ITelephonyClass.getDeclaredMethod("enableDataConnectivity"); 

        } else {
            dataConnSwitchmethod = ITelephonyClass.getDeclaredMethod("disableDataConnectivity");
        }
        dataConnSwitchmethod.setAccessible(true);
        dataConnSwitchmethod.invoke(ITelephonyStub);
        }catch(Exception e){
              Log.e("Error:",e.toString());
        }

    }
     else
    {
       Log.i("version:", "Found Gingerbread+");
       final ConnectivityManager conman = (ConnectivityManager) cx.getApplicationContext().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, ON);
    }
}
基本上,如果希望启用连接,就必须传递true,否则传递false,并传递应用程序的上下文

private final static String COMMAND_L_ON = "svc data enable\n ";
private final static String COMMAND_L_OFF = "svc data disable\n ";
private final static String COMMAND_SU = "su";

public static void setConnection(boolean enable,Context context){

    String command;
    if(enable)
        command = COMMAND_L_ON;
    else
        command = COMMAND_L_OFF;        

    try{
        Process su = Runtime.getRuntime().exec(COMMAND_SU);
        DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());

        outputStream.writeBytes(command);
        outputStream.flush();

        outputStream.writeBytes("exit\n");
        outputStream.flush();
        try {
            su.waitFor();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        outputStream.close();
    }catch(IOException e){
        e.printStackTrace();
    }
}
如果某些设备出现问题,请报告


编辑:现在也与android 5.1兼容了

我注意到服务调用方法并不是在所有设备上都能一致工作。它所使用的数字因设备而异

我发现以下解决方案在所有根设备上都能正常工作

只需通过su执行以下操作

启用移动数据

svc data enable
svc data disable
禁用移动数据

svc data enable
svc data disable

就这么简单。

我也在找同样的东西。如果您找到解决方案,请更新您的答案。如果您仔细查看ConnectionManager源代码中的方法,setMobileDataEnabled仍然存在于Android L中,但是当您通过反射查找它时,它似乎消失了。我也可以使用root权限来实现这一点,但不知道如何实现。在Android L中,如果您推送device_owner.xml,那么您可以使用hv访问权限来启用和禁用Android中提供的apiL@Nactive如果你发现我的answare是正确的,你能检查一下吗?如果不是,你能解释一下原因吗?谢谢你在安卓L上测试过这个吗?将方法设置为不可访问然后调用它是没有意义的。这需要仅授予系统应用程序的“修改手机状态”权限。有没有办法授予root访问权限?如果你有root访问权限,将你的应用推送到system/app,你的应用将成为system-app这是应用自动完成的吗?我不想让我的用户手动执行此操作。@nandeesh:简单地将你的应用程序移动到
/system/app
目录并不能神奇地使你的应用程序成为系统应用程序。您仍然需要使用Android平台证书对应用程序进行签名,并使用适当的指令配置您的
AndroidManifest.xml
,以便应用程序作为系统应用程序运行。我怀疑你上面的答案是否有效,更不用说获得25个赏金荣誉了。不,在安卓4.4及以下版本上,你可以看到与5.1.1 Cyanogenmod兼容的版本