Android(安卓)widget定时更新及事件处理
16lz
2021-01-25
最近在项目里用到widget ,涉及到widget 的定时更新和事件监控与处理。具体效果如图:
功能:
实现定时更新
能展示同一组数据,update 时更新数据源
可以监听事件,并作出不同反应
实现分析:
SDK1.5 之后android:updatePeriodMillis 就失效,改为默认更新,为了实现自定义定时更新,用到了定时器主动更新;
widget 由其它应用程序托管,共用数据十分困难,我将数据写入sharedpreferences ,以记录数据源;
widget 各种状态都是由消息控制,为方便事件管理,向系统注册接受器。
首先在AndroidManifest.xml 文件中注册widget:
- <receiver
- android:name=".widget"
- android:label="@string/app_name"
- >
- <intent-filter>
- <actionandroid:name="android.appwidget.action.APPWIDGET_UPDATE"/>
- </intent-filter>
- <meta-data
- android:name="android.appwidget.provider"
- android:resource="@xml/widget"
- />
- </receiver>
添加res/xml/widget.xml设置widget属性:
- <appwidget-provider
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:minWidth="294dip"
- android:minHeight="72dip"
- android:updatePeriodMillis="5000"
- android:initialLayout="@layout/appwidget"
- >
- </appwidget-provider>
实现定时更新,只需在widget第一次创建或系统重启时开启计时器,于是给来自计时器的消息加上sheme以区分:
- privatevoidsetAlarm(Contextcontext,intappWidgetId,intupdateRateSeconds){
- IntentwidgetUpdate=newIntent();
- widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
- widgetUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,newint[]{appWidgetId});
- //给来自计时器的消息加标识
- widgetUpdate.setData(Uri.withAppendedPath(Uri.parse(URI_SCHEME+"://widget/id/"),String.valueOf(appWidgetId)));
- PendingIntentnewPending=PendingIntent.getBroadcast(context,0,widgetUpdate,PendingIntent.FLAG_UPDATE_CURRENT);
- AlarmManageralarms=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
- if(updateRateSeconds>=0){
- alarms.setRepeating(AlarmManager.ELAPSED_REALTIME,SystemClock.elapsedRealtime(),updateRateSeconds,newPending);
- }else{
- alarms.cancel(newPending);
- }
- }
要接受来自计时器的消息,需要在AndroidManifest.xml另注册接受器:
- <receiver
- android:name=".widget"
- android:label="@string/app_name"
- >
- <intent-filter>
- <actionandroid:name="com.example.widget.APPWIDGET_UPDATE"/>
- <dataandroid:scheme="widget"/>
- </intent-filter>
- <meta-dataandroid:name="android.appwidget.provider"
- android:resource="@xml/widget"
- />
- </receiver>
实现了定时更新。接下来展示界面:
- publicstaticfinalStringPREFS_NAME="com.example.widget_preferences";
- publicstaticfinalStringPREFS_WIDGET_DATA="WidgetData-%d";
- publicstaticfinalStringPREFS_CURRENT_INDEX="CurrentIndex-%d";
- privatestaticfinalStringACTION_WIDGET_CONTROL="com.example.widget.WIDGET_CONTROL";
- publicvoidonUpdate(Contextcontext,AppWidgetManagerappWidgetManager,
- int[]appWidgetIds){
- //TODOAuto-generatedmethodstub
- finalintN=appWidgetIds.length;
- SharedPreferencesshared=context.getSharedPreferences(PREFS_NAME,0);
- SharedPreferences.Editoreditor=shared.edit();
- for(inti=0;i<N;i++)
- {
- if(appWidgetIds[i]==AppWidgetManager.INVALID_APPWIDGET_ID)
- continue;
- intappWidgetId=appWidgetIds[i];
- StringwidgetDataStr=“data1=value|||data2=value|||data3=value|||data4=value”;
- editor.putString(String.format(PREFS_WIDGET_DATA,appWidgetIds[i]),widgetDataStr);
- editor.putInt(String.format(PREFS_CURRENT_INDEX,appWidgetIds[i]),0);
- updateDisplay(context,appWidgetId,getDataByKey(widgetDataStr,0));
- }
- editor.commit();
- }
- privateString[]getDataByKey(StringdataStr,intindex)
- {
- String[]strArr=dataStr.split("//|//|//|");
- if(index<0)
- index=0;
- if(index>=strArr.length)
- index=strArr.length-1;
- strArr=strArr[index].split("=",2);
- if(strArr.length==2)
- returnstrArr;
- returnnewString[]{"",""};
- }
- publicvoidupdateDisplay(Contextcontext,intappWidgetId,String[]playData)
- {
- RemoteViewsremoteView=newRemoteViews(context.getPackageName(),R.layout.appwidget);
- remoteView.setTextViewText(R.id.widget_word,playData[0]);
- remoteView.setTextViewText(R.id.widget_meaning,playData[1]);
- remoteView.setOnClickPendingIntent(R.id.widget_back,makeControlPendingIntent(context,"back",appWidgetId));
- remoteView.setOnClickPendingIntent(R.id.widget_next,makeControlPendingIntent(context,"next",appWidgetId));
- AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId,remoteView);
- }
- publicPendingIntentmakeControlPendingIntent(Contextcontext,Stringcommand,intappWidgetId)
- {
- Intentaction=newIntent();
- action.setAction(ACTION_WIDGET_CONTROL);
- action.putExtra(EXTRA_APPWIDGET_ID,appWidgetId);
- Uridata=Uri.withAppendedPath(Uri.parse(URI_SCHEME+"://widget/id/#"+command),String.valueOf(appWidgetId));
- action.setData(data);
- return(PendingIntent.getBroadcast(context,0,action,PendingIntent.FLAG_ONE_SHOT));
- }
这样widget就可以正常显示了,当然,现在还无法接受消息去处理事件,接下来注册接受器:
然后,处理不同命令:
- <receiver
- android:name=".widget"
- android:label="@string/app_name"
- >
- <intent-filter>
- <actionandroid:name="com.example.widget.WIDGET_CONTROL" />
- <dataandroid:scheme="widget"/>
- </intent-filter>
- <meta-dataandroid:name="android.appwidget.provider"
- android:resource="@xml/widget"
- />
- </receiver>
- publicvoidonReceive(Contextcontext,Intentintent)
- if(ACTION_WIDGET_CONTROL.equals(action))
- {
- finalintappWidgetId=intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,AppWidgetManager.INVALID_APPWIDGET_ID);
- if(appWidgetId!=AppWidgetManager.INVALID_APPWIDGET_ID)
- {
- StringcontrolType=intent.getData().getFragment();
- SharedPreferencesshared=context.getSharedPreferences(PREFS_NAME,0);
- intindex=shared.getInt(String.format(PREFS_CURRENT_INDEX,appWidgetId),0);
- intsize=Integer.parseInt(shared.getString(String.format(PREFS_DATA_SIZE,appWidgetId),"20"));
- if(controlType.equalsIgnoreCase("next"))
- {
- index++;
- if(index>=size)
- index=0;
- }
- elseif(controlType.equalsIgnoreCase("back"))
- {
- index--;
- if(index<0)
- index=size-1;
- }
- shared.edit().putInt(String.format(PREFS_CURRENT_INDEX,appWidgetId),index).commit();
- updateDisplay(
- context,
- appWidgetId,
- getDataByKey(shared.getString(String.format(PREFS_WIDGET_DATA,appWidgetId),""),index)
- );
- }
- }
- }
- 最后,不能忘了收尾工作:
- publicvoidonDeleted(Contextcontext,int[]appWidgetIds){
- //TODOAuto-generatedmethodstub
- SharedPreferencesshared=context.getSharedPreferences(PREFS_NAME,0);
- for(intappWidgetId:appWidgetIds)
- {
- setAlarm(context,appWidgetId,-1);
- shared.edit().remove(String.format(PREFS_WIDGET_DATA,appWidgetId))
- .remove(String.format(PREFS_CURRENT_INDEX,appWidgetId))
- .commit();
- }
- super.onDeleted(context,appWidgetIds);
- }
更多相关文章
- android之handler介绍和使用方法
- [移动] Android推送方案分析(MQTT/XMPP/GCM)
- Android(安卓)推送实现原理解析
- Android推送通知的实现--采用MQTT协议实现Android消息推送
- Android文件上传下载
- Android(安卓)Studio实现一个PC和Android端的聊天室
- Android(安卓)Looper用法及原理
- Android(安卓)第九天(晚上)
- Android用户事件输入路径