android appwidget笔记

一:实现一个Activity配置widget

(1):在widget配置文件中加入如下代码:

[html] view plaincopy
 
  1. <span style="white-space:pre"><appwidget-provider  
  2.   xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:minWidth="250dp"  
  4.   android:minHeight="180dp"  
  5.   android:updatePeriodMillis="0"  
  6.   android:initialLayout="@layout/widget_layout"  
  7.   android:resizeMode="vertical"  
  8.   android:configure="xx.widgets.ExampleAppWidgetConfigure"   
  9.   android:previewImage="@drawable/ic_launcher">  
  10. </appwidget-provider></span>  

(2):在Activity中加入如下代码:

[java] view plaincopy
 
  1. Intent launchIntent = getIntent();  
  2. Bundle extras = launchIntent.getExtras();  
  3. if (extras != null) {  
  4.       
  5.     appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,AppWidgetManager.INVALID_APPWIDGET_ID);  
  6.     Intent cancelResultValue = new Intent();  
  7.     cancelResultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,appWidgetId);  
  8.     //未配置完成返回结果  
  9.     setResult(RESULT_CANCELED, cancelResultValue);  
  10. else {  
  11.     // only launch if it's for configuration  
  12.     // Note: when you launch for debugging, this does prevent this  
  13.     // activity from running. We could also turn off the intent  
  14.     // filtering for main activity.  
  15.     // But, to debug this activity, we can also just comment the  
  16.     // following line out.  
  17.     finish();  
  18. }  
[java] view plaincopy
 
  1. if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID)   
  2. {  
  3.                       
  4.     Intent resultValue = new Intent();  
  5.     resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,appWidgetId);  
  6.     //配置完成返回结果  
  7.     setResult(RESULT_OK, resultValue);  
  8.                       
  9. }  

二:如何在RemoteViews中使用ListView

(1):通过RemoteViewsService 渲染器实现

[java] view plaincopy
 
  1. import java.util.ArrayList;  
  2. import java.util.HashMap;  
  3. import java.util.List;  
  4.   
  5. import android.annotation.SuppressLint;  
  6. import android.content.Context;  
  7. import android.content.Intent;  
  8. import android.content.SharedPreferences;  
  9. import android.database.Cursor;  
  10. import android.database.sqlite.SQLiteDatabase;  
  11. import android.os.IBinder;  
  12. import android.os.Looper;  
  13. import android.widget.RemoteViews;  
  14. import android.widget.RemoteViewsService;  
  15. public class UpdateService extends RemoteViewsService {  
  16.   
  17.     @Override  
  18.     public void onStart(Intent intent, int startId) {  
  19.           
  20.         super.onCreate();  
  21.     }  
  22.   
  23.     @Override  
  24.     public IBinder onBind(Intent intent) {  
  25.         return super.onBind(intent);  
  26.     }  
  27.   
  28.     @Override  
  29.     public RemoteViewsFactory onGetViewFactory(Intent intent) {  
  30.         return new ListRemoteViewsFactory(this.getApplicationContext(), intent);  
  31.     }  
  32.       
  33.       
  34.     class ListRemoteViewsFactory implements  
  35.             RemoteViewsService.RemoteViewsFactory {  
  36.   
  37.         private final Context mContext;  
  38.         private final List<String> mList;  
  39.   
  40.         public ListRemoteViewsFactory(Context context, Intent intent) {  
  41.             mContext = context;  
  42.             mList = getDataSources();//获取数据源  
  43.             if (Looper.myLooper() == null) {  
  44.                 Looper.prepare();  
  45.             }  
  46.         }  
  47.   
  48.         @Override  
  49.         public void onCreate() {  
  50.               
  51.         }  
  52.   
  53.           
  54.         @Override  
  55.         public void onDataSetChanged() {  
  56.   
  57.         }  
  58.   
  59.         @Override  
  60.         public void onDestroy() {  
  61.               
  62.             mList.clear();  
  63.         }  
  64.   
  65.         @Override  
  66.         public int getCount() {  
  67.               
  68.             return mList.size();  
  69.         }  
  70.   
  71.         @Override  
  72.         public RemoteViews getViewAt(int position) {  
  73.             if (position < 0 || position >= mList.size())  
  74.                 return null;  
  75.             String content = mList.get(position);  
  76.             final RemoteViews rv = new RemoteViews(mContext.getPackageName(),  
  77.                     R.layout.row);  
  78.             Intent intent = new Intent();  
  79.             // TODO  
  80.             // intent.setComponent(new ComponentName("包名", "类名"));  
  81.             // 与CustomWidget中remoteViews.setPendingIntentTemplate配对使用实现ListView中的Item的点击事件  
  82.             rv.setOnClickFillInIntent(R.id.widget_list_item_layout, intent);          
  83.             rv.setTextViewText(android.R.id.text1, content);  
  84.   
  85.             return rv;  
  86.         }  
  87.   
  88.         @Override  
  89.         public RemoteViews getLoadingView() {  
  90.             return null;  
  91.         }  
  92.   
  93.         @Override  
  94.         public int getViewTypeCount() {  
  95.             return 1;  
  96.         }  
  97.   
  98.         @Override  
  99.         public long getItemId(int position) {  
  100.             return position;  
  101.         }  
  102.   
  103.         @Override  
  104.         public boolean hasStableIds() {  
  105.             return true;  
  106.         }  
  107.     }  
  108.       
  109.     public List<String>getDataSources() {  
  110.         List<String> list = new ArrayList<String>();  
  111.         ......  
  112.         return list;  
  113.     }  
  114. }  

(2):在widget的onUpdate中添加代码:

[java] view plaincopy
 
  1. for (int i = 0; i < appWidgetIds.length; i++) {//如果使用循环,当调试重新运行程序或者重启机器时widget点击事情会失灵  
  2.         Intent intent = new Intent(ctxt, WidgetService.class);  
  3.         RemoteViews widget = new RemoteViews(ctxt.getPackageName(),  
  4.                 R.layout.widget);  
  5.         widget.setRemoteAdapter(appWidgetIds[i], R.id.words, intent);  
  6.   
  7.         Intent clickIntent = new Intent(ctxt, LoremActivity.class);  
  8.         PendingIntent clickPI = PendingIntent.getActivity(ctxt, 0,  
  9.                 clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);  
  10.         widget.setPendingIntentTemplate(R.id.words, clickPI);//配合getViewAt方法中的setOnClickFillInIntent实现listView中Item的点击事件  
  11.   
  12.         appWidgetManager.updateAppWidget(appWidgetIds[i], widget);  
  13.     }  

(3):widget.xml

[html] view plaincopy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <ListView xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:id="@+id/words"  
  4.   android:layout_width="match_parent"  
  5.   android:layout_height="match_parent"  
  6.   android:layout_marginTop="3dp"  
  7.   android:layout_marginLeft="3dp"  
  8.   android:background="@drawable/widget_frame"  
  9. />  


(4):row.xml

[html] view plaincopy
 
  1. <TextView xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:id="@android:id/text1"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="wrap_content"  
  5.     android:textAppearance="?android:attr/textAppearanceLarge"  
  6.     android:gravity="center_vertical"  
  7.     android:paddingLeft="6dip"  
  8.     android:minHeight="?android:attr/listPreferredItemHeight"  
  9. />  

三:如何更新widget

(1):定时更新

在widget配置文件中有这句 android:updatePeriodMillis="0",这种更新方式已经不能使用了,一般定时更新使用AlarmManager,如下代码

[html] view plaincopy
 
  1. private void setAlarm(Context context, int appWidgetId, int updateRateSeconds) {  
  2.       Intent widgetUpdate = new Intent();  
  3.       widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);  
  4.       widgetUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { appWidgetId });  
  5.   
  6.       // make this pending intent unique by adding a scheme to it  
  7.       widgetUpdate.setData(Uri.withAppendedPath(Uri.parse(ImagesWidgetProvider.URI_SCHEME + "://widget/id/"), String.valueOf(appWidgetId)));  
  8.       PendingIntent newPending = PendingIntent.getBroadcast(context, 0, widgetUpdate, PendingIntent.FLAG_UPDATE_CURRENT);  
  9.   
  10.       // schedule the updating  
  11.       AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);  
  12.       if (updateRateSeconds >= 0) {  
  13.           alarms.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), updateRateSeconds * 1000, newPending);  
  14.       } else {  
  15.           alarms.cancel(newPending);  
  16.       }  
  17.   }  

(2):事件更新,不通过时间更新widget一般使用广播来更新

[java] view plaincopy
 
  1. public void onReceive(Context context, Intent intent) {  
  2.         // TODO Auto-generated method stub  
  3.         if (intent.getAction().equals(  
  4.                 "com.example.widgettestone.WIDGET_CONTROL")) {  
  5.             AppWidgetManager manager = AppWidgetManager.getInstance(context);  
  6.             ComponentName thisWidget = new ComponentName(context, TaskPad.class);  
  7.             int[] appWidgetIds = manager.getAppWidgetIds(thisWidget);  
  8.             manager.notifyAppWidgetViewDataChanged(appWidgetIds,R.id.widget_list);//通知RemoteViews刷新数据,在渲染器中重写onDataSetChanged方法重写获取数据源  
  9.         } else {  
  10.             super.onReceive(context, intent);  
  11.         }  
  12.   
  13.     }  

AndroidManifest.xml中widget的配置中添加:

[html] view plaincopy
 
  1. <action android:name="com.example.widgettestone.WIDGET_CONTROL" />  


当需要更新的时候发出该广播即可更新:

[java] view plaincopy
 
  1. Intent intentUpdate = new Intent("com.example.widgettestone.WIDGET_CONTROL");  
  2. pan style="white-space:pre">        </span>context.sendBroadcast(intentUpdate);  

四:小问题:

(1):ListView的getview()中重复调用(position重复调用)问题:

网友提供的解决方法:

[java] view plaincopy
 
    1. 重写的listview adapter中,在getView()方法中,打印语句时,相同的position打印了多次,修改方法:  
    2. 将布局文件中ListView的高度改为“fill_parent”  
    3.  <ListView  
    4.    android:id="@+id/dynamic_list"  
    5.    android:layout_height="fill_parent"  
    6.    android:layout_width="fill_parent"  
    7.    android:scrollbars="vertical"  
    8.    android:layout_weight="1"  
    9.    android:drawSelectorOnTop="false"      
    10.    android:fadingEdgeLength="0dip"    
    11.    android:divider="@null"   
    12.    android:dividerHeight="0dip"  
    13.    android:cacheColorHint="#00000000"   
    14.    android:background="@color/listview_bg_color" />  

原文:http://blog.csdn.net/limitemp/article/details/9101763

原文地址:https://www.cnblogs.com/veins/p/3838450.html