android进阶(五)-----理解RemoteViews

22 篇文章 0 订阅
12 篇文章 1 订阅

一、RemoteView的应用

RemoteView主要用在通知栏和桌面小部件的开发

1、RemoteView在通知栏上的应用

(1)使用系统默认的样式弹出一个通知栏,代码实例:

Notification notification = new Notification();

notification.icon = R.drawable.ic_launcher;

notification.tickerText = "hello"

notification.when = System.currentTimeMillis();

notification.flags = Notification.FLAG_AUTO_CANCEL;

Intent intent = new Intent(this,MainActivity.class);

PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);

notification.setLatestEventInfo(this,"aaa","bbbb",pendingIntent);

NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

manager.notify(1,notification);

(2)通过RemoteView自定义通知栏布局文件

Notification notification = new Notification();

notification.icon = R.drawable.ic_launcher;

notification.tickerText = "hello"

notification.when = System.currentTimeMillis();

notification.flags = Notification.FLAG_AUTO_CANCEL;

Intent intent = new Intent(this,MainActivity.class);

PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);

RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.notification);

remoteViews.setTextViewText(R.id.msg,"vvvv");

remoteViews.setImageViewResource(R.id.icon,R.drawable.icon1);

PendingIntent openActivityPendingIntent = PendingIntent.getActivity(this,0,new Intent(this,MainActivity.class),PendingIntent.FLAG_UPDATE_CURRENT);

remoteViews.setOnClickPendingIntent(R.id.open_activity2,openActivityPendingIntent);

notification.contentView = remoteViews;

notification.contentIntent = pendingIntent;

NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

manager.notify(2,notification);

 

2、RemoteViews在桌面小部件上的应用

AppWidgetProvider是android中用于实现桌面小部件的类,本质是一个广播

(1)定义小部件界面:widget.xml

<?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">


        <ImageView android:id="@+id/imageView1"

                   android:layout_width="wrap_content"

                   android:layout_height="wrap_content"

                   android:src="@drawable/icon1"/>

</LinearLayout>

(2)定义小部件配置信息:appwidget_provider_info.xml

initialLayout:初始化布局

updatePeriodMillis:自动更新周期,单位是毫秒

<?xml version="1.0" encoding="utf-8">

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

        android:initialLayout="@layout/widget"

        android:minHeight="84dp"

        android:minWidth="84dp"

        android:updatePeriodMillis="86400000">

</appwidget-provider>

(3)定义小部件的实现类

public class AppWidgetProvider extends AppWidgetProvider{

public static final String CLICK_ACTION = "com.test.test.action.CLICK"



public AppWidgetProvider(){

    super();

}

@Override

public void onReceive(final Context context,Intent intent){

    super.onReceive(context,intent);

    //这里判断自己的action,如被单击了

    if(intent.getAction().equals(CLICK_ACTION)){

        Toast.makeText(context,"click",Toast.LENGTH_SHORT).show();

        new Thread(new Runnable(){

            @Override

            public void run(){

                Bitmap srcbBitmap=BitmapFactory.decodeResource(context.getResources(),R.drawable.icon1);

                AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

                for(int i=0;i<37;i++){

                    float degree = (i * 10) %360;

                    RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget);

                    remoteViews.setImageViewBitmap(R.id.imageView1,rotateBitmap(context,srcbBitmap,degree));

                    Intent intentClick = new Intent();

                    intentClick.setAction(CLICK_ACTION);

                    PendingIntent pendingIntent = PendingIntent.getBroadcase(context,0,intentClick,0);

                    remoteViews.setOnClickPendingIntent(R.id.imageView1,pendingIntent);

                    appWidgetManager.updateAppWidget(new ComponentName(context,AppWidgetProvider.class),remoteViews);

                    SystemClock.sleep(30);

                }

            }

        }).start();

    }

}

/**

*每次桌面部件更新时都调用一次该方法

*/

@Override

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

    super.onUpdate(conte,appWidgetManager,appWidgetIds);

    final int counter = appWidgetIds.length;

    for(int i= 0; i < counter;i++){

        int appWidgetId = appWidgetIds[i];

        onWidgetUpdate(context,appWidgetManager,appWidgetId);

    }
}

/**

* 桌面小部件更新

*/
private void onWidgetUpdate(Context context,AppWidgetManager appWidgetManager,int appWidgetId){

    RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget);

    //桌面小部件点击事件发送Intent广播

    Intent intentClick = new Intent();

    intentClick.setAction(CLICK_ACTION);

    PendingIntent pendingIntent = PendingIntent.getBroadcase(context,0,intentClick,0);

    remoteViews.setOnClickPendingIntent(R.id.imageView1,pendingIntent);

    appWidgetManager.updateAppWidget(appwidgetId,remoteViews);

}



private Bitmap rotateBitmap(Context context,Bitmap srcbBitmap,float degree){
    Matrix matrix = new Matrix();

    matrix.reset();

    matrix.setRotate(degree);

    Bitmap tmpBitmap=Bitmap.createBitmap(srcbBitmap,0,0,srcbBitmap.getWidth(),scrbBitmap.getHeight(),matrix,true);
   
    return tmpBitmap;
}

}

(4)在AndroidManifest.xml中声明小部件

3、AppWidgetProvider方法:onUpdate、onEnabled、onDisabled、onDeleted和onReceive

onEnable:当窗口小部件第一次添加到桌面时调用,可添加多次但只在第一次调用

onUpdate:小部件被添加或者小部件更新时都会调用一次该方法,小部件更新时机由updatePeriodMillis来指定,每个周期小部件都会自动更新一次

onDeleted:每次删除一次桌面小部件就会调用一次

onDisabled:当最后一个该类型的桌面小部件被删除是调用该方法

onReceive:广播的内置方法,用于分发具体的事件给其他方法

 

4、PendingIntent介绍

PendingIntent表示一种处于pending状态的意图,,而pending状态表示一种待定、等待、即将发生的意思。

PendingIntent支持三种待定意图:启动Activity、启动Service和发送广播即:

getActivity(Context context,int requestCode,Intent intent,int flags)获得一个PendingIntent,该待定意图发生时,相当于Context.startActivity(intent)

getService(Context context,int requestCode,Intent intent,int flags)获得一个PendingIntent,该待定意图发生时,相当于Context.startService(intent)

getBroadcast(Context context,int requestCode,Intent intent,int flags)获得一个PendingIntent,该待定意图发生时,相当于Context.sendBroadcase(intent)

 

flags常见类型有:

FLAG_ONE_SHOT:PendingIntent只能被使用一次,然后会被自动cancel

FLAG_NO_CREATE:PendiingIntent不会主动创建,如果不存在,那么getActivity、getService和getBroadcast会直接返回null。

FLAG_CANCEL_CURRENT:PendingIntent如果存在,那么他们会被cancel,然后系统会创建一个新的PendingIntent。

FLAG_UPDATE_CURRENT:PendingIntent如果存在,那么他们会被更新。

 

二:RemoteView的内部机制

1、RemoteView的作用是在其他进程中显式并更新View界面。先看一下他的构造方法:

public RemoteView(String packageName,int layoutId),一个表示包名,第二个表示布局文件

RemoteView不支持所有View类型,只支持:FrameLayout、LinearLayout、RelativeLayout、GridLayout、AnalogClock、Button、Chronometer、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView、AdapterViewFlipper、ViewStub。

RemoteView不支持他们子类和其他View类型,无法使用自定义View

2、RemoteViews的set方法

RemoteViews没有提供findViewById方法,无法直接访问里面的View,必须通过set方法

setTextViewText:设置TextView的文本

setTextViewTextSize:设置TextView的字体大小

setTextColor:设置TextView的字体颜色

setImageViewResource:设置ImageView的图片资源

setInt:反射调用View对象的参数类型为int的方法

setLong:反射调用View对象的参数类型为long的方法

setBoolean:反射调用View对象的参数类型为boolean的方法

setOnClickPendingIntent:为View添加单击事件,事件类型只能为PendingIntent

3、RemoteViews的内部机制

通知栏和桌面小部件分别由NotificaionManager和AppWidgetManager管理,而NotificaionManager和AppWidgetManager通过Binder分别和SystemServer进程中的NotificationManagerService以及AppWidgetService进行通信。

RemoteViews通过Binder传递到SystemServer进程,因为RemoteViews实现了Parcelable接口,所以可以跨进程传输,系统根据RemoteViews中的包名去得到该应用的资源,然后通过LayoutInflater去加载RemoteViews中的布局文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值