如何在新的安卓版本中开启/关闭飞行模式(即使已获取root权限)?

3

从Android 4.2开始,使用普通API无法开启/关闭飞行模式。

如果授予WRITE_SECURE_SETTINGS权限,则可能可以正常工作,但这仅适用于系统应用程序(据我所知)。

在具有root的设备上,应该如何操作?

系统应用程序是否也需要root才能切换飞行模式?


请看下面我的回答。 - ChuongPham
1
可能是如何使用root在Android 4.2上切换飞行模式?的重复问题。 - joe1806772
1个回答

13

如果您的安卓设备(手机、平板电脑或笔记本)已获取 root权限,您可以按照以下步骤打开或关闭飞行模式

private final String COMMAND_FLIGHT_MODE_1 = "settings put global airplane_mode_on";
private final String COMMAND_FLIGHT_MODE_2 = "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state";

@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public void setFlightMode(Context context) {
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
        // API 17 onwards.
        if (isRooted(context)) {            
            int enabled = isFlightModeEnabled(context) ? 0 : 1;
            // Set Airplane / Flight mode using su commands.
            String command = COMMAND_FLIGHT_MODE_1 + " " + enabled;
            executeCommandWithoutWait(context, "-c", command);
            command = COMMAND_FLIGHT_MODE_2 + " " + enabled;
            executeCommandWithoutWait(context, "-c", command);
        } else {                
            try {
               // No root permission, just show Airplane / Flight mode setting screen.
               Intent intent = new Intent(Settings.ACTION_AIRPLANE_MODE_SETTINGS);
               intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
               context.startActivity(intent);
            } catch (ActivityNotFoundException e) {
               Log.e(TAG, "Setting screen not found due to: " + e.fillInStackTrace());
            }
        }
    } else {
        // API 16 and earlier.
        boolean enabled = isFlightModeEnabled(context);
        Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, enabled ? 0 : 1);
        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        intent.putExtra("state", !enabled);
        context.sendBroadcast(intent);
    }

要检查飞行模式/飞机模式是否已经开启或关闭,请执行以下操作:

@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
private boolean isFlightModeEnabled(Context context) {
    boolean mode = false;
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
        // API 17 onwards 
        mode = Settings.Global.getInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
    } else {
        // API 16 and earlier.
        mode = Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) == 1;
    }
    return mode;
}

执行su命令,请按照以下步骤操作:

private void executeCommandWithoutWait(Context context, String option, String command) {
    boolean success = false;
    String su = "su";
    for (int i=0; i < 3; i++) {
        // "su" command executed successfully.
        if (success) {
            // Stop executing alternative su commands below. 
            break;
        }
        if (i == 1) {
            su = "/system/xbin/su";
        } else if (i == 2) {
            su = "/system/bin/su";
        }       
        try {
            // execute command
            Runtime.getRuntime().exec(new String[]{su, option, command});
        } catch (IOException e) {
            Log.e(TAG, "su command has failed due to: " + e.fillInStackTrace());
        }   
    }
}

或者,如果您的应用程序:

  1. 使用Android框架的证书进行签名;并且
  2. 已安装到 /system/app/ 目录中;并且
  3. AndroidManifest.xml 文件中声明了相关标记(例如 WRITE_SECURE_SETTINGS 等)。

那么,您只需执行以下操作:

Settings.Global.putInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, isEnabled ? 0 : 1);

由于在Settings.Global中定义的任何内容都可以被系统应用程序读写——即使是作为系统应用程序创建的第三方应用程序。


有趣,谢谢。为什么使用“授权”获取权限不起作用?这是无法授予的权限之一吗?此外,这是否都是一种可能在较新版本的Android上无法正常工作的解决方法? - android developer
从Android 4.2及更高版本开始,Google已将权限限制为仅适用于系统应用程序,因此“grant”无法使用。我已经尝试过这条路,但没有成功。我发布的代码在大多数Android 4.3和4.4的root设备上都能正常工作 - 由于我没有所有运行4.2+固件变体的Android物理设备 - 我不能声称它将在所有4.2+的root Android设备上都能正常工作。然而,迄今为止,我的用户中没有人报告在root 4.2+设备上打开飞行/飞行模式时出现任何错误。所以,我想没有消息就是好消息!;) - ChuongPham
我明白了。这个解决方案在Android L上能用吗?你是怎么得到这个解决方案的?另外,你的应用是什么?我的应用是这个(我不打算添加这个功能,只是觉得有趣):https://play.google.com/store/apps/details?id=com.lb.app_manager - android developer
由于谷歌没有在最近四个固件版本(Android 4.2到Android L)中实施“修复” - 我猜它不是。您提到的功能是我考虑在未来发布我的应用程序时使用的内容。要关闭应用程序,您只需使用设备上的返回按钮 - 因为我不会在我的应用程序中实现退出选项,这是Hackbod(Android框架工程师)和其他在SO上发表评论的高级Android开发人员的建议。 - ChuongPham
我是指关闭应用程序,包括它的通知... 关于安卓系统,好的。谢谢。 - android developer
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接