安卓开发之 App Widget

一、什么是App Widget

Android平台上在桌面上所放置的一种小控件

与App Widget相关的类/对象:

  1. AppWidgetProviderInfo对象:

    定义App Widget的一些信息,为App Widget提供元数据,包括App Widget布局文件的指定,更新频率等数据。
    这个对象被定义在XML文件当中,其相对于一个Config配置“文件”.
    
  2. AppWidgetProvider:

    继承自BroadcastReicever广播接收器。
    定义了App Widget的基本生命周期的回调函数.
    

二、创建一个App Widget的步骤

一、定义AppWidgetProviderInfo:

  1. res/xml文件夹当中定义描述AppWidgetProviderInfo的xml文件。

    例:…\res\xml\appwidget_info.xml

    <?xml version="1.0" encoding="utf-8"?>
    <appwidget-provider 
        xmlns:android="http://schemas.android.com/apk/res/android"
    
        android:minHeight="60dp"
        android:minWidth="200dp"
        android:previewImage="@drawable/default_img"
        android:resizeMode="horizontal|vertical"
        android:updatePeriodMillis="40000"
        android:initialLayout="@layout/appwidget_layout" >
    
    </appwidget-provider>
    

    updatePeriodMillis为更新的毫秒数、initialLayout为初始化的widget布局;
    previewImage为该app widget的预览图,在桌面小部件选择时显示;
    resizeMode:app widget 在水平和垂直方向是否可以调整大小。

二、为App Widget指定布局:

  1. 定义App Widget展示时的布局文件appwidget_layout

    例:…\res\layout\appwidget_layout.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#00000000"
        >
    
        <TextView
            android:id="@+id/widget_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:text="widget text"
            />
    
        <Button
            android:id="@+id/widget_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:text="widget button"
            />
    
    </LinearLayout>
    

三、实现AppWidgetProvider

  • onUpdate:在到达指定的更新时间之后或者当用户向桌面添加App Widget时会调用该方法

  • onDeleted:在App Widget被删除时,会调用该方法

  • onEnable:当一个App Widget的实例第一次被创建时,会调用该方法

  • onDisable:当最后一个App Widget实例被删除后,会调用该方法

  • onReceive:监听/接收广播事件,可用于处理控件的点击事件等

(桌面上可以有多个同样的app widget)

例:

public class MyAppWidgetProvider extends AppWidgetProvider {

    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        super.onDeleted(context, appWidgetIds);
    }

    @Override
    public void onEnabled(Context context) {
        super.onEnabled(context);
    }

    @Override
    public void onDisabled(Context context) {
        super.onDisabled(context);
    }

}

因AppWidgetProvider又继承自BroadcastReceiver,所以需要在AndroidManifest中注册:

    <receiver android:name=".MyAppWidgetProvider">

        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
        </intent-filter>

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

    </receiver>

其中action是引用android自定义的action,meta-data为元数据:resource为说明该App Widget 的配置信息的xml文件,name必须是android.appwidget.provider。

三、使用App Widget布局中的控件

>使用App Widget布局中的控件其中涉及到了PendingIntent,RemoteViews..

一、PendingIntent

Pending:待处理的。PendingIntent 可以看作为一种“留待日后处理”的意图,是对Intent的一种包装,创建之后并不马上使用,一旦某种触发事件的发生,意图才马上执行。

  1. App Widget和应用程序并不是在同一进程当中。
  2. 创建PendingIntent对象的三个静态方法:

    • getActivity(Context context, int requestCode, Intent intent, int flags)
    • getBroadcast(Context context, int requestCode, Intent intent, int flags)
    • getService(Context context, int requestCode, Intent intent, int flags)

    根据PeningIntent具体发送/启动(广播/Activity/服务)来选择对应的一个静态方法来创建PendingIntent对象。

二、RemoteViews的作用

RemoteViews:远程控件。App Widget里的控件和主程序不在同一进程中,所以App Widget里的控件相对于一种远程控件。

  1. RemoteViews对象表示了一系列的View对象。
  2. RemoteViews所表示的对象运行在另外的进程中。
  3. App Widget当中的View运行在Home Screen进程当中。

三、操作AppWidget的Button

由于AppWidget的Button不与主程序在同一进程中,所以无法按照之前惯用的方法给Button绑定监听器。

为AppWidget的Button绑定监听器:

新方法:remoteViews.setOnClickPendingIntent(R.id.widget_button, pendingIntent);
第一个参数为AppWidget的Button的id,第二参数为PendingIntent对象。
当Button被点击时,会引起pendingIntent的执行。

例:重新实现AppWidgetProvider:点击Button时启动Activity

public class MyAppWidgetProvider extends AppWidgetProvider {

    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        Log.i("z","onReceive");
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);

        // appWidgetMahager:管理app widget
        // appWidgetIds : appWidget的id数组(桌面可放置多个同样的小部件)

        for (int i= 0;i< appWidgetIds.length;i++){

            //给每一个小部件的按钮绑定监听器
            Log.i("z",appWidgetIds[i]+" ");

            //创建一个Intent对象
            Intent intent = new Intent(context,MainActivity.class);
            //包装成一个PendingIntent对象
            PendingIntent pendingIntent = PendingIntent.getActivity(context,0,intent,0);

            //得到RemoteViews对象
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.appwidget_layout);
            //给app widget中的Button绑定监听器
            remoteViews.setOnClickPendingIntent(R.id.widget_button,pendingIntent);

            //更新app widget
            appWidgetManager.updateAppWidget(appWidgetIds[i],remoteViews);

        }


    }

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        super.onDeleted(context, appWidgetIds);
        Log.i("z","onDeleted");
    }

    @Override
    public void onEnabled(Context context) {
        super.onEnabled(context);
        Log.i("z","onEnabled");
    }

    @Override
    public void onDisabled(Context context) {
        super.onDisabled(context);
        Log.i("z","onDisabled");
    }

}

四、接收来自AppWidget的广播和更新控件的状态

  1. 在AndroidManifest当中为AppWidgetProvider注册新的intent-filter,配置所要接收的广播行为。AppWidgetProvider本质上是一个广播接收器

  2. 使用getBroadcast(…)方法创建一个发送广播PendingIntent。

  3. 为AppWidget当中的控件注册处理器,用来触发发送广播的行为。

  4. 在onReceive方法当中接收来自AppWidget发送的广播消息,并执行自己的业务逻辑,使用RemoteViews对象更新App Widget当中的控件状态。

  5. AppWidgetProvider的运行机制:通过onReceive来接收广播,接收到特定的系统内置广播时来调用onUpdate(..)等生命周期的回调方法,由onReceive来调用生命周期函数。

例:重新在AndroidMainfest注册AppWidgerProvider:

    <receiver android:name=".MyAppWidgetProvider">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
        </intent-filter>

        <intent-filter>
            <action android:name="my.appwidget.Text_UPDATE"/>
        </intent-filter>

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

    </receiver>

“android.appwidget.action.APPWIDGET_UPDATE”:系统自带广播,用来接收后回调声明周期函数。
“my.appwidget.Text_UPDATE”:自定义广播,用来接收后进行对TextView的操作。

重新实现AppWidgetProvider:

public class MyAppWidgetProvider extends AppWidgetProvider {


    private static final String TEXT_UPDATE = "my.appwidget.Text_UPDATE";

    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);

        if(intent!=null&& TextUtils.equals(TEXT_UPDATE,intent.getAction())){

            Log.i("z","onReceiveTextUpdate");

            //获取app widget的所有控件
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.appwidget_layout);

            //设置TextView的文本
            remoteViews.setTextViewText(R.id.widget_text,"Changed Text");

            //获取app widget的管理器
            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

            //获取app widget的对象
            ComponentName componentName = new ComponentName(context,MyAppWidgetProvider.class);

            //管理器更新app widget
            appWidgetManager.updateAppWidget(componentName,remoteViews);

        }

    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);

        // appWidgetMahager:管理app widget
        // appWidgetIds : appWidget的id数组(桌面小部件可重复放置多个小部件)

        for (int i= 0;i< appWidgetIds.length;i++){

            Log.i("z",appWidgetIds[i]+" ");
            //创建一个发送广播的Intent对象,并设置action
            Intent intent = new Intent();
            intent.setAction(TEXT_UPDATE);
            //包装成一个PendingIntent对象,执行时会发送一个广播。
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0,intent,0);

            //得到RemoteViews对象
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.appwidget_layout);
            //给app widget中的Button绑定监听器
            remoteViews.setOnClickPendingIntent(R.id.widget_button,pendingIntent);

            //更新app widget
            appWidgetManager.updateAppWidget(appWidgetIds[i],remoteViews);
        }


    }

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        super.onDeleted(context, appWidgetIds);
        Log.i("z","onDeleted");
    }

    @Override
    public void onEnabled(Context context) {
        super.onEnabled(context);
        Log.i("z","onEnabled");
    }

    @Override
    public void onDisabled(Context context) {
        super.onDisabled(context);
        Log.i("z","onDisabled");
    }

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值