当前位置: 代码迷 >> Android >> Android AppWidget范例验证
  详细解决方案

Android AppWidget范例验证

热度:33   发布时间:2016-05-01 17:16:59.0
Android AppWidget实例验证

1.创建AppWidget布局,包含两个TextView用来显示内容:?

Xml代码??收藏代码
  1. <?xml?version="1.0"?encoding="utf-8"?>??
  2. <LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"??
  3. ????android:layout_width="fill_parent"?android:layout_height="fill_parent"??
  4. ????android:orientation="vertical">??
  5. ????<TextView?android:layout_height="wrap_content"??
  6. ????????android:layout_width="fill_parent"?android:id="@+id/tv1"??
  7. ????????android:textColor="#FF0000"?android:textSize="24sp"?android:textStyle="bold"??
  8. ????????android:text="-1"></TextView>??
  9. ????<TextView?android:layout_height="wrap_content"?android:id="@+id/tv2"??
  10. ????????android:textSize="24sp"?android:textStyle="bold"?android:textColor="#00FF00"??
  11. ????????android:layout_width="fill_parent"?android:text="-2"></TextView>??
  12. </LinearLayout>??

2.在res下创建xml目录,再在xml目录里面创建AppWidget信息xml文件:?
2.1新建xml文件时,type选择AppWidget Provider。?
?

2.2填充属性:?
?
宽高的计算公式为:占用屏幕格数*74-2?
Update period millis:设置为0,手动刷新。根据实验,设置不为0时,至少在2.2上系统根本不按照设置的值刷新,还是自己控制刷新时机好了。?
Initial layout:就添控件要使用的布局。?
Configure暂时不用,留空。?
3.创建AppWidgetDemo类:?
?
重载AppWidgetProvider中的所有函数,每个函数里面增加输出语句,以查看调用顺序。?
Java代码??收藏代码
  1. public?class?AppWidgetDemo?extends?AppWidgetProvider?{??
  2. ??
  3. ????@Override??
  4. ????public?void?onDeleted(Context?context,?int[]?appWidgetIds)?{??
  5. ????????//?TODO?Auto-generated?method?stub??
  6. ????????super.onDeleted(context,?appWidgetIds);??
  7. ????????Log.e("AppWidgetDemo",?"onDeleted");??
  8. ????}??
  9. ??
  10. ????@Override??
  11. ????public?void?onDisabled(Context?context)?{??
  12. ????????//?TODO?Auto-generated?method?stub??
  13. ????????super.onDisabled(context);??
  14. ????????Log.e("AppWidgetDemo",?"onDisabled");??
  15. ????}??
  16. ??
  17. ????@Override??
  18. ????public?void?onEnabled(Context?context)?{??
  19. ????????//?TODO?Auto-generated?method?stub??
  20. ????????super.onEnabled(context);??
  21. ????????Log.e("AppWidgetDemo",?"onEnabled");??
  22. ????}??
  23. ??
  24. ????@Override??
  25. ????public?void?onReceive(Context?context,?Intent?intent)?{??
  26. ????????//?TODO?Auto-generated?method?stub??
  27. ????????super.onReceive(context,?intent);??
  28. ????????Log.e("AppWidgetDemo",?"onReceive,Action:"?+?intent.getAction());??
  29. ????}??
  30. ??
  31. ????@Override??
  32. ????public?void?onUpdate(Context?context,?AppWidgetManager?appWidgetManager,?int[]?appWidgetIds)?{??
  33. ????????//?TODO?Auto-generated?method?stub??
  34. ????????super.onUpdate(context,?appWidgetManager,?appWidgetIds);??
  35. ????????Log.e("AppWidgetDemo",?"onUpdate,Count:"?+?appWidgetIds.length);??
  36. ????}??
  37. ??
  38. }??

4.在AndroidManifest.xml文件中声明此Widget:?
添加一个Receiver,其name为AppWidgetDemo类的类名。?
Xml代码??收藏代码
  1. <receiver?android:name="AppWidgetDemo"></receiver>??

为此Receiver添加Intent filter,接收系统发出android.appwidget.action.APPWIDGET_UPDATE的Intent。?
Xml代码??收藏代码
  1. <receiver?android:name="AppWidgetDemo">??
  2. ????<intent-filter>??
  3. ????????<action?android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>??
  4. ????</intent-filter>????????????
  5. </receiver>??

此外还要为此receiver添加meta-data信息,以告知系统相关的AppWidgetProvider信息:?
Xml代码??收藏代码
  1. <meta-data?android:name="android.appwidget.provider"??
  2. ????????????????android:resource="@xml/widget_info_demo"></meta-data>??

meta-data的name是约定好的android.appwidget.provider,resource则是第2步创建的AppWidget信息xml文件。?

5.至此AppWidget已经可用了,安装到模拟器上看下运行流程。?
5.1添加一个Widget到桌面上:?
onEnabled被呼叫:按照说明,当桌面上出现第一个此Widget的实例时,此函数被呼叫。?
onReceive被呼叫:onReceive,Action:android.appwidget.action.APPWIDGET_ENABLED?
onUpdate被呼叫:onUpdate,Count:1,并且待更新的AppWidget数量为1?
onReceive被呼叫:onReceive,Action:android.appwidget.action.APPWIDGET_UPDATE?

5.2再添加一个Widget到桌面上:?
onUpdate被呼叫:onUpdate,Count:1,并且待更新的AppWidget数量仍然为1,而不是2。?
onReceive被呼叫:onReceive,Action:android.appwidget.action.APPWIDGET_UPDATE?

5.3从桌面上移除一个Widget:?
onDeleted:每个实例被移除时都会被呼叫?
onReceive,Action:android.appwidget.action.APPWIDGET_DELETED?

5.4再从桌面上移除一个Widget:?
onDeleted:仍然执行?
onReceive,Action:android.appwidget.action.APPWIDGET_DELETED?
onDisabled:因为是最后一个活动的实例被移除了,所以被呼叫。?
onReceive,Action:android.appwidget.action.APPWIDGET_DISABLED?

6.刷新AppWidget?
6.1在onUpdate()中刷新:?
onUpdate在AppWidget放到桌面时会被调用,在Update period millis达到时可能会被调用。?
Java代码??收藏代码
  1. RemoteViews?appWidgetView?=?new?RemoteViews(context.getPackageName(),?R.layout.widget_layout_demo);??
  2. appWidgetView.setTextViewText(R.id.tv1,?String.valueOf(mCount));??
  3. appWidgetView.setTextViewText(R.id.tv2,?String.valueOf(mCount));??
  4. appWidgetManager.updateAppWidget(appWidgetIds,?appWidgetView);??

先获取一个RemoteViews,也就是AppWidget的布局所对应的View;?
使用指定的Id更新要更新的控件;?
更新整个RemoteViews,此时就可以更新AppWidget内容了。?

但是这样的代码还有一个问题,当向桌面依次添加多个控件时会出现下面这样的效果:?
?
即更新时没有同时更新所有的AppWidget,这是因为onUpdate中传进来的数组中只包含了1个id,如果想同时更新多个,那么可以把更新语句更换为:?
Java代码??收藏代码
  1. appWidgetManager.updateAppWidget(new?ComponentName(context,?AppWidgetDemo.class),?appWidgetView);??

通过组件名可以把所有的名字符合的AppWidget都更新。?

6.2在onReceive()中更新?
6.2.1自定义Action通知刷新:?
在AndroidManifest.xml中定义的receiver的intent-filter增加一个自定义的Action:?
com.demo.appwidget.refresh?
Xml代码??收藏代码
  1. ?<receiver?android:name="AppWidgetDemo">??
  2. <intent-filter>??
  3. ????<action?android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>??
  4. ????<action?android:name="com.demo.appwidget.refresh"></action>??
  5. </intent-filter>??
  6. <meta-data?android:name="android.appwidget.provider"??
  7. ????android:resource="@xml/widget_info_demo"></meta-data>??
  8. lt;/receiver>??

包含此Action的Intent可以在后台服务或者Activity中发出,然后会被此Receiver接收,进而触发onReceive。?
本例中采用按钮按下时广播intent:?
Java代码??收藏代码
  1. btnSend.setOnClickListener(new?OnClickListener()?{????????????
  2. ????????????public?void?onClick(View?v)?{??
  3. ????????????????Intent?intent?=?new?Intent();??
  4. ????????????????intent.setAction("com.demo.appwidget.refresh");??
  5. ????????????????intent.putExtra("value",?teInput.getText().toString());??
  6. ????????????????SendMsgActivity.this.sendBroadcast(intent);??
  7. ????????????}??
  8. ????????});??

在接收端:?
Java代码??收藏代码
  1. if(intent.getAction().equals("com.demo.appwidget.refresh"))?{??
  2. ????????????String?value?=?intent.getStringExtra("value");????????????
  3. ????????????RemoteViews?appWidgetView?=?new?RemoteViews(context.getPackageName(),?R.layout.widget_layout_demo);??
  4. ????????????appWidgetView.setTextViewText(R.id.tv1,?value);??
  5. ????????????appWidgetView.setTextViewText(R.id.tv2,?value);??
  6. ????????????AppWidgetManager.getInstance(context).updateAppWidget(new?ComponentName(context,?AppWidgetDemo.class),?appWidgetView);??
  7. ????????}??

判断是否是感兴趣的Action,是的话就取值,然后更新。?
6.2.2接收系统消息刷新:?
比如intent-filter中再增加一个action:"android.provider.Telephony.SMS_RECEIVED",在AndroidMenifest.xml中任意位置添加<uses-permission android:name="android.permission.RECEIVE_SMS" />设置好权限,当系统有短消息收到时就能触发onReceive了。?
但是有些Action比较特殊,比如android.intent.action.TIME_TICK,根据android.content.intent文档中的描述:You can not receive this through components declared in manifests, only by exlicitly registering for it with Context.registerReceiver().?
这个Action在AndroidManifest.xml中声明了也没用,必须要自己开个服务注册receiver才能收到,然后再转发一次给自己。?

6.3直接在外部Activity或者Service中刷新:?
Java代码??收藏代码
  1. btnRefresh.setOnClickListener(new?OnClickListener()?{?????????????
  2. ????public?void?onClick(View?v)?{??
  3. ????????String?value?=?teInput.getText().toString();??
  4. ????????RemoteViews?appWidgetView?=?new?RemoteViews(SendMsgActivity.this.getPackageName(),?R.layout.widget_layout_demo);??
  5. ????????appWidgetView.setTextViewText(R.id.tv1,?value);??
  6. ????????appWidgetView.setTextViewText(R.id.tv2,?value);??
  7. ????????AppWidgetManager.getInstance(SendMsgActivity.this)??
  8. ????????????.updateAppWidget(new?ComponentName(SendMsgActivity.this,?AppWidgetDemo.class),?appWidgetView);??
  9. ????}??
  10. });??

此段代码可直接刷新AppWidget的内容,不会触发其onUpdate()。?
7.响应点击事件?
因为onUpdate是每个AppWidget被放置到桌面上时都会被呼叫的函数,所以在此函数中完成事件的关联:?
Java代码??收藏代码
  1. Intent?intent?=?new?Intent(context,?SendMsgActivity.class);??
  2. PendingIntent?pendingIntent?=?PendingIntent.getActivity(context,?0,?intent,?0);??
  3. appWidgetView.setOnClickPendingIntent(R.id.tv1,?pendingIntent);??


另外要注意此段代码必须要在appWidgetManager.updateAppWidget()之前,否则是不会生效的。?
运行后可以点击AppWidget的第一个控件,就能呼叫指定的Activity了。?
8.Config Activity?
这个可直接参考SDK文档中的Dev Guide-->App Widgets了。

?

?

1 楼 abc670454997 2012-03-13  
哇咔咔,很不错
  相关解决方案