Android基础-AppWidget入门

来源:互联网 发布:阴茎毛囊炎 知乎 编辑:程序博客网 时间:2024/05/22 01:13

AppWidget就是我们平常在桌面上见到的那种一个个的小窗口,利用这个小窗口可以给用户提供一些方便快捷的操作。

AppWidget创建:

      第一步:在res文件夹下新建一个xml文件夹,用来专门存放.xml格式文件,再在xml文件夹下创建一个xml文件,取名为appwidget.xml,其代码如下:

<?xml version="1.0" encoding="utf-8"?> <appwidget-provider  xmlns:android="http://schemas.android.com/apk/res/android"  android:minWidth = "294dp"  android:minHeight = "72dp"  android:updatePeriodMillis = "86400000"  android:initialLayout = "@layout/appwidgetlayout"  > </appwidget-provider>
代码解析:

       第一行是语言版本号以及编码类型;

       第二行及以下是由appwidget-provider包裹的内容,而appwidget-provider内包裹的内容中前三行很容易理解,至于后两行,updatePeriodMillis是用来定时刷新AppWidget控件,最少不能低于30分钟,也就是30*60*1000=1800000,而initialLayout顾名思义就是启动布局,也就是AppWidget的布局,当然现在这个布局还不存在,需要创建。

      创建该xml文件的目的在于定义AppWidget的属性,也就是定义AppWidget的总体外观和刷新时间以及布局来源。


第二步:在res文件夹下的layout文件夹下创建AppWidget的布局文件:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent" android:layout_height="fill_parent">     <TextView android:id="@+id/txtapp" android:text="test" android:layout_width="wrap_content"        android:layout_height="wrap_content" android:background="#ffffff"></TextView>     <Button android:id="@+id/btnSend" android:layout_width="wrap_content"    android:layout_height="wrap_content" android:text="Send"></Button> </LinearLayout>
和普通的创建布局文件几乎没差。

第三步:编写一个继承于AppWidgetProvider类的子类:

public class AppWidget extends AppWidgetProvider {     private final String broadCastString = "com.qlf.appWidgetUpdate";          /**      * 删除一个AppWidget时调用      * */    @Override    public void onDeleted(Context context, int[] appWidgetIds)     {         super.onDeleted(context, appWidgetIds);     }     /**      * 最后一个appWidget被删除时调用      * */    @Override    public void onDisabled(Context context)     {         super.onDisabled(context);     }     /**      * AppWidget的实例第一次被创建时调用      * */    @Override    public void onEnabled(Context context)     {         super.onEnabled(context);     }     /**      * 接受广播事件      * */    @Override    public void onReceive(Context context, Intent intent)     {              super.onReceive(context, intent);     }     /**      * 到达指定的更新时间或者当用户向桌面添加AppWidget时被调用      * */    @Override    public void onUpdate(Context context, AppWidgetManager appWidgetManager,             int[] appWidgetIds)     {                       }      }
第四步,由于AppWidgetProvider是继承于BroadcastReceiver,所以其实AppWidgetProvider是一个广播,既然是广播就需要在AndroidManifest.xml中注册,如下:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.qlf.widget" android:versionCode="1" android:versionName="1.0">     <application android:icon="@drawable/icon" android:label="@string/app_name">         <activity android:name=".MainActivity" android:label="@string/app_name">             <intent-filter>                 <action android:name="android.intent.action.MAIN" />                 <category android:name="android.intent.category.LAUNCHER" />             </intent-filter>         </activity>         <receiver android:name="AppWidget">             <intent-filter>                 <action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>             </intent-filter>             <meta-data android:name="android.appwidget.provider"                android:resource="@xml/appwidget" />         </receiver>     </application>     <uses-sdk android:minSdkVersion="8" /> </manifest>

至此,一个简单的appwidget就完成了。



当然,仅仅这么的appwidget是不够的,我们需要appwidget跟程序进行交互。

于是问题就出来了,首先要知道的一点是AppWidget和主程序并不在一个进程中,也就是说主程序中的控件根本就无法在AppWidget中被找到,那么AppWidget就无法改变主程序内的控件的内容,于是就出现了一个对象,叫做RemoteViews,代码如下:

RemoteViews remoteViews  = new RemoteViews(context.getPackageName(),R.layout.appwidgetlayout); remoteViews.setOnClickPendingIntent(R.id.btnSend, pendingIntent);  //为小工具上的按钮绑定事件
首先是新建一个RemoteViews对象,传入两个参数,第一个参数是所在包名,第二个参数是AppWidget的布局文件ID。一开始我想不明白为什么要穿这两个参数,有点摸不到头脑,但是看了RemoteViews的方法之后,就觉得,这两个参数其实是一个功能,就是定位,首先是找到包,然后再找到包内的布局文件,为的是让RemoteViews的方法中能够顺利的找到AppWidget布局内的控件ID,比如说这里的R.id.btnSend。

然后RemoteViews的功能就很清晰了,就是为pendingIntent绑定按钮,或者是更新主程序内的TextView控件等等(方法未列出)。


然后问题又来了,就是PendingIntent是什么?PendingIntent叫做延时意图,而它其实并不是一个完整的意图,或者说PendingIntent其实是个空盒子,需要Intent去填充它,代码如下:

Intent intent = new Intent(); intent.setAction("com.jsdsm.appwidgetprovider");PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
上两行代码再熟悉不过了,至于第三行等号左边是固定不变得,等号右边则有三种情况,分别是PendingIntent.getActivity,PendingIntent.getBroadcast和PendingIntent.getService,分别是利用PendingIntent内包裹的Intent启动一个Activity,发送一个广播和启动一个服务。

完整代码会是这样:

@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager,         int[] appWidgetIds) {         //创建一个Intent对象         Intent intent = new Intent();         intent.setAction(broadCastString);          //设置pendingIntent的作用         PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);         RemoteViews remoteViews  = new RemoteViews(context.getPackageName(),R.layout.appwidgetlayout);                  //绑定事件         remoteViews.setOnClickPendingIntent(R.id.btnSend, pendingIntent);                  //更新Appwidget         appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); } 

 @Override  public void onReceive(Context context, Intent intent)   {       if (intent.getAction().equals(broadCastString))       {                          //只能通过远程对象来设置appwidget中的控件状态           RemoteViews remoteViews  = new RemoteViews(context.getPackageName(),R.layout.appwidgetlayout);          //通过远程对象将按钮的文字设置为”hihi”           remoteViews.setTextViewText(R.id.btnSend, "hihi");                          //获得appwidget管理实例,用于管理appwidget以便进行更新操作           AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);                      //相当于获得所有本程序创建的appwidget           ComponentName componentName = new ComponentName(context,AppWidget.class);                      //更新appwidget           appWidgetManager.updateAppWidget(componentName, remoteViews);       }       super.onReceive(context, intent);   }
然后就不得不讲一讲AppWidget类内方法的执行顺序了:

首先是用户第一次在桌面添加AppWidget的时候会调用onUpdate,将一切准备工作做完,执行appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);更新;

然后用户点击按钮,由于remoteViews.setOnClickPendingIntent(R.id.btnSend, pendingIntent);的缘故,点击按钮就会将pendingIntent打开,而pendingIntent内包裹一个Intent,这个Intent的功能是发送一个广播;

然后由AndroidManifest.xml中的意图过滤器判断Action是否符合,符合,进入到onReceive方法内,判断是否符合,符合,则更新主程序,并更新AppWidget。

原创粉丝点击