什么是RemoteViews?使用场景有哪些

emoteViews,顾名思义,就是远程的View,也就是可以运行在其他进程中的View。RemoteViews常用在通知和桌面小组件中。

一、RemoteViews应用到通

首先来介绍一下系统自带的通知(Notification)的使用。Notification的使用有两种方法,分别是Notification直接创建的方式和使用Notification.Builder创建者模式创建的方式。先来看一下使用Notification直接创建的方式的代码:

Notification notification =new Notification();

notification.icon = R.mipmap.ic_launcher;// 小图标notification.largeIcon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher_round);// 大图标notification.defaults = Notification.DEFAULT_ALL;// 设置默认的提示音、振动方式、灯光等notification.category = "Category";

notification.when = System.currentTimeMillis();// 设置通知发送的时间戳notification.tickerText = "Ticker Text";// 设置通知首次弹出时,状态栏上显示的文本notification.flags = Notification.FLAG_AUTO_CANCEL;// 点击通知后通知在通知栏上消失notification.contentIntent = PendingIntent.getActivity(MainActivity.this, 0x001,

        newIntent(MainActivity.this, TargetActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);// 设置通知的点击事件((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(1, notification);// 发送系统通知

 通过上面的代码,就可以简单地发送一条通知到通知栏中。使用这种方式不需要有API版本的限制,但可以进行的操作比较少。

  下面来看一下使用Notification.Builder创建者模式创建通知的代码:

PendingIntent pi = PendingIntent.getActivity(MainActivity.this, 0x001,

        newIntent(MainActivity.this, TargetActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);

Notification.Builder nb =newNotification.Builder(MainActivity.this)

        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher_round)) // 大图标.setSmallIcon(R.mipmap.ic_launcher)// 小图标.setContentText("Content Text")// 内容.setSubText("Sub Text")// 在通知中,APP名称的副标题.setContentTitle("Content Title")// 标题.setTicker("Ticker")// 设置通知首次弹出时,状态栏上显示的文本.setWhen(System.currentTimeMillis())// 设置通知发送的时间戳.setAutoCancel(true)// 点击通知后通知在通知栏上消失.setDefaults(Notification.DEFAULT_ALL)// 设置默认的提示音、振动方式、灯光等.setContentIntent(pi);// 设置通知的点击事件((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(1, nb.build());// build()方法需要的最低API为16

使用这种方式,需要注意对项目的API版本进行一定的控制,上面这段代码需要的API版本最低是16。

上面两种方式都是发送系统自带的通知。如果我们需要自定义通知的样式,就需要使用到RemoteViews了。RemoteViews给我们提供了一种可以在其他进程中生成View并进行更新的机制,但是它可以控制和操作的View有一定的限制,具体如下:

Layout:

    FrameLayout、LinearLayout、RelativeLayout、GridLayout

View:

    AnalogClock、Button、Chronometer、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView、AdapterViewFlipper、ViewStub

使用RemoteViews发送一个自定义系统通知的代码如下:

PendingIntent pi = PendingIntent.getActivity(MainActivity.this, 0x001,

        newIntent(MainActivity.this, TargetActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);

RemoteViews remoteView =new RemoteViews(getPackageName(), R.layout.remoteview_main);

remoteView.setTextViewText(R.id.remoteview_main_title, "Title");

remoteView.setTextViewText(R.id.remoteview_main_content, "ContentContentContent");

remoteView.setImageViewResource(R.id.remoteview_main_icon, R.mipmap.ic_launcher_round);

remoteView.setOnClickPendingIntent(R.id.remoteview_main_view, pi);

Notification.Builder nb =newNotification.Builder(MainActivity.this)

        .setSmallIcon(R.mipmap.ic_launcher) // 小图标.setCustomContentView(remoteView)// 设置自定义的RemoteView,需要API最低为24.setWhen(System.currentTimeMillis())// 设置通知发送的时间戳.setAutoCancel(true)// 点击通知后通知在通知栏上消失.setDefaults(Notification.DEFAULT_ALL);// 设置默认的提示音、振动方式、灯光等((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(1, nb.build());// build()方法需要的最低API为16

  可以看到,我们在自定义的通知布局中设置了TextView和ImageView,并在代码中动态地更新了其显示的内容。

二、RemoteViews应用到桌面小组件

  RemoteViews也可以应用到桌面小组件中。这里我们通过一个例子来了解RemoteViews应用到桌面小组件的步骤,它总共分为五步,分别是:设置桌面小组件的布局、编写桌面小组件的配置文件、编写桌面小组件更新的Service、编写桌面小组件的控制类AppWidgetProvider、配置配置文件。

  我们通过下面这个例子来介绍RemoteViews在桌面小组件中的应用。在这个例子中,我们向系统中添加一个小组件,在这个小组件中显示当前的日期和时间。

  首先,设置桌面小组件的布局,具体代码如下:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"><TextView

        android:id="@+id/widget_main_tv_time"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:textColor="@android:color/white"        android:textSize="22.0sp"        android:textStyle="bold"/></LinearLayout>

然后,编写桌面小组件的配置文件,具体步骤是:在项目res文件夹下新建一个xml文件夹,在xml文件夹中创建一个XML文件,具体代码如下:

<?xml version="1.0" encoding="utf-8"?><appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/widget_main" android:minHeight="100.0dip" android:minWidth="150.0dip" android:updatePeriodMillis="8640000"></appwidget-provider>

这个文件中的各个参数的解释如下:

initialLayout:桌面小组件的布局XML文件

minHeight:桌面小组件的最小显示高度

minWidth:桌面小组件的最小显示宽度

updatePeriodMillis:桌面小组件的更新周期。这个周期最短是30分钟

然后,编写一个Service,在这个Service中动态地获取到当前的时间并更新到桌面小组件中,代码如下:

import android.app.Service;import android.appwidget.AppWidgetManager;import android.content.ComponentName;import android.content.Intent;import android.os.IBinder;import android.support.annotation.Nullable;import android.widget.RemoteViews;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;/** * 定时器Service

*/public class TimerService extends Service {

    private Timer timer;

    privateSimpleDateFormat formatter =newSimpleDateFormat("yyyy-MM-dd hh:mm:ss");

    @Override

    public void onCreate() {

        super.onCreate();

        timer =new Timer();

        timer.schedule(new TimerTask() {

            @Override

            public void run() {

                updateViews();

            }

        }, 0, 1000);

    }

    @Nullable

    @Override

    public IBinder onBind(Intent intent) {

        return null;

    }

    private void updateViews() {

        String time = formatter.format(new Date());

        RemoteViews remoteView =new RemoteViews(getPackageName(), R.layout.widget_main);

        remoteView.setTextViewText(R.id.widget_main_tv_time, time);

        AppWidgetManager manager = AppWidgetManager.getInstance(getApplicationContext());

        ComponentName componentName =newComponentName(getApplicationContext(), WidgetProvider.class);

        manager.updateAppWidget(componentName, remoteView);

    }

    @Override

    publicvoid onDestroy() {

        super.onDestroy();

        timer =null;

    }

}

 然后,编写一个类继承自AppWidgetProvier,用来统一管理项目中的小组件,代码如下:

import android.appwidget.AppWidgetManager;import android.appwidget.AppWidgetProvider;import android.content.Context;import android.content.Intent;/** * AppWidgetProvider的子类,相当于一个广播

*/public class WidgetProvider extends AppWidgetProvider {

    /**    * 当小组件被添加到屏幕上时回调

    */    @Override

    public void onEnabled(Context context) {

        super.onEnabled(context);

        context.startService(newIntent(context, TimerService.class));

    }

    /**    * 当小组件被刷新时回调

    */    @Override

    public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {

        super.onUpdate(context, appWidgetManager, appWidgetIds);

    }

    /**    * 当widget小组件从屏幕移除时回调

    */    @Override

    public void onDeleted(Context context, int[] appWidgetIds) {

        super.onDeleted(context, appWidgetIds);

    }

    /**    * 当最后一个小组件被从屏幕中移除时回调

    */    @Override

    public void onDisabled(Context context) {

        super.onDisabled(context);

        context.stopService(newIntent(context, TimerService.class));

    }

}

  最后,在Manifest文件中配置刚刚编写的Service和BroadcastReceiver(AppWidgetProvider相当于一个广播),代码如下:

<service android:name=".TimerService"/><receiver android:name=".WidgetProvider"><intent-filter><action android:name="android.appwidget.action.APPWIDGET_UPDATE"/></intent-filter><meta-data

        android:name="android.appwidget.provider"        android:resource="@xml/widget"/></receiver>

  这里需要注意,<intent-filter>标签中的action的name和<meta-data>标签中的name的值是固定的,reousrce代表的是第二步中配置文件的位置。

  编写完上述代码之后,运行结果如下图所示:


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,192评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,858评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,517评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,148评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,162评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,905评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,537评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,439评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,956评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,083评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,218评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,899评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,565评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,093评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,201评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,539评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,215评论 2 358

推荐阅读更多精彩内容