亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android?Notification使用教程詳解

 更新時(shí)間:2022年07月11日 10:11:37   作者:初學(xué)者-Study  
這篇文章主要介紹了Android?Notification使用,通知的使用的內(nèi)容還是比較多的,此篇文章將會(huì)盡可能詳細(xì)的介紹Notification的內(nèi)容,需要的朋友可以參考下

前言

在應(yīng)用的開(kāi)發(fā)中,我們必然會(huì)接觸到應(yīng)用通知這個(gè)知識(shí),而在通知是隨著Android版本進(jìn)行不斷變化,為了能在高版本和低版本中使用,就需要開(kāi)發(fā)者去做適配,也屬于查漏補(bǔ)缺。了解之前,先看一個(gè)效果圖吧。

正文

通知的使用的內(nèi)容還是比較多的,此篇文章將會(huì)盡可能詳細(xì)的介紹Notification的內(nèi)容。

一、Android中通知的變化

1. Android 4.1,API 16

  • 推出了展開(kāi)式通知模板(稱(chēng)為通知樣式),可以提供較大的通知內(nèi)容區(qū)域來(lái)顯示信息。
  • 用戶(hù)可以通過(guò)單指向上/向下滑動(dòng)的手勢(shì)來(lái)展開(kāi)通知。還支持以按鈕的形式向通知添加其他操作。
  • 允許用戶(hù)在設(shè)置中按應(yīng)用關(guān)閉通知。

2. Android 4.4,API 19 和 20

  • 向 API 中添加了通知監(jiān)聽(tīng)器服務(wù)。
  • API 級(jí)別 20 中新增了 Android Wear(現(xiàn)已更名為 Wear OS)支持。

3. Android 5.0,API 21

  • 推出了鎖定屏幕和提醒式通知。
  • 用戶(hù)現(xiàn)在可以將手機(jī)設(shè)為勿擾模式,并配置允許哪些通知在設(shè)備處于“僅限優(yōu)先事項(xiàng)”模式時(shí)打擾他們。
  • 向 API 集添加了通知是否在鎖定屏幕上顯示的方法 (setVisibility()),以及指定通知文本的“公開(kāi)”版本的方法。
  • 添加了 setPriority() 方法,告知系統(tǒng)通知的“干擾性”(例如,將其設(shè)為“高”可使通知以提醒式通知的形式顯示)。
  • 向 Android Wear(現(xiàn)已更名為 Wear OS)設(shè)備添加了通知堆棧支持。使用 setGroup() 將通知放入堆棧。請(qǐng)注意,平板電腦和手機(jī)尚不支持通知堆棧。通知堆棧以后會(huì)稱(chēng)為組或 Bundle。

4. Android 7.0,API 24

  • 重新設(shè)置了通知模板的樣式以強(qiáng)調(diào)主打圖片和頭像。
  • 添加了三個(gè)通知模板:一個(gè)用于短信應(yīng)用,另外兩個(gè)用于借助展開(kāi)式選項(xiàng)和其他系統(tǒng)裝飾來(lái)裝飾自定義內(nèi)容視圖。
  • 向手持設(shè)備(手機(jī)和平板電腦)添加了對(duì)通知組的支持。使用與 Android 5.0(API 級(jí)別 21)中推出的 Android Wear(現(xiàn)已更名為 Wear OS)通知堆棧相同的 API。
  • 用戶(hù)可以使用內(nèi)嵌回復(fù)功能直接在通知內(nèi)進(jìn)行回復(fù)(他們輸入的文本將轉(zhuǎn)發(fā)到通知的父應(yīng)用)。

5. Android 8.0,API 26

  • 必須將各個(gè)通知放入特定渠道中。
  • 用戶(hù)可以按渠道關(guān)閉通知,而非關(guān)閉來(lái)自某個(gè)應(yīng)用的所有通知。
  • 包含有效通知的應(yīng)用將在主屏幕/啟動(dòng)器屏幕上相應(yīng)應(yīng)用圖標(biāo)的上方顯示通知“標(biāo)志”。
  • 用戶(hù)可以從抽屜式通知欄中暫停某個(gè)通知。您可以為通知設(shè)置自動(dòng)超時(shí)時(shí)間。
  • 您還可以設(shè)置通知的背景顏色。
  • 部分與通知行為相關(guān)的 API 已從 Notification 移至 NotificationChannel。例如,在搭載 Android 8.0 及更高版本的設(shè)備中,使用 NotificationChannel.setImportance(),而非 NotificationCompat.Builder.setPriority()。

6. Android 12.0,API 31

  • 自定義通知,提供通知模板。
  • 更改了完全自定義通知的外觀和行為。

下面就開(kāi)始我們的適配之旅吧。

二、創(chuàng)建項(xiàng)目

新建一個(gè)名為NotificationStudy的項(xiàng)目,如下圖所示:

點(diǎn)擊Finish完成項(xiàng)目創(chuàng)建,然后在app的build.gradle中的android{}閉包中開(kāi)啟viewBinding,代碼如下:

	buildFeatures {
        viewBinding true
    }

項(xiàng)目創(chuàng)建好之后,我們首先改動(dòng)一下activity_main.xml布局。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn_show"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="顯示通知"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

放一個(gè)按鈕,然后再修改一下MainActivity中的代碼,如下所示:

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        //顯示通知
        binding.btnShow.setOnClickListener {
            
        }
    }
}

這里就是綁定ViewBinding,然后設(shè)置按鈕點(diǎn)擊監(jiān)聽(tīng),下面我們就要開(kāi)始做顯示通知的操作了。

三、顯示通知

常規(guī)的通知由三個(gè)內(nèi)容構(gòu)成:標(biāo)題、內(nèi)容和圖標(biāo)。在8.0中還有一個(gè)通知渠道,所以我們需要先創(chuàng)建一個(gè)通知渠道。

① 創(chuàng)建通知渠道

創(chuàng)建通知渠道需要三個(gè)參數(shù),渠道ID、渠道名稱(chēng)和渠道重要性。

首先在MainActivity中增加幾個(gè)變量。

	//渠道Id
    private val channelId = "test"
    //渠道名
    private val channelName = "測(cè)試通知"
    //渠道重要級(jí)
    private val importance = NotificationManagerCompat.IMPORTANCE_HIGH
    //通知管理者
    private lateinit var notificationManager: NotificationManager
    //通知
    private lateinit var notification: Notification
    //通知Id
    private val notificationId = 1

發(fā)送通知首先要通過(guò)通知服務(wù)得到通知管理者,在onCreate方法中增加如下代碼:

	override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        //獲取系統(tǒng)通知服務(wù)
        notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        
        ...
        }
    }

然后是創(chuàng)建通知渠道,在MainActivity中新增如下函數(shù)。

	/**
     * 創(chuàng)建通知渠道
     */
    @RequiresApi(Build.VERSION_CODES.O)
    private fun createNotificationChannel(channelId: String, channelName: String, importance: Int) =
        notificationManager.createNotificationChannel(NotificationChannel(channelId, channelName, importance))

因?yàn)橥ㄖ朗茿ndroid8.0才有的,因此我們添加一個(gè)注解,然后將數(shù)據(jù)構(gòu)建通知渠道的參數(shù)傳入進(jìn)來(lái),注意我們通過(guò)notificationManager的createNotificationChannel()函數(shù)去創(chuàng)建渠道的,如果notificationManager沒(méi)有初始化的話(huà),毫無(wú)疑問(wèn)你的這一行代碼會(huì)報(bào)錯(cuò)。

② 初始化通知

通知渠道創(chuàng)建好了,下面我們?nèi)コ跏蓟ㄖ?,同樣在MainActivity中新增一個(gè)initNotification()函數(shù),代碼如下:

	/**
     * 初始化通知
     */
    private fun initNotification() {
        notification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            //創(chuàng)建通知渠道
            createNotificationChannel(channelId,channelName,importance)
            NotificationCompat.Builder(this, channelId)
        } else {
            NotificationCompat.Builder(this)
        }.apply {
            setSmallIcon(R.mipmap.ic_launcher)//小圖標(biāo)(顯示在狀態(tài)欄)
            setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))//大圖標(biāo)(顯示在通知上)
            setContentTitle("打工人")//標(biāo)題
            setContentText("我要搞錢(qián)?。?!")//內(nèi)容
        }.build()
    }

這里首先通過(guò)版本判斷檢查是否需要?jiǎng)?chuàng)建通知渠道,然后會(huì)得到一個(gè)通知的Builder,通過(guò)Builder去配置通知所需要的基本參數(shù),這里我設(shè)置了圖標(biāo),標(biāo)題,內(nèi)容,配置完之后調(diào)用build(),完成通知的構(gòu)建,最后返回一個(gè)notification,現(xiàn)在我們的通知就構(gòu)建好了。

③ 顯示通知

然后我們?cè)傩薷囊幌耾nCreate中的代碼,如下所示

	override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        //獲取系統(tǒng)通知服務(wù)
        notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        //初始化通知
        initNotification()
        //顯示通知
        binding.btnShow.setOnClickListener {
            notificationManager.notify(notificationId, notification)
        }
    }

這里我們調(diào)用了initNotification()函數(shù),然后在點(diǎn)擊按鈕時(shí)發(fā)送通知。

	binding.btnShow.setOnClickListener {
		notificationManager.notify(notificationId, notification)
	}

運(yùn)行一下,效果如下圖所示:

四、通知點(diǎn)擊

在上面的gif中,我們成功顯示了通知,其中我們嘗試去做了點(diǎn)擊通知的動(dòng)作,但是沒(méi)有什么反應(yīng),因?yàn)檫@方面的功能還沒(méi)有寫(xiě),下面我們就來(lái)寫(xiě)。

首先要想一下點(diǎn)擊之后要干嘛?通常來(lái)說(shuō)都是跳轉(zhuǎn)到指定的Activity,我們當(dāng)前只有一個(gè)MainActivity,因此我們需要?jiǎng)?chuàng)建一個(gè)。

① 創(chuàng)建目的Activity

我們?cè)赾om.llw.notification下創(chuàng)建DetailsActivity,對(duì)應(yīng)activity_details.xml布局文件,修改一下布局文件,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".DetailsActivity">

    <TextView
        android:id="@+id/tv_notification_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

這里增加一個(gè)TextView,然后回到DetailsActivity中,修改代碼如下:

class DetailsActivity : AppCompatActivity() {
    private lateinit var binding: ActivityDetailsBinding
    @SuppressLint("SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityDetailsBinding.inflate(layoutInflater)
        setContentView(binding.root)

        intent?.let {
            binding.tvNotificationContent.text =
                "${it.getStringExtra("title")}\n" + "${it.getStringExtra("content")}"
        }
    }
}

這里的代碼也很簡(jiǎn)單,就是獲取傳遞過(guò)來(lái)的intent中攜帶的參數(shù)顯示在TextView上,假設(shè)我們?cè)贛ainActivity中點(diǎn)擊時(shí)傳遞title和content。

② PendingIntent使用

我們經(jīng)常使用Intent,但是接觸PendingIntent是比較少的,PendingIntent可以看作是對(duì)Intent的一個(gè)封裝,但它不是立刻執(zhí)行某個(gè)行為,而是滿(mǎn)足某些條件或觸發(fā)某些事件后才執(zhí)行指定的行為。

PendingIntent獲取有三種方式:Activity、Service和BroadcastReceiver獲取。PendingIntent有一個(gè)比較簡(jiǎn)單的使用方式,例如我們現(xiàn)在要在Activity中使用,修改initNotification()函數(shù)中的代碼:

	private fun initNotification() {
        val title = "打工人"
        val content = "我要搞錢(qián)?。?!"
        // 為DetailsActivity 創(chuàng)建顯式 Intent
        val intent = Intent(this, DetailsActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
            putExtra("title", title).putExtra("content", content)
        }
        val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)

        notification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            //創(chuàng)建通知渠道
            createNotificationChannel(channelId, channelName, importance)
            NotificationCompat.Builder(this, channelId)
        } else {
            NotificationCompat.Builder(this)
        }.apply {
            setSmallIcon(R.mipmap.ic_launcher)//小圖標(biāo)(顯示在狀態(tài)欄)
            setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))//大圖標(biāo)(顯示在通知上)
            setContentTitle(title)//標(biāo)題
            setContentText(content)//內(nèi)容
            setContentIntent(pendingIntent)//設(shè)置內(nèi)容意圖
        }.build()
    }

這里的代碼解釋一下,首先將title、content抽離出來(lái),然后創(chuàng)建intent,再創(chuàng)建pendingIntent 。最后在配置build中設(shè)置setContentIntent(pendingIntent),下面我們運(yùn)行一下。


這里已經(jīng)完成了點(diǎn)擊通知并傳遞的操作,這里還有一個(gè)細(xì)節(jié)就是常規(guī)來(lái)說(shuō)我們點(diǎn)擊了這個(gè)通知表示我們已經(jīng)看到了,或者已經(jīng)知曉了內(nèi)容,因此通知就會(huì)消失,而這里通知并沒(méi)有消息。

只需要一個(gè)配置就可以做到。

setAutoCancel(true)//設(shè)置自動(dòng)取消

添加位置如下圖所示:

運(yùn)行測(cè)試一下就行,我就不用gif說(shuō)明了。

五、折疊通知

有時(shí)候我們?cè)O(shè)置通知的內(nèi)容可能一行放不下,這個(gè)時(shí)候就需要收縮和展開(kāi)通知,讓用戶(hù)看到完整的信息。

① 長(zhǎng)文本

現(xiàn)在我將content的內(nèi)容修改一下:

val content = "我要搞錢(qián)?。?!富強(qiáng)、明主、文明、和諧、自由、平等、公正、法治、愛(ài)國(guó)、敬業(yè)、誠(chéng)信、友善"

然后我們什么都不做去運(yùn)行看看。

這里并沒(méi)有顯示多行,同時(shí)也沒(méi)有那個(gè)向下展開(kāi)的按鈕,內(nèi)容文字做了省略,因此這說(shuō)明那個(gè)展開(kāi)需要我們?nèi)ピO(shè)置。

一行代碼搞定:

setStyle(NotificationCompat.BigTextStyle().bigText(content))

通過(guò)設(shè)置通知的風(fēng)格樣式,這里使用的是長(zhǎng)文本信息樣式,將content傳遞進(jìn)去。添加位置如下圖所示:

運(yùn)行一下看看

② 顯示圖片

有時(shí)候我們會(huì)在通知中展開(kāi)時(shí)看到圖片,實(shí)際上就是使用了另一個(gè)樣式,也是一行代碼解決。

setStyle(NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(resources,R.drawable.logo)))//設(shè)置樣式

這行代碼的位置和替換掉剛才哪一行,通知只能設(shè)置一個(gè)樣式,后面設(shè)置的樣式會(huì)覆蓋掉前面的樣式,這里我們使用大圖片樣式,傳進(jìn)入一個(gè)logo.jpg圖片,你在寫(xiě)的時(shí)候隨便用什么都行,然后我們?cè)龠\(yùn)行一下。

六、回復(fù)通知

有時(shí)候我們的手機(jī)收到短信消息,是可以直接回復(fù)的。當(dāng)然了這個(gè)功能是需要手動(dòng)去寫(xiě)的。流程就是點(diǎn)擊按鈕出現(xiàn)一個(gè)通知,通知中回復(fù)消息,廣播或服務(wù)收到消息后更新通知,然后關(guān)閉通知。

① 創(chuàng)建廣播

這里我們先來(lái)寫(xiě)這個(gè)接收回復(fù)消息的處理,這里用廣播來(lái)處理,首先我們需要?jiǎng)?chuàng)建一個(gè)廣播,在com.llw.notification下新建一個(gè)ReplyMessageReceiver類(lèi),里面的代碼如下:

class ReplyMessageReceiver : BroadcastReceiver() {

    private val TAG = ReplyMessageReceiver::class.java.simpleName

    override fun onReceive(context: Context, intent: Intent) {
        //獲取回復(fù)消息的內(nèi)容
        val inputContent =
            RemoteInput.getResultsFromIntent(intent)?.getCharSequence("key_text_reply")?.toString()
        Log.d(TAG, "onReceive: $inputContent")
  
        if (inputContent == null) {
            Log.e(TAG, "onReceive: 沒(méi)有回復(fù)消息!")
            return
        }
        //構(gòu)建回復(fù)消息通知
        val repliedNotification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationCompat.Builder(context, "reply")
        } else {
            NotificationCompat.Builder(context)
        }.apply {
            setSmallIcon(R.mipmap.ic_launcher)//小圖標(biāo)(顯示在狀態(tài)欄)
            setContentTitle("1008666")//標(biāo)題
            setContentText("消息發(fā)送成功!")//內(nèi)容
        }.build()

        val notificationManager =
            context.getSystemService(AppCompatActivity.NOTIFICATION_SERVICE) as NotificationManager
        //發(fā)送通知
        notificationManager.notify(2, repliedNotification)
        //1秒后取消通知
        Timer().schedule(1000){
            notificationManager.cancel(2)
        }
    }
}

這里說(shuō)明一下:首先是RemoteInput表示遠(yuǎn)程輸入,也就是通知欄上輸入框,這里就是獲取輸入框的內(nèi)容,注意"key_text_reply"這個(gè)值,我們?cè)跇?gòu)建RemoteInput時(shí)使用的值要與這個(gè)一致,不一致你在廣播中就拿不到輸入的值。

然后是構(gòu)建通知了,這里的設(shè)置都是常規(guī)操作,渠道id我是寫(xiě)死的,因此在Activity中創(chuàng)建通知時(shí)渠道Id也要一致。最后就是在發(fā)送通知之后加了一個(gè)1秒的延時(shí)去取消通知,表示收到回復(fù)的處理。

廣播是需要在AndroidManifest.xml注冊(cè)的,代碼如下:

<receiver android:name=".ReplyMessageReceiver"/>

位置如下:

下面就是要構(gòu)建回復(fù)通知了。因?yàn)橐獏^(qū)別于之前的普通通知,所以這里我需要更改一下activity_main.xml中的布局代碼

	<Button
        android:id="@+id/btn_show_reply"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="顯示回復(fù)通知"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn_show" />

增加一個(gè)按鈕,點(diǎn)擊事件后面再寫(xiě)。

② RemoteInput

為了區(qū)分普通通知和回復(fù)通知,在MainActivity中定義一下。

	//回復(fù)通知Id
    private val replyNotificationId = 2
    //回復(fù)通知
    private lateinit var replyNotification: Notification

下面我們新建一個(gè)initReplyNotification()函數(shù),在里面對(duì)RemoteInput進(jìn)行構(gòu)建。

	private fun initReplyNotification() {
        //遠(yuǎn)程輸入
        val remoteInput = RemoteInput.Builder("key_text_reply").setLabel("快速回復(fù)").build()
    }

這里RemoteInput的構(gòu)建也很簡(jiǎn)單,最關(guān)鍵的就是"key_text_reply",剛才在適配器中已經(jīng)說(shuō)了,而Label就是一個(gè)輸入框的提示文本。

③ PendingIntent

現(xiàn)在我們要通過(guò)BroadcastReceiver獲取PendingIntent,在initReplyNotification()函數(shù)中新增代碼:

	private fun initReplyNotification() {
        ...
        //構(gòu)建回復(fù)pendingIntent
        val replyIntent = Intent(this, ReplyMessageReceiver::class.java)
        val pendingIntent = PendingIntent.getBroadcast(this, 0, replyIntent, PendingIntent.FLAG_ONE_SHOT)
    }

④ NotificationCompat.Action

通知?jiǎng)幼?,我們?cè)谳斎肟驅(qū)懭胄畔ⅲ枰粋€(gè)按鈕發(fā)送這個(gè)按鈕,這個(gè)Action就是用來(lái)做這個(gè)事情的,在initReplyNotification()函數(shù)中新增代碼:

	private fun initReplyNotification() {
        ...
        //構(gòu)建回復(fù)pendingIntent
        val replyIntent = Intent(this, ReplyMessageReceiver::class.java)
        val pendingIntent = PendingIntent.getBroadcast(this, 0, replyIntent, PendingIntent.FLAG_ONE_SHOT)
    }

⑤ 構(gòu)建通知

下面就是構(gòu)建通知,在initReplyNotification()函數(shù)中新增代碼:

	private fun initReplyNotification() {
        ...
        //構(gòu)建通知
        replyNotification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createNotificationChannel("reply", "回復(fù)消息", importance)
            NotificationCompat.Builder(this, "reply")
        } else {
            NotificationCompat.Builder(this)
        }.apply {
            setSmallIcon(R.mipmap.ic_launcher)//小圖標(biāo)(顯示在狀態(tài)欄)
            setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))//大圖標(biāo)(顯示在通知上)
            setContentTitle("1008666")//標(biāo)題
            setContentText("你的賬號(hào)已欠費(fèi)2000元!")//內(nèi)容
            addAction(action)
        }.build()
    }

這里的關(guān)鍵就在于這個(gè)addAction(action),下面我們運(yùn)行一下:


然后我們看看日志:

七、橫幅通知

橫幅通知我相信你一定見(jiàn)過(guò),例如收到短信、QQ、微信、釘釘?shù)南?,都?huì)有出現(xiàn)在屏幕頂部,主要是用于提醒用戶(hù)的。

首先我們修改布局,在activity_main.xml中新增一個(gè)按鈕,代碼如下:

	<Button
        android:id="@+id/btn_show_banner"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="顯示橫幅通知"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn_show_reply" />

① 檢查橫幅通知是否打開(kāi)

首先在MainActivity中定義幾個(gè)變量

	//橫幅通知
    private lateinit var bannerNotification: Notification
    //橫幅通知Id
    private val bannerNotificationId = 3
    //開(kāi)啟橫幅通知返回
    private val bannerLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            if (it.resultCode == RESULT_OK) {
                Log.d("TAG", "返回結(jié)果")
            }
        }

然后新增一個(gè)openBannerNotification()函數(shù),代碼如下:

	private fun openBannerNotification() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val bannerImportance = notificationManager.getNotificationChannel("banner").importance
        if (bannerImportance == NotificationManager.IMPORTANCE_DEFAULT) {
            val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
                .putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
                .putExtra(Settings.EXTRA_CHANNEL_ID, "banner")
            bannerLauncher.launch(intent); false
        } else true
    } else true

這里通過(guò)檢查通知遇到的重要級(jí)判斷是否開(kāi)啟橫幅通知。

② 構(gòu)建橫幅通知渠道

在MainActivity中新增createBannerNotificationChannel()函數(shù),代碼如下:

	@RequiresApi(Build.VERSION_CODES.O)
    private fun createBannerNotificationChannel(channelId: String, channelName: String, importance: Int) =
        notificationManager.createNotificationChannel(
            NotificationChannel(channelId, channelName, importance).apply {
                description = "提醒式通知"http://渠道描述
                enableLights(true)//開(kāi)啟閃光燈
                lightColor = Color.BLUE//設(shè)置閃光燈顏色
                enableVibration(true)//開(kāi)啟震動(dòng)
                vibrationPattern = longArrayOf(0, 1000, 500, 1000)//震動(dòng)模式
                setSound(null, null)//沒(méi)有提示音
            }
        )

這里的內(nèi)容相對(duì)于之前來(lái)說(shuō)就多一些,有注釋也好理解。

③ 構(gòu)建橫幅通知

在MainActivity中新增initBannerNotification()函數(shù),代碼如下:

	private fun initBannerNotification() {
        //構(gòu)建通知
        bannerNotification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createBannerNotificationChannel("banner", "提醒消息", importance)
            NotificationCompat.Builder(this, "banner")
        } else {
            NotificationCompat.Builder(this)
        }.apply {
            setSmallIcon(R.mipmap.ic_launcher)//小圖標(biāo)(顯示在狀態(tài)欄)
            setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))//大圖標(biāo)(顯示在通知上)
            setContentTitle("落魄Android在線(xiàn)炒粉")//標(biāo)題
            setContentText("不要9塊9,不要6塊9,只要3塊9。")//內(nèi)容
            setWhen(System.currentTimeMillis())//通知顯示時(shí)間
            setAutoCancel(true)//設(shè)置自動(dòng)取消
        }.build()
    }

這里也就是一些常規(guī)的設(shè)置。

④ 顯示橫幅通知

最后我們?cè)趏nCreate()函數(shù)中,新增如下代碼:

		//顯示橫幅通知
        binding.btnShowBanner.setOnClickListener {
            //檢查是否授予訪(fǎng)問(wèn)權(quán)限
            if (openBannerNotification()) {
                notificationManager.notify(bannerNotificationId, bannerNotification)
            }
        }

下面我們運(yùn)行一下:

OK,這樣就可以了。

八、常駐通知

我們知道有一些通知,當(dāng)程序運(yùn)行的時(shí)候就會(huì)出現(xiàn),例如我們最常見(jiàn)的音樂(lè)類(lèi)App,而且這個(gè)通知并不是馬上出現(xiàn)的,在此之前還有很多內(nèi)容要初始化,一切就緒之后出現(xiàn)這個(gè)通知,就可以通過(guò)通知去控制音樂(lè)了。

我們并不需要這種復(fù)雜的操作,只有有一個(gè)通知能在App啟動(dòng)的時(shí)候顯示出來(lái),并且App進(jìn)入后臺(tái)時(shí),通知也還在。

在MainActivity創(chuàng)建變量。

	//常駐通知
    private lateinit var permanentNotification: 
    //常駐通知Id
    private val permanentNotificationId = 4Notification

然后在MainActivity中新增一個(gè)showPermanentNotification()函數(shù),代碼如下:

	private fun showPermanentNotification() {
        //構(gòu)建回復(fù)pendingIntent
        val permanentIntent = Intent(this, MainActivity::class.java)
        val pendingIntent =
            PendingIntent.getActivity(this, 0, permanentIntent, PendingIntent.FLAG_UPDATE_CURRENT)
        //構(gòu)建通知
        permanentNotification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createNotificationChannel("permanent", "我一直存在", importance)
            NotificationCompat.Builder(this, "permanent")
        } else {
            NotificationCompat.Builder(this)
        }.apply {
            setSmallIcon(R.mipmap.ic_launcher)//小圖標(biāo)(顯示在狀態(tài)欄)
            setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))//大圖標(biāo)(顯示在通知上)
            setContentTitle("你在努力些什么?")//標(biāo)題
            setContentText("搞錢(qián)!搞錢(qián)!還是搞錢(qián)!")//內(nèi)容
            setWhen(System.currentTimeMillis())//通知顯示時(shí)間
            setContentIntent(pendingIntent)
        }.build()
        permanentNotification.flags = Notification.FLAG_ONGOING_EVENT
        notificationManager.notify(permanentNotificationId, permanentNotification)
    }

這里就很簡(jiǎn)單了,主要就是去掉通知取消設(shè)置,同時(shí)設(shè)置FLAG_ONGOING_EVENT,另外在點(diǎn)擊通知的時(shí)候進(jìn)入主頁(yè)面。在onCreate()函數(shù)中調(diào)用。

運(yùn)行一下:

可以看到這里我用別的通知顯示出來(lái)之后,清理一下,其他通知就沒(méi)有了,而常駐通知還在,然后我程序進(jìn)入后臺(tái),點(diǎn)擊常駐通知,又會(huì)啟動(dòng)到前臺(tái)。

九、自定義樣式通知

現(xiàn)在我們使用的都是常規(guī)的樣式通知,實(shí)際上我們可以自定義的,就是自定義通知布局,我們先來(lái)設(shè)計(jì)自定義布局的樣式,就做一個(gè)音樂(lè)通知欄吧,首先是三個(gè)圖標(biāo)。

① 自定義通知布局

在drawable文件夾下新建ic_previous.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="36dp"
    android:height="36dp"
    android:tint="@color/white"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path
        android:fillColor="@android:color/white"
        android:pathData="M7,6c0.55,0 1,0.45 1,1v10c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1L6,7c0,-0.55 0.45,-1 1,-1zM10.66,12.82l5.77,4.07c0.66,0.47 1.58,-0.01 1.58,-0.82L18.01,7.93c0,-0.81 -0.91,-1.28 -1.58,-0.82l-5.77,4.07c-0.57,0.4 -0.57,1.24 0,1.64z" />
</vector>

ic_play.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="36dp"
    android:height="36dp"
    android:tint="@color/white"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path
        android:fillColor="@android:color/white"
        android:pathData="M8,6.82v10.36c0,0.79 0.87,1.27 1.54,0.84l8.14,-5.18c0.62,-0.39 0.62,-1.29 0,-1.69L9.54,5.98C8.87,5.55 8,6.03 8,6.82z" />
</vector>

ic_next.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="36dp"
    android:height="36dp"
    android:tint="@color/white"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path
        android:fillColor="@android:color/white"
        android:pathData="M7.58,16.89l5.77,-4.07c0.56,-0.4 0.56,-1.24 0,-1.63L7.58,7.11C6.91,6.65 6,7.12 6,7.93v8.14c0,0.81 0.91,1.28 1.58,0.82zM16,7v10c0,0.55 0.45,1 1,1s1,-0.45 1,-1V7c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1z" />
</vector>

然后在layout下新建一個(gè)layout_custom_notification.xml,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/black"
    android:gravity="center_vertical">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_song_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:text="雨下一整晚"
            android:textColor="@color/white"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/tv_singer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="4dp"
            android:text="周杰倫"
            android:textColor="@color/white"
            android:textSize="12sp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center">

        <ImageButton
            android:id="@+id/iv_previous"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:src="@drawable/ic_previous" />

        <ImageButton
            android:id="@+id/iv_play"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="16dp"
            android:background="@null"
            android:src="@drawable/ic_play" />

        <ImageButton
            android:id="@+id/iv_next"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:src="@drawable/ic_next" />
    </LinearLayout>

    <ImageView
        android:id="@+id/iv_avatar"
        android:layout_width="72dp"
        android:layout_height="72dp"
        android:src="@drawable/jay" />
</LinearLayout>

這里要注意一點(diǎn)自定義通知的界面布局只支持LinearLayout、RelativeLayout、FrameLayout,目前不支持ConstraintLayout通知布局里有ConstraintLayout的話(huà),彈通知不會(huì)顯示。

jpg圖標(biāo)用自己的,或者用我源碼里面都可以,然后就很簡(jiǎn)單了,回到MainActivity。

② 顯示自定義通知

	//自定義通知
    private lateinit var customNotification: Notification
    //自定義通知Id
    private val customNotificationId = 5

然后創(chuàng)建initCustomNotification()函數(shù),代碼如下:

	@SuppressLint("RemoteViewLayout")
    private fun initCustomNotification() {
        //RemoteView
        val remoteViews = RemoteViews(packageName, R.layout.layout_custom_notification)
        customNotification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createNotificationChannel("custom", "自定義通知", importance)
            NotificationCompat.Builder(this, "custom")
        } else {
            NotificationCompat.Builder(this)
        }.apply {
            setSmallIcon(R.mipmap.ic_launcher)//小圖標(biāo)(顯示在狀態(tài)欄)
            setCustomContentView(remoteViews)//設(shè)置自定義內(nèi)容視圖
            setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
            setOnlyAlertOnce(true)
            setOngoing(true)
        }.build()
    }

在onCreate中調(diào)用

c

然后我們?cè)赼ctivity_main.xml中新增一個(gè)按鈕:

	<Button
        android:id="@+id/btn_show_custom"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="顯示自定義通知"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn_show_banner" />

最后在MainActivity中的onCreate()函數(shù)中新增按鈕點(diǎn)擊事件,同時(shí)點(diǎn)擊調(diào)用通知顯示:

		//顯示自定義通知
        binding.btnShowCustom.setOnClickListener {
            notificationManager.notify(customNotificationId, customNotification)
        }

運(yùn)行一下:

③ 自定義通知大小

通知布局視圖布局的高度上限為 64 dp,展開(kāi)后的視圖布局的高度上限為 256 dp,剛才我們只設(shè)置了小的通知,那么如果要展開(kāi)一個(gè)大一點(diǎn)的通知,最好是能夠滑動(dòng)通知的時(shí)候有大小變化。

其實(shí)很簡(jiǎn)單,首先我們同樣要定義一個(gè)大一點(diǎn)同通知布局,在layout下新建一個(gè)layout_custom_notification_big.xml,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/black"
    android:gravity="center_vertical">

    <TextView
        android:id="@+id/tv_song_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:text="雨下一整晚"
        android:textColor="@color/white"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_singer"
        android:layout_below="@+id/tv_song_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="6dp"
        android:text="周杰倫"
        android:textColor="@color/white"
        android:textSize="16sp" />

    <LinearLayout
        android:layout_marginTop="16dp"
        android:layout_below="@+id/tv_singer"
        android:layout_alignParentStart="true"
        android:layout_toStartOf="@+id/iv_avatar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center">

        <ImageButton
            android:id="@+id/iv_previous"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:src="@drawable/ic_previous" />

        <ImageButton
            android:id="@+id/iv_play"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="16dp"
            android:background="@null"
            android:src="@drawable/ic_play" />

        <ImageButton
            android:id="@+id/iv_next"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:src="@drawable/ic_next" />
    </LinearLayout>

    <ImageView
        android:layout_alignParentEnd="true"
        android:id="@+id/iv_avatar"
        android:layout_width="144dp"
        android:layout_height="144dp"
        android:src="@drawable/jay" />
</RelativeLayout>

然后我們修改initCustomNotification()函數(shù)中的代碼:

	@SuppressLint("RemoteViewLayout")
    private fun initCustomNotification() {
        //RemoteView
        val remoteViews = RemoteViews(packageName, R.layout.layout_custom_notification)
        val bigRemoteViews = RemoteViews(packageName, R.layout.layout_custom_notification_big)
        customNotification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createNotificationChannel("custom", "自定義通知", importance)
            NotificationCompat.Builder(this, "custom")
        } else {
            NotificationCompat.Builder(this)
        }.apply {
            setSmallIcon(R.mipmap.ic_launcher)//小圖標(biāo)(顯示在狀態(tài)欄)
            setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
            setCustomContentView(remoteViews)
            setCustomBigContentView(bigRemoteViews)
            setOnlyAlertOnce(true)
            setOngoing(true)
        }.build()
    }

我們?cè)賱?chuàng)建一個(gè)RemoteView,然后通過(guò)setCustomBigContentView設(shè)置一下就可以了,下面運(yùn)行一下,看看效果。

十、源碼

如果你覺(jué)得代碼對(duì)你有幫助的話(huà),不妨Fork或者Star一下~
GitHub:NotificationStudy

到此這篇關(guān)于Android Notification使用的文章就介紹到這了,更多相關(guān)Android Notification使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論