Android通知频道,通知点

In this tutorial, we’ll be looking into how the introduction of Android Oreo has brought a drastic change in the Notifications. You aren’t far away from getting an Android Oreo update. Before you do get, let’s look into the working of notifications and what you need to change and adapt as Android Developer.

在本教程中,我们将研究Android Oreo的引入如何在Notifications中带来了翻天覆地的变化。 您离Android Oreo更新不远。 在获得通知之前,让我们研究一下通知的工作以及需要更改和适应作为Android Developer的内容。

Android通知频道 (Android Notification Channel)

We have discussed and implemented Notification, here and here.

我们已经在这里这里讨论并实现了Notification

With the introduction of Android Oreo, Google has strived the Notifications system more user-friendly. Android Oreo has completely redesigned notifications. The power to receive the kinds of notifications has been given in the hands of the end users. The reason this all became possible is: Notification Channels.

android oreo notification channel

Notification Channels allow us to separate notifications into different groups/categories. Every channel would have a common functionality. It allows the user to customize their notification settings.

随着Android Oreo的推出,Google努力使Notifications系统更加用户友好。 Android Oreo完全重新设计了通知。 接收各种通知的权力已经在最终用户手中。 所有这一切成为可能的原因是: 通知渠道

通知渠道使我们可以将通知分为不同的组/类别。 每个通道将具有共同的功能。 它允许用户自定义其通知设置。

Thanks to this feature the user can do the following things from the Apps Settings:

借助此功能,用户可以从“应用程序设置”中执行以下操作:

  • Block notifications from a particular channel.

    阻止来自特定渠道的通知。
  • Set priority/silent on different notification channels.

    在不同的通知渠道上设置优先级/静音。

Without configuring Notification Channels, you cannot build notification for applications with Android API >=26. Notification Channels would be ignored for older applications with the Android API < 26.Let's get down to the creation part.

如果不配置通知通道,则无法为Android API> = 26的应用程序构建通知。 对于Android API <26的旧版应用程序,通知通道将被忽略。让我们进入创建部分。

建立通知频道 (Creating Notification Channel)

Following code creates a notification channel:

以下代码创建一个通知通道:

NotificationChannel notificationChannel = new NotificationChannel(channel_id , channel_name, NotificationManager.IMPORTANCE_HIGH);
                notificationChannel.enableLights(true);
                notificationChannel.enableVibration(true);
                notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(notificationChannel);

The NotificationChannel constructor requires us to specify the channel_id and channel_name strings. The Importance argument is an int which specifies the level of interruption by the notification. It can be one of the following values:

NotificationChannel构造函数要求我们指定channel_id和channel_name字符串。 重要性参数是一个整数,它指定通知的中断级别。 它可以是下列值之一:

  • IMPORTANCE_DEFAULT – Shows up in the system tray. Makes sound. Doesn’t visually pop up.

    IMPORTANCE_DEFAULT –显示在系统托盘中。 发出声音。 不会从视觉上弹出。
  • IMPORTANCE_HIGH – Visually pops up too.

    IMPORTANCE_HIGH –也在视觉上弹出。
  • IMPORTANCE_LOW – Shows in the tray. No pop up. No sound.

    IMPORTANCE_LOW –显示在托盘中。 没有弹出。 没有声音。
  • IMPORTANCE_NONE – Doesn’t show up. Kind of blocked notifications.

    IMPORTANCE_NONE-不显示。 阻止通知的种类。

Besides the public methods specified above, following are some handy methods that come with NotificationChannels.

除了上面指定的公共方法外,以下是NotificationChannels附带的一些便捷方法。

  • setGroup()/getGroup() – Setters and getters for the channel. We’ll look at this later.

    setGroup() / getGroup() –通道的设置器和获取器。 我们待会再看。
  • ?

  • setBypassDnd()?- Set the INTERRUPTION_PRIORITY_VALUE to bypass do not disturb.

    setBypassDnd() ?-将INTERRUPTION_PRIORITY_VALUE设置为不打扰。
  • canBypassDnd() – Check whether the notification channel can display notification in DND mode.

    canBypassDnd() –检查通知通道是否可以在DND模式下显示通知。
  • setLockScreenVisibility() – Set whether notifications from this channel should be displayed on the lock screen or not.

    setLockScreenVisibility() –设置是否应在锁定屏幕上显示此通道的通知。
  • canShowBadge() – Can show the badge/notification dot on the application icon.

    canShowBadge() –可以在应用程序图标上显示徽章/通知点。
  • getName()/getId() – Retrieve the channel name and id respectively.

    getName() / getId() –分别获取通道名称和ID。

Once the Notification Channel is created using createNotificationChannel(), every notification created from it will have common properties unless modified.

使用createNotificationChannel()创建通知通道后,从其中创建的每个通知都将具有公共属性,除非进行了修改。

Note: The above code snippet is valid for Android version Oreo and above only. Hence it must be enclosed in the following condition.

注意:上面的代码段仅对Android版本Oreo及更高版本有效。 因此,必须将其放在以下条件中。

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
}

创建通知 (Creating a Notification)

The following code snippet creates a Notification from NotificationChannel.

以下代码段从NotificationChannel创建一个Notification。

NotificationCompat.Builder notification = new NotificationCompat.Builder(this, "channel_id")
                            .setContentTitle("Test Title")
                            .setContentText("Test Message")
                            .setSmallIcon(R.mipmap.ic_launcher);

notificationManager.notify(1, notification.build());

From Android Oreo, it is mandatory to specify the NotificationChannel id in the Builder constructor itself.

在Android Oreo中,必须在Builder构造函数本身中指定NotificationChannel id

读取和删除通知通道 (Reading And Deleting Notification Channels)

To retrieve a notification channel we can call the method getNotificationChannel() on the NotificationManager.
We need to pass the channel_id of the relevant channel.
Also, to retrieve a list of all NotificationChannels we can invoke the method getNotificationChannels().

要检索通知通道,我们可以在NotificationManager上调用方法getNotificationChannel()。
我们需要传递相关频道的channel_id。
同样,要检索所有NotificationChannel的列表,我们可以调用方法getNotificationChannels()。

List<NotificationChannel> notificationChannels = notificationManager.getNotificationChannels();

Deleting a NotificationChannel
To delete a NotificationChannel, the following snippet is used.

删除NotificationChannel
要删除NotificationChannel,请使用以下代码段。

notificationManager.deleteNotificationChannel("channel_id");

通知渠道组 (Notification Channel Groups)

A NotificationChannelGroup is used to created different categories for NotificationChannels.
The same NotificationChannels can be used in different circumstances depending on the group from which they are invoked.
You can have two groups named Hourly, Daily. All the Notification Channels would be present in both the groups. It’s your choice from which group you want to use the channel to create Notifications.

NotificationChannelGroup用于为NotificationChannel创建不同的类别。
相同的NotificationChannels可以在不同的情况下使用,具体取决于调用它们的组。
您可以有两个名为“每小时”,“每日”的组。 所有通知通道都将出现在两个组中。 您可以从哪个组中选择使用该通道来创建通知。

创建NotificationChannelGroup (Creating NotificationChannelGroup)

Following is one way to create NotificationChannelGroups.

以下是创建NotificationChannelGroups的一种方法。

List<NotificationChannelGroup> list = new ArrayList<>();
            list.add(new NotificationChannelGroup(group_id_1, group_name_2));
            list.add(new NotificationChannelGroup(group_id_2, group_name_2));

            notificationManager.createNotificationChannelGroups(list);

You need to set the group_id and group_name.
Furthermore, you need to set the group on the NotificationChannel too using setGroup(). Pass in the group_id in the setGroup() method.

您需要设置group_id和group_name。
此外,您还需要使用setGroup()在NotificationChannel上设置组。 在setGroup()方法中传递group_id。

通过设置修改通知 (Modifying Notification from Settings)

The end user can modify the Notification Channel from the Settings.
Settings | Apps | App Name | App Notifications

最终用户可以从“设置”中修改“通知通道”。
设置| 应用程式| 应用名称| 应用程序提醒

Alternatively we can redirect them from the app itself using Intents.

另外,我们可以使用Intents从应用程序本身重定向它们。

Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_CHANNEL_ID, notificationChannel.getId());
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
startActivity(intent);

We pass the channel id and app package name. This specifically opens the particular channel ID.

我们传递频道ID和应用程序包名称。 这专门打开了特定的通道ID。

Let’s create a basic application with the use cases of NotificationChannel and NotificationChannelGroup

让我们使用NotificationChannel和NotificationChannelGroup的用例创建一个基本应用程序

项目结构 (Project Structure)

In this application, we’ll be using RadioButton to change between the groups and Spinners to choose the current NotificationChannel. The EditText would be used to set the body of the notification.

在此应用程序中,我们将使用RadioButton在组之间切换,并使用Spinners选择当前的NotificationChannel。 EditText将用于设置通知的正文。

Android NotificationChannel代码 (Android NotificationChannel Code)

The code for the activity_main.xml layout file is given below.

下面给出了activity_main.xml布局文件的代码。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Choose the group for the channel"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:padding="16dp"
        app:layout_constraintBottom_toTopOf="@+id/radioGroup"/>

    <RadioGroup
        android:id="@+id/radioGroup"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="8dp"
        android:orientation="horizontal"
        android:weightSum="2"
        app:layout_constraintBottom_toTopOf="@+id/spinner"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">

        <RadioButton
            android:id="@+id/radioButton1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="First Type"
            android:layout_weight="1"
            android:textSize="18sp" />

        <RadioButton
            android:id="@+id/radioButton2"
            android:layout_width="wrap_content"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="Second Type"
            android:textSize="18sp" />
    </RadioGroup>


    <Spinner
        android:id="@+id/spinner"
        style="@style/Widget.AppCompat.Spinner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="8dp"
        app:layout_constraintBottom_toTopOf="@+id/inContent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />


    <EditText
        android:id="@+id/inContent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="8dp"
        android:hint="Enter message"
        app:layout_constraintBottom_toTopOf="@+id/btnNotification"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />


    <Button
        android:id="@+id/btnNotification"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Create New Notification"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


</android.support.constraint.ConstraintLayout>

The code for the MainActivity.java class is given below.

下面给出MainActivity.java class的代码。

package com.journaldev.notificationchannels;

import android.app.AlertDialog;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {


    List<String> data = new ArrayList<>();

    int notifier_counter = 0;
    NotificationManager notificationManager;
    RadioButton radioButtonFirst;
    RadioButton radioButtonSecond;
    RadioGroup radioGroup;
    EditText editText;
    Button btnNotification;
    Spinner spinner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initViews();
        notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);


        data.add("Bitcoin");
        data.add("Ethereum");
        data.add("Litecoin");
        data.add("Ripple");

        createNotificationGroups();
        createNotificationChannels();


        ArrayAdapter<String> dataAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, data);
        dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(dataAdapter);
        spinner.setOnItemSelectedListener(this);


        radioGroup.check(R.id.radioButton1);


        btnNotification.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (editText.getText().toString().length() > 0) {
                    String channel_id = "";
                    String group_id = "";
                    PendingIntent contentIntent = PendingIntent.getActivity(MainActivity.this, 0, new Intent(MainActivity.this, MainActivity.class), 0);

                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {


                        RadioButton radioButton = findViewById(radioGroup.getCheckedRadioButtonId());
                        group_id = radioButton.getText().toString();
                        channel_id = notificationManager.getNotificationChannel(spinner.getSelectedItem().toString() + "_" + group_id).getId();
                        contentIntent = PendingIntent.getActivity(MainActivity.this, 0, new Intent(MainActivity.this, MainActivity.class).putExtra("importance", notificationManager.getNotificationChannel(channel_id).getImportance()).putExtra("channel_id", channel_id), PendingIntent.FLAG_UPDATE_CURRENT);
                    }


                    NotificationCompat.Builder notification = new NotificationCompat.Builder(MainActivity.this, channel_id)
                            .setContentTitle(spinner.getSelectedItem().toString())
                            .setContentText(editText.getText().toString())
                            .setGroup(group_id)
                            .setContentIntent(contentIntent)
                            .setSmallIcon(R.mipmap.ic_launcher);

                    notifier_counter++;
                    notificationManager.notify(notifier_counter, notification.build());
                } else {
                    Toast.makeText(getApplicationContext(), "Please enter something in EditText", Toast.LENGTH_LONG).show();
                }
            }
        });
    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {

    }

    private void initViews() {
        spinner = findViewById(R.id.spinner);
        btnNotification = findViewById(R.id.btnNotification);
        editText = findViewById(R.id.inContent);
        radioGroup = findViewById(R.id.radioGroup);
        radioButtonFirst = findViewById(R.id.radioButton1);
        radioButtonSecond = findViewById(R.id.radioButton2);
    }

    private void createNotificationGroups() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            List<NotificationChannelGroup> list = new ArrayList<>();
            list.add(new NotificationChannelGroup(radioButtonFirst.getText().toString(), radioButtonFirst.getText()));
            list.add(new NotificationChannelGroup(radioButtonSecond.getText().toString(), radioButtonSecond.getText()));

            notificationManager.createNotificationChannelGroups(list);

        }
    }


    private void createNotificationChannels() {
        for (String s : data) {
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {

                NotificationChannel notificationChannel = new NotificationChannel(s + "_" + radioButtonFirst.getText().toString(), s, NotificationManager.IMPORTANCE_HIGH);
                notificationChannel.enableLights(true);
                notificationChannel.enableVibration(true);
                notificationChannel.setGroup(radioButtonFirst.getText().toString());
                notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});

                NotificationChannel notificationChannel2 = new NotificationChannel(s + "_" + radioButtonSecond.getText().toString(), s, NotificationManager.IMPORTANCE_NONE);
                notificationChannel2.enableLights(true);
                notificationChannel2.enableVibration(true);
                notificationChannel2.setGroup(radioButtonSecond.getText().toString());
                notificationChannel2.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});


                if (notificationManager != null) {
                    notificationManager.createNotificationChannel(notificationChannel);
                    notificationManager.createNotificationChannel(notificationChannel2);
                }
            }
        }
    }


    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            final Bundle bundle = intent.getExtras();
            int importance = -1;
            if (bundle != null) {
                importance = bundle.getInt("importance");
            }
            if (importance != -1) {

                AlertDialog.Builder alert = new AlertDialog.Builder(this);
                alert.setMessage("Goto settings to change the Notification channel")
                        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                updateNotificationSettings(bundle.getString("channel_id"));
                            }
                        }).setNegativeButton("CANCEL", null)
                        .show();


            }

        }


    }

    private void updateNotificationSettings(String channel_id) {
        Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
        intent.putExtra(Settings.EXTRA_CHANNEL_ID, channel_id);
        intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
        startActivity(intent);
    }


}

In the above code, we begin by creating the NotificationChannelGroup and NotificationChannel for the RadioButtons and Spinners respectively.

在上面的代码中,我们首先分别为RadioButtons和Spinners创建NotificationChannelGroup和NotificationChannel。

The channel_id is appended with the group_id in order to know which group does the channel belong to.

channel_id附加有group_id ,以便知道该通道属于哪个组。

On Button click we create the notification based on which radio button and spinners were selected and retrieve the channel_id and group_id accordingly.

在“单击按钮”上,我们基于选择了哪个单选按钮和微调框来创建通知,并相应地检索channel_id和group_id。

For this example, by default, we’ve blocked notifications from all the channels belonging to second group.
(Enable that channel from the settings to view those notifications).

对于此示例,默认情况下,我们已阻止来自属于第二组的所有渠道的通知。
(从设置中启用该频道以查看那些通知)。

On a notification click, we show up a dialog that allows the user to goto the settings to change the current NotificationChannel settings.

单击通知后,我们将显示一个对话框,允许用户转到设置以更改当前的NotificationChannel设置。

On Notification click launches the same activity. Hence in the Manifest file we need to set android:launchMode="singleTop" in the activity tag.

在通知上,单击启动相同的活动。 因此,在清单文件中,我们需要在活动标记中设置android:launchMode="singleTop"

输出量 (Output)

The output of the above application in action is given below.

下面给出了上面应用程序的输出。

Long Press on a Notification, it allows us to change the current channel settings with the slider.

长按通知,它可以让我们使用滑块更改当前频道设置。

The All categories option that’s visible lets us view all types of channels and groups.

可见的“所有类别”选项使我们可以查看所有类型的渠道和群组。

Do take note that we’d toggled a few channels from the first and second group. It lead to blocked notifications in the first group and default notifications in the second.

请注意,我们从第一组和第二组切换了几个通道。 它导致第一个组中的通知被阻止,第二个组中的默认通知。

Android通知点 (Android Notification Dots)

Notification Dots/Badges are displayed on the app icon if there are unread notifications.

如果有未读的通知,则通知点/徽章将显示在应用程序图标上。

We can use the method setShowBage(boolean) on the notification to display/hide the dot for the particular channel.

我们可以在通知中使用setShowBage(boolean)方法来显示/隐藏特定频道的点。

Thanks to Notification Dots, long pressing the app icon can now display/cancel the pending notifications too as shown below.

借助通知点,长按应用程序图标现在也可以显示/取消待处理的通知,如下所示。

Do note that the count for the pending notifications is displayed in the Notification Dot menu too.

请注意,待处理通知的计数也显示在“通知点”菜单中。

This brings an end to this tutorial. You can download the final Android NotificationChannels Project from the link below.

本教程到此结束。 您可以从下面的链接下载最终的Android NotificationChannels项目

翻译自: https://www.journaldev.com/19421/android-notification-channel-dots

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值