Android跨应用调用:从普通应用触发系统应用执行关机操作
跨应用触发关机的最优方案
针对你的场景(同签名的普通应用调用系统权限应用执行关机),下面几种方案比Service和普通广播更贴合需求:
1. 显式定向广播(最简洁)
你之前认为BroadcastReceiver无法指定目标组件是误解了,显式广播可以直接指定接收组件,完全不会被其他应用拦截,完美匹配“定向触发”的需求:
- 系统应用中实现BroadcastReceiver:
在Manifest中注册时无需添加public class ShutdownReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 执行关机逻辑 PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); pm.shutdown(); } }<intent-filter>,直接声明即可(因为用显式Intent调用,无需过滤):
为了安全,可添加同签名权限验证:在系统应用Manifest中定义权限<receiver android:name=".ShutdownReceiver" android:exported="true" />
给Receiver绑定该权限,确保只有同签名应用能发送广播:<permission android:name="com.your.app.permission.SEND_SHUTDOWN_CMD" android:protectionLevel="signature" /><receiver android:name=".ShutdownReceiver" android:exported="true" android:permission="com.your.app.permission.SEND_SHUTDOWN_CMD" /> - 普通应用中发送显式广播:
同时普通应用Manifest中需要声明使用该权限:Intent shutdownIntent = new Intent(); // 指定系统应用包名和Receiver类名 shutdownIntent.setComponent(new ComponentName("com.your.system.app", "com.your.system.app.ShutdownReceiver")); context.sendBroadcast(shutdownIntent);<uses-permission android:name="com.your.app.permission.SEND_SHUTDOWN_CMD" />
2. 无界面Activity(语义最贴合“调用方法”)
如果觉得广播还是不够像“直接调用”,可以用一个无界面的Activity,执行完关机立刻销毁,完全没有后台残留:
- 系统应用中创建无界面Activity:
在Manifest中注册时设置无界面主题,并添加权限验证:public class ShutdownActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 执行关机 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); pm.shutdown(); // 立即结束Activity finish(); } }<activity android:name=".ShutdownActivity" android:theme="@android:style/Theme.NoDisplay" android:exported="true" android:permission="com.your.app.permission.TRIGGER_SHUTDOWN" /> - 普通应用中启动该Activity:
Intent intent = new Intent(); intent.setComponent(new ComponentName("com.your.system.app", "com.your.system.app.ShutdownActivity")); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 启动外部Activity必须的flag context.startActivity(intent);
3. AIDL跨进程调用(适合复杂交互)
如果后续需要更复杂的跨进程交互(比如获取操作结果),AIDL是标准方案,但对于简单关机场景稍显繁琐:
- 定义AIDL接口
IShutdown.aidl:interface IShutdown { void shutdownDevice(); } - 系统应用中实现AIDL服务:
Manifest中注册服务并添加权限:public class ShutdownAidlService extends Service { private final IShutdown.Stub mBinder = new IShutdown.Stub() { @Override public void shutdownDevice() throws RemoteException { PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); pm.shutdown(); } }; @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } }<service android:name=".ShutdownAidlService" android:exported="true" android:permission="com.your.app.permission.BIND_SHUTDOWN_SERVICE" /> - 普通应用中绑定服务并调用方法:
private IShutdown mShutdownService; private ServiceConnection mConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mShutdownService = IShutdown.Stub.asInterface(service); try { mShutdownService.shutdownDevice(); unbindService(this); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { mShutdownService = null; } }; // 触发关机的方法 public void callShutdown(Context context) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.your.system.app", "com.your.system.app.ShutdownAidlService")); context.bindService(intent, mConn, Context.BIND_AUTO_CREATE); }
推荐选择
如果只是简单触发关机,显式定向广播是最优解:代码简洁、无后台残留、安全性高。如果追求更接近“直接调用方法”的语义,无界面Activity是更好的选择,实现成本远低于AIDL。
内容的提问来源于stack exchange,提问作者AndreKR
相关产品推荐
相关产品推荐

