如何在 Android 上自定义来电通知?带有代码示例

news/2025/2/12 23:36:54/

您将从本文中学习如何在 Android 上进行从基本布局到高级布局的来电通知。使用我们的示例自定义通知屏幕。

今天,我们将处理来电通知:我们将从最简单和最简约的通知开始,并以采用非系统设计的全屏通知结束。让我们开始吧!

频道创建 (api 26+)

从 Android 8.0 开始,每个通知都必须有一个它所属的通知通道。在这个版本的系统之前,用户可以允许或禁止应用程序显示通知,而不能只关闭某个类别,这不是很方便。另一方面,通过频道,用户可以关闭来自应用程序的烦人通知,例如广告和不必要的提醒,而只留下他需要的通知(新消息、电话等)。

如果我们不指定频道 ID,请使用 Deprecated 构建器。如果我们不创建具有此类 ID 的频道,Android 8 或更高版本将不会显示通知。

我们需要你可能已经连接的 androidx.core 库。我们用 Kotlin 编写,所以我们使用该语言的库版本:

dependencies {implementation("androidx.core:core-ktx:1.5.0")
}

通知的所有工作都是通过系统服务 NotificationManager 完成的。为了向后兼容,如果你有 Android 类的 Compat 版本总是更好,所以我们将使用 NotificationManagerCompat。获取实例:

val notificationManager = NotificationManagerCompat.from(context)

让我们创建我们的频道。您可以为频道设置很多参数,例如通知的一般声音和振动模式。

val INCOMING_CALL_CHANNEL_ID = “incoming_call”// Creating an object with channel dataval channel = NotificationChannelCompat.Builder(// channel ID, it must be unique within the packageINCOMING_CALL_CHANNEL_ID,// The importance of the notification affects whether the notification makes a sound, is shown immediately, and so on. We set it to maximum, it’s a call after all.NotificationManagerCompat.IMPORTANCE_HIGH)// the name of the channel, which will be displayed in the system notification settings of the application.setName(“Incoming calls”)// channel description, will be displayed in the same place.setDescription(“Incoming audio and video call alerts”).build()// Creating the channel. If such a channel already exists, nothing happens, so this method can be used before sending each notification to the channel.notificationManager.createNotificationChannel(channel)

显示通知

太好了,现在我们可以开始创建通知本身了,让我们从最简单的例子开始:

val notificationBuilder = NotificationCompat.Builder( this, // channel ID againINCOMING_CALL_CHANNEL_ID)// A small icon that will be displayed in the status bar.setSmallIcon(R.drawable.icon)// Notification title.setContentTitle(“Incoming call”)// Notification text, usually the caller’s name.setContentText(“James Smith”)// Large image, usually a photo / avatar of the caller.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.logo))// For notification of an incoming call, it’s wise to make it so that it can’t be “swiped”.setOngoing(true)So far we’ve only created a sort of “description” of the notification, but it’s not yet shown to the user. To display it, let’s turn to the manager again:// Let’s get to building our notificationval notification = notificationBuilder.build()// We ask the system to display itnotificationManager.notify(INCOMING_CALL_NOTIFICATION_ID, notification)

INCOMING_CALL_NOTIFICATION_ID 是一个通知标识符,可用于查找已显示的通知并与之交互。

例如,用户长时间没有接听电话,来电者厌倦了等待并取消了通话。然后我们可以取消通知:

notificationManager.cancel(INCOMING_CALL_NOTIFICATION_ID)

或者,在会议应用程序的情况下,如果不止一个人加入了呼叫者,我们可以更新我们的通知。为此,只需创建一个新通知并在通知调用中传递相同的通知 ID——然后旧通知将仅使用数据更新,而不会为新通知的外观设置动画。为此,我们可以通过简单地替换其中更改的部分来重用旧的 notificationBuilder:

notificationBuilder.setContentText(“James Smith, George Watson”)notificationManager.notify(INCOMING_CALL_NOTIFICATION_ID, notificationBuilder.build())

单击时的按钮操作

一个简单的来电通知,之后用户必须自己找到我们的应用程序并接受或拒绝来电,这并不是一件很有用的事情。幸运的是,我们可以在通知中添加操作按钮!

为此,我们在创建通知时添加一个或多个操作。创建它们将如下所示:

val action = NotificationCompat.Action.Builder(// The icon that will be displayed on the button (or not, depends on the Android version)IconCompat.createWithResource(applicationContext, R.drawable.icon_accept_call),// The text on the buttongetString(R.string.accept_call),// The action itself, PendingIntentacceptCallIntent).build()

等一下,另一个 PendingIntent 是什么意思?这是一个非常广泛的话题,值得单独写一篇文章,但简单地说,它是对如何运行我们应用程序的元素(例如活动或服务)的描述。最简单的形式是这样的:

const val ACTION_ACCEPT_CALL = 101// We create a normal intent, just like when we start a new Activityval intent = Intent(applicationContext, MainActivity::class.java).apply {action = ACTION_ACCEPT_CALL}// But we don’t run it ourselves, we pass it to PendingIntent, which will be called later when the button is pressedval acceptCallIntent = PendingIntent.getActivity(applicationContext, REQUEST_CODE_ACCEPT_CALL, intent, PendingIntent.FLAG_UPDATE_CURRENT)

因此,我们需要在活动本身中处理这个动作。为此,在onCreate()(onNewIntent()如果您将标志FLAG_ACTIVITY_SINGLE_TOP用于您的活动),action从intent并采取行动:

override fun onNewIntent(intent: Intent?) {super.onNewIntent(intent)if (intent?.action == ACTION_ACCEPT_CALL) imaginaryCallManager.acceptCall()}

现在我们已经为我们的行动做好了一切准备,我们可以通过以下方式将其添加到我们的通知中Builder

notificationBuilder.addAction(action)

除了按钮之外,我们还可以通过单击按钮之外的通知本身来分配操作。转到来电屏幕似乎是最好的解决方案——为此,我们重复创建操作的所有步骤,但使用不同的操作 id 而不是ACTION_ACCEPT_CALL,并通过导航MainActivity.onCreate()处理它action

override fun onNewIntent(intent: Intent?) {…if (intent?.action == ACTION_SHOW_INCOMING_CALL_SCREEN)imaginaryNavigator.navigate(IncomingCallScreen())}

您也可以使用service而不是activity来处理事件。

具有自己设计的通知

通知本身是系统界面的一部分,因此它们将以相同的系统样式显示。但是,如果您想脱颖而出,或者如果按钮和其他通知元素的标准排列不适合您,您可以为通知赋予您自己独特的风格。

免责声明:由于具有不同屏幕尺寸和纵横比的 Android 设备种类繁多,再加上通知中元素的定位有限(相对于常规应用程序屏幕),自定义内容通知更难以支持。

通知仍然会由系统呈现,也就是在我们的应用程序进程之外,所以我们需要使用RemoteViews而不是常规的 View。请注意,此机制不支持所有熟悉的元素,特别ConstraintLayout是 不可用。

一个简单的示例是带有一个用于接听电话的按钮的自定义通知:

<!– notification_custom.xml –><RelativeLayout …android:layout_width=”match_parent”android:layout_height=”match_parent”><Buttonandroid:id=”@+id/button_accept_call”android:layout_width=”wrap_content”android:layout_height=”wrap_content”android:layout_centerHorizontal=”true”android:layout_alignParentBottom=”true”android:backgroundTint=”@color/green_accept”android:text=”@string/accept_call”android:textColor=”@color/fora_white” /></RelativeLayout>.

布局已准备就绪,现在我们需要创建一个实例 RemoteViews 并将其传递给通知构造函数。

val remoteView = RemoteViews(packageName, R.layout.notification_custom)// Set the PendingIntent that will “shoot” when the button is clicked. A normal onClickListener won’t work here – again, the notification will live outside our processremoteView.setOnClickPendingIntent(R.id.button_accept_call, pendingIntent)// Add to our long-suffering buildernotificationBuilder.setCustomContentView(remoteView)

我们的例子尽可能简单,当然,有点不和谐。通常,自定义通知的样式类似于系统通知,但采用品牌配色方案,例如 Skype 中的通知。

除了 .setCustomContentView 是一个普通的通知之外,我们还可以分别指定展开状态的标记 .setCustomBigContentView 和抬头状态的标记 .setCustomHeadsUpContentView

全屏通知

现在我们的自定义通知布局与应用程序内部的设计相匹配,但它们仍然是带有小按钮的小通知。当您接到正常的来电时会发生什么?我们的眼睛呈现在一个漂亮的屏幕上,它占据了所有可用空间。幸运的是,我们可以使用此功能!而且我们不害怕与 RemoteViews 相关的任何限制,因为我们可以显示完整的activity.

首先,我们要添加一个权限AndroidManifest.xml

<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />

在创建activity具有所需设计和功能的之后,我们初始化 PendingIntent 并将其添加到通知中:

val intent = Intent(this, FullscreenNotificationActivity::class.java)val pendingIntent = PendingIntent.getActivity(applicationContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)// At the same time we set highPriority to true, so what is highPriority if not an incoming call?notificationBuilder.setFullScreenIntent(pendingIntent, highPriority = true)

是的,就是这样!尽管这个功能很容易添加,但由于某种原因,并非所有与呼叫相关的应用程序都使用它。但是,Whatsapp 和 Telegram 等巨头已经通过这种方式实现了来电通知!

底线

Android上的来电通知是应用程序中非常重要的一部分。有很多要求:要及时,醒目,但不烦人。今天,我们了解了可用于实现所有这些目标的工具。让您的通知永远美丽!


http://www.ppmy.cn/news/583056.html

相关文章

iOS中如何监测来电

问题 最近在做一个有录音功能的App&#xff0c;要求当用户接到来电时&#xff0c;要停止录音。该如何实现这个功能呢&#xff1f; 解决方案 我首先想到了AppDelegate里的applicationWillResignActive:方法&#xff0c;在该方法的注释中就写到到收到来电或短信时&#xff0c;…

寻找两个正序数组的中位数,js实现

寻找两个正序数组的中位数&#xff0c;js实现 题目描述思路分析算法 题目描述 给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&#xff09;数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O(log (mn)) 。 实例1&#xff1a; …

INTERSPEECH 2023论文|基于自监督学习表示的具有持久性口音记忆的口音识别

论文题目&#xff1a; Self-supervised Learning Representation based Accent Recognition with Persistent Accent Memory 作者列表&#xff1a; 李睿&#xff0c;谢志伟&#xff0c;徐海华&#xff0c;彭亦周&#xff0c;刘和鑫&#xff0c;黄浩&#xff0c;Chng Eng Sio…

Open ai 开发指南:gpt接口的第一个问答机器人demo

目录 内容 Python代码 C 代码 workspace 文件 BUILD文件 Java 代码 maven文件 执行效果 内容 基于openai接口实现循环gpt问答&#xff0c;并使用一个文件将问答内容进行记录。 Python代码 # -*- coding: utf-8 -*- import openai import time from pathlib import P…

Android13 安装最新版 Frida

本文所有教程及源码、软件仅为技术研究。不涉及计算机信息系统功能的删除、修改、增加、干扰&#xff0c;更不会影响计算机信息系统的正常运行。不得将代码用于非法用途&#xff0c;如侵立删&#xff01; Android13 安装最新版 Frida 环境 win10Pixel4Android13Python3.9Frida1…

计算机主机箱进行总结,工业级主机用机箱分类总结

原标题&#xff1a;工业级主机用机箱分类总结 由于工业控制计算机的应用环境不同&#xff0c;从机箱的组成上可以分为多种。这也是工业控制计算机的一个主要特点&#xff01;在工业控制计算机的整个组成中&#xff0c;工业级机箱的重要性仍然是相当大的&#xff0c;那么工业级机…

1u服务器系统风扇,1U工控服务器机箱介绍

原标题&#xff1a;1U工控服务器机箱介绍 随着服务器的集成度越来越高&#xff0c;像INTEL的XEON刀片服务器(其广告随处可见)和1U服务器等大量的普及使用&#xff0c;并且国内的服务器市场逐步升温服务器的情况下。服务器散热受到散热器厂商和服务器用户的高度重视&#xff0c;…

哪个型号服务器静音风扇可调,全新 原装台达 4020 4厘米服务器静音风扇 DSB0412LD 12V 0.10A...

品牌&#xff1a;台湾台达 DELTA 型号&#xff1a;DSB0412LD-7S43 外形尺寸&#xff1a;40*40*20mm 4020 电压&#xff1a;12V DC 电流&#xff1a; 0.10A 超静音风扇 功率&#xff1a; 1.2W AFB02505LAAFB02505MAAFB0250512MAAFB02505HAAFB02505HHAAFB02512HHAAFB0305LAAFB031…