理解PendingIntent的作用

理解PendingIntent的作用

官方文档:https://developer.android.google.cn/reference/android/app/PendingIntent

PendingIntent是什么

PendingIntent实际上包含了一个意图(Intent),以及这个意图的行为(action)。

通俗来说,就是把想要的操作(调用broadcast、打开activity、打开service)保存到PendingIntent中,在合适的时候执行这个操作。

按照官方文档,使用PendingIntent,可以赋予其他应用足够的权限(as if yourself)来执行包含的Intent的行为。

有四个方法可以获得PendingIntent的实例:

  • getActivity(Context, int, Intent, int)
  • getActivities(Context, int, Intent[] int)
  • getBroadcast(Context, int, Intent, int)
  • getService(Context, int, Intent, int)

对应着
- context.startActivity
- context.sendBroadcast
- context.startService

A PendingIntent itself is simply a reference to a token maintained by the system describing the original data used to retrieve it. This means that, even if its owning application’s process is killed, the PendingIntent itself will remain usable from other processes that have been given it.

文档上还说:PendingIntent指向了一个系统维护的令牌(App Token),同时描述了原始的数据(Context..)。据我理解,App Token是代表原应用的执行权限,Context代表原应用的上下文环境。

非暴露组件的权限问题

非暴露组件是指exported=false的组件,设置了intent-filter的组件默认export=true,否则默认为false。

非暴露组件不能被外部唤起(会报出权限拒绝异常):

C:\Users\mingC\AndroidStudioProjects\NewsApp>adb shell am start -n com.newsapp/com.newsapp.main.UnexportedActivity
Starting: Intent { cmp=com.newsapp/.main.UnexportedActivity }
java.lang.SecurityException: Permission Denial: starting Intent { flg=0x10000000 cmp=com.newsapp/.main.UnexportedActivity } from null (pid=661, uid=2000) not exported from uid 10094
        at android.os.Parcel.readException(Parcel.java:1683)
        at android.os.Parcel.readException(Parcel.java:1636)
        at android.app.ActivityManagerProxy.startActivityAsUser(ActivityManagerNative.java:3107)
        at com.android.commands.am.Am.runStart(Am.java:635)
        at com.android.commands.am.Am.onRun(Am.java:388)
        at com.android.internal.os.BaseCommand.run(BaseCommand.java:51)
        at com.android.commands.am.Am.main(Am.java:121)
        at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
        at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:262)

同样的,在其他应用使用context.startActivity也是无法唤醒该活动;如果Service设置了exported=false,意味着无法跨进程调用。

实例:让其他应用打开本应用的非暴露组件

现在有一个需求,就是在我的app已经关闭的情况下,如何调起我的app里的设置为export=false的组件呢?

答案是使用PendingIntent。因为PendingIntent可以将本应用的权限临时赋予其他应用,这些权限只能用于执行PendingIntent的行为。

设置非暴露组件UnexportedActivity:

<activity android:name=".main.UnexportedActivity" android:exported="false">

以下可以实现在当前应用关闭,5秒后打开UnexportedActivity:

public class MainActivity extends AppCompatActivity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(Util.getContext(), UnexportedActivity.class);
        PendingIntent restartIntent = PendingIntent.getActivity(Util.getContext(), 0, intent, 0);
        AlarmManager mgr = (AlarmManager) Util.getContext().getSystemService(Context.ALARM_SERVICE);
        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 5000, restartIntent);
        finish();
    }
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值