桌面小控件_窗口小部件_窗口小工具_android.appwidget


1.应用场景:需求,便利需求,想快捷进行信息获取或操作手机,例如调节亮度,查看彩票,查看日历……

2.功能实现:如何为自己的程序提供一个桌面小控件,为程序提供一个功能操作的快捷方式?

  思考:

      a.组件类型:目前android系统只会调用四大组件,那么桌面小控件是哪类组件呢?

      b.生命周期:窗口小部件是如何启动的?谁负责启动它?在什么时候启动?

      c.UI设计:View来自哪里?在哪里进行设计UI?

      d.业务处理:如何更新数据?数据来自哪里?如何响应点击触摸事件?

  结论:

     a.桌面小控件,需要继承AppWidgetProvider,而AppWidgetProvider又是BroadcastReceiver的子类,所以桌面小控件是广播接受者类型;

                        public class AppWidgetProvider extends BroadcastReceiver

                        A convenience class to aid in implementing an AppWidget provider. Everything you can do with AppWidgetProvider, you can do with a regular BroadcastReceiver. AppWidgetProvider merely parses the relevant fields out of the Intent that is received in onReceive(Context,Intent), and calls hook methods with the received extras.

     b.生命周期:用户添加获删除小控件时,系统发出广播,当AppWidgetProvider接受到广播时,从Intent中获取action,判断action是以下那种:

                                      AppWidgetManager.ACTION_APPWIDGET_UPDATE,//创建对象时发的action;

                                      AppWidgetManager.ACTION_APPWIDGET_DELETED,//删除对象时发的action;

                                      AppWidgetManager.ACTION_APPWIDGET_ENABLED,//第一个对象被创建时,发的action;

                                      AppWidgetManager.ACTION_APPWIDGET_DISABLED。//最后一个对象被销毁时发的action;

代码如下:

 public void onReceive(Context context, Intent intent) {
        // Protect against rogue update broadcasts (not really a security issue,
        // just filter bad broacasts out so subclasses are less likely to crash).
        String action = intent.getAction();
        if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
            Bundle extras = intent.getExtras();
            if (extras != null) {
                int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
                if (appWidgetIds != null && appWidgetIds.length > 0) {
                    this.onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds);
                }
            }
        }
        else if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
            Bundle extras = intent.getExtras();
            if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
                final int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
                this.onDeleted(context, new int[] { appWidgetId });
            }
        }
        else if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) {
            this.onEnabled(context);
        }
        else if (AppWidgetManager.ACTION_APPWIDGET_DISABLED.equals(action)) {
            this.onDisabled(context);
        }
    }

 Log如下:

当第一个widget被创建出来的时候
06-15 09:31:13.025: INFO/System.out(570): onreceive
06-15 09:31:13.025: INFO/System.out(570): onEnabled
06-15 09:31:13.045: INFO/System.out(570): onreceive
06-15 09:31:13.045: INFO/System.out(570): onUpdate

当第二个相同的widget被创建的时候
06-15 09:32:24.895: INFO/System.out(570): onreceive
06-15 09:32:24.935: INFO/System.out(570): onUpdate

当第三个被创建的时候
06-15 09:32:55.995: INFO/System.out(570): onreceive
06-15 09:32:55.995: INFO/System.out(570): onUpdate

删除一个条目的时候
06-15 09:33:19.766: INFO/System.out(570): onreceive
06-15 09:33:19.766: INFO/System.out(570): onDeleted

最后一个widget被移除的时候
06-15 09:33:48.525: INFO/System.out(570): onreceive
06-15 09:33:48.525: INFO/System.out(570): onDeleted
06-15 09:33:48.545: INFO/System.out(570): onreceive
06-15 09:33:48.545: INFO/System.out(570): onDisabled

             c.UI设计:View来自哪里?在哪里进行设计UI? 在清单文件注册广播接受者,在意图过滤器中指明action name,在元数据中指明name和resource;

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


               在资源文件中指定minWith,minHight,updatePeriodMillis和initialLayout;


    example_appwidget_info 配置文件
    android:minWidth="294dp" 最小宽度
    android:minHeight="72dp" 最小高度
    android:updatePeriodMillis="86400000"  代表的是widget自动更新的时间 单位是毫秒1000
      最小值是30分钟 60*1000*30 = 1800000
      如果需要在小于30分钟内更新widget的内容需要利用widget的管理服务
      手动的更新 widget里面显示的内容
    android:initialLayout="@layout/main" widget最开始的布局(界面).


        d.业务处理:如何更新数据?数据来自哪里?如何响应点击触摸事件?

                     要更新数据,首先启动带特定功能的服务,所以创建一个service子类,在小控件的onEnable()方法中去startService,在onDisable()方法中stopService;

                     数据更新,需要通过Timer和TimerTask去执行,timer.schedule(task, 1000, 1000);

                    响应点击事件:给RemoteViews设置OnClickPendingIntent,指定某个view被点击时调用发出PendingIntent给启动服务或发送广播;

                    响应事件后需要更新数据:让AppWidgetManager通过ComponentName和RemoteViews去updatAppWidget();


A description of an Intent and target action to perform with it. Instances of this class are created with getActivity, getBroadcast, getService; the returned object can be handed to other applications so that they can perform the action you described on your behalf at a later time.


                Intent autoKillIntent = new Intent("com.example.killtask");
                PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, autoKillIntent, 0);
                views.setOnClickPendingIntent(R.id.btn_clear, pendingIntent);
                appWidgetManager.updateAppWidget(proceeWidget, views);


      总结:1.用什么组件?          android.appwidget.AppWidgetProvider extends BroadcastReceiver;

                  2.用什么控件?          android.widget.RemoteViews implements Parcelable, Filter;

                  3.用什么管理器?      AppWidgetManager

                  4.用什么意图包装类?android.app.PendingIntent;

                  5.使用到什么通信技术?AppWidgetManager.getgetInstance(Context context).是如何得到桌面程序Launcher的IAppWidgetService服务的?

                                     IPC技术,aidl:sService = IAppWidgetService.Stub.asInterface(b);

                                     注意:由于该管理器是随时获取的,不需要进行长时间缓存,所有使用弱引用来包装;


获取AppWidgetManager的代码实现:

public static AppWidgetManager getInstance(Context context) {
        synchronized (sManagerCache) {
            if (sService == null) {
                IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE);
                sService = IAppWidgetService.Stub.asInterface(b);
            }
             //由于该管理器是随时获取的,不需要进行长时间缓存,所有使用弱引用来包装;
            WeakReference<AppWidgetManager> ref = sManagerCache.get(context);
            AppWidgetManager result = null;
            if (ref != null) {
                result = ref.get();
            }
            if (result == null) {
                result = new AppWidgetManager(context);
                sManagerCache.put(context, new WeakReference<AppWidgetManager>(result));
            }
            return result;
        }
    }






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值