1. 程式人生 > >Android之Notification製作多媒體控制器

Android之Notification製作多媒體控制器

    上一篇講述了Notification的基礎用法,本篇將介紹,自定義通知欄,並利用講到的內容,實現一個簡單的音樂播發器。

 1.自定義通知的實現;

  Notification有一個contentView屬性,該屬性接受的物件是RemoteView物件,用它即可實現自定義佈局.

  獲取RemoteView物件的方法:

<span style="font-size:14px;">RemoteView remoteViews = new RemoteViews(getPackageName(),R.layout.notify_view);</span>

2.新增通知欄響應事件

Intent buttonplayIntent = new Intent("play");
		PendingIntent pendplayButtonIntent = PendingIntent.getBroadcast(
				getApplicationContext(), 0, buttonplayIntent, 0);

		mRemoteViews.setOnClickPendingIntent(R.id.play, pendplayButtonIntent);

 其中關於PendingIntent

 PendingIntent用於描述Intent及其最終的行為. 
        你可以通過getActivity(Context context, int requestCode, Intent intent, int flags)系列方法從系統取得一個用於啟動一個Activity的PendingIntent物件,


       可以通過getService(Context context, int requestCode, Intent intent, int flags)方法從系統取得一個用於啟動一個Service的PendingIntent物件

        可以通過getBroadcast(Context context, int requestCode, Intent intent, int flags)方法從系統取得一個用於向BroadcastReceiver的Intent廣播的PendingIntent物件

         返回的PendingIntent可以遞交給別的應用程式,然後繼續處理。這裡的話你可以稍後才處理PendingIntent中描述的Intent及其最終行為。

3.完整的建立自定義通知方法:

Notification mNotification;
	RemoteViews mRemoteViews;
	NotificationManager notificationManager;

	public void createNotifiView() {
		notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		mNotification = new Notification(R.drawable.ic_launcher, "MusicDemo",
				System.currentTimeMillis());
		mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
		Intent intent = new Intent(Intent.ACTION_MAIN);
		intent.setClass(getApplicationContext(), MainActivity.class);
		PendingIntent pendingIntent = PendingIntent.getActivity(
				getApplicationContext(), 0, intent,
				PendingIntent.FLAG_CANCEL_CURRENT);
		mNotification.contentIntent = pendingIntent;
		if (mRemoteViews == null) {
			mRemoteViews = new RemoteViews(getPackageName(),
					R.layout.notify_view);
		}
		Intent buttoncloseIntent = new Intent("close");
		PendingIntent pendcloseButtonIntent = PendingIntent.getBroadcast(
				getApplicationContext(), 0, buttoncloseIntent, 0);
		mRemoteViews.setOnClickPendingIntent(R.id.close, pendcloseButtonIntent);

		Intent buttonplayIntent = new Intent("play");
		PendingIntent pendplayButtonIntent = PendingIntent.getBroadcast(
				getApplicationContext(), 0, buttonplayIntent, 0);

		mRemoteViews.setOnClickPendingIntent(R.id.play, pendplayButtonIntent);

		//
		Intent buttonnextIntent = new Intent("next");
		PendingIntent pendnextButtonIntent = PendingIntent.getBroadcast(
				getApplicationContext(), 0, buttonnextIntent, 0);

		mRemoteViews.setOnClickPendingIntent(R.id.next, pendnextButtonIntent);

		Intent buttonprewtIntent = new Intent("prew");
		PendingIntent pendprewButtonIntent = PendingIntent.getBroadcast(
				getApplicationContext(), 0, buttonprewtIntent, 0);

		mRemoteViews.setOnClickPendingIntent(R.id.prew, pendprewButtonIntent);

		mRemoteViews.setTextViewText(R.id.songName, "歌曲名");

		if (!MainActivity.isPlay) {
			mRemoteViews.setImageViewResource(R.id.play,
					R.drawable.statusbar_btn_play);
			mRemoteViews.setOnClickPendingIntent(R.id.play,
					pendplayButtonIntent);
		} else {
			mRemoteViews.setImageViewResource(R.id.play,
					R.drawable.statusbar_btn_pause);
			mRemoteViews.setOnClickPendingIntent(R.id.play,
					pendplayButtonIntent);
		}

		mNotification.contentView = mRemoteViews;
		notificationManager.notify(0, mNotification);

	}

因為這裡用了getBroadCast()獲取PendingIntent,所以該Intent是通過傳送廣播來告知通知欄控制元件發生了觸發事件。

所以,需要在響應介面過濾action,註冊響應廣播。

先給出通知佈局檔案notifiy_view:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:ignore="ContentDescription" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="64dp"
        android:orientation="vertical" >

        <ImageView
            android:id="@+id/icon_pic"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_centerVertical="true" />

        <ImageButton
            android:id="@+id/close"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_marginRight="10dp"
            android:layout_marginTop="10dp"
            android:background="@drawable/status_bg"
            android:src="@drawable/statusbar_close" />

        <TextView
            android:id="@+id/songName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="5dp"
            android:layout_marginTop="10dp"
            android:layout_toLeftOf="@+id/close"
            android:layout_toRightOf="@+id/icon_pic"
            android:ellipsize="end"
            android:singleLine="true"
            android:text="歌名"
            android:textSize="15dp" />

        <ImageButton
            android:id="@+id/prew"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_alignParentBottom="true"
            android:layout_centerInParent="true"
            android:background="@drawable/status_bg"
            android:src="@drawable/statusbar_btn_prev" />

        <ImageButton
            android:id="@+id/play"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_alignTop="@+id/prew"
            android:layout_marginLeft="10dp"
            android:layout_toRightOf="@+id/prew"
            android:background="@drawable/status_bg"
            android:src="@drawable/statusbar_btn_play" />

        <ImageButton
            android:id="@+id/next"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_alignTop="@+id/prew"
            android:layout_marginLeft="10dp"
            android:layout_toRightOf="@+id/play"
            android:background="@drawable/status_bg"
            android:src="@drawable/statusbar_btn_next" />
    </RelativeLayout>

</LinearLayout>

我將會把專案放在CSDN上,大家可以下載,獲取相應的資原始檔

在這個小專案中,我將播放的service做為的是後臺服務,然後廣播也提出來了,作為一個公用的廣播,如果只是做簡單播放用,可以將廣播放在播放介面。

專案中用到的廣播:

public class MusicBroadCast extends BroadcastReceiver {
	@Override
	public void onReceive(Context context, Intent intent) {
		Intent musicServiceIntent = new Intent(context, MusicService.class);
		if (intent.getAction().equals("play")) {
			musicServiceIntent.putExtra(MusicService.MusicCommandKey, ""
					+ MusicService.MusicPlayCommand);
			context.startService(musicServiceIntent);
		} else if (intent.getAction().equals("next")) {

			musicServiceIntent.putExtra(MusicService.MusicCommandKey, ""
					+ MusicService.MusicNextCommand);
			context.startService(musicServiceIntent);

		} else if (intent.getAction().equals("prew")) {

			musicServiceIntent.putExtra(MusicService.MusicCommandKey, ""
					+ MusicService.MusicNextCommand);
			context.startService(musicServiceIntent);

		} else if (intent.getAction().equals("close")) {

			musicServiceIntent.putExtra(MusicService.MusicCommandKey, "");
			context.startService(musicServiceIntent);
		} else if (intent.getAction().equals(
				"android.media.AUDIO_BECOMING_NOISY")) {// 耳機拔出事件

			musicServiceIntent.putExtra(MusicService.MusicCommandKey,
					MusicService.MusicPauseCommand
							+ MusicService.MusicPauseCommand);
			context.startService(musicServiceIntent);
		}
	}

}

我這裡是在service註冊的廣播,這個應該有點誇張了,由於專案需要全域性播放,然後由通知欄也可以控制,就這樣做了。

service檔案程式碼:

package com.example.musicdemo;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.RemoteViews;

import java.io.IOException;

/**
 * Create by gaylen on 2015/12/9 11:07
 */

public class MusicService extends Service {

	// 其他物件控制Service進行音訊播放操作
	// 全部採用命令+命令引數的形式處理
	public static final int MusicInitCommand = 0;
	public static final int MusicPlayCommand = 10;
	public static final int MusicStopCommand = 20;
	public static final int MusicPauseCommand = 30;
	public static final int MusicSeekToCommand = 40;
	public static final int MusicNextCommand = 50;
	public static final int MusicPrevCommand = 60;
	public static final int MusicNotificationCommand = 70;

	// 所有的命令引數都String傳遞
	// 非String型別,採取轉型處理
	public static String MusicCommandKey = "CtrlCommand";
	public static String MusicParameterKey = "CommandParameter";

	private MusicBroadCast broadCast;

	@Override
	public void onCreate() {
		super.onCreate();

		broadCast = new MusicBroadCast();
		IntentFilter filter = new IntentFilter();
		filter.addAction("play");
		filter.addAction("next");
		filter.addAction("prew");
		filter.addAction("close");
		// 耳機
		filter.addAction("android.media.AUDIO_BECOMING_NOISY");
		// 簡訊
		// mSystemFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
		registerReceiver(broadCast, filter);
		regeisterCallLisenler();
		/**
		 * 為了防止通知欄點選時出現閃屏,在開啟service就將一些物件例項化了
		 */
		notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		mNotification = new Notification(R.drawable.ic_launcher, "MusicDemo",
				System.currentTimeMillis());
		mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
		Intent intent = new Intent(Intent.ACTION_MAIN);
		intent.setClass(getApplicationContext(), MainActivity.class);
		PendingIntent pendingIntent = PendingIntent.getActivity(
				getApplicationContext(), 0, intent,
				PendingIntent.FLAG_CANCEL_CURRENT);
		mNotification.contentIntent = pendingIntent;
	}

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

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {

		// 分析傳入的命令,根據不同命令呼叫不同方法
		String commandValue = intent.getStringExtra(MusicCommandKey);
		if (commandValue != null) {
			int command = Integer.parseInt(commandValue);
			switch (command) {
			case MusicService.MusicPlayCommand:
				// 得到play命令對應的引數
				String Param = intent.getStringExtra(MusicParameterKey);
				// 執行doPlayCommand方法
				doPlayCommand(Param);
				break;
			case MusicService.MusicStopCommand:
				stopPlayCommand();
				break;
			case MusicService.MusicSeekToCommand:
				// 解析命令引數執行相關方法
				// 得到SeekTo的進度(字串形式)
				String strProgressSet = intent
						.getStringExtra(MusicService.MusicParameterKey);
				doSeekToCommand(strProgressSet);
				break;
			case MusicService.MusicNextCommand:
				doNextCommand();
				break;
			case MusicService.MusicPrevCommand:
				doPreCommand();
				break;
			case MusicService.MusicNotificationCommand:
				createNotifiView();
				break;
			}
		}
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		// Service 被結束,則音樂停止
		unregisterReceiver(broadCast);
	}

	/**
	 * 停止播放
	 */
	private void stopPlayCommand() {
		Log.i("play", "stop");
		createNotifiView();
	}

	private void doPause() {
		Log.i("play", "pause");
	}

	/**
	 * 播放
	 * 
	 * @param param
	 */
	private void doPlayCommand(String param) {

		if (MainActivity.isPlay) {
			doPause();
		} else {
			Log.i("play", "play");
		}
		createNotifiView();

	}

	// 播放下一首命令處理
	private void doNextCommand() {
		Log.i("play", "next");
	}

	// 播放上一首命令處理
	private void doPreCommand() {
		Log.i("play", "pre");
	}

	private void doSeekToCommand(String seekToValue) {
		int seekTo = Integer.parseInt(seekToValue);
		// 設定跳轉進度
		// mMediaPlayer.seekTo(seekTo);
	}

	Notification mNotification;
	RemoteViews mRemoteViews;
	NotificationManager notificationManager;

	public void createNotifiView() {
		if (mRemoteViews == null) {
			mRemoteViews = new RemoteViews(getPackageName(),
					R.layout.notify_view);
		}
		Intent buttoncloseIntent = new Intent("close");
		PendingIntent pendcloseButtonIntent = PendingIntent.getBroadcast(
				getApplicationContext(), 0, buttoncloseIntent, 0);
		mRemoteViews.setOnClickPendingIntent(R.id.close, pendcloseButtonIntent);

		Intent buttonplayIntent = new Intent("play");
		PendingIntent pendplayButtonIntent = PendingIntent.getBroadcast(
				getApplicationContext(), 0, buttonplayIntent, 0);

		mRemoteViews.setOnClickPendingIntent(R.id.play, pendplayButtonIntent);

		//
		Intent buttonnextIntent = new Intent("next");
		PendingIntent pendnextButtonIntent = PendingIntent.getBroadcast(
				getApplicationContext(), 0, buttonnextIntent, 0);

		mRemoteViews.setOnClickPendingIntent(R.id.next, pendnextButtonIntent);

		Intent buttonprewtIntent = new Intent("prew");
		PendingIntent pendprewButtonIntent = PendingIntent.getBroadcast(
				getApplicationContext(), 0, buttonprewtIntent, 0);

		mRemoteViews.setOnClickPendingIntent(R.id.prew, pendprewButtonIntent);

		mRemoteViews.setTextViewText(R.id.songName, "歌曲名");

		if (!MainActivity.isPlay) {
			mRemoteViews.setImageViewResource(R.id.play,
					R.drawable.statusbar_btn_play);
			mRemoteViews.setOnClickPendingIntent(R.id.play,
					pendplayButtonIntent);
		} else {
			mRemoteViews.setImageViewResource(R.id.play,
					R.drawable.statusbar_btn_pause);
			mRemoteViews.setOnClickPendingIntent(R.id.play,
					pendplayButtonIntent);
		}

		mNotification.contentView = mRemoteViews;
		notificationManager.notify(0, mNotification);

	}

	private AudioManager mAudioManager;

	public void regeisterCallLisenler() {
		mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

		// 新增來電監聽事件
		TelephonyManager telManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); // 獲取系統服務
		telManager.listen(new MobliePhoneStateListener(),
				PhoneStateListener.LISTEN_CALL_STATE);
	}

	/**
	 * @author wwj 電話監聽器類
	 */
	private class MobliePhoneStateListener extends PhoneStateListener {
		@Override
		public void onCallStateChanged(int state, String incomingNumber) {
			switch (state) {
			case TelephonyManager.CALL_STATE_IDLE: // 掛機狀態
				// doPlayCommand("");
				break;
			case TelephonyManager.CALL_STATE_OFFHOOK: // 通話狀態
			case TelephonyManager.CALL_STATE_RINGING: // 響鈴狀態
				Log.i("tag", "接收到來電-->");
				doPause();
				break;
			default:
				break;
			}
		}
	}
}

最後就是播放主介面:
public class MainActivity extends ActionBarActivity {
	public static boolean isPlay = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		player();
	}

	public void player() {

		Intent musicServiceIntent = new Intent(MainActivity.this,
				MusicService.class);
		// 設定播放控制命令:playCommand
		musicServiceIntent.putExtra(MusicService.MusicCommandKey, ""
				+ MusicService.MusicPlayCommand);
		MainActivity.this.startService(musicServiceIntent);
	}
}

佈局跟通知欄佈局差不多,這裡就不寫了。

完整專案原始碼可以去:http://download.csdn.net/detail/caihuajian235/9365027下載。