Android开发:用通知栏(Notification Bar)控制音乐的后台播放

本文记录了一种实现Android后台音乐播放的方法,通过通知栏控制音乐播放。利用Service播放音乐,并使用RemoteView自定义Notification,通过PendingIntent实现点击通知栏控制音乐播放的功能。

最近要制作一个后台播放音乐的功能,可是在UI中不给控制按钮,于是只好通过通知栏来控制了,网上找了许多,没有找到相关的文章,经过不断摸索,终于实现了该功能,在此记录下来,即作为备忘,也可作为分享。


1、首先,创建一个service来播放音乐:


public class AudioService extends Service {
    private MediaPlayer mediaPlayer;
    private final static String TAG = "debug";
    public ButtonBroadcastReceiver bReceiver;
    public final static String ACTION_BUTTON = "com.weidongjian.weigan.ButtonClick";
    public NotificationManager mNotificationManager;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("debug", "oncrete");
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        try {
            mediaPlayer.setDataSource("http://abv.cn/music/%E5%85%89%E8%BE%89%E5%B2%81%E6%9C%88.mp3");
            mediaPlayer.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        initButtonReceiver();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("debug", "onStartCommnad");
        if (!mediaPlayer.isPlaying()){
            mediaPlayer.start();
        }
        showButtonNotify();
        return START_STICKY;
    }

    public void onDestroy(){
        Log.i("debug", "onDestory");
        //super.onDestroy();
        if(mediaPlayer.isPlaying()){
            mediaPlayer.stop();
        }
        mediaPlayer.release();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

我在onCreate里面,初始化了MediaPlayer对象,并用于播放网络地址音乐,并有一个初始化Receive的公式: initButtonReceiver();,这个留到后面讲。


2、第二部是创建一个Notification了,这个在网上有许多的资源了,我这里用的是remoteView创建一个自定义的Notification,而且在控制音乐这里,只能用remoteView;

public void showButtonNotify(){
        Notification.Builder mBuilder = new Notification.Builder(this);
        RemoteViews mRemoteViews = new RemoteViews(getPackageName(), R.layout.view_custom_button);
        mRemoteViews.setImageViewResource(R.id.custom_song_icon, R.drawable.sing_icon);
       
        mBuilder.setContent(mRemoteViews)
                .setContentIntent(getDefalutIntent(Notification.FLAG_ONGOING_EVENT))
                .setWhen(System.currentTimeMillis())// 通知产生的时间,会在通知信息里显示
                .setTicker("正在播放")
                .setPriority(Notification.PRIORITY_DEFAULT)// 设置该通知优先级
                .setOngoing(true)
                .setSmallIcon(R.drawable.sing_icon);
        Notification notify = mBuilder.build();
        notify.flags = Notification.FLAG_ONGOING_EVENT;
        //会报错,还在找解决思路
//		notify.contentView = mRemoteViews;
//		notify.contentIntent = PendingIntent.getActivity(this, 0, new Intent(), 0);
        mNotificationManager.notify(200, notify);
    }

这个是RemoteView的layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/custom_song_icon"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:src="@drawable/sing_icon" />

    <LinearLayout
        android:id="@+id/ll_custom_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="5dip"
        android:gravity="center_vertical"
        android:orientation="horizontal" >

        <ImageButton
            android:id="@+id/btn_custom_prev"
            style="@style/btn_custom_style"
            android:src="@drawable/btn_prev" />

        <ImageButton
            android:id="@+id/btn_custom_play"
            style="@style/btn_custom_style"
            android:contentDescription="播放"
            android:src="@drawable/btn_play" />

        <ImageButton
            android:id="@+id/btn_custom_next"
            style="@style/btn_custom_style"
            android:contentDescription="下一首"
            android:src="@drawable/btn_next" />
    </LinearLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginBottom="5dip"
        android:layout_marginLeft="5dip"
        android:layout_marginTop="5dip"
        android:layout_toLeftOf="@id/ll_custom_button"
        android:layout_toRightOf="@id/custom_song_icon"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/tv_custom_song_singer"
            style="@style/NotificationTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:text="title"
            android:textSize="15sp" />

        <TextView
            android:id="@+id/tv_custom_song_name"
            style="@style/NotificationContent"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:text="content"
            android:textSize="12sp" />
    </RelativeLayout>

</RelativeLayout>

现在问题来了,如何处理RemoteView上面的点击事件,并且传给service呢,原来RemoteView有一个可以发广播的方法,如下:
public void setOnClickPendingIntent (int viewId, PendingIntent pendingIntent)
Added in  API level 3

Equivalent to calling setOnClickListener(android.view.View.OnClickListener) to launch the provided PendingIntent. When setting the on-click action of items within collections (eg. ListViewStackView etc.), this method will not work. Instead, use {@link RemoteViews#setPendingIntentTemplate(int, PendingIntent) in conjunction with RemoteViews#setOnClickFillInIntent(int, Intent).

Parameters
viewId The id of the view that will trigger the PendingIntent when clicked
pendingIntent The PendingIntent to send when user clicks
点击后,用PendingIntent.gotbroadCast来发送广播,实现代码如下:

<span style="white-space:pre">	</span> Intent buttonIntent = new Intent(ACTION_BUTTON);
		/* 上一首按钮 */
        buttonIntent.putExtra(INTENT_BUTTONID_TAG, BUTTON_PREV_ID);
        //这里加了广播,所及INTENT的必须用getBroadcast方法
        PendingIntent intent_prev = PendingIntent.getBroadcast(this, 1, buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        mRemoteViews.setOnClickPendingIntent(R.id.btn_custom_prev, intent_prev);
		/* 播放/暂停  按钮 */
        buttonIntent.putExtra(INTENT_BUTTONID_TAG, BUTTON_PALY_ID);
        PendingIntent intent_paly = PendingIntent.getBroadcast(this, 2, buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        mRemoteViews.setOnClickPendingIntent(R.id.btn_custom_play, intent_paly);
		/* 下一首 按钮  */
        buttonIntent.putExtra(INTENT_BUTTONID_TAG, BUTTON_NEXT_ID);
        PendingIntent intent_next = PendingIntent.getBroadcast(this, 3, buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        mRemoteViews.setOnClickPendingIntent(R.id.btn_custom_next, intent_next);

这样的话,只要在service里面,建立一个receiver,就可以接收广播了,从而操控音乐的播放:

public void initButtonReceiver(){
        bReceiver = new ButtonBroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ACTION_BUTTON);
        registerReceiver(bReceiver, intentFilter);

    }

    public final static String INTENT_BUTTONID_TAG = "ButtonId";
    /** 上一首 按钮点击 ID */
    public final static int BUTTON_PREV_ID = 1;
    /** 播放/暂停 按钮点击 ID */
    public final static int BUTTON_PALY_ID = 2;
    /** 下一首 按钮点击 ID */
    public final static int BUTTON_NEXT_ID = 3;

    public class ButtonBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO Auto-generated method stub
            String action = intent.getAction();
            if(action.equals(ACTION_BUTTON)){
                //通过传递过来的ID判断按钮点击属性或者通过getResultCode()获得相应点击事件
                int buttonId = intent.getIntExtra(INTENT_BUTTONID_TAG, 0);
                switch (buttonId) {
                    case BUTTON_PREV_ID:
                        Log.d(TAG , "上一首01");
                        Toast.makeText(getApplicationContext(), "上一首", Toast.LENGTH_SHORT).show();
                        break;
                    case BUTTON_PALY_ID:
                        Log.d(TAG , "play");
                        Toast.makeText(getApplicationContext(), play_status, Toast.LENGTH_SHORT).show();
                        break;
                    case BUTTON_NEXT_ID:
                        Log.d(TAG , "next song);
                        Toast.makeText(getApplicationContext(), "下一首", Toast.LENGTH_SHORT).show();
                        break;
                    default:
                        break;
                }
            }
        }
    }

这样我们就可以在service的广播里面处理Notification的点击事件了。


参考文章:





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值