每天一练 2015/04/06 widget的用法
来源:互联网 发布:淘宝账号怎么找回 编辑:程序博客网 时间:2024/05/20 00:09
1. 声明一个widget的布局文件(.xml格式)置于res/layout文件夹下
2. 声明一个widget的元数据文件(.xml格式)置于res/xml文件夹下。在这个元数据文件中至少要声明如下几个属性:minHeight,minWidth,updatePeriodMillis和initialLayout。其中initalLayout的属性值就是第一步中建立的widget布局文件
3. 在AndroidManifest文件中“注册”widget。注册的时候使用的是<receiver>标签。为了体现与一般的receiver的区别,在<receiver>中必须有如下子节点:
<receiver android:name=”.自己的AppWidgetProvider实现类”>
<intent-filter>
<action android:name=”android.appwidget.action.APPWIDGET_UPDATE”>
</intent-filter>
<meta-dataandroid:name=”android.appwidget.provider”
android:resource=”@xml/第2步中声明的widget元数据文件”
/>
</receiver>
4. 声明一个自己的AppWidgetProvider实现类。widget的新建,删除等动作都会触发相应的widget广播,这些广播需要通过继承AppWidgetProvider来接收。通过重写AppWidgetProvider的相应回调方法(onUpdate,onDelete,onEnable等),来处理事件发生时的行为。
注意:1. 因为AppWidgetProvider继承自BroadcastReceiver,那么在写相应的回调方法时必须要考虑ANR问题,不能超时。
2. 所有widget的UI操作相关操作(例如UI的更新,数据的输入等等)都是不能直接在widget本身上面进行的,必须借助于PendingIntent、RemoteViews和AppWidgetManager来辅助完成
3. 一个AppWidgetProvider可以对应多个widget。因为一个widget可以设定不同的大小,可以被反复添加到页面上,这样一个AppWidgetProvider就可能要在onUpdate等回调方法中去同时更新多个widget了
一个完整的例子:
本例提供一个widget,widget中有一个刷新按钮,每次点击时,都可以生成一个随机数字。点击widget的文本区域,可以打开一个activity,通过activity中的按钮也可以对widget中的内容进行刷新。
本例需要如下文件:
1)res/layout/simple_widget_layout.xml widget的布局文件
2) res/xml/simple_widet.xml widget的元数据文件
3)AndroidManifest.xml 注册相关activity,receiver,service
4)MyAppWidgetProvider.java 继承自AppWidgetProvider,监听widget的各种动作
5)RandomService.java 继承自Service,完成widget的刷新,以及与MainActivity的通信
6)MainActivity.java 继承自Activiy,提供一个与widget“绑定”组件,通过该Activity利用RandomService,也能进行widget的更新
1)res/layout/simple_widget_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:padding="10dp" android:background="@drawable/widget_background" > <LinearLayout android:id="@+id/container" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_weight="1" android:orientation="vertical" > <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="Random Number" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/tv_number" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textStyle="bold" android:textAppearance="?android:attr/textAppearanceMedium" /> </LinearLayout> <ImageButton android:id="@+id/btn_refresh" android:layout_width="55dp" android:layout_height="55dp" android:layout_gravity="center_vertical" android:background="@null" android:contentDescription="@null" android:src="@android:drawable/ic_menu_rotate" /></LinearLayout>
widget布局中有两个文本框,tv_title显示提示信息,tv_number显示随机数字,btn_refresh是一个刷新按钮,每次点击,都会生成一个随机数字显示在tv_number中。
2)res/xml/simple_widget.xml
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="180dp" android:minHeight="40dp" android:updatePeriodMillis="86400000" android:initialLayout="@layout/simple_widget_layout" />updatePeriodMillis的属性值官方建议不易短于30分钟。如果需求是频繁刷新widget,不要依赖于widget自身的这个时间刷新设定,而应该使用AlarmManager或者Intent等来完成刷新。
3)AndroidManifest.xml (局部)
<activity android:name="com.example.widgettest.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".MyAppWidgetProvider"> <intent-filter > <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/simple_widget" /> </receiver> <service android:name="RandomService"></service>一个activity,一个receiver(AppWidgetProvider是BroadcastReceiver的继承者),一个service
4)MyAppWidgetProvider
public class MyAppWidgetProvider extends AppWidgetProvider{@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {Intent intent=new Intent(context,RandomService.class);context.startService(intent);}}这里只监听onUpdate事件,该事件在widget被新建的时候会被回调。这里不做任何直接处理而是启动一个RandomService来进行数据的生成和widget的刷新
5)RandomService
public class RandomService extends Service{public static final String ACTION="com.example.widgettest.ACTION";public static int sRandomNumber;public static int getRandomNumber(){return sRandomNumber;}@Overridepublic void onCreate() {super.onCreate();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {sRandomNumber=(int) (Math.random()*100);RemoteViews rv=new RemoteViews(getPackageName(), R.layout.simple_widget_layout);rv.setTextViewText(R.id.tv_number, String.valueOf(sRandomNumber));PendingIntent pi1=PendingIntent.getService(this, 0, new Intent(this, RandomService.class), 0);rv.setOnClickPendingIntent(R.id.btn_refresh, pi1);PendingIntent pi2=PendingIntent.getActivity(this, 0, new Intent(this,MainActivity.class), 0);rv.setOnClickPendingIntent(R.id.container, pi2);AppWidgetManager manager=AppWidgetManager.getInstance(this);ComponentName widget=new ComponentName(this, MyAppWidgetProvider.class);manager.updateAppWidget(widget, rv);Intent broad=new Intent(ACTION);sendBroadcast(broad);return START_NOT_STICKY;}@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn null;}}这里onStartCommand一共做了如下几件事情:
i. 生成一个随机数
ii. 将widget包装成一个RemoteViews,利用RemoteViews提供的API设置组件应该显示的内容。这里的API设计非常讲究,签名是SetTextViewText而不是setTextView,意在明确RemoteViews是不能直接设置相关组件的内容的,只能提供相关相关组件应该显示的内容是什么
iii. 继续利用RemoteViews提供的API,使用PendingIntent为widget里面的相关组件绑定“监听器”
iv. 获得AppWidgetManager,利用AppWidgetManager来做widget的具体更新工作
v. AppWidgetManager更新完毕后,Service发送一个广播(这个广播的主要作用是在MainActivity中更新widget时会用到的)
通过pi1,为widget的刷新按钮绑定了一个单击响应。每次在widget中单击刷新按钮,RandomService都会被启动,并生成一个随机数,然后通过RemoteViews、AppWidgetManager将结果刷新到widget。pi2为widget单击面板绑定了一个单击响应,当单击widget面板的时候会启动MainActivity。
非常重要的是,任何针对RemoteView的改动(比如显示内容的变化)或者设置(比如为按钮添加单击事件)必须调用AppWidgetManager的 updateAppwidget方法才会让这些改动或者设置生效。
6)MainActivity
public class MainActivity extends Activity {@ViewInject(R.id.tv_main_number)private TextView tv;@ViewInject(R.id.btn_main_generate)private Button btn;private BroadcastReceiver mReceiver=new BroadcastReceiver(){@Overridepublic void onReceive(Context context, Intent intent) { updateView();}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ViewUtils.inject(this);updateView();}protected void updateView() {tv.setText(String.valueOf(RandomService.getRandomNumber()));}@OnClick({R.id.btn_main_generate})public void doClick(View view){startService(new Intent(this,RandomService.class));}@Overrideprotected void onResume() {super.onResume();IntentFilter filter=new IntentFilter(RandomService.ACTION);registerReceiver(mReceiver, filter);}@Overrideprotected void onPause() {unregisterReceiver(mReceiver);super.onPause();}}R.layout.activity_main的内容如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/btn_main_generate" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Generate Number" > </Button> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="Current Random Number" android:textAppearance="?android:attr/textAppearanceLarge" /> <TextView android:id="@+id/tv_main_number" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textSize="55sp" android:textStyle="bold" /></LinearLayout>当MainActivity新建的时候,tv_main_number会从RandomService中拿数据显示出当前widget显示的数字。当点击btn_main_generate的时候,会启动RandomService,此时如果MainActivity保持在前台,那么它会收到RandomService更新完widget界面后发送的广播。在onReceive方法中,会去更新MainActivity的tv_main_number的内容,该数字显然与widget中的数字是一样的,都是RandomService的sRandomNumber。
- 每天一练 2015/04/06 widget的用法
- 每天一练-fopen
- thinkphp widget的用法
- widget的基本用法
- RemoteViews用法一:widget简单用法
- cocos中Widget 的用法
- [每天一练]统计文件中所有数字之和
- 每天一练-c语言点点滴滴-约瑟夫环:
- C++数据结构和算法每天一练(线性表)
- android widget的研究(一)
- App Widget的使用(一)
- Widget用法
- $.widget 关于jquery 插件的用法
- Widget对应QWidget类的用法
- android自定义桌面挂件widget用法(一)
- BREW的Widget实现分析(一)
- 创建一个 iOS 的 Widget (一)
- 测试的每天一小步
- NGUI笔记
- 如何在tomcat中配置其他的虚拟主机?
- GreenDao简述
- 关于DarkZone的开发者如何获利细则
- 重新理解Java的抽象类和接口(anroid_164)
- 每天一练 2015/04/06 widget的用法
- Java jvisualvm简要说明
- JS中打印DIV
- CEdit一行一行读取字符串
- a_time--授权部分及所用知识点(含转载CONST&)
- 第五周 阅读程序 1
- 实现下拉刷新
- hdu 4006 The kth great number/SBT
- c语言节点定义