Android中AppWidget的学习整理(附demo)

来源:互联网 发布:网络理财客服招聘 编辑:程序博客网 时间:2024/05/02 01:54

今天写的是AppWidget,这是我工作之后接触的第一个模块。乘着有时间整理下知识点。

先附上DEMO:http://download.csdn.net/detail/violetjack0808/9433218


这里实现的是一个用来计数的AppWidget桌面小部件。效果图如下:

演示图片

下面是实现步骤


1.创建AppWidget配置文件

在res/xml目录下创建app_widget_config.xml文件,用来配置widget属性。

<?xml version="1.0" encoding="utf-8"?><appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"    android:initialLayout="@layout/widget_ui"    android:minHeight="140dip"    android:minWidth="140dip"    android:updatePeriodMillis="6890000" ></appwidget-provider>

这个xml是用来描述所要创建的appWidget的一些描述信息的,所描述的属性分别有最小高度、最小宽度、刷新间隔和关联布局文件布局文件。

特别要说的是AppWidget的大小是以格为单位来计算的,手机屏幕被分为一个4*4的格阵,当宽高到达一定值时就会显示并占满相应的格数,不会出现自定义不规则的大小的。网上资料显示说N格的长宽为(74*N)-2。我设定的140*140显示的是2*2的界面。


2.创建布局文件

在res/layout中创建widget_ui.xml这个布局文件。这里画的布局就会是我们在手机桌面上看到的widget的样子啦~

<?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/tvTitle"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="this is a widget" />    <TextView        android:id="@+id/tvResult"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="result = 0"/>    <Button        android:id="@+id/btnAdd"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="add one"/></LinearLayout>


3.创建AppWidgetProvider

在src目录下创建AppWidget类继承自AppWidgetProvider,用以实现widget的交互。

当我看到onReceive方法觉得奇怪,这不是广播接收器吗?结果进去一看发现AppWidgetProvider就是继承自BroadcastReceiver的

public class AppWidgetProvider extends BroadcastReceiver

所以,widget的工作原理就是通过广播来实现对它的控制的。


3.1 AppWidgetProvider的生命周期:

onEnabled当AppWidget实例第一次被创建时调用

onReceive接收广播事件

onUpdate到达指定的更新时间或用户向桌面添加widget时候调用

onDeleted当AppWidget被删除时调用

onDisabled当最后一个AppWidget被删除时调用


3.2.RemoteViews和PendingIntent

在onUpDate方法中用到了RemoteViews与PendingIntent, 是因为AppWidget和其原本的App并不在同一个进程中,而是运行在HomeScreen进程当中,因此,在控件监听器的绑定,更新等操作都会与以前基本的方法有所不同。

PendingIntent是一个特殊的Intent,实际上它像一个邮包,其中包裹着真正的Intent,当邮包未打开时,Intent是被“挂起”的,所以并不执行,只有当邮包拆开时才会执行。它与Intent的区别在于:Intent 是及时启动,intent 随所在的activity 消失而消失。 进程A创建PendingIntent,发送给进程B,进程B此事并不执行,直到用户出发某一事件时,包裹被拆开,里面的Intent真正执行。所以Intent什么时候被执行是不知道的,由用户出发事件来决定。

RemoteViews表示了一系列view对象,即AppWidget所有的控件。它的应用方法如下源码所示,使用了views.setOnClickPendingIntent(所需控件的ID,定义的pendingintent)方法来为控件绑定监听器。


3.3 源码

/** * AppWidget学习demo * 个人心得: * onUpDate方法用于创建和更新AppWidget,将所需的ID通过intent进行传递。 * onReceive方法通过接收intent传送的广播事件实现AppWidget的变化操作。 */public class AppWidget extends AppWidgetProvider {    private static int i = 1;    private static final String ACTION = "click";    //当AppWidget实例第一次被创建时调用。    @Override    public void onEnabled(Context context) {        super.onEnabled(context);    }    //接收广播事件。    @Override    public void onReceive(Context context, Intent intent) {        Log.e("widget", "onReceive + " + intent.getAction());        super.onReceive(context, intent);        ComponentName thisWidget = new ComponentName(context,AppWidget.class);//定义容器        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_ui);//定义RemoteViews        //定义AppWidgetManager,用于之后更新AppWidget        AppWidgetManager appWidgetManager = AppWidgetManager                .getInstance(context);        //通过接收广播的Intent来进行widget的UI操作        if (intent.getAction().equals(ACTION)) {            views.setTextViewText(R.id.tvResult, "result = " + i);            i++;        }        //更新AppWidget        appWidgetManager.updateAppWidget(thisWidget, views);    }    //到达指定的更新时间或用户向桌面添加widget时候调用。    public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {        Log.e("widget", "onUpdate");        for (int id : appWidgetIds) {            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_ui);            Intent intent1 = new Intent("click");//定义intent            PendingIntent pendingIntentOne = PendingIntent.getBroadcast(context, 0, intent1, 0);//用PendingIntent将Intent包裹起来            views.setOnClickPendingIntent(R.id.btnAdd, pendingIntentOne);//按钮点击事件监听            //更新AppWidget            appWidgetManager.updateAppWidget(id, views);        }    }    //当AppWidget被删除时调用。    @Override    public void onDeleted(Context context, int[] appWidgetIds) {        super.onDeleted(context, appWidgetIds);    }    //当最后一个AppWidget被删除时调用。    @Override    public void onDisabled(Context context) {        super.onDisabled(context);    }}


4.注册广播

上面提到了,AppWidgetProvider其实就是广播,所以我们需要在Manifest文件中注册广播。

这里注意Action的一致。关于广播的知识可以看我的Blog:Android广播Broadcast的学习(附demo)

代码:

<application    .... >    .....    <receiver android:name=".AppWidget" >        <meta-data            android:name="android.appwidget.provider"            android:resource="@xml/app_widget_config" />        <intent-filter>            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />            <action android:name="click" />        </intent-filter>    </receiver>    ....</application>
注意:resource要关联我们之前写的app_widget_provider.xml文件;action中第一个必须写,第二个就是自定义action了。


这样一个计数的桌面小部件就完成啦~

0 0
原创粉丝点击