AppWidget(桌面小控件详解)

介绍

Android widget
也称为桌面插件,其是android系统应用开发层面的一部分,但是又有特殊用途,而且会成为整个android系统的亮点。Android中的AppWidget与google
widget和中移动的widget并不是一个概念,这里的AppWidget只是把一个进程的控件嵌入到别外一个进程的窗口里的一种方法。(复制粘贴都懂^_^)

废话不多说上来就是干,直接上一个widget

1、新建一个继承AppWidgetProvider类

public class NewAppWidget extends AppWidgetProvider {

    private static String TAG = "NewAppWidget";
    public static final String CLICK_ACTION = "com.example.action.CLICK";//自己定义的action
    private static RemoteViews views;


    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                                int appWidgetId) {
       Intent intentClick = new Intent(context, NewAppWidget.class);
        intentClick.setAction(CLICK_ACTION);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intentClick, 0);

        CharSequence widgetText = context.getString(R.string.appwidget_text);//文字:状态很棒哦!
        // Construct the RemoteViews object
        views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
        // "窗口小部件"整个点击事件注册,只要点击了就会发送相应的广播
        views.setOnClickPendingIntent(R.id.appwidget_RelativeLayout, pendingIntent);
        views.setTextViewText(R.id.appwidget_text, widgetText);//设置文字
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.xiao);//笑的图片
        views.setImageViewBitmap(R.id.appwidget_image, bitmap);//设置图片
        ComponentName name = new ComponentName(context, NewAppWidget.class);
        appWidgetManager.updateAppWidget(name, views);//更新widget
    }


    //接受到相应的广播
    @Override
    public void onReceive(final Context context, Intent intent) {
        super.onReceive(context, intent);
        Log.e(TAG, "onReceive : action = " + intent.getAction());
        //这里判断是自己的action,做自己的事情
        if (intent.getAction().equals(CLICK_ACTION)) {
            Intent intent1 = new Intent(context, ControlActivity.class);
            intent1.setFlags(FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent1);
        }
    }


    // 刷新的时候执行
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        for (int appWidgetId : appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId);
        }
    }

    // 第一个添加到屏幕上执行
    @Override
    public void onEnabled(Context context) {
        //我这是开启一个服务
        context.startService(new Intent(context, ConnectService.class));
    }

    // 最后一个widget从屏幕移除执行
    @Override
    public void onDisabled(Context context) {

    }

    // 从屏幕移除执行
    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        super.onDeleted(context, appWidgetIds);
    }


}

2、新建一个new_app_widget文件

相信看完上面的代码你就发现还需要一个布局文件,然后我们就做一个布局文件呗
代码我就不想贴了直接上图,自己写布局去
这里写图片描述
就是一个这样的样式了一个背景一个imageview一个textview

3在Manifest文件中声明

<receiver android:name=".NewAppWidget">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
                <action android:name="com.example.action.CLICK" />
            </intent-filter>

            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/new_app_widget_info" />
        </receiver>

然后你就会发现这就是一个receiver,没错这就是一个receiver,AppWidgetProvider 就是继承的BroadcastReceiver
这里写图片描述

添加Widget配置信息

看到清单文件是不是还少了一个叫new_app_widget_info的xml文件,没错,这个是widget的配置文件。

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialKeyguardLayout="@layout/new_app_widget"
    android:initialLayout="@layout/new_app_widget"
    android:minHeight="40dp"
    android:minWidth="250dp"
    android:previewImage="@drawable/example_appwidget_preview"
    android:resizeMode="horizontal|vertical"
    android:updatePeriodMillis="86400000"
    android:widgetCategory="home_screen"></appwidget-provider>

好了到了这里你就会发现可以创建一个widget了。但是怎么更新widget呢?

更新widget

调用一下代码

//使用RemoteViews 
 RemoteViews views = new RemoteViews(getPackageName(), R.layout.new_app_widget);
//获取AppWidgetManager
 AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.cry);//哭的图片
//相当于找id设置图片
views.setImageViewBitmap(R.id.appwidget_image, bitmap);
views.setTextViewText(R.id.appwidget_text, "状态不好哦!");
//更新widget
appWidgetManager.updateAppWidget(new ComponentName(context, NewAppWidget.class), views);

然后你就会发现换了一张图片,换了几个字

开发中的一些坑

1、appWidgetManager更新的两个方法

updateAppWidget(int[] appWidgetIds, RemoteViews views)
updateAppWidget(ComponentName provider, RemoteViews views)
我们使用的是第二个方法如图
这里写图片描述
但是我当时使用的是第一个方法如图
这里写图片描述

当你使用第二张图的方法时,你会发现一个问题在应用退出后,或是被第三方软件杀死,点击桌面widget就不会更新了。原因是updateid是用一个数组保存的,应用退出后,这个数组就被清空了,后面又换成了updateAppWidget(ComponentName)方法后就好了。

2、new_app_widget_info里的android:configure属性

一开始的时候照着官方文档在new_app_widget_info.xml文件里设置了这个属性,在添加到桌面上的时候总是不成功,将这个属性去掉就可以了,不知道这个属性具体怎么用,有知道的麻烦留个言,谢谢

3、在用setOnClickPendingIntent()方法设置点击事件发送Broadcast时,不能直接new Intent(acton)

Intent intentClick = new Intent(CLICK_ACTION);
views.setOnClickPendingIntent(R.id.appwidget_RelativeLayout, PendingIntent.getBroadcast(context, 0, intent, 0));

上面这种写法在应用退出后在有些手机上收不到广播,然后换成下面这种写法

Intent intentClick = new Intent(context, NewAppWidget.class);
intentClick.setAction(CLICK_ACTION);
views.setOnClickPendingIntent(R.id.appwidget_RelativeLayout, PendingIntent.getBroadcast(context, 0, intent, 0));
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章