一、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中的布局文件