Android一些基础-08-一个简单的通知

通知

通知为应用在未运行或处于后台时向用户传达消息提供了一种方式。例如,消息应用可能会发出通知,让用户知道有来自联系人的新消息到达。通知可分为本地通知和远程通知。本地通知由应用本身在其运行的设备上触发。另一方面,远程通知由远程服务器发起并传送到设备以供呈现给用户。通知出现在从屏幕状态栏下拉的通知抽屉中,每个通知可以包括诸如打开发送通知的应用的按钮等操作。Android 还支持直接回复通知,这一功能允许用户在通知面板内输入并提交对通知的响应。

当在 Android 设备上发起通知时,它会以图标的形式出现在状态栏中。

要查看通知,用户从状态栏开始向下滑动,以拉下通知抽屉

Android 8 及更高版本还支持通知点,当有通知等待用户查看时,这些通知点会出现在应用启动器图标上。一个典型的通知只会显示一条消息,当被点击时,会启动负责发出该通知的应用。通知也可能包含操作按钮,当被点击时,这些按钮会执行特定于相应应用的任务。例如,一个包含两个操作按钮的通知,允许用户删除或保存一条传入的消息。

在应用能够发送通知之前,它必须首先创建一个通知渠道。通知渠道由一个在应用内唯一标识该渠道的 ID、一个渠道名称和一个渠道描述组成(其中只有后两者会被用户看到)。通过配置 NotificationChannel 实例,然后将该对象传递给 NotificationManager 类的 createNotificationChannel()方法来创建渠道。

一个本地通知的简单实现

1、创建发送通知的Activity 第一步:

创建通知频道,配置通知频道的相关信息,Id、name和重要程度

light:表示呼吸灯相关

enableVibration:表示震动相关

100ms震动 → 200ms停 → 300ms震动...

java 复制代码
protected void createNotificationChannel(String id, String name, String description) {  
    int importance = NotificationManager.IMPORTANCE_LOW;  
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {  
        NotificationChannel channel = new NotificationChannel(id, name, importance);  
        channel.setDescription(description);  
        channel.enableLights(true);  
        channel.setLightColor(Color.RED);  
        channel.enableVibration(true);
        channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});  
        notificationManager.createNotificationChannel(channel);  
    }  
}

第二步:

创建请求权限方法

通过ContextCompat.checkSelfPermission()方法检测当前权限状态

返回值为PackageManager.PERMISSION_GRANTED(已授权)或PERMISSION_DENIED(未授权)

如果未授权,则调用ActivityCompat.requestPermissions()方法进行权限的请求
ActivityCompat.requestPermissions()接收三个参数:

第一个参数是Activity实例(否则无法弹出系统权限对话框)

第二个参数是权限字符串数组(支持批量请求多个权限)

第三个参数是自定义请求码,用于在回调中识别请求来源

java 复制代码
protected void requestPermission(String permissionType, int requestCode) {  
    int permission = ContextCompat.checkSelfPermission(context, permissionType);  
  
    if (permission != PackageManager.PERMISSION_GRANTED) {  
        ActivityCompat.requestPermissions(context, new String[]{permissionType}, requestCode);  
    }  
}

第三步:

重载请求权限方法

请求权限不通过进行提示

java 复制代码
@Override  
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {  
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);  
    if (requestCode == NOTIFICATION_REQUEST_CODE) {  
        if (grantResults.length == 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {  
            // 权限被拒绝  
            Toast.makeText(context, "需要通知权限", Toast.LENGTH_SHORT).show();  
        }  
    }  
}

第五步:

创建发送通知方法

1、通知唯一标识符,用于后续更新或取消通知

2、创建跳转 Intent(目标为你的通知要打开跳转页面的Activity)

3、创建延迟 Intent(用于用户点击后启动Activity)

4、创建动作,设置动作的属性

5、设置通知频道Id

6、创建通知对象

7、通过Manager发送通知

java 复制代码
private void sendNotification() {
    // 1. 通知唯一标识符,用于后续更新或取消通知
    int notificationID = 101;

    // 2. 创建跳转意图(目标为ResultActivity)
    Intent resultIntent = new Intent(context, ResultActivity.class);
    
    // 3. 创建延迟意图(用于用户点击后启动Activity)
    // FLAG_UPDATE_CURRENT:如果已存在则更新内容
    // FLAG_IMMUTABLE:Android 12+要求显式声明不可变标志
    PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, 
        resultIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

    // 4. 创建通知动作按钮(需Android 4.1+)
    NotificationCompat.Action action = new NotificationCompat.Action.Builder(
            R.drawable.ic_launcher_foreground, // 动作图标
            "查看",                           // 动作文本
            resultPendingIntent               // 点击动作的意图
    ).build();

    // 5. 通知渠道ID(必须与创建的渠道ID一致,Android 8.0+必须配置)
    String channelId = "com.greenfred.realNews";

    // 6. 构建通知对象
    NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId)
            .setContentTitle("号外号外")        // 主标题(状态栏显示)
            .setContentText("今天是个好日子")    // 正文内容
            .setSmallIcon(R.drawable.ic_launcher_foreground) // 必须设置的小图标(纯alpha通道)
            .setPriority(NotificationCompat.PRIORITY_HIGH)  // 设置优先级(Android7.1及以下有效)
            .setContentIntent(resultPendingIntent)  // 设置主内容点击意图
            .setAutoCancel(true)         // 点击后自动移除通知
            .addAction(action)            // 添加动作按钮(最多显示3个)
            .setChannelId(channelId);     // 显式设置渠道ID(兼容性处理)
            
    Notification notification = builder.build();
    
    // 7. 发送通知(需确保已创建通知渠道)
    notificationManager.notify(notificationID, notification);
}

完整代码如下

java 复制代码
package com.example.basepractice.base.notification;  
  
import android.app.Notification;  
import android.app.NotificationChannel;  
import android.app.NotificationManager;  
import android.app.PendingIntent;  
import android.content.Intent;  
import android.content.pm.PackageManager;  
import android.graphics.Color;  
import android.os.Build;  
import android.os.Bundle;  
import android.view.View;  
import android.widget.Button;  
import android.widget.TextView;  
import android.widget.Toast;  
  
import androidx.activity.EdgeToEdge;  
import androidx.appcompat.app.AppCompatActivity;  
import androidx.core.app.ActivityCompat;  
import androidx.core.app.NotificationCompat;  
import androidx.core.content.ContextCompat;  
import androidx.core.graphics.Insets;  
import androidx.core.view.ViewCompat;  
import androidx.core.view.WindowInsetsCompat;  
  
import com.example.basepractice.R;  
import com.example.basepractice.baseUI.basic.BasicActivity;  
  
public class NotificationSendActivity extends BasicActivity {  
    private Button backButton;  
  
    private Button sendNotifyButton;  
  
    NotificationManager notificationManager;  
  
    private static final int NOTIFICATION_REQUEST_CODE = 101;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        EdgeToEdge.enable(this);  
        setContentView(R.layout.activity_notification_send);  
        setupUI();  
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);  
        createNotificationChannel("com.greenfred.realNews", "超级真新闻", "爱信不信");  
        requestPermission(android.Manifest.permission.POST_NOTIFICATIONS, NOTIFICATION_REQUEST_CODE);  
    }  
  
    private void sendNotification() {  
  
        int notificationID = 101;  
  
        Intent resultIntent = new Intent(context, ResultActivity.class);  
  
        PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);  
        String channelId = "com.greenfred.realNews";  
  
        NotificationCompat.Action action = new NotificationCompat.Action.Builder(  
                R.drawable.ic_launcher_foreground,  
                "查看",  
                resultPendingIntent  
        ).build();  
  
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId)  
                .setContentTitle("号外号外")  
                .setContentText("今天是个好日子")  
                .setSmallIcon(R.drawable.ic_launcher_foreground)  
                .setPriority(NotificationCompat.PRIORITY_HIGH)  
                .setContentIntent(resultPendingIntent)  
                .setAutoCancel(true)  
                .addAction(action)  
                .setChannelId(channelId);  
  
        Notification notification = builder.build();  
        notificationManager.notify(notificationID, notification);  
    }  
  
    @Override  
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {  
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);  
        if (requestCode == NOTIFICATION_REQUEST_CODE) {  
            if (grantResults.length == 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {  
                // 权限被拒绝  
                Toast.makeText(context, "需要通知权限", Toast.LENGTH_SHORT).show();  
            }  
        }  
    }  
  
    protected void requestPermission(String permissionType, int requestCode) {  
        int permission = ContextCompat.checkSelfPermission(context, permissionType);  
  
        if (permission != PackageManager.PERMISSION_GRANTED) {  
            ActivityCompat.requestPermissions(context, new String[]{permissionType}, requestCode);  
        }  
    }  
  
    protected void createNotificationChannel(String id, String name, String description) {  
        int importance = NotificationManager.IMPORTANCE_LOW;  
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {  
            NotificationChannel channel = new NotificationChannel(id, name, importance);  
            channel.setDescription(description);  
            channel.enableLights(true);  
            channel.setLightColor(Color.RED);  
            channel.enableVibration(true);  
            channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});  
            notificationManager.createNotificationChannel(channel);  
        }  
    }  
  
    private void setupUI() {  
        backButton = findViewById(R.id.back);  
        backButton.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                finish();  
            }  
        });  
        sendNotifyButton = findViewById(R.id.notify_button);  
        sendNotifyButton.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                sendNotification();  
            }  
        });  
    }  
}

通知的跳转的页面

java 复制代码
package com.example.basepractice.base.notification;  
  
import android.os.Bundle;  
  
import androidx.activity.EdgeToEdge;  
import androidx.appcompat.app.AppCompatActivity;  
import androidx.core.graphics.Insets;  
import androidx.core.view.ViewCompat;  
import androidx.core.view.WindowInsetsCompat;  
  
import com.example.basepractice.R;  
import com.example.basepractice.baseUI.basic.BasicActivity;  
  
public class ResultActivity extends BasicActivity {  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        EdgeToEdge.enable(this);  
        setContentView(R.layout.activity_result);  
  
    }  
}
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:id="@+id/main"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    tools:context=".base.notification.ResultActivity">  
    <TextView  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        app:layout_constraintTop_toTopOf="parent"  
        app:layout_constraintStart_toStartOf="parent"  
        app:layout_constraintEnd_toEndOf="parent"  
        app:layout_constraintBottom_toBottomOf="parent"  
        android:text="今天是个好日子"  
        >  
  
    </TextView>  
</androidx.constraintlayout.widget.ConstraintLayout>

运行效果

相关推荐
xianrenli383 小时前
android特许权限调试
android
*拯6 小时前
Uniapp Android/IOS 获取手机通讯录
android·ios·uni-app
天天打码8 小时前
Lynx-字节跳动跨平台框架多端兼容Android, iOS, Web 原生渲染
android·前端·javascript·ios
lilili啊啊啊10 小时前
iOS safari和android chrome开启网页调试与检查器的方法
android·ios·safari
Blue.ztl12 小时前
菜鸟之路day31一一MySQL之多表设计
android·数据库·mysql
练习本16 小时前
Android系统架构模式分析
android·java·架构·系统架构
每次的天空21 小时前
Kotlin 内联函数深度解析:从源码到实践优化
android·开发语言·kotlin
练习本21 小时前
Android MVC架构的现代化改造:构建清晰单向数据流
android·架构·mvc
早上好啊! 树哥21 小时前
android studio开发:设置屏幕朝向为竖屏,强制应用的包体始终以竖屏(纵向)展示
android·ide·android studio
YY_pdd1 天前
使用go开发安卓程序
android·golang