[置顶] 安卓学习笔记之RemoteViews
android,RemoteView,widget,通知2016-11-01
1 桌面widget小部件( 使用戳这里)
2 通知栏通知信息
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
remoteViews = new RemoteViews(getPackageName(), R.layout.remoteviews_item_dl);
remoteViews.setTextViewText(R.id.tv_filename, getPackageName()); // 设置标题
// remoteViews.setTextViewText(R.id.tv_content, "this is notification"); // 设置内容
Intent btIntent = new Intent();
btIntent.setAction("com.yu.sendnotification.action_dl");
PendingIntent btPendingIntent = PendingIntent.getBroadcast(this, 1, btIntent, PendingIntent.FLAG_CANCEL_CURRENT); // 发送广播意图
remoteViews.setOnClickPendingIntent(R.id.bt_stop, btPendingIntent); // 设置点击事件
Intent intent = new Intent(this, NewActivity.class);
PendingIntent pi = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
noti = new Notification.Builder(context).setSmallIcon(R.mipmap.ic_launcher)
.setTicker("Hellonotification")
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setContentIntent(pi).build();
manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(0, noti);
}
1 通过Notification.Builder创建一个builder对象
Notification.Builder builder = new Notification.Builder(context);
2 给builder设置相关选项
setContent(remoteViews) // 设置RemoteViews
setContentIntent(intent) // 设置view的intent事件
setContentText() // 设置内容文字
setContentTitle() //设置标题文字
setAutoCancel(bool) //设置自动取消
setSmallIcon(). //设置小图标
setTicker(CharSequence tickerText) // 设置新消息状态栏滚动文字
setDeleteIntent(PendingIntent intent) // 设置用户滑动删除通知intent
setProgress(int max,int progress,boolean indeterminate) //设置进度
setWhen(long when) // 设置发送时间
setSound(Uri sound):设定一个铃声,用于在通知的时候响应。传递一个Uri的参数,格式为“file:///mnt/sdcard/Xxx.mp3”。
setLights(int argb, int onMs, int offMs):设定前置LED灯的闪烁速率,持续毫秒数,停顿毫秒数。
setVibrate(long[] pattern):设定震动的模式,以一个long数组保存毫秒级间隔的震动。
setDefaults(int)方法设定默认响应参数,在Notification中,对它的参数使用常量定义了,我们只需使用即可:
--DEFAULT_ALL:铃声、闪光、震动均系统默认。
--DEFAULT_SOUND:系统默认铃声。
--DEFAULT_VIBRATE:系统默认震动。
--DEFAULT_LIGHTS:系统默认闪光。
需要权限
<!-- 闪光灯权限 -->
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<!-- 振动器权限 -->
<uses-permission android:name="android.permission.VIBRATE"/>
3 builder.build() 创建一个Notification对象
4 获取NotificationManger并发送通知
manager=(NotificationManager)=getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(0, noti);
PendingIntent表示即将发生的意图,在RemoteViews的应用中起着非常关键的作用。
1) intent是即时发生的意图,PendingIntent不确定发生时间的意图
2) 用于给RemoteViews添加点击事件
3) PendingIntent支持启动Activity、启动Service,发送广播三种意图,对应如下方法
(Context context, int requestCode, Intent intent, int flags)
requestCode表示请求码Private request code for the sender
flags标志,有4种
intent 意图
1 FLAG_CANCEL_CURRENT:如果当前系统中已经存在一个相同的PendingIntent对象,
那么就将先将已有的PendingIntent取消,然后重新生成一个PendingIntent对象。
2 FLAG_NO_CREATE:如果当前系统中不存在相同的PendingIntent对象,
系统将不会创建该PendingIntent对象而是直接返回null。
3 FLAG_ONE_SHOT:该PendingIntent只作用一次。在该PendingIntent对象通过send()方法触发过
后,PendingIntent将自动调用cancel()进行销毁,那么如果你再调用send()方法的话,系统将会返回一个SendIntentException。
4 FLAG_UPDATE_CURRENT:如果系统中有一个和你描述的PendingIntent对等的PendingInent,
那么系统将使用该PendingIntent对象,但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据,
例如更新Intent中的Extras。
两个PendingInent相同条件:requestCode与Intent都相同
Intent相同指Component与intent-filter相同(与Extras无关)
manager.notify(id, notification)发通知
1、当id相同时,后面的通知覆盖原来
2、当id不同时
--当PendingIntent不匹配时, 通知间不互相干扰,不受flags影响
--当PendingIntent匹配时,按flags分析
*使用FLAG_ONE_SHOT:后续的PendingIntent会和第一条保持一致,包括Extras,单击任意一条后,其他无法打开
*使用FLAG_CANCEL_CURRENT:只有最新的通知可以打开
*使用FLAG_UPDATE_CURRENT:之前弹出的通知中的PendingIntent都会被更新,包括Extras,并且通知都可以打开
public RemoteViews(String packageName, int layoutId)
layout:
FrameLayout LinearLayout RelativeLayout GridLayout
View:
AnalogClock button Chronometer ImageButton ImageView ProgressBar TextView ViewFlipper ListView GridView
如下图所示
1 RemoteViews通过Binder传递至SystemServer进程(因为RemoteViews实现了Parcelable接口,因此它可以跨进程传输)
2 系统根据RemoteViews中的packageName, layoutId去得到该应用的资源,之后通过LayoutInflater去加载RemoteViews中的布局文件 (在SystemServer中加载的是一个普通的View,只不过相对于我们的进程他是一个RemoteView而已)
3 系统对View界面执行一系列的更新操作,即通过set方法提交的,但更新操作不是立即执行(在RemoteViews内部会记录所有的更新操作),而是到RemoteViews被加载后执行
4 RemoteViews显示后,再次更新时,则调用set方法并通过NotificationManger与AppWidgetManger来提交更新任务,具体更新操作在SystemServer中完成
5 每一次的set操作对应着一个action (对应着一个view操作,实现了Parcelable接口),RemoteViews会添加一个对应的action对象 ,当这些更新操作被提交时,这些action会被跨进程传输到远程进程中并在远程进程执行。远程进程通过RemoteViews的apply方法进行view的更新操作(apply内部回去遍历所有的action并执行action的apply方法),通知栏和桌面小插件在初始化界面时调用apply,后续更新界面会调用reapply。如图示
RemoteViews中只支持发起PendingIntent,不支持onClickListener模式
例:
Intent btIntent = new Intent();
btIntent.setAction("com.yu.sendnotification.action_dl");
PendingIntent btPendingIntent = PendingIntent.getBroadcast(this, 1, btIntent, PendingIntent.FLAG_CANCEL_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.bt_stop, btPendingIntent);//给id为stop的view设置点击事件
setPendingIntentTemplatey与setOnClickFillInIntent须结合,给ListView和StackView中的item添加点击事件
1 一个应用简单的更新另一个应用的界面,可以选择AIDL去实现。但对界面的更新比较频繁,这个时候就会有效率问题,同时AIDL接口就有可能使问题复杂化,此时不宜使用aidl
2 对于界面更新比较频繁,适宜采用RemoteView来实现就,当然remoteView也有点缺点,remoteView仅支持一些常见的View,不支持自定View
后记:此篇为总结篇,作了个人梳理。参照了安卓开发艺术探索相关内容。