music的 桌面小部件的更新不及时问题
来源:互联网 发布:淘宝助理5.5无数据 编辑:程序博客网 时间:2024/05/12 02:19
Android 开发中遇到music的 桌面4*2小部件的更新不及时问题,尤其在重启手机,切换语言,开关机过程中等情况下尤为明显,表现在小部件界面一片空白.现在优化了一番,小部件更新的问题就解决了,方案如下:
源码里面music小部件的代码主要在src/com/android/music/MediaAppWidgetProvider.java里面
未改动之前的代码:public class MediaAppWidgetProvider extends AppWidgetProvider {
@Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { MusicLogUtils.i(TAG, "onUpdate"); isAppWidget = true; defaultAppWidget(context, appWidgetIds); // Send broadcast intent to any running MediaPlaybackService so it can // wrap around with an immediate update. Intent updateIntent = new Intent(context, MediaPlaybackService.class); updateIntent.setAction(MediaPlaybackService.SERVICECMD); updateIntent.putExtra(MediaPlaybackService.CMDNAME, MediaAppWidgetProvider.CMDAPPWIDGETUPDATE); updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); updateIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); context.startService(updateIntent); } //重写appWidgetProvider的onUpdate方法,此方法当小部件更新时会触发. private void defaultAppWidget(Context context, int[] appWidgetIds) { final Resources res = context.getResources(); final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.album_appwidget); views.setViewVisibility(R.id.title, View.GONE); /// M: Set default play/pause button image resource views.setImageViewResource(R.id.control_play, R.drawable.rgk_music_btn_play); views.setTextViewText(R.id.artist, res.getText(R.string.widget_initial_text)); linkButtons(context, views, false /* not playing */); pushUpdate(context, appWidgetIds, views); } private void pushUpdate(Context context, int[] appWidgetIds, RemoteViews views) { // Update specific list of appWidgetIds if given, otherwise default to // all final AppWidgetManager gm = AppWidgetManager.getInstance(context); MusicLogUtils.i(TAG, "pushUpdate"); /// M: update app widget @{ if (appWidgetIds != null) {4 gm.updateAppWidget(appWidgetIds, views); } else { gm.updateAppWidget(new ComponentName(context, this.getClass()), views); } /// @} } private boolean hasInstances(Context context) { AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, this.getClass())); /// M: log appWidgetIds status @{ int widgetLength = (appWidgetIds == null ? 0 : appWidgetIds.length); MusicLogUtils.i(TAG, "hasInstances number is " + widgetLength); /// @} return (widgetLength > 0); } void notifyChange(MediaPlaybackService service, String what) { /// M: add QUIT_PLAYBACK status to update widget and log something @{ if (hasInstances(service)) { if (MediaPlaybackService.META_CHANGED.equals(what) || MediaPlaybackService.PLAYSTATE_CHANGED.equals(what) || MediaPlaybackService.QUIT_PLAYBACK.equals(what)) { performUpdate(service, null); } else { MusicLogUtils.d(TAG, "notifyChange(" + what + "):discard!"); } } else { MusicLogUtils.d(TAG, "notifyChange: no Instance"); } /// @} } void performUpdate(MediaPlaybackService service, int[] appWidgetIds) { MusicLogUtils.d(TAG, "performUpdate"); final Resources res = service.getResources(); final RemoteViews views = new RemoteViews(service.getPackageName(), R.layout.album_appwidget); titleName = service.getTrackName(); artistName = service.getArtistName(); errorState = null; mAlbumId = service.getAlbumId(); // modify start Bitmap icon = BitmapFactory.decodeResource(res, R.drawable.rgk_default_nowplaying_thumb_1); int w = icon.getWidth(); int h = icon.getHeight(); /// M: call getArtwork to get album art bitmap //add (start) Bitmap b = null; if (MusicUtils.isMusicPermissionGrant(service.getApplicationContext())) { b = MusicUtils.getArtwork(service.getApplicationContext(), -1, mAlbumId, false); } //add (end) // modify end if (b == null) { b = icon; } b = Bitmap.createScaledBitmap(b, w, h, true); /// M: If artist name get from database is equal to "unknown",use /// unknown_artist_name replace. if (MediaStore.UNKNOWN_STRING.equals(artistName)) { artistName = res.getString(R.string.unknown_artist_name); } // Format title string with track number, or show SD card message String status = Environment.getExternalStorageState(); if (status.equals(Environment.MEDIA_SHARED) || status.equals(Environment.MEDIA_UNMOUNTED)) { /// M: Remove check external storage @{ // if (android.os.Environment.isExternalStorageRemovable()) { errorState = res.getText(R.string.sdcard_busy_title); // } else { // errorState = res.getText(R.string.sdcard_busy_title_nosdcard); // } /// @} } else if (status.equals(Environment.MEDIA_REMOVED)) { /// M: Remove check external storage @{ // if (android.os.Environment.isExternalStorageRemovable()) { errorState = res.getText(R.string.sdcard_missing_title); // } else { // errorState = res.getText(R.string.sdcard_missing_title_nosdcard); // } /// @} } else if (titleName == null) { errorState = res.getText(R.string.widget_initial_text); } if (errorState != null) { /// M: Show error state to user views.setViewVisibility(R.id.artist, View.VISIBLE); views.setViewVisibility(R.id.title, View.GONE); views.setTextViewText(R.id.artist, errorState); views.setImageViewBitmap(R.id.music_photo, icon); } else { /// M: No error, so show normal titles @{ final String httpHeader = "http://"; if ((titleName != null) && titleName.toString().startsWith(httpHeader)) { views.setViewVisibility(R.id.title, View.VISIBLE); views.setViewVisibility(R.id.artist, View.GONE); views.setTextViewText(R.id.title, titleName); } else { views.setViewVisibility(R.id.title, View.VISIBLE); views.setViewVisibility(R.id.artist, View.VISIBLE); views.setTextViewText(R.id.title, titleName); views.setTextViewText(R.id.artist, artistName); } // modify (end) if (b != null) { views.setImageViewBitmap(R.id.music_photo, b); } else { views.setImageViewBitmap(R.id.music_photo, icon); } /// @} } // Set correct drawable for pause state isPlaying = service.isPlaying(); if (isPlaying) { views.setImageViewResource(R.id.control_play, R.drawable.rgk_music_btn_pause); } else { views.setImageViewResource(R.id.control_play, R.drawable.rgk_music_btn_play); }views.setProgressBar(R.id.widget_music_mini_progressBar, 1000, mProgress, false); views.setTextViewText(R.id.currenttime, mcurrenttime); views.setTextViewText(R.id.totaltime, mtotaltime); // Link actions buttons to intents linkButtons(service, views, isPlaying); pushUpdate(service, appWidgetIds, views); } public void updateTime(MediaPlaybackService service) { final RemoteViews views = new RemoteViews(service.getApplicationContext().getPackageName(), R.layout.album_appwidget); long pos = service.position(); long duration = service.duration(); //A: { long expand = (long) (pos/(duration/1000)); pos += expand; //A: } if (duration != 0) { if (pos >= service.duration()) { pos = service.duration(); } mProgress = (int) (1000 * pos / duration); } mtotaltime = MusicUtils.makeTimeString(service, service.duration() / 1000); mcurrenttime = MusicUtils.makeTimeString(service, pos / 1000); views.setProgressBar(R.id.widget_music_mini_progressBar, 1000, mProgress, false); views.setTextViewText(R.id.currenttime, mcurrenttime); views.setTextViewText(R.id.totaltime, mtotaltime); pushUpdate(service, null, views); } private void linkButtons(Context context, RemoteViews views, boolean playerActive) { // Connect up various buttons and touch events Intent intent; PendingIntent pendingIntent; final ComponentName serviceName = new ComponentName(context, MediaPlaybackService.class); if (playerActive) { intent = new Intent(context, MediaPlaybackActivity.class); pendingIntent = PendingIntent.getActivity(context, 0 /* no requestCode */, intent, 0 /* no flag */); views.setOnClickPendingIntent(R.id.album_appwidget, pendingIntent); } else { intent = new Intent(context, MusicBrowserActivity.class); pendingIntent = PendingIntent.getActivity(context, 0 /* no requestCode */, intent, 0 /* no flag */); views.setOnClickPendingIntent(R.id.album_appwidget, pendingIntent); } // add start intent = new Intent(MediaPlaybackService.PREVIOUS_ACTION); intent.setComponent(serviceName); /// M: set this pendingintent to use one time only pendingIntent = PendingIntent.getService(context, 0 /* no requestCode */, intent, PendingIntent.FLAG_ONE_SHOT); views.setOnClickPendingIntent(R.id.control_prev, pendingIntent); // add end intent = new Intent(MediaPlaybackService.TOGGLEPAUSE_ACTION); intent.setComponent(serviceName); pendingIntent = PendingIntent.getService(context, 0 /* no requestCode */, intent, 0 /* no flag */); views.setOnClickPendingIntent(R.id.control_play, pendingIntent); intent = new Intent(MediaPlaybackService.NEXT_ACTION); intent.setComponent(serviceName); /// M: set this pendingintent to use one time only pendingIntent = PendingIntent.getService(context, 0 /* no requestCode */, intent, PendingIntent.FLAG_ONE_SHOT); views.setOnClickPendingIntent(R.id.control_next, pendingIntent); } public static class PackageDataClearedReceiver extends BroadcastReceiver { private static final String ACTION_PACKAGE_DATA_CLEARED = "com.mediatek.intent.action.SETTINGS_PACKAGE_DATA_CLEARED"; public void onReceive(Context context, Intent intent) { if (!ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) { return; } String pkgName = intent.getStringExtra("packageName"); MusicLogUtils.v(TAG, "PackageDataClearedReceiver recevied pkgName = " + pkgName); if (pkgName != null && pkgName.equals(context.getPackageName())) { MediaAppWidgetProvider mediaAppWidgetProvider = MediaAppWidgetProvider.getInstance(); if (mediaAppWidgetProvider == null) { MusicLogUtils.v(TAG, "mediaAppWidgetProvider is null "); return; } mediaAppWidgetProvider.defaultAppWidget(context, null); } } } ``` }代码这么写会在切换语言后或开关机后导致小部件界面加载异常,原因是因为小部件界面的进度条更新和其他更新分开了,在service里面的更新代码里只调用了updateTime,会导致更新的不同步,所以优化后的代码将updateTime的部分移到performUpdate里面,这样可以实现更新的一体化,而不会出现在某些情况下小部件界面部分显示部分显示不了的情况.优化后的代码如下:
void performUpdate(MediaPlaybackService service, int[] appWidgetIds) {
// Set correct drawable for pause state
isPlaying = service.isPlaying();
if (isPlaying) {
views.setImageViewResource(R.id.control_play, R.drawable.rgk_music_btn_pause);
} else {
views.setImageViewResource(R.id.control_play, R.drawable.rgk_music_btn_play);
}
// modify start
if (MusicUtils.isMusicPermissionGrant(service.getApplicationContext())) {
//A: {
long pos = service.position();
long duration = service.duration();
//A: {
if ((duration/1000) != 0) {
long expand = (long) (pos/(duration/1000));
pos += expand;
}
//A: }
if (duration != 0) {
if (pos >= service.duration()) {
pos = service.duration();
}
mProgress = (int) (1000 * pos / duration);
}
mtotaltime = MusicUtils.makeTimeString(service, service.duration() / 1000);
mcurrenttime = MusicUtils.makeTimeString(service, pos / 1000);
//A: }
}
// modify end
views.setProgressBar(R.id.widget_music_mini_progressBar, 1000, mProgress, false);
views.setTextViewText(R.id.currenttime, mcurrenttime);
}
//delete start
/*public void updateTime(MediaPlaybackService service) {
final RemoteViews views = new RemoteViews(service.getApplicationContext().getPackageName(), R.layout.album_appwidget);
long pos = service.position();
long duration = service.duration();
//A: {
if ((duration/1000) != 0) {
long expand = (long) (pos/(duration/1000));
pos += expand;
}
//A: }
if (duration != 0) {
if (pos >= service.duration()) {
pos = service.duration();
}
mProgress = (int) (1000 * pos / duration);
}
mtotaltime = MusicUtils.makeTimeString(service, service.duration() / 1000);
mcurrenttime = MusicUtils.makeTimeString(service, pos / 1000);
views.setProgressBar(R.id.widget_music_mini_progressBar, 1000, mProgress, false);
views.setTextViewText(R.id.currenttime, mcurrenttime);
views.setTextViewText(R.id.totaltime, mtotaltime);
pushUpdate(service, null, views);
}*/
//delete end
“`
- music的 桌面小部件的更新不及时问题
- 简单的桌面小部件
- gulp 疑似缓存的问题,watch更新不及时
- 7.4 桌面小部件:widgit的创建
- Android 桌面小部件(AppWidgetProvider)的应用
- 桌面小部件的简单开发步骤
- mt6735第一次开机或者恢复出厂设置后,桌面小部件一直不更新无图标
- 安卓桌面插件(窗口小部件)的各种问题
- ALV 编辑及时更新的问题
- ALV 编辑及时更新的问题
- [FAQ16697]第一开机或者恢复出厂设置后,桌面小部件很长时间才更新到正常的画面
- 解决Gradle插件在eclipse或打包时不及时更新缓存的问题
- RemoteViews在桌面小部件和通知栏的使用
- 关于RemoteView的一点愚见(实现桌面小部件)
- Notification及桌面小部件的应用(RemoteViews)
- img动态改变src的参数,图片不及时更新
- 创建追踪小部件的问题?
- 桌面小部件
- dp斜率优化 锯木厂选址(CEOI 2003)题解
- jsfiddle的demo
- c++学习笔记5:运算符重载、友元和类的类型转换
- unity3d开发环境搭建
- linux安装redis
- music的 桌面小部件的更新不及时问题
- Maven入门(含实例教程)
- 信号量与锁的差别
- vue动画 -组件
- [leetcode: Python]459. Repeated Substring Pattern
- Oracle查行号为100到110的10条数据
- PHP设计模式系列
- 面试题2—交换a和b
- 树状数组_Ping pong