Android基础-AppWidget入门

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,发送一个广播和启动一个服务。

完整代码会是这样:

@Override
public 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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值