RemoteViews应用以及内部机制、原理(上)。
来源:互联网 发布:软件过程管理 pdf 编辑:程序博客网 时间:2024/04/20 11:28
一、概述。
RemoteViews是一种远程View,它提供了一组基础的操作用于跨进程更新它的界面。
一般RemoteViews在android中的应用场景有两种:一种是通知栏,另一种是桌面小部件。
二、应用。
(1)、通知栏。
首先使用系统默认的样式创建一个通知,
Intent intent = new Intent(this, NotificationActivity.class); PendingIntent pi = PendingIntent.getActivity(this,0,intent,0); //待定时刻发生的Intent NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); Notification notification = new NotificationCompat.Builder(this) .setContentTitle("This is context title") // 标题 .setContentText("This is context text") // 内容 .setWhen(System.currentTimeMillis()) //创建通知的时间 .setSmallIcon(R.mipmap.ic_launcher) //状态栏图标 .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher)) //通知栏的图标 .setContentIntent(pi) //单击跳转 .setAutoCancel(true) // 点击后清除本身// .setDefaults(NotificationCompat.DEFAULT_ALL)// .setStyle(new NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(), R.drawable.zz)))// .setStyle(new NotificationCompat.BigTextStyle().bigText("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"))上述代码会创建一个系统默认的通知栏,单击后会跳转至NotificationActivity,并且会清除本身。.build();
manager.notify(1,notification);
接下来,我们需要新建一个布局文件,然后使用RemoteViews加载这个布局文件,并且将那Notification的RemoteViews设置为新建的RemoteViews,即可改变通知样式。
布局文件remote_view.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/image" android:layout_width="100dp" android:layout_height="100dp" android:src="@drawable/back" /> <TextView android:id="@+id/content_text" android:layout_width="match_parent" android:textSize="20dp" android:layout_height="100dp" android:text="This is a aircraft" /></LinearLayout>创建样式为RemoteView的通知:
Intent intent = new Intent(this, NotificationActivity.class);PendingIntent pi = PendingIntent.getActivity(this,0,intent,0); //待定时刻发生的IntentNotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.remote_views);remoteViews.setTextViewText(R.id.content_text,"This is a airCraft, la la la !"); //设置TextView内容remoteViews.setImageViewResource(R.id.image,R.drawable.back); // 设置ImageView 图片Notification notification = new NotificationCompat.Builder(this) .setContentTitle("This is context title") // 标题 .setCustomContentView(remoteViews) .setWhen(System.currentTimeMillis()) //创建通知的时间 .setSmallIcon(R.mipmap.ic_launcher) //状态栏图标 .setContentIntent(pi) //单击跳转 .setAutoCancel(true) // 点击后取消通知 .build();manager.notify(2,notification);上述需要注意的是RemoteViews的构造函数,参数1为包名,参数2为布局资源Id。
RemoteView无法像Activity那样直接更新View,为了跨进程更新界面,因此它提供了许多set方法。
setTextViewText中第一个参数为TextView的id,第二个参数为内容。
setImageViewResource中第一个参数也为ImageView的id,第二个参数即为要设置图片资源的id.
结果如下,底下为系统默认样式,
上边为RemoteViews样式。
(2)桌面小部件。
AppWidgetProvider是用于实现桌面小部件的类,本质是一个广播,继承自BroadcastReceiver。
本例实现一个桌面计数的小部件。
首先需要在layout下新建一个XML文件,命名widget.xml,内容自定义。
由于我们只需要计数,所以一个TextView即可。
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/high_low_wather" android:layout_gravity="center" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout>
其次需要定义小部件的配置信息。
新建文件夹res/xml,在此文件夹下新建weather.xml,添加内容如下:
<?xml version="1.0" encoding="utf-8"?><appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="294dp" android:minHeight="72dp" android:updatePeriodMillis="86400000" android:initialLayout="@layout/widget" android:resizeMode="horizontal|vertical"></appwidget-provider>initialLayout 为初始化的布局。
minHeight和minWidth定义小工具的最小尺寸,
updatePeriodMillis自动更新周期,单位为毫秒,每隔一个周期,小工具自动更新就会触发。
新建一个服务用来每隔一秒发送一个广播(action为con.yang.widget.UPDATE_ALL)并且给NumProvider提供的数据加1。
public class NumUpdateService extends Service { private static final String TAG="WeatherUpdateService"; // 更新 widget 的广播对应的action private final String ACTION_UPDATE_ALL = "com.yang.widget.UPDATE_ALL"; // 周期性更新 widget 的周期 private static final int UPDATE_TIME = 1000; // 周期性更新 widget 的线程 private UpdateThread mUpdateThread; private Context mContext; private int temp = 0; @Override public void onCreate() { // 创建并开启线程UpdateThread mUpdateThread = new UpdateThread(); mUpdateThread.start(); mContext = this.getApplicationContext(); super.onCreate(); } @Override public void onDestroy(){ // 中断线程,即结束线程。 if (mUpdateThread != null) { mUpdateThread.interrupt(); } super.onDestroy(); } @Override public IBinder onBind(Intent intent) { return null; } /* * 服务开始时,即调用startService()时,onStartCommand()被执行。 */ @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand"); super.onStartCommand(intent, flags, startId); return START_STICKY; } private class UpdateThread extends Thread { @Override public void run() { super.run(); try { while (true) { Intent updateIntent=new Intent(ACTION_UPDATE_ALL); updateIntent.putExtra("temp",temp); temp++;// updateIntent.putExtra("high_low",32); mContext.sendBroadcast(updateIntent); Thread.sleep(UPDATE_TIME); } } catch (InterruptedException e) { // 将 InterruptedException 定义在while循环之外,意味着抛出 InterruptedException 异常时,终止线程。 e.printStackTrace(); } } }}
定义小部件的实现类NumProvider
public class NumProvider extends AppWidgetProvider { private static final String TAG = "WeatherProvider"; private boolean DEBUG = false; // 启动ExampleAppWidgetService服务对应的action private final Intent EXAMPLE_SERVICE_INTENT = new Intent("android.appwidget.action.EXAMPLE_APP_WIDGET_SERVICE"); // 更新 widget 的广播对应的action private final String ACTION_UPDATE_ALL = "com.yang.widget.UPDATE_ALL"; // 保存 widget 的id的HashSet,每新建一个 widget 都会为该 widget 分配一个 id。 private int appId; private AppWidgetManager mAppWidgetManager; private int mTemp; @Override public void onEnabled(Context context) { Log.d(TAG, "onEnabled"); Intent _intent = new Intent(context, NumUpdateService.class); context.startService(_intent); super.onEnabled(context); } @Override public void onDisabled(Context context) { Log.d(TAG, "onDisabled"); Intent _intent = new Intent(context, NumUpdateService.class); context.stopService(_intent); super.onDisabled(context); } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); appId = appWidgetIds[0]; } @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); ComponentName thisWidget = new ComponentName(context,NumProvider.class);//定义容器 int temp = intent.getIntExtra("temp",0); AppWidgetManager appWidgetManager = AppWidgetManager .getInstance(context); if (ACTION_UPDATE_ALL.equals(action)) { // “更新”广播 Log.d(TAG, "update"); mTemp = temp; RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.widget); remoteView.setTextViewText(R.id.high_low_wather,String.valueOf(mTemp)); remoteView.setTextViewTextSize(R.id.high_low_wather,TypedValue.COMPLEX_UNIT_DIP,150); appWidgetManager.updateAppWidget(thisWidget, remoteView); } super.onReceive(context, intent); }}在配置文件AndroidManifest.xml声明小部件:
<receiver android:name=".NumProvider" > <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="com.yang.widget.UPDATE_ALL"/> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/weather" /></receiver>
当广播到来时,AppWidgetProvider会根据广播的action通过onReceive方法进行自动分发广播。
通过新建一个RemoteViews,通过set方法设置TextView内容以及字体大小,然后通过AppWidgetManager的updateAppWidget方法更新界面,方法中第一个参数为容器,第二个参数为RemoteViews的实例。
结果如图所示
AppWidgetProvider包含如下几个方法,
onEnable:
当窗口小部件第一次添加到桌面时调用该方法,可添加多次但只在第一次调用。
onUpdate:
小部件被添加时或者每次小部件更新时都会调用一次该方法,小部件的更新时机由updatePeriodMillis来指定,每个周期小部件都会自动更新一次。
onDeleted:
每删除一次桌面小部件就调用一次。
onDisabled:
当最后一个该类型的桌面小部件被删除时调用该方法,注意是最后一个。
onReceive:
广播的内置方法,用来分发具体事件给其它方法。
这两个例子在我的github上,需要的可以直接下载
通知: https://github.com/wangchenyangzz/NotificationTest
小部件: https://github.com/wangchenyangzz/AppWidget
RemoteViews的应用就先说到这,下篇会分析RemoteViews的内部机制及原理。
- RemoteViews应用以及内部机制、原理(上)。
- RemoteViews内部实现机制及应用
- RemoteViews的内部机制
- RemoteViews之RemoteViews的内部机制
- 024.RemoteViews的内部机制
- RemoteViews原理分析及应用
- SDWebImage的内部原理、实现机制以及优化方式
- Windows上CAtlFileMapping共享内存的使用以及内部机制
- RemoteViews(一):应用
- RemoteViews的应用
- RemoteViews的简单应用
- AppWidgetProvider小部件开发(RemoteViews 机制分析)
- ConcurrentLinkedQueue的原理以及CAS机制在其中的应用
- Notification及桌面小部件的应用(RemoteViews)
- Study-Hard-数据库连接及实现内部原理(上)
- CA认证原理以及实现(上)
- CA认证原理以及实现(上)
- java 动态绑定 以及 内部实现机制
- 二叉树的广度与深度遍历
- Springmvc中@RequestParam传值中文乱码解决方案
- Oracle基础查询语句80条
- 使用java底层实现邮件的发送(含测试,源码)
- java 学生成绩管理系统
- RemoteViews应用以及内部机制、原理(上)。
- C++综合系列之模拟事件机制
- 欢迎使用CSDN-markdown编辑器
- Java Swing 图形界面开发简介
- 与第三方ERP系统同步数据总结
- 无限极下拉列表数据库和代码
- 多态
- C++11之智能指针
- 《一斛珠·元夜月蚀》