码迷,mamicode.com
首页 > 其他好文 > 详细

PendingIntent详解

时间:2014-07-27 21:54:19      阅读:409      评论:0      收藏:0      [点我收藏+]

标签:

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详解

标签:

原文地址:http://www.cnblogs.com/zhiqixue/p/3871241.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!