Android 4.1 Music 通知栏的音乐控制

来源:互联网 发布:建模 软件 数据 编辑:程序博客网 时间:2024/05/16 05:34


本文根据原生Android 4.1.1 Music 源码做修改。

1 原生Music 暂停的时候,会删除通知栏上的通知。

2 原生Music 通知栏不能控制音乐,比如下一首,上一首,暂停/播放。

一 解决思路:

1 接到暂停广播时,只暂停,不去除通知。

/packages/apps/Music/src/com/android/music/MediaPlaybackService.java中

调用的 stopForeground(true)方法控制去除通知

2 自定义音乐通知,添加按钮事件。

   /packages/apps/Music/src/com/android/music/MediaPlaybackService.java中

  updateNotification()方法中自定义Notification,关键对RemoteViews 的理解

二  修改后效果图:


三 详细代码

1 接到暂停广播时,只暂停,不去除通知

源代码 采取的策略是 只要暂停就去除通知,这就会造成一个问题就是,当播放视频的时候音乐播放器接受到暂停的广播,于是消除了通知栏。

1.1 添加暂停 不消除通知的方法 pause(boolean isStopForeground)

private void pause(boolean isStopForeground) {        synchronized(this) {            mMediaplayerHandler.removeMessages(FADEUP);            if (isPlaying()) {                mPlayer.pause();                gotoIdleState(isStopForeground);                mIsSupposedToBePlaying = false;                notifyChange(PLAYSTATE_CHANGED);                saveBookmarkIfNeeded();            }        }    }        private void gotoIdleState(boolean isStopForeground) {        mDelayedStopHandler.removeCallbacksAndMessages(null);        Message msg = mDelayedStopHandler.obtainMessage();        mDelayedStopHandler.sendMessageDelayed(msg, IDLE_DELAY);       //此方法控制消除通知        stopForeground(isStopForeground);    }
1.2 接收暂停广播的时候将pause()方法换为:pause(false)

private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            String action = intent.getAction();            String cmd = intent.getStringExtra("command");            MusicUtils.debugLog("mIntentReceiver.onReceive " + action + " / " + cmd);            if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {                gotoNext(true);            } else if (CMDPREVIOUS.equals(cmd) || PREVIOUS_ACTION.equals(action)) {                prev();            } else if (CMDTOGGLEPAUSE.equals(cmd) || TOGGLEPAUSE_ACTION.equals(action)) {                if (isPlaying()) {                    /*Begin: modified  */                    pause(false);                    updateNotification();                    /*End: */                    mPausedByTransientLossOfFocus = false;                } else {                    play();                }            } else if (CMDPAUSE.equals(cmd) || PAUSE_ACTION.equals(action)) {                /*Begin: modified  */                pause(false);                updateNotification();                /*End:*/                mPausedByTransientLossOfFocus = false;            } else if (CMDPLAY.equals(cmd)) {                              ...

2 Music 音乐通知控制 

2.1 通知的布局文件 /packages/apps/Music/res/layout/statusbar.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="horizontal" >    <LinearLayout        xmlns:android="http://schemas.android.com/apk/res/android"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:orientation="horizontal"         android:layout_gravity="center_vertical">        <!-- 图标 -->        <ImageView            android:id="@+id/icon"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:gravity="center"            android:padding="4dip" >        </ImageView>    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="vertical" >        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="horizontal" >              <!-- 音乐名 -->            <TextView                android:id="@+id/trackname"                style="@android:style/TextAppearance.StatusBar.EventContent.Title"                android:layout_width="80dip"                android:layout_height="wrap_content"                android:layout_gravity="left"                android:ellipsize="marquee"                android:focusable="true"                android:singleLine="true" />            <RelativeLayout                android:layout_width="match_parent"                android:layout_height="match_parent" >                  <!-- 上一首 -->                <ImageButton                    android:id="@+id/statusbar_prev"                    style="@android:style/MediaButton.Previous"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_alignParentLeft="true" />                  <!-- 暂停/播放 -->                <ImageButton                    android:id="@+id/statusbar_pause"                    style="@android:style/MediaButton.Pause"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_centerHorizontal="true" />                  <!-- 下一首 -->                <ImageButton                    android:id="@+id/statusbar_next"                    style="@android:style/MediaButton.Next"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_alignParentRight="true"                    android:gravity="right" />            </RelativeLayout>        </LinearLayout>         <!-- 专辑信息,歌手 -->        <TextView            android:id="@+id/artistalbum"            style="@android:style/TextAppearance.StatusBar.EventContent"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="left"            android:ellipsize="end"            android:maxLines="2"            android:scrollHorizontally="true" />    </LinearLayout></LinearLayout>


2.2  通知栏控制:

/packages/apps/Music/src/com/android/music/MediaPlaybackService.java中

 updateNotification()为发送的通知代码,在这里面修改

private void updateNotification() {        //RemoteViews未自定义布局,   R.layout.statusbar 为通知的布局文件        RemoteViews views = new RemoteViews(getPackageName(), R.layout.statusbar);        views.setImageViewResource(R.id.icon, R.drawable.stat_notify_musicplayer);        if (getAudioId() < 0) {            // streaming            views.setTextViewText(R.id.trackname, getPath());            views.setTextViewText(R.id.artistalbum, null);        } else {            String artist = getArtistName();            views.setTextViewText(R.id.trackname, getTrackName());            if (artist == null || artist.equals(MediaStore.UNKNOWN_STRING)) {                artist = getString(R.string.unknown_artist_name);            }            String album = getAlbumName();            if (album == null || album.equals(MediaStore.UNKNOWN_STRING)) {                album = getString(R.string.unknown_album_name);            }            views.setTextViewText(R.id.artistalbum,                    getString(R.string.notification_artist_album, artist, album)                    );        }        Notification status = new Notification();        /*Begin: modified 添加修改代码*/        //status_icon 为状态栏图标,R.id.statusbar_pause 为通知 的 暂停/开始按钮        int status_icon = R.drawable.ic_appwidget_music_play;        //根据播放状态,来决定 暂停/开始 图标        if(isPlaying()){            views.setImageViewResource(R.id.statusbar_pause, R.drawable.ic_appwidget_music_pause);         }else{            views.setImageViewResource(R.id.statusbar_pause, R.drawable.ic_appwidget_music_play);            status_icon = R.drawable.ic_appwidget_music_pause;         }         // 给通知栏 上一首 按钮 添加点击事件          views.setOnClickPendingIntent(R.id.statusbar_prev, pre_PendingIntent());        //给通知栏 暂停/开始 按钮 添加点击事件         views.setOnClickPendingIntent(R.id.statusbar_pause, pause_PendingIntent());        //给通知栏 下一首 按钮 添加点击事件        views.setOnClickPendingIntent(R.id.statusbar_next, next_PendingIntent());        /*End:  */                 status.contentView = views;        status.flags |= Notification.FLAG_ONGOING_EVENT;        status.icon = status_icon;        status.contentIntent = PendingIntent.getActivity(this, 0,                new Intent("com.android.music.PLAYBACK_VIEWER")                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0);        startForeground(PLAYBACKSERVICE_STATUS, status);    }

添加的点击事件函数:

/*Begin:  modify  利用MediaPlaybackService 现有的广播监听 实现播放控制 */    //上一首,    private PendingIntent pre_PendingIntent(){        Intent intent = new Intent(PREVIOUS_ACTION);        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);         return pendingIntent;    }    //暂停开始     private PendingIntent pause_PendingIntent(){        Intent intent = new Intent(TOGGLEPAUSE_ACTION);        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);         return pendingIntent;    }    //下一首     private PendingIntent next_PendingIntent(){        Intent intent = new Intent(NEXT_ACTION);        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);         return pendingIntent;    }        /*end:  */

为了实现暂停/开始按钮通知栏图标显示与音乐播放 的一致 改了以下两个地方:

其一 play()  方法中 将  updateNotification() 放在了

if (!mIsSupposedToBePlaying) {
                mIsSupposedToBePlaying = true;
                notifyChange(PLAYSTATE_CHANGED);
            }

之后

public void play() {            ...if (!mIsSupposedToBePlaying) {                mIsSupposedToBePlaying = true;                notifyChange(PLAYSTATE_CHANGED);            }updateNotification();          ...}
其二:当接受到 暂停/开始  事件的 广播后,如果 暂停音乐,则调用updateNotification()更新方法

 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            String action = intent.getAction();            String cmd = intent.getStringExtra("command");            MusicUtils.debugLog("mIntentReceiver.onReceive " + action + " / " + cmd);            Log.e(LOGTAG, "  mIntentReceiver   action = "+action+"   cmd ="+cmd+"===");            if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {                gotoNext(true);            } else if (CMDPREVIOUS.equals(cmd) || PREVIOUS_ACTION.equals(action)) {                prev();            } else if (CMDTOGGLEPAUSE.equals(cmd) || TOGGLEPAUSE_ACTION.equals(action)) {                if (isPlaying()) {                    /*Begin: 开始修改*/                   // pause(false); 暂停时不消除通知栏                    pause(false);                    updateNotification();                    /*End: modified*/                    mPausedByTransientLossOfFocus = false;                } else {                    play();                }                                ...





原创粉丝点击