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
“`

原创粉丝点击