Android应用执行命令失败求助:非Root设备无法锁屏
解决未Root Android设备的代码锁屏问题
首先得明确:你遇到的java.io.Exception直接原因是你的设备没有Root权限——su命令是只有Root用户才能执行的,未Root设备里根本不存在这个可执行文件,自然会触发执行错误。
针对未Root设备,Android官方提供了合法的锁屏方式,下面给你两个可行的方案:
方案一:使用DevicePolicyManager(官方推荐)
这是Android系统提供的标准设备管理API,专门用于实现锁屏、重置设备等管理功能,不需要Root,但需要用户手动授权你的应用成为设备管理员。
步骤1:创建设备管理员接收器
新建一个继承自DeviceAdminReceiver的类,基础实现即可(可选重写状态监听方法):
public class MyDeviceAdminReceiver extends DeviceAdminReceiver { @Override public void onEnabled(Context context, Intent intent) { super.onEnabled(context, intent); Toast.makeText(context, "设备管理员已激活", Toast.LENGTH_SHORT).show(); } }
步骤2:在AndroidManifest中注册接收器
添加BIND_DEVICE_ADMIN权限,并配置对应的meta-data和intent-filter:
<receiver android:name=".MyDeviceAdminReceiver" android:permission="android.permission.BIND_DEVICE_ADMIN"> <meta-data android:name="android.app.device_admin" android:resource="@xml/device_admin" /> <intent-filter> <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" /> </intent-filter> </receiver>
步骤3:创建设备管理员配置文件
在res/xml目录下新建device_admin.xml,声明锁屏所需的权限:
<device-admin xmlns:android="http://schemas.android.com/apk/res/android"> <uses-policies> <force-lock /> <!-- 锁屏必须的权限 --> </uses-policies> </device-admin>
步骤4:在Activity中申请权限并执行锁屏
在你的MainActivity中,获取实例、引导授权后调用锁屏方法:
public class MainActivity extends AppCompatActivity { private static final int REQUEST_CODE_ENABLE_ADMIN = 1001; private DevicePolicyManager mDpm; private ComponentName mAdminComponent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); mAdminComponent = new ComponentName(this, MyDeviceAdminReceiver.class); // 检查权限状态 if (mDpm.isAdminActive(mAdminComponent)) { mDpm.lockNow(); // 已授权直接锁屏 } else { // 引导用户开启设备管理员 Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN); intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mAdminComponent); intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "需要激活权限以实现锁屏"); startActivityForResult(intent, REQUEST_CODE_ENABLE_ADMIN); } } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_ENABLE_ADMIN && resultCode == RESULT_OK) { mDpm.lockNow(); // 用户授权成功后锁屏 } else { Toast.makeText(this, "未授权无法执行锁屏", Toast.LENGTH_SHORT).show(); } } }
方案二:使用AccessibilityService(Android 10+)
如果你的应用目标版本是Android 10(API 29)及以上,还可以通过辅助功能服务模拟锁屏操作,同样不需要Root,但需要用户手动开启辅助功能权限。
步骤1:创建辅助功能服务类
public class LockAccessibilityService extends AccessibilityService { @Override public void onAccessibilityEvent(AccessibilityEvent event) {} @Override public void onInterrupt() {} // 对外暴露锁屏方法 public void lockScreen() { performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN); } // 用于绑定服务的Binder类 private final IBinder mBinder = new LocalBinder(); public class LocalBinder extends Binder { LockAccessibilityService getService() { return LockAccessibilityService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } }
步骤2:在Manifest中注册服务
<service android:name=".LockAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_service_config" /> </service>
步骤3:创建辅助功能配置文件
在res/xml目录下新建accessibility_service_config.xml:
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeAllMask" android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="flagDefault" android:canPerformGestures="true" android:description="@string/accessibility_desc" />
记得在strings.xml添加描述:
<string name="accessibility_desc">本服务用于实现锁屏功能</string>
步骤4:引导用户开启权限并锁屏
在Activity中检查权限并调用:
public class MainActivity extends AppCompatActivity { private static final int REQUEST_ACCESSIBILITY = 1002; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (!isAccessibilityEnabled()) { // 引导用户打开辅助功能设置 startActivityForResult(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), REQUEST_ACCESSIBILITY); } else { performLock(); } } // 检查辅助功能是否开启 private boolean isAccessibilityEnabled() { final String service = getPackageName() + "/" + LockAccessibilityService.class.getCanonicalName(); int enabled = 0; try { enabled = Settings.Secure.getInt(getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED); } catch (Settings.SettingNotFoundException e) { e.printStackTrace(); } if (enabled == 1) { String services = Settings.Secure.getString(getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); if (services != null) { for (String s : services.split(":")) { if (s.equalsIgnoreCase(service)) return true; } } } return false; } // 执行锁屏 private void performLock() { bindService(new Intent(this, LockAccessibilityService.class), new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { LockAccessibilityService.LocalBinder binder = (LockAccessibilityService.LocalBinder) service; binder.getService().lockScreen(); unbindService(this); } @Override public void onServiceDisconnected(ComponentName name) {} }, Context.BIND_AUTO_CREATE); } }
总结
- 未Root设备绝对无法使用
su命令,这是系统级安全限制,没有合法绕过的方式。 - 上述两个方案都是Android官方允许的合法途径,虽需用户手动授权,但这是保障用户隐私的必要流程。
- 优先推荐方案一(DevicePolicyManager),权限逻辑更清晰,用户接受度更高。
内容的提问来源于stack exchange,提问作者Angel C
相关产品推荐
相关产品推荐

