android進階(五)-----理解RemoteViews

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章