桌面小部件开发:
一,AppWidgetProvider
(本质是一个广播) 运行在SystemServier 通过RemoteViews 跨进程更新
1.xml文件
注册的xml文件:
<receiver android:name=".widget.TableWidget"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
<action android:name="com.com.example.cuizehui.estore.widget.Click"/>
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/example_appwidget_info" />
</receiver>
配置 长相的XML文件:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="80dp"
android:minHeight="80dp"
android:previewImage="@drawable/shop_normal"
android:initialLayout="@layout/tablewidget_layout"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen|keyguard">
<!--
android:minWidth : 最小宽度
android:minHeight : 最小高度
android:updatePeriodMillis : 更新widget的时间间隔(ms),"86400000"为1个小时
android:previewImage : 预览图片
android:initialLayout : 加载到桌面时对应的布局文件
android:resizeMode : widget可以被拉伸的方向。horizontal表示可以水平拉伸,vertical表示可以竖直拉伸
android:widgetCategory : widget可以被显示的位置。home_screen表示可以将widget添加到桌面,keyguard表示widget可以被添加到锁屏界面。
android:initialKeyguardLayout : 加载到锁屏界面时对应的布局文件
-->
</appwidget-provider>
2.实现类
public class TableWidget extends AppWidgetProvider {
public static final String ClickAction="com.com.example.cuizehui.estore.widget.Click" ;
public TableWidget() {
super();
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
//对ui进行初始化
RemoteViews remoteViews=new RemoteViews(context.getPackageName(), R.layout.tablewidget_layout);//
包名和布局文件名
remoteViews.setImageViewResource(R.id.table_imageview,R.drawable.tabl);
ComponentName componentName=new ComponentName(context,TableWidget.class);
//设置点击事件
Intent intentclick=new Intent(context,MainActivity.class);
// intentclick.setAction(ClickAction);
PendingIntent pendingIntent=PendingIntent.getActivity(context,0,intentclick,0);
remoteViews.setOnClickPendingIntent(R.id.table_imageview,pendingIntent);
/* //如果时内部 则相当于给自己发送广播 注册好action 后自己发送
Intent intentaciton=new Intent();
PendingIntent pendingIntentclick=PendingIntent.getBroadcast(context,0,intentaciton,0);
remoteViews.setOnClickPendingIntent(R.id.table_imageview,pendingIntentclick);
*/
appWidgetManager.updateAppWidget(componentName,remoteViews);
}
//接受到广播后自己要做什么
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent.getAction().equals(ClickAction)){
AppWidgetManager appWidgetManager=AppWidgetManager.getInstance(context);
//对ui进行修改
RemoteViews remoteViews=new RemoteViews(context.getPackageName(), R.layout.tablewidget_layout);
Bitmap bitmap= BitmapFactory.decodeResource(context.getResources(),R.drawable.tabl);
remoteViews.setImageViewBitmap(R.id.table_imageview,rotateBitmap(context,bitmap,180));
appWidgetManager.updateAppWidget(new ComponentName(context,TableWidget.class),remoteViews);
}
}
private Bitmap rotateBitmap(Context context,Bitmap srcbBitmap ,float degeree){
Matrix matrix=new Matrix();
matrix.reset();
matrix.setRotate(degeree);
Bitmap tmpBitmap=Bitmap.createBitmap(srcbBitmap,0,0,srcbBitmap.getWidth(),srcbBitmap.getHeight(),matrix,true);
return tmpBitmap;
}
}
onRreceive 源码可以看到
是根据Intent 来判断 并自动调用其中的 onUpdata/onDisable/....等几个方法的
(所以我们也可以自己注册Action 并获取 在其中写自己的逻辑)
3.点击事件
PedingIntent (send/cancel)
支持三种待定的意图 (activity /broadcast/service)
4个参数, 最后一个Flag的作用是通过前两个 参数(requestcode 和intent 其中的intent-fitlter和conponext)用来标识 是否是同一 来选择是否send/cancel。
setOnclickPedingIntent() 即可完成点击事件的注册。
4.更新UI的方式
这段代码是用来更新UI的:
AppWidgetManager appWidgetManager=AppWidgetManager.getInstance(context);
//对ui进行修改
RemoteViews remoteViews=new RemoteViews(context.getPackageName(), R.layout.tablewidget_layout);
Bitmap bitmap= BitmapFactory.decodeResource(context.getResources(),R.drawable.tabl);
remoteViews.setImageViewBitmap(R.id.table_imageview,rotateBitmap(context,bitmap,180));
appWidgetManager.updateAppWidget(new ComponentName(context,TableWidget.class),remoteViews);
本质上是AppwidgetManager 通过Binder 和SystemService中的 AppwigetService 进行通信
Remoteview 实现了parcelable 接口所以可以通过Binder进行传输
每次Remoteview的set方法本质都是产生了一个RemotionAction对象放到 list中, 传递过去后通过 apply 拆包的(最终是RemoteView的Apply 和reApply 方法获取的)
http://blog.csdn.net/qq_26787115/article/details/54427183