<Android>桌面小组件实现过程

来源:互联网 发布:北京网络电视台直播 编辑:程序博客网 时间:2024/04/28 06:01

Widget桌面小组件实现

      1)要更新Widget中的内容,一般都是写在onUpdate方法里面,但是更新的时候,要把Widget当做一个RemoteViews来处理。利用Service更新Widget中的内容。
      2)Widget中:在onEnable方法中启动Service,在onDisable方法中停止Service,在onUpdate方法中为按钮绑定一个监听器,但是此时不能利用传统的方式进行绑定。
                       (传统方式:Button btn = view.findViewById(id);             btn.setOnClickListener(listener);)
       3)在Widget中绑定监听器必须利用RemoteViews提供的相关API才可以:   view.setOnClickPendingIntent(id,pendingIntent);
             当id对应的按钮点击的时候,会触发PendingIntent,随着PendingIntent的触发,就会发送广播。 该广播被Service中的广播接收器接收,执行对应的代码逻辑。

Step1  res/layout下面,写Widget的布局文件(一个Button,点击获取一个随机数字,显示到TextView上)

<?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" >    <TextView     android:id="@+id/tv_widget_number"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:textSize="16sp"    android:hint="..."    /><Button     android:id="@+id/btn_widget_button"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:text="获取数字"        /></LinearLayout>

Step2    res/xml,要写一个xml文件,该文件用来向系统描述widget的一些特性,res下新建xml文件夹,新建xml文件

            1)minWidth/minHeight:用来指定widget的最小尺寸, 尺寸的经验公式:70*n-30(例:n取值为4*1中的4)。

            2)android:updatePeriodMillis="86400000"   ,毫秒值,告诉系统间隔多长时间调用一下Widget中更新Widget界面显示的方法,这个值不能低于30分钟(1800000毫秒),然后低于该长度的时间值均无效,系统会按照默认的30分钟来进行更新,一般写一天的毫秒值。
            3)android:initialLayout="@layout/widget_layout"   告诉系统,当widget拖动到桌面上显示的时候,使用的布局文件。

<?xml version="1.0" encoding="utf-8"?><appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"     android:minWidth="250dp"    android:minHeight="40dp"    android:updatePeriodMillis="86400000"    android:initialLayout="@layout/widget_layout"    ></appwidget-provider>                                   

Step3   写MyService类


/** * 用来与widget进行交互的Service 提供Widget中显示的数字 */public class MyService extends Service {MyReceiver receiver;@Overridepublic void onCreate() {super.onCreate();//动态注册广播接收器receiver = new MyReceiver();IntentFilter filter = new IntentFilter();filter.addAction("ACTION_MAKE_NUMBER");registerReceiver(receiver, filter);}@Overridepublic void onDestroy() {//注销广播接收器unregisterReceiver(receiver);super.onDestroy();}@Overridepublic IBinder onBind(Intent intent) {return null;}/** * 广播接收器 */private class MyReceiver extends BroadcastReceiver {// 接收到Widget发送的广播@Overridepublic void onReceive(Context context, Intent intent) {if ("ACTION_MAKE_NUMBER".equals(intent.getAction())) {// 生成一个随机数字,以系统广播的形式将这个数字提交到AppWidgetManager manager = AppWidgetManager.getInstance(context);ComponentName provider = new ComponentName(context,MyWidget.class);RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);//设置要显示的TextView,及显示的内容views.setTextViewText(R.id.tv_widget_number, new Random().nextInt(2000)+"");// 发送一个系统广播manager.updateAppWidget(provider, views);}}}}



Step4   要真正去写Widget类。写的时候需要继承自AppWidgetProvider!

1)去重写AppWidgetProvider中的若干方法,选择性重写AppWidgetProvider的:onEnable,onDisable,onUpdate,onDelete,onReceive方法

2)同一个Widget可以被多次拖动放到桌面上,每一个桌面上的widget,就相当于该Widget类的一个对象。当且仅当第一个Widget被拖动到

面上的时候,会调用onEnable方法和onUpdate方法,随后再次拖动第二个第三个...Widget到桌面上,仅仅会调用,widget的onUpdate

了,再删除桌面上的Widget的时候,当且仅当删除最后一个Widget对象的时候,会调用该widget的onDelete方法和onDisable方法,删除

数第二个第三个...Widget的时候,仅仅会调用Widget的,onDelete方法。随着onEnable,onUpdate,onDelete,onDisable方法的调用

都会产生系统广播,从而让Widget的onReceive方法被调用

           

                                                  

public class MyWidget extends AppWidgetProvider{@Overridepublic void onReceive(Context context, Intent intent) {super.onReceive(context, intent);Log.d("TAG","onReceive方法调用了");}@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {super.onUpdate(context, appWidgetManager, appWidgetIds);Log.d("TAG","onUpdate方法调用了");//给Button绑定一个PendingIntent,当点击按钮是发送给Service发广播//当点击Button时,触发PendingIntent,发广播给MyServiceAppWidgetManager manager = AppWidgetManager.getInstance(context);ComponentName provider = new ComponentName(context,MyWidget.class);RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.widget_layout);Intent numberIntent = new Intent("ACTION_MAKE_NUMBER");views.setOnClickPendingIntent(R.id.btn_widget_button, PendingIntent.getBroadcast(context, 0, numberIntent , PendingIntent.FLAG_UPDATE_CURRENT));manager.updateAppWidget(provider, views);}@Overridepublic void onDeleted(Context context, int[] appWidgetIds) {super.onDeleted(context, appWidgetIds);Log.d("TAG","onDeleted方法调用了");}@Overridepublic void onEnabled(Context context) {super.onEnabled(context);Log.d("TAG","onEnabled方法调用了");//启动MyServiceIntent intent = new Intent(context,MyService.class);context.startService(intent);}@Overridepublic void onDisabled(Context context) {super.onDisabled(context);Log.d("TAG","onDisabled方法调用了");//停止MyServiceIntent intent = new Intent(context,MyService.class);context.stopService(intent);}}

Step5  注册

           在AndroidManifest中注册该Widget,在application标签下,activity标签外 

           其中<intent-filter>节点中写Widget接收的广播Action类型,widget是一个特殊的"广播接收器",还必须要添加一个<meta-data>节点   

       <receiver android:name="com.example.widgetdemo.MyWidget" >            <intent-filter>                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" >                </action>            </intent-filter>            <meta-data                android:name="android.appwidget.provider"                android:resource="@xml/mywidget" />        </receiver>

            在AndroidManifest中注册MyService,在application标签下,activity标签外

        <service            android:name="com.example.widgetdemo.MyService"            android:enabled="true"            android:exported="true" >        </service>

至此,功能实现!!!


0 0
原创粉丝点击