widget开发之helloworld(测试版)

接上篇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停止运行

log显示内存过大导致停止运行。
网上找到原因:频繁切换图片的widget,需要每次update的时候new remoteview 并设置新的界面,不能一直使用同一个remoteview。

问题5、清除数据导致widget显示异常

除了上面提到的 android:allowClearUserData属性外,我们通过自己桌面发送广播来强行刷新一下widget,并启动服务(属于一种保护措施)
/*********************************************************************************************************************************/
/*********************************************************************************************************************************/
/*********************************************************************************************************************************/

关于上篇文章中后面的两个疑问

1、widget动画
原生widget我暂时仍没有实现。
2、widget的拉伸
拉伸在manifest中,widgetinfo关联的布局里设置。
<!-- 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"
	/>
暂时更新到这里,准备换工作啦。
之后有涉及到再进一步更新。
欢迎大神指导,欢迎大家留言相互交流。
 


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值