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下載。