【原创】Android学习appwidget制作一个桌面相册幻灯片

最近在学习android的appwidget,看了一些文章,决定做一个相册幻灯片来练手,下面写写过程来给大家共享:

  1. 在项目的res/xml/下建立一个appwidget_info.xml文件,内容如下:
        <?xml version="1.0" encoding="utf-8"?>
        <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
            android:initialLayout="@layout/appwidget"
            android:minHeight="800dp"
            android:minWidth="240dp"
            android:updatePeriodMillis="300000" >
        
        </appwidget-provider>

    在这里定义appwidget的基本信息,宽度,高度,以及刷新的频率等

  2. 在layout/下建立appwidget的layout文件
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        android:padding="20dp" >
    
        <Button
            android:id="@+id/button1"
            android:layout_width="120dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="播放图片" />
    
        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="#FFFF"
            android:padding="2dp"
            android:scaleType="fitXY"
            android:src="@drawable/p1" />
    
    </LinearLayout>

    这个layout比较简单,里面仅仅包含一个button和一个imageview,设置 android:padding="2dp"来让图片有一个简单的边框样式

  3. 建立MyAppWidgetProvider继承AppWidgetProvider,重写父类的生命周期函数,这里的原理google一下有很多,就不多写了。首先重写onUpdate,这个方法在appwidget第一次加载时会被调用,在这里我们主要使用ContentResolver查询出本机所有图片;接下来新建一个PendingIntent将图片路径的集合封装到其中,最后将pendingIntent设置给button
    Intent intent = new Intent("com.jaredluo.appwidget.change");
    intent.putExtra("path", pathStrArr);
    
    //设置pending,发送广播,注意设置
    //PendingIntent.FLAG_UPDATE_CURRENT
    //否则onRecieve函数中接收不到intent中的数据
    PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
    
    for (int j = 0; j < appWidgetIds.length; j++) {
    
    //RemoteView是appwidget中很重要的一个类,基本上对appwidget中
    //所有控件的操作都要基于RemoteView来操作
    
      RemoteViews remoteView = new RemoteViews(context.getPackageName(),
                        R.layout.appwidget);
       remoteView.setOnClickPendingIntent(R.id.button1, pIntent);
       appWidgetManager.updateAppWidget(appWidgetIds[j], remoteView);
       remoteView = null;
    }

    由于appwidget与主程序处于不同的进程中,所以通讯都需要依靠PendingIntent。

  4. 接下来在onReceive中接收我们刚才设置给button的广播,首先新开一个线程控制图片的播放,接下来在Handler中为ImageView设置图片源
    final RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.appwidget);
    String path = paths[msg.getData().getInt("i")];
    remoteViews.setImageViewBitmap(R.id.imageView1,BitmapUtil.getBitmap(path, 200, 200));
    appWidgetManager.updateAppWidget(componentName,remoteViews);

    这里需要注意一个问题,我在把图片设置给appwidget时,跑不了几张图片就会出现!!! FAILED BINDER TRANSACTION !!!这个错误,最先以为是图片太大造成的,结果压缩图片也无果;后面在网上搜索一番发现:Binder data size limit is 512K 由于传输图片到appwidget进程中的Binder最大数据量是512k,并且RemoteView也不会每次清理,所以如果每次都使用同一个RemoteView进行传输会因为溢出而报错。最后每次都新建一个RemoteView问题才解决掉。

    看看最后的效果,点击播放图片按钮,图片就开始更替:

代码还有很多问题和不完善,接下来有空会继续修改。

posted @ 2012-05-01 23:19  JaredLam  阅读(2307)  评论(0编辑  收藏  举报