PendingIntent延迟意图

QuibblerQuibbler 2019-12-31 约 17 分钟 1725 次阅读

PendingIntent延迟意图

PendingIntent一般用在Notification和桌面小挂件AppWidgetProvider的点击事件发生时传递的Intent意图。这里主要了解一下PendingIntent,至于具体使用场景参考另外两篇详细介绍。

1、什么是PendingIntent

PendingIntent谷歌官方文档的解释是“A description of an Intent and target action to perform with it.(要执行的意图和目标动作的描述)”。位于android.app包中。

PendingIntent就是一个Intent的描述,是对真实Intent的一种封装载体。不是立刻执行某个行为,而是满足某些条件或触发某些事件后才执行指定的行为。

2、获取PendingInteng

一共有五种方法创建PendingIntent对象,都是PendingIntent类中提供的static方法:

最常用的三种获取PendingIntent的方式:

  • getActivities(Context context, int requestCode, Intent[] intents, int flags):从系统 取得一个用于启动一个Activity的PendingIntent对象
  • getBroadcast(Context context, int requestCode, Intent intent, int flags):从系统取得一个向BroadcastReceiver的发送广播的PendingIntent对象
  • getService(Context context, int requestCode, Intent intent, int flags):从系统取得一个 用于启动一个Service的PendingIntent对象

不难发现它们的参数都有4个:Context、requestCode、Intent、flags。分别是上下文、请求码、意图、标志位。最后一个参数flags有四种可选,每种都代表不同的意义:

  • FLAG_ONE_SHOT
/ **
     *标志指示此PendingIntent只能使用一次。
	 *如果已设置,则在send()被调用,它将自动
     *已为您取消,以后再尝试通过它发送都会失败。
     * /
    public static final int FLAG_ONE_SHOT = 1 << 30;
  • FLAG_NO_CREATE
/ **
     *标志,指示如果描述的PendingIntent不
     *已经存在,然后简单地返回null而不是创建它。
     * /
    public static final int FLAG_NO_CREATE = 1 << 29;
  • FLAG_CANCEL_CURRENT
/ **
     *如果当前系统中已经存在一个相同的PendingIntent对象,
     *那么就将先将已有的PendingIntent取消
     *然后重新生成一个PendingIntent对象。
     * /
    public static final int FLAG_CANCEL_CURRENT = 1 << 28;
  • FLAG_UPDATE_CURRENT
/ **
     *如果系统中有一个和你描述的PendingIntent对等的PendingInent,
	 *那么系统将使用该PendingIntent对象,
	 *但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据
	 *例如更新Intent中的Extras
     * /
    public static final int FLAG_UPDATE_CURRENT = 1 << 27;

3、PendingInteng用途

PendingIntent本身只是对系统维护的令牌的引用,该令牌描述了用于检索令牌的原始数据。这意味着,即使其拥有的应用程序的进程被杀死,PendingIntent本身也将在已赋予它的其他进程中保持可用。

PendingIntent中保存有当前App的Context,使它赋予外部App一种能力,使得外部App可以如同当前App一样的执行pendingIntent里的Intent,算在执行时当前App已经不存在了,也能通过存在pendingintent里的Context照样执行Intent。

①PendingIntent的使用场景主要用于闹钟、通知、桌面部件。定时服务AlarmManager设置闹铃时间到时触发PendingIntent:

setAlarmClock(AlarmManager.AlarmClockInfo info, PendingIntent operation);
    set(int type, long triggerAtMillis, PendingIntent operation);
    setAlarmClock(AlarmManager.AlarmClockInfo info, PendingIntent operation);

②用于Notification通知,给通知添加点击事件PendingIntent

Notification.Builder.setContentIntent(PendingIntent intent

4、PendingInteng和Intent区别

①Intent是立即使用的,而PendingIntent可以等到事件发生后触发,PendingIntent可以cancel

②Intent在程序结束后即终止,而PendingIntent在程序结束后依然有效

③PendingIntent自带Context,而Intent需要在某个Context内运行

④Intent在原task中运行,PendingIntent在新的task中运行

5、PendingInteng示例

常常用来给通知设置一些事件,如:

Notification.Builder builder = new Notification.Builder(this);
    Intent intent = new Intent();
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    ... ...
    builder.setContentIntent(pendingIntent);
    ... ...


附:PendingIntent创建部分源码

        ①getActivity

public static PendingIntent getActivity(Context context, int requestCode,
            @NonNull Intent intent, @Flags int flags, @Nullable Bundle options) {
        String packageName = context.getPackageName();
        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
                context.getContentResolver()) : null;
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(context);
            IIntentSender target =
                ActivityManager.getService().getIntentSender(
                    ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
                    null, null, requestCode, new Intent[] { intent },
                    resolvedType != null ? new String[] { resolvedType } : null,
                    flags, options, context.getUserId());
            return target != null ? new PendingIntent(target) : null;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

        ②getBroadcast

public static PendingIntent getBroadcast(Context context, int requestCode,
            Intent intent, @Flags int flags) {
        return getBroadcastAsUser(context, requestCode, intent, flags, context.getUser());
    }
    
    public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
            Intent intent, int flags, UserHandle userHandle) {
        String packageName = context.getPackageName();
        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
                context.getContentResolver()) : null;
        try {
            intent.prepareToLeaveProcess(context);
            IIntentSender target =
                ActivityManager.getService().getIntentSender(
                    ActivityManager.INTENT_SENDER_BROADCAST, packageName,
                    null, null, requestCode, new Intent[] { intent },
                    resolvedType != null ? new String[] { resolvedType } : null,
                    flags, null, userHandle.getIdentifier());
            return target != null ? new PendingIntent(target) : null;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

        ③getService

public static PendingIntent getService(Context context, int requestCode,
            @NonNull Intent intent, @Flags int flags) {
        return buildServicePendingIntent(context, requestCode, intent, flags,
                ActivityManager.INTENT_SENDER_SERVICE);
    }


       同时查看PendingIntent 类可以看到许多的Send函数,就是PendingIntent在进行被赋予的相关的操作。send()方法执行与此PendingIntent相关的操作,允许调用方指定有关要使用的Intent的信息,并在发送完成时得到通知。

public void send(Context context, int code, @Nullable Intent intent,
            @Nullable OnFinished onFinished, @Nullable Handler handler) throws CanceledException {
        send(context, code, intent, onFinished, handler, null, null);
    }



参考资料:

         Android Documentation of PendingIntent

         Android基础——PendingIntent理解

         PendingIntent详解

         Intent和PendingIntent的区别

        

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w