Android学习笔记之桌面小工具AppWidget

实现桌面小工具的关键类AppWidgProvider

AppWidgetProvider的本质是一个广播接收者,如下:

public class AppWidgetProvider extends BroadcastReceiver 

说道广播接收者,那么它的工作原理应该是接收到对应的广播后会去调用其onReceive方法。接下来就来看它的onReceive方法:

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_OPTIONS_CHANGED.equals(action)) {
        Bundle extras = intent.getExtras();
        if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)
                && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS)) {
            int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
            Bundle widgetExtras = extras.getBundle(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS);
            this.onAppWidgetOptionsChanged(context, AppWidgetManager.getInstance(context),
                    appWidgetId, widgetExtras);
        }
    } else if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) {
        this.onEnabled(context);
    } else if (AppWidgetManager.ACTION_APPWIDGET_DISABLED.equals(action)) {
        this.onDisabled(context);
    } else if (AppWidgetManager.ACTION_APPWIDGET_RESTORED.equals(action)) {
        Bundle extras = intent.getExtras();
        if (extras != null) {
            int[] oldIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS);
            int[] newIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
            if (oldIds != null && oldIds.length > 0) {
                this.onRestored(context, oldIds, newIds);
                this.onUpdate(context, AppWidgetManager.getInstance(context), newIds);
            }
        }
    }
}

从上述源码中可以看出其逻辑近似于switch,APPWidgetProvider 会自动比对广播的 Action,从而分发广播,也就是分情况调用 onUpdate,onEnabled,onDisabled,onDeleted等方法。而这几种方法的调用时机如下:

  • onEnable:当该桌面小工具第一次添加到桌面时调用该方法,可添加多次但只在第一次调用
  • onUpdate:小工具被添加时或者每次小工具更新时都会调用一次该方法,小工具的更新时机由updatePeriodMillis来指定,每个周期小工具都会自动更新一次
  • onDeleted:每删除一次桌面小工具就调用一次
  • onDisabled:当最后一个该类型的桌面小工具被删除时调用该方法
  • onReceive:这是广播的内置方法,用于分发具体的事件给其他方法

实现桌面小工具的步骤

1.定义小工具的界面

和创建布局文件一样,在res/layout/目录下新建一个xml文件即可,名称和内容均可自定义。这里只是简单的添加了一个ImageView.


    

2.定义小工具的配置信息

在res/xml/目录下新建一个xml文件,名称可以自定义,这里新建了一个appwidget_info.xml:



 这里只用到了最基本的最小宽高属性以及刷新频率,其中86400000单位是ms即24小时,也就是一天一次。除此之外,它还支持一些其他的属性,如下:

  • previewImage:当用户选择添加 widget 时的预览图片。如果该属性没有定义,则展示 applicationg 的 launcher icon
  • configure:定义了用户在添加 widget 时弹出的配置页面的 Activity,用户可以在此进行 Widget 的一些配置,该 Activity 是可选的,如果不需要可以不进行声明
  • resizeMode:widget 在水平和垂直方向是否可以调整大小,值可以为:horizontal(水平方向可以调整大小),vertical (垂直方向可以调整大小),none(不可以调整大小),也可以 horizontal|vertical 组合表示水平和垂直方向均可以调整大小
  • widgetCategory:表示 widget 可以显示的位置,包括 home_screen(桌面),keyboard(锁屏)

3. 定义小工具的实现类

这个类需要继承AppWidge Provider,代码如下:

public class MyAppWidgetProvider extends AppWidgetProvider {
    private static final String TAG = "MyAppWidgetProvider";
    public static final String CLICK_ACTION = "com.appwidget.action.CLICK";
    public MyAppWidgetProvider() {
        super();
    }

    @Override
    public void onReceive(final Context context, Intent intent) {
        super.onReceive(context, intent);
        Log.d(TAG, "onReceive: ");
        if(intent.getAction().equals(CLICK_ACTION)){//如果是自己的Action
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Bitmap srcBitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.timg);
                    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
                    //旋转
                    for(int i=0;i<37;i++){
                        float degree = (i*10)%360;
                        RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget);
                        //设置旋转后的图片
                        remoteViews.setImageViewBitmap(R.id.iv_icon,rotateBitmap(srcBitmap,degree));

                        Intent intentClick = new Intent();
                        intentClick.setAction(CLICK_ACTION);
                        PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0,intentClick,0);
                        remoteViews.setOnClickPendingIntent(R.id.iv_icon,pendingIntent);//设置点击事件监听

                        appWidgetManager.updateAppWidget(new ComponentName(context,MyAppWidgetProvider.class),remoteViews);
                        SystemClock.sleep(30);
                    }
                }
            }).start();
        }
    }
    /**
     * 每次桌面小工具更新时都会调用一次该方法
     * */
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
        final int counter = appWidgetIds.length;
        for(int i = 0;i

上面的代码实现了一个简单的桌面小工具,该小工具展示一张图片,并且点击它之后,这个图片会旋转一周。当这个桌面小工具被添加到桌面后,会通过 RemoteViews 来加载布局文件,而当桌面小工具被单击之后的旋转效果则是通过不断的更新RemoteViews 来实现的。

4.在AndroidManifest.xml文件中声明该桌面小工具、然后动态注册小工具的实现类(广播接收者)


    
    
        
    
MyAppWidgetProvider appWidgetProvider = new MyAppWidgetProvider();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(MyAppWidgetProvider.CLICK_ACTION);
registerReceiver(appWidgetProvider,intentFilter);

其中 AndroidManifest 中的 action 是桌面小工具的标识,是系统规范,如果不加那么这个 receiver 则不是一个桌面小工具,无法在手机的小工具列表中找到它。

你可能感兴趣的:(Android)