接上篇widget开发之后,测试妹子提出了13个bug。。。。。。我的天哪,原以为简简单单的widget,居然这么多问题点。
主要表现为以下几点:
1、切换语言后,插件显示默认值的问题(天气、时钟、音乐)
2、切换时间格式后,时间为跟随更新的问题
3、一段时间过后,时间卡在某个点不更新(怀疑是进程或者服务被杀死,log显示为收不到广播)
4、频繁切换歌曲导致widget停止运行
5、清除widget数据导致widget无法正常更新
经过一番挣扎和借鉴已有的widget代码,get到一些新技能。在这里记录一番,虽然周期有点长,但是有成长总是好的。。。(也只能这么安慰自己了)
问题1、切换语言(WidgetProviderAll extends AppWidgetProvider)会回调WidgetProviderAll 里的onUpdate方法。
在onUpdate中做一些处理就好了,比如获取当前时间、获取当前天气等等
这里有必要讲一下音乐,一开始我在receiver里监听了
<!-- 音乐改变广播 -->
<action android:name="com.android.music.playstatechanged" />
<action android:name="com.android.music.metachanged" />
后来发现,如果是静态注册的,那么添加上去是默认界面,不会变为当前正在播放的音乐,需要切换歌曲或者播放暂停,才能再收到系统广播改变播放状态以及背景。
后来改为在service里动态注册,广播注册后,就会收到一个playstatechanged和一个metachanged。此时就可以根据收到的广播来改变播放/暂停、和歌曲信息(因为它们是粘性广播)。
问题2、修改时间格式,会受到系统广播
关于时间更新的action:
filter.addAction( Intent.ACTION_DATE_CHANGED );
filter.addAction( Intent.ACTION_TIMEZONE_CHANGED );
filter.addAction( Intent.ACTION_TIME_CHANGED );
filter.addAction( Intent.ACTION_TIME_TICK );
filter.addAction( "android.intent.action.TIME_SET" );
动态注册,因为time_set只能动态注册才能接收到广播。(百度到的)
问题3、进程或者服务被杀死
1、提高优先级,避免被杀死。
/**
* 增加一个1X1的悬浮窗,提升服务的优先级
* @author yangtianyu 2016-5-11
*/
private void addForegroundView()
{
WindowManager wm = (WindowManager)getApplicationContext().getSystemService( Context.WINDOW_SERVICE );
ForegroundView = new LinearLayout( this );
WindowManager.LayoutParams ForegroundParams = new WindowManager.LayoutParams();
ForegroundParams.type = WindowManager.LayoutParams.TYPE_PHONE;
ForegroundParams.format = PixelFormat.RGBA_8888;
ForegroundParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
ForegroundParams.x = 0;
ForegroundParams.y = 0;
ForegroundParams.width = 1;
ForegroundParams.height = 1;
ForegroundParams.gravity = Gravity.BOTTOM;
wm.addView( ForegroundView , ForegroundParams );
}
2、被杀死后复活
在service中注册需要的广播,并重写方法:
public int onStartCommand(
Intent intent ,
int flags ,
int startId )
{
super.onStartCommand( intent , flags , startId );
Log.v( TAG , "onStartCommand" );
// 为防止用户使用内存整理,把widget和服务一并关掉,我们的服务还是永远开启吧
//restartByAlarmManager(intent);
return START_STICKY;
}
@Override
public void onDestroy()
{
super.onDestroy();
Log.v( TAG , "onDestroy" );
Log.v( TAG , "unregisterReceiver action " + Intent.ACTION_TIME_TICK );
this.unregisterReceiver( mIntentReceiver );
// 非常奇怪的是,系统关闭服务竟然使用的是stopService而不是kill,导致服务没有自动重启
// 所以我们再加个定时器1秒后把自己启动
long now = System.currentTimeMillis();
long updateMilis = 1000;
PendingIntent pendingIntent = PendingIntent.getService( this , 0 , new Intent( this , ClockWeatherMusicService.class ) , 0 );
// Schedule alarm, and force the device awake for this update
AlarmManager alarmManager = (AlarmManager)getSystemService( Context.ALARM_SERVICE );
alarmManager.set( AlarmManager.RTC_WAKEUP , now + updateMilis , pendingIntent );
if( ForegroundView != null )
{
WindowManager wm = (WindowManager)getApplicationContext().getSystemService( Context.WINDOW_SERVICE );
wm.removeView( ForegroundView );
}
}
并且设置manifest属性:
<application
android:allowBackup="true"
android:icon="@drawable/widget_icon"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:allowClearUserData="false"
android:persistent="true" >
android:persistent:设置应用常驻
android:allowClearUserData:是否允许用户清除数据(问题5也可以用这个方法解决)
问题4、频繁更换图片导致widget停止运行
问题5、清除数据导致widget显示异常
关于上篇文章中后面的两个疑问
<!-- appwidget-provider Widget的配置文件 -->
<!-- android:minWidth 最小宽度 -->
<!-- android:minHeight 最小高度 -->
<!-- android:updatePeriodMillis 组件更新频率(毫秒) -->
<!-- android:initialLayout 添加到桌面时widget的布局文件 -->
<!-- android:configure Widget设置用Activity -->
<!-- android:resizeMode widget可以被拉伸的方向。horizontal表示可以水平拉伸,vertical表示可以竖直拉伸 -->
<!-- android:widgetCategory widget可以被显示的位置。home_screen表示可以将widget添加到桌面,keyguard表示widget可以被添加到锁屏界面。 -->
<!-- android:previewImage widget的预览图,显示在launcher中的小部件列表界面的图片-->
<appwidget-provider
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/widget_layout"
android:minWidth="@dimen/widget_minwidth"
android:minHeight="@dimen/widget_minheight"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen"
android:previewImage="@drawable/widget_icon"
/>
暂时更新到这里,准备换工作啦。