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