首页 > 代码库 > PendingIntent详解

PendingIntent详解

PendingIntent详解

http://blog.csdn.net/hudashi/article/details/7060837

 

ppWidget(二) PendingIntent

 

关于android中PendingIntent.getBroadcase的注册广播

 


 

 

1)什么是PendingIntent

PendingIntent和Intent略有不同,它可以设置执行次数,主要用于远程服务通信、闹铃、通知、启动器、短信中,在一般情况下用的比较少。

 

 2)PendingIntent什么用  
Notification支持多种Intent来响应单击事件、消除事件、处理紧急状态的全屏事件等。 
这里就用到了setContentIntent(PendingIntent intent)来处理以上这么多的事件。

这边就是 把 PendingIntent 交给 Notification 通知栏 这个程序,当 Notification 通知栏 执行 点击事件后,执行 PendingIntent 这个意图。

 

3)相关属性和方法

属性:

PendingIntent的位标识符:

FLAG_ONE_SHOT   表示返回的PendingIntent仅能执行一次,执行完后自动取消。 在该PendingIntent对象通过send()方法触发过后,PendingIntent将自动调用cancel()进行销毁,那么如果你再调用send()方法的话,系统将会返回一个SendIntentException
FLAG_NO_CREATE     表示如果描述的PendingIntent不存在,并不创建相应的PendingIntent,而是返回NULL
FLAG_CANCEL_CURRENT      表示相应的PendingIntent已经存在,则取消前者,然后创建新的PendingIntent,这个有利于数据保持为最新的,可以用于即时通信的通信场景 FLAG_UPDATE_CURRENT     表示更新的PendingIntent。 如果之前的PendingIntent有多个属性,当前改了其中一个属性,那么这个PendingIntent只更新当前的属性,其他没有改变的属性 不更新

 

 

 

 


 

 

PendingIntent  是系统用于检索原始数据的一个标记,即使一个application停止了,但如果又新建application  , 检索个相同intent的PendingIntent 它将和原来的PndingIntent 拥有相同的标记, 必须通过remove 移除它,否者可能会出现该应用出现上次应用的数据。

PendingIntent 可以通过getService,getActivity,getBroadcast 来启动相应的组件

 

=============================================

getActivity(Context context, int requestCode, Intent intent, int flags)
从系统取得一个用于启动一个Activity的  PendingIntent对象,

 

 

=============================================

 

getService(Context context, int requestCode, Intent intent, int flags)
从系统取得一个用于启动一个Service的  PendingIntent对象

 用Intent实例化一个PendingIntent,利用PendingIntent的getService方法来启动一个服务

 

=============================================

getBroadcast(Context context, int requestCode, Intent intent, int flags)
系统取得一个用于向BroadcastReceiver的发送Intent广播的  PendingIntent对象  (广播 事先要在代码中先注册,或者直接在清单文件中注册

 

 

=============================================

 

返回的PendingIntent可以递交给别的应用程序,然后继续处理。这里的话你可以稍后才处理PendingIntent中描述的Intent及其最终行为。

 

 

因为对于Context的startActivity方法,如果不是在其子类(Activity)中调用,那么必须对Intent加上FLAG_ACTIVITY_NEW_TASK。

 

 

 


 

 

 

当你把PendingIntent递交给别的程序进行处理时,PendingIntent仍然拥有PendingIntent原程序所拥有的权限(with the same permissions and identity).当你从系统取得一个PendingIntent时,一定要非常小心才行。比如,通常,如果Intent目的地是你自己的component(Activity/Service/BroadcastReceiver)的话,你最好采用在Intent中显示指定目的component名字的方式,以确保Intent最终能发到目的,否则Intent最后可能不知道发到哪里了。一个PendingIntent就是Android系统中的一个token(节点,这个应该是Linux或C\C++用语)的一个对象引用,它描述了一些将用于retrieve的数据(这里,这些数据描述了Intent及其最终的行为)。

 

这就意味着即使PendingIntent原进程结束了的话, PendingIntent本身仍然还存在,可在其他进程(PendingIntent被递交到的其他程序)中继续使用.如果我在从系统中提取一个PendingIntent的,而系统中有一个和你描述的PendingIntent对等的PendingInent, 那么系统会直接返回和该PendingIntent其实是同一token的PendingIntent,而不是一个新的tokenPendingIntent。然而你在从提取PendingIntent时,通过FLAG_CANCEL_CURRENT参数,让这个老PendingIntent的先cancel()掉,这样得到的pendingInten和其token的就是新的了。

 

通过FLAG_UPDATE_CURRENT参数的话,可以让新的Intent会更新之前PendingIntent中的Intent对象数据,例如更新Intent中的Extras。另外,我们也可以在PendingIntent的原进程中调用PendingIntent的cancel ()把其从系统中移除掉。

 

 

 

注意:两个PendingIntent对等是指它们的operation一样, 且其它们的Intent的action, data, categories, components和flags都一样。但是它们的Intent的Extra可以不一样

 

 

 


 

 

开启Service

        /**         * 1、定义一个intent来开启Service         * 注:参数为开启Service的动作         */        Intent startServiceInten=new Intent("zyf.temp.Service.START");        /**         * 2、用Intent实例化一个PendingIntent,利用PendingIntent的getService方法来启动一个服务         */        PendingIntent pfullintent= PendingIntent.getService(context, 0, startServiceInten, 0);        /**         * 实例化RemoteView,其对应相应的Widget布局         */        RemoteViews views= new RemoteViews(getPackageName(), R.layout.widget);        /**         * 4、给RemoteView上的Button或ImageButton设置按钮事件         */        views.setOnClickPendingIntent(R.id.IBfullscreen, pfullintent);

 

 


 

 

例如:Mp3 中多个button绑定pendingIntent 事件:

@Override    public void onUpdate(Context context, AppWidgetManager appWidgetManager,            int[] appWidgetIds) {        System.out.println("onUpdate");            for(int i=0;i<appWidgetIds.length;i++){                //创建一个Intent对象                RemoteViews remoteViews=new RemoteViews(context.getPackageName(),R.layout.appwidget_music);                //前一首歌            Intent intent=new Intent( MUSIC_PLAY_STATE);            Bundle bundle=new Bundle();            bundle.putString("action","prev");            bundle.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID,appWidgetIds[i]);            intent.putExtras(bundle);            // 创建一个PendingIntent对象            PendingIntent pendingIntent=PendingIntent.getBroadcast(context,0,intent,                    PendingIntent.FLAG_UPDATE_CURRENT);            remoteViews.setOnClickPendingIntent(R.id.prevMusicImage,pendingIntent);                        //下一首            intent=new Intent( MUSIC_PLAY_STATE);            bundle=intent.getExtras();            bundle=new Bundle();            bundle.putString("action","next");            bundle.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID,appWidgetIds[i]);            intent.putExtras(bundle);         pendingIntent=PendingIntent.getBroadcast(context,1,intent,PendingIntent.FLAG_UPDATE_CURRENT);            remoteViews.setOnClickPendingIntent(R.id.nextMusicImage,pendingIntent);                                    //播放或暂停            intent=new Intent( MUSIC_PLAY_STATE);            bundle=new Bundle();            bundle.putString("action","playOrPause");            intent.putExtras(bundle);            pendingIntent=PendingIntent.getBroadcast(context,2,intent,PendingIntent.FLAG_UPDATE_CURRENT);            remoteViews.setOnClickPendingIntent(R.id.playOrPauseImage,pendingIntent);                        System.out.println("appWidgetIds======"+appWidgetIds[i]);            appWidgetManager.updateAppWidget(appWidgetIds[i],remoteViews);            }        super.onUpdate(context, appWidgetManager, appWidgetIds);    }

 

 


 

 

例如: 签到红包的广播

 

    /**     * 签到红包的广播 意图。     * 这个广播 是在清单文件中注册的     * @return     */    private PendingIntent initRedBagIntent()    {          Intent intent =new Intent(WifiApplication.getInstance(), RedBagNotiReceiver.class);          intent.setAction("com.wifibanlv.action.GET_REDBAG_Notification");          PendingIntent operation = PendingIntent                 .getBroadcast(WifiApplication.getInstance(), 0, intent, 0);          return operation;    }

 

 

PendingIntent 发送一个广播,执行 发送一个通知栏的事件。

/** * 设置开启 签到红包的广播 * @author Administrator * */public class RedBagNotiReceiver extends BroadcastReceiver {    private Context mContext;    private Logger logger = LoggerFactory.getLogger(LoggerKind.WH_LOGGER, AuthorType.ZhiQi, "AAAA");    @Override    public void onReceive(Context context, Intent intent) {        mContext = context;        logger.d("红包通知的广播 " + intent.getAction() + " , " + intent.getDataString()); //intent.getDataString() 好像是包名        showNotification();    }    ....}

 

 

 

 


 

 

点击通知栏,通过 PendingIntent 打开一个应用

 

        PendingIntent contentItent = PendingIntent.getActivity(mContext, 0, runApp(WIFIBL.WIFIBL_PACKAGENAME), 0);        notification.flags |= Notification.FLAG_AUTO_CANCEL;        notification.setLatestEventInfo(mContext, contentTitle, contentText, contentItent);        // 把Notification传递给NotificationManager           notificationManager.notify(0, notification);

 

 

 

private Intent runApp(String packageName) {        // 法一 : 但 只会获得用户安装程序的意图,如果是系统的应用程序,都会获取失败        // getPackageManager().queryIntentActivities(intent, flags);        try {            // PackageManager.GET_ACTIVITIES 解析Activity 节点 , 获取 详细信息。 在 该应用程序的清单文件中的 Activity节点            PackageInfo itemPackageInfo = mContext.getPackageManager().getPackageInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_ACTIVITIES);            //得到所有的Activity 信息的数组。  数组存放的是 当前包里面 所有的Activity 节点信息。            //数组中第一个元素,具有启动属性的Activity。 所以 需要 "PackageManager.GET_ACTIVITIES" 解析节点。解析是很耗时的            ActivityInfo[] activityinfos = itemPackageInfo.activities;            //系统有一般的应用程序 是不具备启动节点的功能。 所以 判断 下面获得的Activity数组 长度大于0,才可以运行。            if (activityinfos.length > 0) {                /**                 * 激活 一个意图 让 应用程序  运行                 * 数组中第一个元素,具有启动属性的Activity                 */                ActivityInfo startActivity = activityinfos[0];                String className = startActivity.name;                for (ActivityInfo activity : activityinfos) {                    if (activity.name.equals("com.wifibanlv.www.activity.MainViewPagerActivity")) {                        className = "com.wifibanlv.www.activity.MainViewPagerActivity";                    }                }                Intent intent = new Intent();                intent.setClassName(packageName, className);                if(className.equals("com.wifibanlv.www.activity.MainViewPagerActivity"))                {                    intent.putExtra("OffscreenPage", MainViewPagerActivity.OFFSCREEN_PAGE_WAI);                }                return intent;                //                mContext.startActivity(intent);            } else {                Toast.makeText(mContext, "该应用无法运行", 0).show();            }        } catch (Exception e) {            Toast.makeText(mContext, "应用程序无法启动", 0).show();            e.printStackTrace();        }        return null;    }

 


 

PendingIntent详解