參考文章
仿微信通知欄
Android基礎(chǔ)知識(shí)(二十):Notification、提醒式通知(橫幅)踩坑與通知界面設(shè)置跳轉(zhuǎn)
PendingIntent.getActivity的使用
Android平臺(tái)App進(jìn)程優(yōu)先級(jí)
Android 程序后臺(tái)運(yùn)行和鎖屏運(yùn)行
重要記錄點(diǎn)
1、setSmallIcon、setLargeIcon 必須設(shè)置半沽。設(shè)置小圖標(biāo)的時(shí)候实抡,小圖標(biāo)是需要透明背景脂矫,實(shí)體區(qū)域用白色的就可以了吏垮,大小64 * 64吧捐腿,這個(gè)可以修改
2课锌、華為目前是不可以通過代碼設(shè)置橫幅的厨内,想要顯示橫幅出來祈秕,需要自己手動(dòng)的去通知欄那打開。微信,QQ有錢沒辦法雏胃,天生就可以默認(rèn)橫幅请毛,在notification設(shè)置震動(dòng)也無效,估計(jì)所有的開發(fā)商都有修改過notification吧
3瞭亮、可以在線程創(chuàng)建notification
4方仿、開啟橫幅方式(修改過底層的除開),將通知等級(jí)設(shè)置最高
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//android 8.0
val channel = NotificationChannel(ConversionChannelId, ConversionChannelName, IMPORTANCE_HIGH)
} else {
notificationBuilder.setPriority(NotificationCompat.PRIORITY_HIGH)
}
importance统翩、priority都必須設(shè)置到高值
5仙蚜、設(shè)置通知欄不消失的方式
var notificationBuilder: NotificationCompat.Builder? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//android 8.0
notificationBuilder = NotificationCompat.Builder(CommonApplication.getContext(), SingleAppChannelId)
} else {
notificationBuilder = NotificationCompat.Builder(CommonApplication.getContext())
}
notificationBuilder.let {
val notification = notificationBuilder.build();
notification.flags = notification.flags or Notification.FLAG_ONGOING_EVENT//不消失的通知欄
}
6、如果我不開啟前臺(tái)service厂汗,只是將notification設(shè)置為不消失的通知欄委粉,按下home鍵后,主oom_adj的值為11娶桦,子進(jìn)程為15贾节。主與子易被殺死
7、主進(jìn)程開啟前臺(tái)Service趟紊,按下home鍵后,oom_adj的值為3碰酝,如果此時(shí)有子進(jìn)程霎匈,子進(jìn)程的oom_adj的值為15。子易被殺死
8送爸、目前學(xué)習(xí)到盡量不被殺的辦法
1铛嘱、主進(jìn)程開啟前臺(tái)service
2、service里面監(jiān)聽開屏袭厂、息屏廣播墨吓。不管開屏、息屏都循環(huán)播放無聲音樂纹磺。目前oppo是無法監(jiān)聽到開屏息屏的通知的帖烘,所以需要單獨(dú)處理,如果是oppo橄杨,vivo秘症,直接播放無聲音樂好了
3、定時(shí)的調(diào)用startForeground刷新notification式矫,當(dāng)然要保證notification的id都相同
4乡摹、開啟service同時(shí)獲取PowerManager,并且調(diào)用acquire()方法采转,避免息屏的時(shí)候CPU直接睡眠聪廉,不執(zhí)行代碼
當(dāng)然了,你退出APP之后,以上系列的所有操作板熊,都需要進(jìn)行 一 一 關(guān)閉
知識(shí)點(diǎn)記錄
1框全、PendingIntent.getActivity知識(shí)點(diǎn)
PendingIntent.getActivity(Context context, int requestCode, intent, int flags)
第一個(gè)參數(shù)連接上下文的context
第二個(gè)參數(shù)是對(duì)PendingIntent的描述,請(qǐng)求值不同Intent就不同
第三個(gè)參數(shù)是一個(gè)Intent對(duì)象邻邮,包含跳轉(zhuǎn)目標(biāo)
第四個(gè)參數(shù)有4種狀態(tài)
FLAG_CANCEL_CURRENT:如果當(dāng)前系統(tǒng)中已經(jīng)存在一個(gè)相同的PendingIntent對(duì)象竣况,那么就將先將已有的PendingIntent取消,然后重新生成一個(gè)PendingIntent對(duì)象筒严。
FLAG_NO_CREATE:如果當(dāng)前系統(tǒng)中不存在相同的PendingIntent對(duì)象丹泉,系統(tǒng)將不會(huì)創(chuàng)建該P(yáng)endingIntent對(duì)象而是直接返回null。
FLAG_ONE_SHOT:該P(yáng)endingIntent只作用一次鸭蛙。在該P(yáng)endingIntent對(duì)象通過send()方法觸發(fā)過后摹恨,PendingIntent將自動(dòng)調(diào)用cancel()進(jìn)行銷毀,那么如果你再調(diào)用send()方法的話娶视,系統(tǒng)將會(huì)返回一個(gè)SendIntentException晒哄。
FLAG_UPDATE_CURRENT:如果系統(tǒng)中有一個(gè)和你描述的PendingIntent對(duì)等的PendingInent,那么系統(tǒng)將使用該P(yáng)endingIntent對(duì)象肪获,但是會(huì)使用新的Intent來更新之前PendingIntent中的Intent對(duì)象數(shù)據(jù)寝凌,例如更新Intent中的Extras。
notification詳細(xì)代碼
/**
* @date 創(chuàng)建時(shí)間: 2021/2/1
* @auther gaoxiaoxiong
* @description 顯示信息孝赫,這個(gè)需要在線程創(chuàng)建较木,因?yàn)轭^像的獲取是線程
**/
fun showChatNotification(context: Context) {
// 創(chuàng)建一個(gè)NotificationManager的引用
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
var notificationBuilder: NotificationCompat.Builder? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//android 8.0
notificationBuilder = NotificationCompat.Builder(CommonApplication.getContext(), ConversionChannelId)
val channel = NotificationChannel(ConversionChannelId, ConversionChannelName, IMPORTANCE_HIGH)
channel.description = ConversionChannelName;
mNotificationManager.createNotificationChannel(channel);
} else {
notificationBuilder = NotificationCompat.Builder(CommonApplication.getContext())
notificationBuilder.setPriority(NotificationCompat.PRIORITY_HIGH)
}
val intent = Intent(context,MainActivity::class.java);
intent.putExtra(MainActivity.ID,10);
notificationBuilder.let {
it.setWhen(System.currentTimeMillis());
it.setSmallIcon(R.drawable.icon_sml_notification)//設(shè)置小圖標(biāo),設(shè)置后在狀態(tài)欄部分顯示青柄,注意伐债,小圖標(biāo)是需要透明背景的,實(shí)體會(huì)話部分用白色的就可以了致开。大小64 * 64吧峰锁,這個(gè)可以修改
var userHeaderBitmap = GetImageInputStream(daoChatRecordModel.visitorAvatar);//獲取網(wǎng)絡(luò)圖片
if (userHeaderBitmap == null) {
userHeaderBitmap = BitmapFactory.decodeResource(CommonApplication.getContext().getResources(), R.mipmap.icon_logo)
}
it.setLargeIcon(userHeaderBitmap);//設(shè)置大圖標(biāo)
it.setContentTitle(StringUtils.isEmptyValue(daoChatRecordModel.visitorVame));//設(shè)置標(biāo)題
it.setContentText(ResourcesUtils.getResourcesString(context, R.string.conversation_shopmessage))//設(shè)置文本信息
//設(shè)置當(dāng)點(diǎn)擊通知之后,將要跳轉(zhuǎn)的Activity
it.setContentIntent(PendingIntent.getActivity(context, 15, intent, PendingIntent.FLAG_UPDATE_CURRENT))
//彈出通知双戳,懸浮在通知欄
it.setFullScreenIntent(PendingIntent.getActivity(context, 15, intent, PendingIntent.FLAG_UPDATE_CURRENT), true)
//設(shè)置通知在第一次到達(dá)時(shí)在狀態(tài)欄中顯示的文本
it.setTicker(StringUtils.isEmptyValue(daoChatRecordModel.content))
it.setAutoCancel(true)//可以取消
it.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)//顯示通知的全部?jī)?nèi)容
it.setPriority(NotificationManager.IMPORTANCE_MAX)// 當(dāng)發(fā)出此類型的通知時(shí)虹蒋,通知會(huì)以懸掛的方法顯示在屏幕上
it.setSound(defaultNoticeVoice);//聲音
it.setVibrate(longArrayOf(0, 500, 1000, 1500));//震動(dòng)
val notification = notificationBuilder.build();
it.setPublicVersion(notification);//安全鎖屏下的通知
mNotificationManager.notify(11, notification)
}
}
/**
* 獲取網(wǎng)絡(luò)圖片
*
* @param imageurl 圖片網(wǎng)絡(luò)地址
* @return Bitmap 返回位圖
*/
private fun GetImageInputStream(imageurl: String): Bitmap? {
if (StringUtils.isEmpty(imageurl)) {
return null;
}
val url: URL
var connection: HttpURLConnection? = null
var bitmap: Bitmap? = null
try {
url = URL(imageurl)
connection = url.openConnection() as HttpURLConnection
connection.setConnectTimeout(2 * 1000) //超時(shí)設(shè)置
connection.setDoInput(true)
connection.setUseCaches(false) //設(shè)置不使用緩存
val inputStream: InputStream = connection.getInputStream()
bitmap = BitmapFactory.decodeStream(inputStream)
inputStream.close()
} catch (e: Exception) {
e.printStackTrace()
}
return bitmap
}
/**
* @date 創(chuàng)建時(shí)間:2021/2/3 0003
* @auther gaoxiaoxiong
* @Descriptiion 獲取默認(rèn)的提示音
**/
public Uri getDefaultNoticeVoice() {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
if (notification == null) {//獲取本地的
return Uri.parse("android.resource://" + CommonApplication.getContext().getPackageName() + "/" + R.raw.default_notice_voice);
} else {
return notification;
}
}