zoukankan      html  css  js  c++  java
  • Android Widget(窗口小部件)

    Android Widget简介
    应用程序窗口小部件(Widget)是微型的应用程序视图,它可以被嵌入到其它应用程序中(比如桌面)并接收周期性的更新。你可以通过一个App Widget Provider来发布一个Widget。可以容纳其它App Widget的应用程序组件被称为App Widget宿主程序.
        为了创建一个App Widget,你需要使用下面这些:
      1.AppWidgetProviderInfo 对象(定义在XML文件里面)
        描述一个App Widget元数据,比如App Widget的布局,更新频率,以及AppWidgetProvider 类。这个应该在XML里定义。
      2.AppWidgetProvider 类的实现(主要是接收广播并进行相应操作)
        定义基本方法以允许你通过编程来和App Widget通信,这基于广播事件。通过它,当App Widget被更新、可用、禁用和删除的时候,都将接收到广播通知。
      3.视图布局
        在XML中定义App Widget初始布局。
        另外,你可以实现App Widget配置Activity 。这是一个可选的Activity,当用户添加App Widget时加载它并允许用户修改App Widget的设置。(当用户添加到桌面时会自动调用该Activity)
     
    Android Widget具体使用
     1.首先,在应用程序AndroidManifest.xml文件中声明AppWidgetProvider 类
     <receiver android:name="ExampleAppWidgetProvider" >     
         <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>  

    说明:

      <receiver>元素需要android:name属性,指定了App Widget使用的AppWidgetProvider 。
      <intent-filter>元素必须包括一个含有android:name属性的<action>元素。该元素指定AppWidgetProvider接受ACTION_APPWIDGET_UPDATE 广播。这是唯    一你必须显式声明的广播。当需要的时候,必要时AppWidgetManager会自动发送所有其它App Widget广播给AppWidgetProvider。
      <meta-data> 元素指定了AppWidgetProviderInfo 资源并需要以下属性:
      • android:name–指定元数据名称,使用android.appwidget.provider 来 确定AppWidgetProviderInfo描述的数据。
      • android:resource–指定AppWidgetProviderInfo 资源路径
     2.添加AppWidgetProviderInfo元数据
        AppWidgetProviderInfo定义一个App Widget的基本特性,比如最小布局尺寸,初始布局资源,刷新频率,以及创建时加载的一个配置Activity(可选的)。使用单独的一个<appwidget-provider>元素在XML资源里定义AppWidgetProviderInfo 对象并保存到项目的res/xml/目录下
    <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"  
        android:minWidth="294dp"  
        android:minHeight="72dp"  
        android:updatePeriodMillis="86400000"  
        android:initialLayout="@layout/example_appwidget"  
        android:configure="com.example.android.ExampleAppWidgetConfigure" >  
    </appwidget-provider>  

      下面是<appwidget-provider>属性的总结: 

      a)minWidth 和minHeight 属性的值指定了App Widget布局需要的最小区域。

      缺省的App Widgets所在窗口的桌面位置基于有确定高度和宽度的单元网格中。如果App Widget的最小长度或宽度和这些网格单元的尺寸不匹配,那么这个App Widget将上舍入(上舍入即取比该值大的最接近的整数——译者注)到最接近的单元尺寸。

      一般说来桌面布局方向可以变化(由此单元的尺寸也会变化),你应该假设最坏情况即单元尺寸高和宽是74像素。不过,你必须从最终的尺寸中减去2以把像素计算过程中产生的任何的整数舍入误差考虑在内。要找到像素密度无关的最小宽度和高度,使用这个公式:(number of cells * 74) - 2.依据这个公式,你应该使用72dp作为高度,294dp作为宽度。

      b)updatePerdiodMillis 属性定义了App Widget框架调用onUpdate()方法来从AppWidgetProvider请求一次更新的频度。实际更新时间并不那么精确,而且我们建议更新频率越低越好——最好每小时不超过一次以节省电源。你也许还会允许用户在配置中调整这个频率——一些人可能想每15分钟一次股票报价,或者一天只要四次。

      注意:当到个更新的时间时,如果设备处于休眠状态,则设备将会被唤醒来执行更新操作。如果更新频率每小时不超过一次,这可能对电池的寿命不会产生值得注意的问题。但是,如果更新的很频繁,或者当设备处于休眠状态时不更新,那么你最好使用一个alarm来代替执行更新操作,这样不会唤醒设备。这种方式可以通过使用AlarmManager类实现。设置alarm的类型为 ELAPSED_REALTIME或者RTC,这两种类型只有在设备处于唤醒状态时才会传递alarm,同时设置updatePeriodMillis 为0.

      c)initialLayout属性指向定义App Widget布局的资源。

      d)configure属性定义了当用户添加App Widget时启动的Activity,配置App Widget特性。这是可选的

    3.创建App Widget布局

        你必须在XML中为你的App Widget定义一个初始布局并保存到项目的res/layout/ 目录下。你可以使用如下所列的View对象来设计你的App Widget,但是,你必须注意App Widget布局是基于RemoteViews, 而RemoteViews并不支持所有类型的布局或视图小部件。

      一个RemoteViews对象(对应的,一个App Widget)可以支持下面这个布局类(但是不支持这些类的派生):

      • FrameLayout 
      • LinearLayout 
      • RelativeLayout 

      以及下面的控件类:

      • AnalogClock 
      • Button 
      • Chronometer 
      • ImageButton 
      • ImageView 
      • ProgressBar 
      • TextView 
    4.使用AppWidgetProvider类
        AppWidgetProvider类扩展自BroadcastReceiver ,作为处理App Widget广播一个简便类,AppWidgetProvider只接收和这个App Widget相关的事件广播,比如这个App Widget被更新、删除、启用以及禁用。当这些广播事件发生时,AppWidgetProvider 将接收到下面的方法调用:
      onUpdate(Context, AppWidgetManager, int[]) //最常用的因为它是在每个App Widget添加进宿主时被调用的(除非你使用一个配置活动)
        这个方法调用来间隔性的更新App Widget,间隔时间用AppWidgetProviderInfo 里的updatePeriodMillis属性定义。这个方法也会在用户添加App Widget时被调用,因此它应该执行必要的设置,比如为控件定义事件处理器并启动一个临时的服务Service,如果需要的话。但是,如果你已经声明了一个配置Activity,这个方法在用户添加App Widget时将不会被调用,而只在后续更新时被调用。配置Activity有责任在配置完成时负责执行第一次更新。
      onDeleted(Context, int[]) 
        当App Widget从宿主App Widget  中删除时被调用。
      onEnabled(Context) 
        当一个App Widget实例第一次创建时被调用。比如,如果用户添加两个你的App Widget实例,只在第一次被调用。如果你需要打开一个新的数据库或者执行其他对于所有的App Widget实例只需要发生一次的设置,那么这里是完成这个工作的好地方。
      onDisabled(Context) 
        当你的App Widget的最后一个实例被从宿主中删除时被调用。你应该在onEnabled(Context)中做一些清理工作,比如删除一个临时的数据库。
      onReceive(Context, Intent) 
        这个接收到每个广播时都会被调用,而且在上面的回调函数之前。你通常不需要实现这个方法,因为缺省的AppWidgetProvider 实现过滤所有App Widget 广播并恰当的调用上述方法。
    public class ExampleAppWidgetProvider extends AppWidgetProvider {  
      
        public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {  
            final int N = appWidgetIds.length;  
      
            // Perform this loop procedure for each App Widget that belongs to this provider  
            for (int i=0; i<N; i++) {  
                int appWidgetId = appWidgetIds[i];  
      
                // Create an Intent to launch ExampleActivity  
                Intent intent = new Intent(context, ExampleActivity.class);  
                PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);  
      
                // Get the layout for the App Widget and attach an on-click listener to the button  
                RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);  
                views.setOnClickPendingIntent(R.id.button, pendingIntent);  
      
                // Tell the AppWidgetManager to perform an update on the current App Widget  
                appWidgetManager.updateAppWidget(appWidgetId, views);  
            }  
        }  
    }    
        注意: 因为这个AppWidgetProvider 是一个广播接收器BroadcastReceiver,不能保证你的进程在回调函数返回后仍然继续运行。如果你的App Widget设置过程能持续几秒钟(比如当执行网页请求时)而且你要求你的进程继续,考虑在onUpdated()方法里启动一个服务Service。从这个服务里,你可以执行自己的App Widget更新,而不必担心AppWidget Provider 由于一个应用程序无响应错误Application Not Responding (ANR)而关闭。
      AppWidgetProvider 只是一个简便类。如果你想直接接收App Widget广播,你可以实现自己的BroadcastReceiver 或者重写 onReceive(Context, Intent) 回调函数。你需要注意如下4个Intents
    • ACTION_APPWIDGET_UPDATE 
    • ACTION_APPWIDGET_DELETED 
    •  ACTION_APPWIDGET_ENABLED 
    • ACTION_APPWIDGET_DISABLED 
    5.创建一个App Widget 配置Activity()
      如果你想让用户在添加一个新的App Widget时调整设置,你可以创建一个App Widget配置Activity 。这个Activity 将被App Widget宿主自动启动并允许用户在创建时配置可用的设置,比如App Widget颜色,尺寸,更新周期或者其它功能设置。 
      这个配置Activity应该在Android清单文件中声明为一个通用Activity。不过,它将被通过ACTION_APPWIDGET_CONFIGUREaction而被App Widget宿主启动,因此这个Activity需要接受这个Intent 。比如:
    <activity android:name=".ExampleAppWidgetConfigure">  
      <intent-filter>  
        <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> 
      </intent-filter>  
    </activity>  

      当然,Activity必须在AppWidgetProviderInfo XML 文件中声明,通过android:configure属性。比如,配置Activity可以声明如下:

    <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"  
        ...  
        android:configure="com.example.android.ExampleAppWidgetConfigure"   
        ... >  
    </appwidget-provider>  
      注意这个Activity是用全包名声明的,因为它将从你的程序包外被引用。
      这就是所有关于配置活动你一开始需要了解的。现在你需要一个真实的Activity。这儿就有,不过,当你实现这个Activity时记住两件重要的事情:
      • App Widget 宿主调用配置Activity而且配置Activity应该总是返回一个结果.这个结果应该包含这个通过启动该活动的意图传递App Widget ID(以EXTRA_APPWIDGET_ID保存在Intent的附加段Intent extras中) 
      • 当这个 App Widget 被创建时将不会调用onUpdate() 方法(当一个配置活动启动时,系统将不会发送ACTION_APPWIDGET_UPDATE广播).配置活动应该在 App Widget 第一次被创建时负责从AppWidgetManager请求一个更新.不过, onUpdate() 将在后续更新中被调用-只忽略第一次.

     

    从配置Activity中更新一个App Widget


      当一个App Widget使用一个配置Activity,那么当配置结束时,就应该由这个Activity来更新这个App Widget.你可以直接通过AppWidgetManager请求一次更新操作.下面是恰当的更新App Widget 以及关闭配置Activity这个过程的一个概要描述:

      1.首先,从启动这个Activity的Intent中获取App Widget ID:  

    Intent intent = getIntent();  
    Bundle extras = intent.getExtras();  
    if (extras != null) {  
        mAppWidgetId = extras.getInt(  
                AppWidgetManager.EXTRA_APPWIDGET_ID,   
                AppWidgetManager.INVALID_APPWIDGET_ID);  
    } 

      2.实施你的App Widget 配置。

       3.当配置完成后,通过调用getInstance(Context)获取一个AppWidgetManager实例:   

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);  
      4.以一个RemoteViews布局调用updateAppWidget(int, RemoteViews)更新App Widget: 
    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget);  
    appWidgetManager.updateAppWidget(mAppWidgetId, views);  
      5.最后,创建返回Intent ,设置到Activity结果,并结束这个Activity: 
    Intent resultValue = new Intent();  
    resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);  
    setResult(RESULT_OK, resultValue);  
    finish();  

      提示: 当你的配置Activity  第一次打开时,设置Activity 结果为RESULT_CANCELED。这样,如果用户在结束之前从Activity 外返回,这个App Widget宿主会接收到配置取消通知而不会添加这个App Widget。

    实例代码位于APIDemos中。

  • 相关阅读:
    组合两个表(sql查询语句)
    The six Day 数组中找出和为目标值
    实时监控-CPU
    使用 python 的细碎总结
    Visual Studio 2017 运行、调试使用CMake构建的多可执行程序项目
    git 学习笔记 —— 在不同的提交间进行切换和重置( git reset/reflog/tag 命令)
    git 学习笔记 —— 保留/丢弃当前分支修改并切换至其他分支
    git 学习笔记 —— 获取远端仓库以及提交信息至远端 git remote/fetch/branch
    git 学习记录—— git 中的仓库、文件状态等概念介绍
    VScode 配置 C++ 环境进行编译和调试
  • 原文地址:https://www.cnblogs.com/adm1989/p/3291982.html
Copyright © 2011-2022 走看看