這兩天開始做一個(gè)音樂播放器,慢慢完善功能,打算把遇到的一些問題記下來,故對(duì)代碼沒有什么解釋。。希望讀者能有所收獲。
為了能讓讀者看的不那么難受,我把代碼拆開來講(完整的代碼就是拆分的拼起來),包括筆者遇到的兩個(gè)報(bào)異常的地方,解決后終于成功開啟。
效果圖在最后(簡(jiǎn)陋版看看就好)
如果哪里有誤歡迎指正,不,請(qǐng)務(wù)必指正。
先初始化我們定義的Layout
這個(gè)Layout就是下拉菜單欄顯示的樣式。
views = new RemoteViews(getPackageName(), R.layout.notification_music);
views.setTextViewText(R.id.tv_playmusic, musics.get(curMusic).getMusic());
views.setTextViewText(R.id.tv_playsinger, musics.get(curMusic).getSinger());
RemoteViews能夠支持更改Layout中控件用到的資源(如更換背景),使用
setInt(int viewId, String methodName, int value),
其中methodName是調(diào)用的方法名(實(shí)際是以方法名通過反射),value是資源文件的id。
定義Layout中控件的點(diǎn)擊效果
//next music
Intent intentSkipNext = new Intent(MusicChangedReceiver.Action_Notification_SkipNext);
PendingIntent skipNextPendingIntent = PendingIntent.getBroadcast(this, NEXT_PENDINGINTENT_REQUESTCODE,
intentSkipNext, PendingIntent.FLAG_CANCEL_CURRENT);
views.setOnClickPendingIntent(R.id.btn_skip_next, skipNextPendingIntent);
這部分只貼一個(gè),實(shí)際是通過發(fā)送廣播實(shí)現(xiàn)的,需要綁定一個(gè)BroadcastReceiver來接受廣播,在通過switch分Action進(jìn)行對(duì)應(yīng)處理。
定義點(diǎn)擊Notification的動(dòng)作(就是Layout除去定義了點(diǎn)擊事件的控件的位置)
我這里的動(dòng)作是啟動(dòng)MainActivity(設(shè)置了singleTask的啟動(dòng)模式)
注意這里沒有把PendingIntent放入RemoteViews中,而是要直接設(shè)置在Notification中(下一部分)
Intent intentContent = new Intent(this, MainActivity.class);
PendingIntent contentPendingIntent = PendingIntent.getActivity(this, CONTENT_PENDINGINTENT_REQUESTCODE,
intentContent, PendingIntent.FLAG_CANCEL_CURRENT);
定義Notification移除時(shí)的動(dòng)作
我沒有定義,暫時(shí)沒這個(gè)需求。
創(chuàng)建Notification.Builder
從這里就可以看出來Notification使用了Builder模式
其中 setSmallIcon, setContentTitle, setContentText 是必須要有的,不然會(huì)出現(xiàn)異常前臺(tái)開啟失敗,反正最后不會(huì)顯示出來(因?yàn)樵O(shè)置了自定義的布局)
builder = new Notification.Builder(this)
// 設(shè)置小圖標(biāo)
.setSmallIcon(R.drawable.ic_stop_red_40dp)
// 設(shè)置標(biāo)題
.setContentTitle("nemuniPlayer")
// 設(shè)置內(nèi)容
.setContentText("content")
.setAutoCancel(false)
//這里設(shè)置點(diǎn)擊Notification的動(dòng)作
//這里設(shè)置點(diǎn)擊Notification的動(dòng)作
//這里設(shè)置點(diǎn)擊Notification的動(dòng)作
.setContentIntent(contentPendingIntent)
.setContent(views);
獲取NotificationManager
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
!重點(diǎn)!設(shè)置NotificationChannel,8.0以上不設(shè)會(huì)報(bào)異常啟動(dòng)失敗
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String CHANNEL_ID = "com.example.nemuni.channel";
String CHANNEL_NAME = "Music Channel";
NotificationChannel notificationChannel= new NotificationChannel(CHANNEL_ID, CHANNEL_NAME,
NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
notificationManager.createNotificationChannel(notificationChannel);
builder.setChannelId(CHANNEL_ID);
}
(我是不會(huì)說ID和NAME的命名都是我隨意的,確保ID唯一應(yīng)該就沒問題了吧)
剩下的就是啟動(dòng)了
startForeground(NOTIFICATION_PENDINGINTENT_ID, builder.build());
這里的ID我使用了進(jìn)程的ID(反正我也就啟動(dòng)這一個(gè)前臺(tái)服務(wù))
private static final int NOTIFICATION_PENDINGINTENT_ID = android.os.Process.myPid();
順便貼onDestroy()里的取消操作吧
if (notificationManager != null) {
notificationManager.cancel(NOTIFICATION_PENDINGINTENT_ID);
stopForeground(true);
}
