通知(Notification)是 Android 中最常见的功能之一。下面我来讲讲通知功能是怎么实现的吧,也算是对自己学习的总结了。
1、创建通知详解
1.1 创建通知渠道
首先,Google 是从 Android 8.0才开始引入了NotificationChannel(通知渠道)的概念,因此,在创建通知渠道时需要做适配处理。
public NotificationChannel(String channel_Id, CharSequence channel_Name, int importance){
……
}
其次,需要创建 一个 NotificationChannel 对象,然后这个对象需要接收三个参数:
- channel_id : 渠道id ,channel 的唯一标识
- channel_name : 渠道名称,给用户看的
- importance : 通知重要程度
参数 importance 是 NotificationManager 中定义的常量属性值,主要有以下五个:
- IMPORTANCE_NONE 无。关闭通知
- IMPORTANCE_MIN 小。开启通知,不会弹出,没有提示音,状态栏中不显示
- IMPORTANCE_LOW 低。开启通知,不会弹出,没有提示音,但状态栏中显示
- IMPORTANCE_DEFAULT 默认。开启通知,不会弹出,但有提示音,状态栏中显示
- IMPORTANCE_HIGH 高。开启通知,会弹出,发出提示音,状态栏中显示
这些值可以理解为通知的优先级,通过它们能够设置通知是否有提示音、是否弹出和是否显示到状态栏等。
最后,通过调用 NotificationManager 的 createNotificationChannel() 方法创建通知渠道。
以下是创建通知渠道的示例:
//适配 Android 8.0
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
//创建 NotificationChannel 对象
NotificationChannel channel = new NotificationChannel(CHANNAL_ID,
"chat message",NotificationManager.IMPORTANCE_DEFAULT);
//创建通知渠道
mNotificationManager.createNotificationChannel(channel);
}
1.2 创建通知
创建通知涉及到 NotificationManager 和 NotificationCompat 两个类:
- NotificationCompat : 用于兼容不同版本的 Notification。
- NotificationManager : 状态栏通知的管理类,负责发通知,清除通知等操作。
第一步:获取 NotificationManager 对象来管理通知
获取方法:可以通过调用 Contxt 的 getSystemService() 方法获取系统服务,然后接收它返回一个 NotificationManager 对象。需要注意的是,该方法需要传入一个字符串参数 Context.NOTIFICATION_SERVICE 来指定获取的服务是系统通知服务。
NotificationManager manager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
第二步:设置通知属性
这里通过创建 NotificationCompat.Builder 对象( NotificationCompat对象的构造器类) 并调用以下属性对应的方法来设置通知的相应属性:
小图标:未下拉状态栏时显示的图标,通过 setSmallIcon() 进行设置。
时间戳:用于显示通知发布了多久时间,由系统默认提供,可通过 setWhen() 自行设置,也可通过 setShowWhen(false) 将其隐藏。
大图标:通常仅用于联系人照片显示(位于通知内容右侧),通过 setLargeIcon() 进行设置。
通知标题:通过 setContentTitle() 进行设置。
通知内容:通过 setContentText() 进行设置。
需要注意的是,以上属性中的小图标、通知标题和通知内容为必须添加的属性。
第三步:调用 NotificationManager 的 notify() 方法创建通知。
以下是创建通知的示例:
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context,CHANNAL_ID)
.setContentTitle("这是通知标题")
.setContentText("这是通知内容")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.wechat)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),R.drawable.wechat));
//发送通知( id唯一,可用于更新通知时对应旧通知; 通过mBuilder.build()拿到notification对象 )
mNotificationManager.notify(1,mBuilder.build());
1.3 更新通知
更新通知就简单多了,只需要在创建过通知的前提下,重新编辑通知标题和内容,然后调用 notify() 的方法发送通知即可。以下是更新通知的示例:
mBuilder.setContentTitle("你更新了通知标题");
mBuilder.setContentText("你更新了通知内容");
mNotificationManager.notify(1,mBuilder.build());
1.4 设置通知的点击事件
设置通知的点击事件需要用到一个叫 PendingIntent 的类,学习过 Intent (意图)的人对它可能有点眼熟。没错,它和 Intent 一样,都能够执行某些动作,包括启动活动、服务,或是发送广播等。 但它有和 Intent 也有些不同之处:Intent 倾向于立即去执行某个动作,而 PengdingIntent 更倾向于在某个合适的时机去执行某个动作,即延迟执行 Intent。以下是设置通知的点击事件实现步骤:
(1)获取 PengdingIntent 实例对象
通过调用 PendingIntent 类的 getActivity()、getBroadcast() 或 getService() 其中一个方法获取,这些方法有4个参数,
- 参数1:Context
- 参数2:一般填0
- 参数3:Intent 对象,用于构建意图
- 参数4:FLAG_ONE_SHORT、FLAG_ONE_CREATE、FLAG_CANCEL_CURRENT和FLAG_UPDATE_CURRENT ,用于确定PengdingIntent的行为,一般填0
(2)调用通知构造器的 setContentIntent() 的方法设置点击事件。
(3)设置点击后通知自动消失的功能
此外,我们一般希望在点击通知后,通知自动消失。这个功能可以通过调用通知构造器的 setAutoCancel() 方法实现,它接收一个布尔类型的参数,这里传入一个 true 即可。以下是设置点击事件的示例:
ntent intent = new Intent(context, NotificationActivity.class);
PendingIntent pi = PendingIntent.getActivity(context, 0 ,intent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat
.Builder(context, CHANNEL_ID)
……
.setContentIntent(pi)
.setAutoCancel(true);
1.5 通知内容的显示技巧
短内容通知:通过 setContentText() 方法设置,它只会显示一行文字,再多的话会用省略号省略。
长内容通知:通过 setStyle(new NotificationCompat.BigTextStyle().bigText()) 方法设置,它可以显示多行文字。
图片通知:通过 setStyle(new NotificationCompat.BigPictureStyle() .bigPicture(BitmapFactory.decodeResource(getResources(),R.drawable.apple))) 方法设置,它可以在通知时显示一张图片。
如果在同一个通知构造器里设置上述两个以上通知内容的方法,最后一个设置的会把前面所有的内容覆盖。
2 实现代码示例
2.1 工具类
public class Utils {
private static NotificationManager mNotificationManager;
private static NotificationCompat.Builder mBuilder;
/**
* 发送通知
*/
public static void sendNotification(Context context){
//设置 channel_id
final String CHANNAL_ID = "chat";
//获取 PendingIntent 对象,NotificationActivity是另一个活动
Intent intent = new Intent(context, NotificationActivity.class);
PendingIntent pi = PendingIntent.getActivity(context, 0 ,intent, 0);
//获取系统通知服务
mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
//Android 8.0开始要设置通知渠道
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel channel = new NotificationChannel(CHANNAL_ID,
"chat message",NotificationManager.IMPORTANCE_DEFAULT);
mNotificationManager.createNotificationChannel(channel);
}
//创建通知
mBuilder = new NotificationCompat.Builder(context,CHANNAL_ID)
.setContentTitle("这是通知标题")
.setContentText("这是通知内容")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.wechat)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),R.drawable.wechat))
.setContentIntent(pi)
.setAutoCancel(true);
//发送通知( id唯一,可用于更新通知时对应旧通知; 通过mBuilder.build()拿到notification对象 )
mNotificationManager.notify(1,mBuilder.build());
}
/**
* 更新通知
*/
public static void updateNotification(){
mBuilder.setContentTitle("你更新了通知标题");
mBuilder.setContentText("你更新了通知内容");
mNotificationManager.notify(1,mBuilder.build());
}
}
2.2 布局文件
布局这里添加发送和更新通知的两个按钮,其中更新按钮默认不显示,即 visibility="gone"
<?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="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
<Button
android:id="@+id/bt_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="send"
android:textAllCaps="false"/>
<Button
android:id="@+id/bt_update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:text="update"
android:textAllCaps="false"/>
</LinearLayout>
2.3 主活动
活动这里分别为发送和更新通知按钮的点击事件实现对应的功能,其中设置点击发送按钮后才显示更新按钮,即 setVisibility(View.VISIBLE) ,因为未发送通知就点击更新会报错。
public class MainActivity extends AppCompatActivity {
private Button sendNotification;
private Button updateNotification;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendNotification = (Button)findViewById(R.id.bt_send);
updateNotification = (Button)findViewById(R.id.bt_update);
sendNotification.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Utils.sendNotification(MainActivity.this);
//显示更新按钮
updateNotification.setVisibility(View.VISIBLE);
}
});
updateNotification.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Utils.updateNotification();
}
});
}
}