You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android跨应用调用:从普通应用触发系统应用执行关机操作

跨应用触发关机的最优方案

针对你的场景(同签名的普通应用调用系统权限应用执行关机),下面几种方案比Service和普通广播更贴合需求:

1. 显式定向广播(最简洁)

你之前认为BroadcastReceiver无法指定目标组件是误解了,显式广播可以直接指定接收组件,完全不会被其他应用拦截,完美匹配“定向触发”的需求:

  • 系统应用中实现BroadcastReceiver:
    public class ShutdownReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // 执行关机逻辑
            PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
            pm.shutdown();
        }
    }
    
    在Manifest中注册时无需添加<intent-filter>,直接声明即可(因为用显式Intent调用,无需过滤):
    <receiver
        android:name=".ShutdownReceiver"
        android:exported="true" />
    
    为了安全,可添加同签名权限验证:在系统应用Manifest中定义权限
    <permission
        android:name="com.your.app.permission.SEND_SHUTDOWN_CMD"
        android:protectionLevel="signature" />
    
    给Receiver绑定该权限,确保只有同签名应用能发送广播:
    <receiver
        android:name=".ShutdownReceiver"
        android:exported="true"
        android:permission="com.your.app.permission.SEND_SHUTDOWN_CMD" />
    
  • 普通应用中发送显式广播:
    Intent shutdownIntent = new Intent();
    // 指定系统应用包名和Receiver类名
    shutdownIntent.setComponent(new ComponentName("com.your.system.app", "com.your.system.app.ShutdownReceiver"));
    context.sendBroadcast(shutdownIntent);
    
    同时普通应用Manifest中需要声明使用该权限:
    <uses-permission android:name="com.your.app.permission.SEND_SHUTDOWN_CMD" />
    

2. 无界面Activity(语义最贴合“调用方法”)

如果觉得广播还是不够像“直接调用”,可以用一个无界面的Activity,执行完关机立刻销毁,完全没有后台残留:

  • 系统应用中创建无界面Activity:
    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();
        }
    }
    
    在Manifest中注册时设置无界面主题,并添加权限验证:
    <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服务:
    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;
        }
    }
    
    Manifest中注册服务并添加权限:
    <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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 06:35:27