`
univasity
  • 浏览: 801394 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

[Android API学习]AppWidget

阅读更多

其实Android API开发指南中的App Widgets章节 已经说得很清楚了,下面只是对自己的理解进行一次梳理。

--
AppWidget 就是HomeScreen上显示的小部件,提供直观的交互操作。通过在HomeScreen中长按,在弹出的对话框中选择Widget部件来进行创建,长按部件后并拖动到垃圾箱里进行删除。同一个Widget部件可以同时创建多个。

AppWidget的实现主要涉及到以下类:
AppWidgetProvider
RemoteViews
AppWidgetManager


1.
首先需要提供一个定义了Widget界面布局的XML文件(位于res/layout/..),需要注意的是使用的组件必须是RemoteViews所支持的,目前原生API中支持的组件如下:
FrameLayout
LinearLayout
RelativeLayout

AnalogClock
Button
Chronmeter
ImageButton
ImageView
ProgressBar
TextView


*如果使用了除此之外的组件,则在Widget创建时会导致android.view.InflateExceptionn异常。


PS:这就导致有一些功能或样式无法实现,如很基本的list或文本编辑框都是无法直接实现的。如果想自定义Widget中的View的话只能通过修改framework来提供相应组件的支持。

2.
然后需要提供一个xml文件来定义Widget的基本属性,放置到res/xml/..目录下。
如果使用的是Eclipse可按如下操作:
1) 在res/目录下创建xml/目录
2)创建xml文件(名字可任意),选择类型为AppWidgetProvider
3)在弹出的便捷界面进行参数设置

主要设置的参数如下:
minWidth: 定义Wdiget组件的宽度
minHeight: 定义Wdiget组件的高度
updatePeriodMillis: 更新的时间周期
initialLayout: Widget的布局文件
configure: 如果需要在启动前先启动一个Activity进行设置,在这里给出Activity的完整类名(后面会说到,与一般Activity的实现有些许差别)

*Widget大小的计算 :(单元格数*74)-2,API上说是为了防止像素计算时的整数舍入导致错所以-2...不是很明白

一个完整的样例:

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
      android:minWidth="80dp"
      android:minHeight="32dp"
      android:updatePeriodMillis="86400000"
      android:initialLayout="@layout/widget_provider"
      android:configure="com.demo.widget.MyWidgetConfiguration" >
</appwidget-provider>

 

3.
xml都定义好后,接下来就是创建一个继承自AppWidgetProvider的子类,AppWidgetProvider实际上就是一个BroadcastReceiver,里面提供了以下函数:
onReceive(Context, Intent)
onUpdate(Context , AppWidgetManager, int[] appWidgetIds)
onEnabled(Context)
onDeleted(Context, int[] appWidgetIds)
onDisabled(Context)
可通过重写以上函数来监听Widget状态的变化并进行相应的处理。

以上函数具体调用情况归纳如下:
[启动 - 无confiure Activity]
onReceive
onEnabled —— 第一个widget被显示
onReceive
onUpdate —— 刷新界面

[启动 - 带confiuration Activity]
onReceive
onUpdate

[拖动]
<无状态变化>

[周期更新]
onReceive
onUpdate

[删除]
onReceive
onDeleted —— widget被删除
onReceive
onDisabled —— 最后一个widget被移除

[启动时位置不够]
onReceive
onEnabled
onReceive
onUpdate
onReceive
onDeleted
onReceive
onDisabled

*每次状态的变化会触发onReceive,一般该函数是不需要重写的。

简单了解AppWidgetProvider之后,我们来看具体实现。
这里创建一个MyAppWidgetProvider继承AppWidgetProvider:

public class MyWidgetProvider extends AppWidgetProvider {

      static final String TAG = "widget";
     
      /**
       * 更新
       */
      public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
            Log.i(TAG, "onUpdate");
      }
     
      /**
       * 第一个Widget组件启动时触发
       */
      public void onEnabled(Context context){
            Log.i(TAG, "onEnabled");
      }
     
      /**
       * 最后一个Widget组件关闭时触发
       */
      public void onDisabled(Context context){
            Log.i(TAG, "onDisabled");
      }
     
      /**
       * 任一Widget组件被删除时触发
       */
      public void onDeleted(Context context, int[] appWidgetIds){
            Log.i(TAG, "onDeleted");
      }
     
      /**
       * 以上函数触发前会先触发该函数,一般不需要重写
       */
      public void onReceive(Context context, Intent intent){
            Log.i(TAG, "onReceive");
            super.onReceive(context, intent);
      }
     
}

 

其中onUpdate顾名思义是对Widget进行更新的,前面定义的更新周期就是作用于该函数的。
Widget的更新与Activity不同,必须借助于RemoteViews和AppWidgetMananger。具体实现如下:

public void onUpdate(Context context, AppWidgetMananger appWidgetManager, int[] appWidgetIds){
    int N = appWidgetIds.length; // 可能启动了多个Widget,appWidgetIds记录了这些Widget的ID
    for(int i=0; i<N; i++){
        RemoteViews  views = new RemoteViews(getPackageName(), R.layout.widget_views);
        appWidgetManager.updateAppWidget(appWidgetIds[i], views);
    }
}

 
其中需要注意的是,虽然RemoteViews参数都是一样的,但是对于每个Widget最好都新创建一个再进行传递,否则会导致一些错误。具体可参考AppWidget RemoteViews 内存溢出

其他函数的可以根据需要实现。

由于无法获取到RemoteViews创建的界面中的元素,对于Widget中组件的操作只能通过RemoteViews所提供的有限的函数进行,常用的有:
setOnClickPendingIntent(int viewId, PendingIntent pendingIntent)
setProgressBar(int viewId, int max, int progress, boolean indeterminate)
setTextViewText(int viewId, CharSequence text)
setViewVisibility(int viewId, int visibility)
详细函数列表可参考API中的RemoteViews类

4.
最后,更新AndroidManifest.xml。
AppWidgetProvider对应一个receiver属性:

<receiver android:name="MyWidgetProvider">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>
            </intent-filter>
            <meta-data android:resource="@xml/widget_property" android:name="android.appwidget.provider"></meta-data>
        </receiver>

 

5.
提供Configuration Activity
Configuration Activity是一个在Widget启动前先启动的Activity,方便用户对Widget的属性进行设置。

在res/xml/...下对应的"属性文件"中添加configure字段指定启动的Activity,并在AndroidManifest.xml中该Activity下提供一个action为android.appwidget.action.APPWIDGET_CONFIGURE 的IntenFilter。

需要注意的是,
如果设置了Configure属性,则必须在指定的Activity中进行如下处理:
1.在onCreate中setContentView()函数前添加setResult(RESULT_CANCLE) ,这样如果在Activity初始化完成前按下了BACK按键,则Widget不会启动;
2.在setContentView()函数之后(不一定要在onCreate中,在Activity退出前即可),添加如下设置以指定需要启动的Widget:

int mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);

否则会导致退出Activity后Widget不启动。

>> Widget创建步骤汇总:
1.定义Widget布局XML -> res/layout/...
2.定义Widget属性文件(xml) -> res/xml/...
3. 创建AppWidgetProider子类,实现onUpdate()等函数,在manifest中注册receiver,添加一个action为 android.appwidget.action.APPWIDGET_UPDATE 的IntentFilter,并添加如下<meta- data>标识:

<meta-data android:resource="@xml/<属性文件xml>" android:name="android.appwidget.provider"></meta-data>
 

4. 创建Coniguration Activity(注意处理好setResult),添加到属性文件中的Configure属性,在manifest中注册activity,添加一个 action为android.appwidget.action.APPWIDGET_CONFIGURE 的IntentFilter

最后附上一个完整的例子,
实现思路如下:
1. 提供一个Configuration Activity,这里只简单显示一行文字;
2.退出后Widget启动;
3.点击Widget中的按钮会启动一个Activity。

分享到:
评论
3 楼 windloverain 2011-03-08  
学习,多谢分享
2 楼 daaoke 2011-03-02  
写的很好。。很需要哈
1 楼 elena_java 2011-02-25  

相关推荐

    android api,demo

    很多的官方demo,api,超值的啊。 animation ApiDemos.java ApiDemosApplication.java app appwidget content graphics media os text view

    Android Widget 桌面组件开发介绍

    本篇文章主要介绍了Android中的 widget 桌面组件开发教程,对AppWidget 框架以及AppWidgetManger类进行详细讲解,开发Android widget 开发的朋友可以参考下

    AndroidSDK下/platform-tools/api/annotations.zip

    编译时遇到以下报错:app:...java.io.IOException: Could not parse XML from annotations/android/widget/annotations.xml 请将本文件替换SDK目录下的/platform-tools/api/annotations.zip文件,建议替换前备份原文件

    android sdk platform-tools下的api文件夹中的annotations.zip

    Could not read /Users/panxin/Library/Android/sdk/platform-tools/api/annotations.zip java.io.IOException: Could not parse XML from annotations/android/widget/annotations.xml 请将本文件替换SDK目录下的/...

    android开发入门与实战(上)

    3.3.1 开发的基石——AndroidAPI核心开发包介绍 3.3.2 拓展开发外延——Android可选API介绍 3.4 本章小结 第4章 赚钱的市场——AndroidMarket及应用发布 4.1 GoogleMarket产生背景与目的 4.2 体验“选货”的乐趣...

    AndroidSDK下/platform-tools/api/annotations.zip资源api.rar

    编译时如果遇到以下报错:app:lintVitalRelease[Fatal Error] :43:...java.io.IOException: Could not parse XML from annotations/android/widget/annotations.xml 请将本文件替换SDK目录下的/platform-tools/api资源

    Android代码-Torch

    This is a simple flashlight app, free and without ads. This includes features like : Flash camera Lighting of the screen SOS mode Flashlight widget Hide the icon Color customization Permissions ...

    新版Android开发教程.rar

    的 Android SDK 提供了在 Android 平台上使用 JaVa 语言进行 Android 应用开发必须的工具和 API 接口。 特性 • 应用程序框架 支持组件的重用与替换 • Dalvik Dalvik Dalvik Dalvik 虚拟机 专为移动设备优化 • ...

    android 百度地图 定位示例

    android:label="@string/app_name" &gt; 这里需要添加key,创建应用后,会有这个key android:name="com.baidu.lbsapi.API_KEY" android:value="6t2yuIFylnRG7ECj1xHYuelY" /&gt; ..... package com.obtk.mapdemo...

    AndroidDemos:Android API 练习

    ├ apis.appwidget --窗口控件开发 相关 ├ apis.location --位置相关 ├ apis.net --网络相关 ├ apis.phone --手机功能 ├ apis.project --项目Demo ├ apis.thread --多线程 ├ apis.ui --界面相关 ├ resources ...

    android开发资料大全

    android用户界面之Widget教程实例汇总 android用户界面之TabHost教程实例汇总 android用户界面之Gallery教程实例汇总 android用户界面之按钮(Button)教程实例汇 android用户界面之ProgressBar教程实例汇总 android...

    Android 上应用Googlemap

    android:apiKey="YOUR API key" /&gt; &lt;Button android:text="@+id/Button01" android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content"&gt; //--------------------- ...

    机智云公版开源App-智能插座Android版

    智能云插座 使用机智云开源APP之前,需要先在...com.gizwits.framework.widget -机智云设备开源APP框架自定义控件 com.gizwits.framework.XpgApplication -机智云设备开源APP框架自定义Application ...

    android 完全中文版 开发应用详解

    目录: 结构如下,非常详细 第1章 android系统概述 1 ...15.1.6 app widget的使用 379 15.2 android应用开发实例 381 15.2.1 gui依赖类的程序 382 15.2.2 单独模块类程序 387 15.3 android的设计理念 393

    Google Android SDK开发范例大全(第3版) 1/5

    4.30 实时配置桌面上的AppWidget UI Layout 4.31 识别输入装置ID与InputDevice装置 4.32 选取文字的聪明文字联想 4.33 设计与Launcher相同的三页滑动Layout 第5章 交互式通信服务与手机控制 5.1 具有正则表达式的...

    《Google Android SDK开发范例大全(第3版)》.pdf

    4.30 实时配置桌面上的appwidget ui layout 163 4.31 识别输入装置id与inputdevice装置 166 4.32 选取文字的聪明文字联想 169 4.33 设计与launcher相同的三页滑动layout 172 第5章 交互式通信服务与...

    annotations.zip

    android/widget/annotations.xml android/view/annotations.xml android/view/textclassifier/annotations.xml android/bluetooth/le/annotations.xml android/media/annotations.xml android/preference...

    Google Android SDK开发范例大全(第3版) 4/5

    4.30 实时配置桌面上的AppWidget UI Layout 4.31 识别输入装置ID与InputDevice装置 4.32 选取文字的聪明文字联想 4.33 设计与Launcher相同的三页滑动Layout 第5章 交互式通信服务与手机控制 5.1 具有正则表达式的...

    Google Android SDK开发范例大全(第3版) 3/5

    4.30 实时配置桌面上的AppWidget UI Layout 4.31 识别输入装置ID与InputDevice装置 4.32 选取文字的聪明文字联想 4.33 设计与Launcher相同的三页滑动Layout 第5章 交互式通信服务与手机控制 5.1 具有正则表达式的...

Global site tag (gtag.js) - Google Analytics