RemoteView
字面意思可以翻译为远程view,该view运行于其他进程中,主要是系统进程,多用于通知栏和桌面widget中,当view运行在其他进程的时候 我们无法像在Activity中那样直接更新view,为了能够跨进程更新view,RomoteView提供了一系列的set方法
RemoteView在通知栏中的应用简单举例
- 使用系统默认样式弹出一个通知栏
Notification notification = new Notification(); notification.icon = R.mipmap.ic_launcher; notification.tickerText = "hello world"; notification.when = System.currentTimeMillis()+1000; notification.flags = Notification.FLAG_AUTO_CANCEL; Intent intent = new Intent(this,xxx.class); PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT); notification..setLatestEventInfo(this,"","",pendingIntent); NotificationManager manager =(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(1,notification);
2. 自定义样式的通知栏
Notification notification = new Notification(); notification.icon = R.mipmap.ic_launcher; notification.tickerText = "hello world"; notification.when = System.currentTimeMillis()+1000; notification.flags = Notification.FLAG_AUTO_CANCEL; Intent intent = new Intent(this,xxx.class); PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT); RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.xxx); remoteViews.setTextViewText(R.id.xx,"xxx"); remoteViews.setImageViewResource(R.id.xx,R.mipmap.xx); PendingIntent openActivityPendingIntent = PendingIntent.getActivity(this,0,new Intent(this,xxx.class),PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.xxx,openActivityPendingIntent); notification.contentView = remoteViews; notification.contentIntent = pendingIntent; NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(2.notification);
RemoteViews的使用很简单,只需要提供当前应用的包名和布局文件的资源id即可创建一个RemoteViews对象,更新RemoteViews的方法比较复杂,因为RemoteViews运行在系统的进程中 我们无法直接访问里面的view 所以必须通过,RemoteViews提供的一系列方法来更新view
remoteViews.setTextViewText(R.id.xx,"");//参数分别为TextView的id和要设置的文本 remoteViews.setImageViewResource(R.id.xx,R.mipmap.xx);//参数分别为ImageView的id和要设置的图片的资源id remoteViews.setOnClickPendingIntent(R.id.xx,pendingIntent);//参数分别为要加点击事件的控件的id和pendingIntent
RomoteViews在桌面小部件中的应用
AppWidgetProvider是Android提供的用于实现桌面小部件的类,其本质是一个广播,继承自BroadcaseReceiver
具体使用步骤可分为以下几步
- 定义小部件界面
在layout中定义widget.xml文件 定义小部件配置信息
在res/xml文件夹中定义appwidget_info.xml文件<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="84dp" android:minHeight="84dp" android:updatePeriodMillis="86400000" android:previewImage="@mipmap/ic_launcher" android:initialLayout="@layout/widget" android:resizeMode="horizontal|vertical" android:widgetCategory="home_screen|keyguard" android:initialKeyguardLayout="@layout/widget"> <!-- 简单介绍一下上述的属性 minWidth和minHeight是最小的宽高 updatePeriodMillis 是指更新周期 每过一段时间appwidget会自动更新一次 previewImage是指预览图 如果不设置则默认显示应用图标 initialLayout是指appWidget的布局文件 resizeMode是指appWidget的可伸缩方向 widgetCategory是指appWidget只用的位置 包括桌面和锁屏 initialKeyguardLayout是指appWidget在锁屏模式的资源文件 --> </appwidget-provider>
定义小部件的实现类
package com.zzp.example.remoteviews; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; import android.content.Intent; import android.widget.RemoteViews; import com.zzp.example.R; /** *桌面小部件的实现类 具体使用方法参见本包中的ReadMe文件 */ public class MyAppWidgetProvider extends AppWidgetProvider{ private static final String TAG = "MyAppWidgetProvider"; public static final String CLICK_ACTION = ""; public MyAppWidgetProvider(){ super(); } /** *当该窗口小部件第一次添加到桌面的时候调用该方法 *添加多次 但只会调用一次 *@param context */ @Override public void onEnabled(Context context) { super.onEnabled(context); } /** *小部件被添加或者更新的时候回调用该方法 *小部件的更新时机由updatePeriodMills来制定 每个周期都会自动更新一次 *@param context *@param appWidgetManager *@param appWidgetIds */ @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); int count = appWidgetIds.length; for(int i = 0;i<count;i++){ int appWidgetId = appWidgetIds[i]; //更新桌面小部件 onWidgetUpdate( context,appWidgetManager,appWidgetId); } } /** *更新桌面小部件 *@param context *@param appWidgetManager *@param appWidgetId */ private void onWidgetUpdate(Context context, AppWidgetManager appWidgetManager, int appWidgetId) { RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget); //定义桌面小部件单击事件要发送的广播 Intent intent = new Intent(); intent.setAction(CLICK_ACTION); PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0,intent,0); remoteViews.setOnClickPendingIntent( R.id.iamgeView1,pendingIntent); appWidgetManager.updateAppWidget( appWidgetId,remoteViews); } /** *每删除一个桌面小部件就会调用一次 *@param context *@param appWidgetIds */ @Override public void onDeleted(Context context, int[] appWidgetIds) { super.onDeleted(context, appWidgetIds); } /** *当最后一个桌面小部件被删除的时候会调用该方法 只会调用一次 *@param context */ @Override public void onDisabled(Context context) { super.onDisabled(context); } /** *这是广播的内置方法 用于分发具体的事件给其他方法 *@param context *@param intent */ @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); //这里是判断我们自己定义的action 做对应的事情 比如被单击了要做什么事情 if(intent.getAction().equals(CLICK_ACTION)){ //doSomething } } }
在AndroidManifest中声明小部件
<receiver android:name=".remoteviews.MyAppWidgetProvider"> <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_info" /> <intent-filter> <action android:name="xxx" /> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <!-- 这两个action第一个是我们自定义的 第二个是作为小部件的标识而必须存在的 如果不加 那么这个receiver就不是一个桌面小部件 并且无法出现在系统的小部件列表中--> </intent-filter> </receiver>
- 定义小部件界面
参考资料:Android开发艺术探索