Java Android O-通知通道和通知兼容性
我无法改变这种感觉:再一次,Android开发人员想出了一些新的东西,让每个人都不知道他们认为该功能是如何使用的 我说的是Android O中的通知通道 多年来,我一直在使用兼容性支持库来避免处理特定的平台细节。即:Java Android O-通知通道和通知兼容性,java,android-notifications,android-support-library,android-8.0-oreo,Java,Android Notifications,Android Support Library,Android 8.0 Oreo,我无法改变这种感觉:再一次,Android开发人员想出了一些新的东西,让每个人都不知道他们认为该功能是如何使用的 我说的是Android O中的通知通道 多年来,我一直在使用兼容性支持库来避免处理特定的平台细节。即:NotificationCompat 现在,Builder要求我提供一个通知频道id,这很好,但完全让我自己创建这样一个频道。我找不到任何compat支持创建频道。我也无法找到一种合理的方法在正确的位置创建它们 这些文件只是简单地说明应该在“某个地方”和“在发出通知时可能不这样做”。
NotificationCompat
现在,
Builder
要求我提供一个通知频道id,这很好,但完全让我自己创建这样一个频道。我找不到任何compat支持创建频道。我也无法找到一种合理的方法在正确的位置创建它们
这些文件只是简单地说明应该在“某个地方”和“在发出通知时可能不这样做”。但我到底该怎么办呢?我讨厌为简单的任务编写特定于版本的东西——这就是我使用compat库的原因
有人对如何处理这件事有什么建议吗?每当我想要显示通知时,创建通知是否“昂贵”?这并不像你想象的那么昂贵! 您只需创建一个通知通道并将其绑定到通知 您可以通过两种方式解决此问题,但对于这两种方式,您都需要创建具有特定通道id的通知通道
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String id = "my_channel_01";
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = new NotificationChannel(id, name,importance);
mChannel.enableLights(true);
mNotificationManager.createNotificationChannel(mChannel);
第一种方法是在构造函数中设置通知通道:
Notification notification = new Notification.Builder(MainActivity.this , id).setContentTitle("Title");
mNotificationManager.notify("your_notification_id", notification);
第二种方法是通过notification.Builder.setChannelId()设置通道
希望这有帮助这是我在Android O上生成通知并保持向后兼容性的解决方案:
String idChannel = "my_channel_01";
Intent mainIntent;
mainIntent = new Intent(context, LauncherActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, mainIntent, 0);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel mChannel = null;
// The id of the channel.
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, null);
builder.setContentTitle(context.getString(R.string.app_name))
.setSmallIcon(getNotificationIcon())
.setContentIntent(pendingIntent)
.setContentText(context.getString(R.string.alarm_notification) + ManagementDate.getIstance().hourFormat.format(getAlarm(context, 0)));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mChannel = new NotificationChannel(idChannel, context.getString(R.string.app_name), importance);
// Configure the notification channel.
mChannel.setDescription(context.getString(R.string.alarm_notification));
mChannel.enableLights(true);
mChannel.setLightColor(Color.RED);
mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
mNotificationManager.createNotificationChannel(mChannel);
} else {
builder.setContentTitle(context.getString(R.string.app_name))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setColor(ContextCompat.getColor(context, R.color.transparent))
.setVibrate(new long[]{100, 250})
.setLights(Color.YELLOW, 500, 5000)
.setAutoCancel(true);
}
mNotificationManager.notify(1, builder.build());
这里有一个替代解决方案,它使用反射来创建通知通道,这样您就可以将
compileSdkVersion
设置为低于26
private void createNotificationChannel(NotificationManager notificationManager) {
// Channel details
String channelId = "myChannelId";
String channelName = "Notifications";
// Channel importance (3 means default importance)
int channelImportance = 3;
try {
// Get NotificationChannel class via reflection (only available on devices running Android O or newer)
Class notificationChannelClass = Class.forName("android.app.NotificationChannel");
// Get NotificationChannel constructor
Constructor<?> notificationChannelConstructor = notificationChannelClass.getDeclaredConstructor(String.class, CharSequence.class, int.class);
// Instantiate new notification channel
Object notificationChannel = notificationChannelConstructor.newInstance(channelId, channelName, channelImportance);
// Get notification channel creation method via reflection
Method createNotificationChannelMethod = notificationManager.getClass().getDeclaredMethod("createNotificationChannel", notificationChannelClass);
// Invoke method on NotificationManager, passing in the channel object
createNotificationChannelMethod.invoke(notificationManager, notificationChannel);
// Log success to console
Log.d("MyApp", "Notification channel created successfully");
}
catch (Exception exc) {
// Log exception to console
Log.e("MyApp", "Creating notification channel failed", exc);
}
}
注意:您需要在build.gradle
中将appcompat-v7
库更新为版本26.x.x
:
compile 'com.android.support:appcompat-v7:26.1.0'
如果您的通知代码每次都具有相同的结构,那么您应该创建一个静态方法,并传递所有您想要的内容,并将检查API级别的代码放入此方法中。使用通知通道非常简单 NotificationChannel实际上将多个通知分组到多个通道中。它基本上为用户提供了更多的通知行为控制。有关通知通道及其实现的更多信息,请访问 创建通知通道
// This is the Notification Channel ID. More about this in the next section
public static final String NOTIFICATION_CHANNEL_ID="channel_id";
//User visible Channel Name
public static final String CHANNEL_NAME="Notification Channel";
// Importance applicable to all the notifications in this Channel
int importance=NotificationManager.IMPORTANCE_DEFAULT;
//Notification channel should only be created for devices running Android 26
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, CHANNEL_NAME, importance);
//Boolean value to set if lights are enabled for Notifications from this Channel
notificationChannel.enableLights(true);
//Boolean value to set if vibration is enabled for Notifications from this Channel
notificationChannel.enableVibration(true);
//Sets the color of Notification Light
notificationChannel.setLightColor(Color.GREEN);
//Set the vibration pattern for notifications. Pattern is in milliseconds with the format {delay,play,sleep,play,sleep...}
notificationChannel.setVibrationPattern(new long[]{500,500,500,500,500});
//Sets whether notifications from these Channel should be visible on Lockscreen or not
notificationChannel.setLockscreenVisibility(
Notification.VISIBILITY_PUBLIC);
}
// Creating the Channel
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(notificationChannel);
现在,在创建通知时,只需将通道ID传递给通知生成器构造函数,如下所示
//We pass the unique channel id as the second parameter in the constructor
NotificationCompat.Builder notificationCompatBuilder=new NotificationCompat.Builder(this,NOTIFICATION_CHANNEL_ID);
//Title for your notification
notificationCompatBuilder.setContentTitle("This is title");
//Subtext for your notification
notificationCompatBuilder.setContentText("This is subtext");
//Small Icon for your notificatiom
notificationCompatBuilder.setSmallIcon(R.id.icon);
//Large Icon for your notification
notificationCompatBuilder.setLargeIcon( BitmapFactory.decodeResource(getResources(),R.id.icon));
notificationManager.notify( NOTIFICATION_ID,notificationCompatBuilder.build());
随着上述通知成为第一步中创建的通知通道的一部分,如果您希望支持以前版本的Android(
NotificationManager
包装起来,在NotificationHelper
中创建和构建Notification.Builder
实例,如下所示:
/**
* Helper class to manage notification channels, and create notifications.
* <p>
* Created by teocci.
*
* @author teocci@yandex.com on 2018-Oct-02
*/
public class NotificationHelper extends ContextWrapper
{
public static final String NOTIFICATION_CHANNEL_PRIMARY = "notification_channel_primary";
public static final int NOTIFICATION_ID_PRIMARY = 1100;
private NotificationManager manager;
/**
* Registers notification channels, which can be used later by individual notifications.
*
* @param ctx The application context
*/
public NotificationHelper(Context ctx)
{
super(ctx);
// For API 26+ create notification channels
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_PRIMARY,
getString(R.string.channel_name),
NotificationManager.IMPORTANCE_DEFAULT
);
channel.setLightColor(Color.BLUE);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
channel.setDescription(getString(R.string.channel_description));
getManager().createNotificationChannel(channel);
}
}
/**
* Cancel a previously shown notification. If it's transient, the view
* will be hidden. If it's persistent, it will be removed from the status
* bar.
*
* @param id The ID of the notification
*/
public void remove(int id){
manager.cancel(id);
}
/**
* Get a notification of type 1
* <p>
* Provide the builder rather than the notification it's self as useful for making notification
* changes.
*
* @return the builder as it keeps a reference to the notification (since API 24)
*/
public Notification getNotification()
{
return getNotification(getTitle(), getBody()).build();
}
/**
* Get a notification of type 1
* <p>
* Provide the builder rather than the notification it's self as useful for making notification
* changes.
*
* @param title the title of the notification
* @param body the body text for the notification
* @return the builder as it keeps a reference to the notification (since API 24)
*/
public Notification.Builder getNotification(String title, String body)
{
Notification.Builder builder = new Notification.Builder(getApplicationContext())
.setOngoing(true) // Persistent notification!
.setAutoCancel(true)
.setTicker(title)
.setContentTitle(title)
.setContentText(body)
.setSmallIcon(getSmallIcon());
// Set the Channel ID for Android O.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(NOTIFICATION_CHANNEL_PRIMARY); // Channel ID
}
return builder;
}
/**
* Send a notification.
*
* @param id The ID of the notification
* @param notification The notification object
*/
public void notify(int id, Notification.Builder notification)
{
getManager().notify(id, notification.build());
}
/**
* Get the notification manager.
* <p>
* Utility method as this helper works with it a lot.
*
* @return The system service NotificationManager
*/
private NotificationManager getManager()
{
if (manager == null) {
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
return manager;
}
/**
* Get the small icon for this app
*
* @return The small icon resource id
*/
private int getSmallIcon()
{
return R.drawable.ic_smart_audio_noti_icon;
}
/**
* Get the notification title for this app
*
* @return The notification title as string
*/
private String getTitle()
{
return getString(R.string.notification_title);
}
/**
* Get the notification content for this app
*
* @return The notification content as string
*/
private String getBody()
{
return getString(R.string.notification_content);
}
}
@Override
public void onCreate()
{
...
notificationHelper = new NotificationHelper(this);
notificationHelper.notify(NotificationHelper.NOTIFICATION_ID_PRIMARY, "App is running");
...
}
@Override
public void onDestroy()
{
notificationHelper.remove(NotificationHelper.NOTIFICATION_ID_PRIMARY)
}
“我也找不到一个合理的方法在正确的位置创建它们”——我会在你的应用程序第一次运行时创建,如果它们还不存在,我会根据需要懒洋洋地创建。“当我希望显示通知时,每次都创建频道是否“昂贵?”——每次创建相同的频道充其量是浪费,或者最坏的情况是为您提供N组频道,因为没有更新机制。“我找不到任何compat支持创建频道”--v26库处于测试阶段;也许他们会添加它。这是为了通知,而不是为了通知。如果我为应用程序设置了通知频道,是否可以获取我为特定应用程序更改的声音
URI
。借助渠道
/**
* Helper class to manage notification channels, and create notifications.
* <p>
* Created by teocci.
*
* @author teocci@yandex.com on 2018-Oct-02
*/
public class NotificationHelper extends ContextWrapper
{
public static final String NOTIFICATION_CHANNEL_PRIMARY = "notification_channel_primary";
public static final int NOTIFICATION_ID_PRIMARY = 1100;
private NotificationManager manager;
/**
* Registers notification channels, which can be used later by individual notifications.
*
* @param ctx The application context
*/
public NotificationHelper(Context ctx)
{
super(ctx);
// For API 26+ create notification channels
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_PRIMARY,
getString(R.string.channel_name),
NotificationManager.IMPORTANCE_DEFAULT
);
channel.setLightColor(Color.BLUE);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
channel.setDescription(getString(R.string.channel_description));
getManager().createNotificationChannel(channel);
}
}
/**
* Cancel a previously shown notification. If it's transient, the view
* will be hidden. If it's persistent, it will be removed from the status
* bar.
*
* @param id The ID of the notification
*/
public void remove(int id){
manager.cancel(id);
}
/**
* Get a notification of type 1
* <p>
* Provide the builder rather than the notification it's self as useful for making notification
* changes.
*
* @return the builder as it keeps a reference to the notification (since API 24)
*/
public Notification getNotification()
{
return getNotification(getTitle(), getBody()).build();
}
/**
* Get a notification of type 1
* <p>
* Provide the builder rather than the notification it's self as useful for making notification
* changes.
*
* @param title the title of the notification
* @param body the body text for the notification
* @return the builder as it keeps a reference to the notification (since API 24)
*/
public Notification.Builder getNotification(String title, String body)
{
Notification.Builder builder = new Notification.Builder(getApplicationContext())
.setOngoing(true) // Persistent notification!
.setAutoCancel(true)
.setTicker(title)
.setContentTitle(title)
.setContentText(body)
.setSmallIcon(getSmallIcon());
// Set the Channel ID for Android O.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(NOTIFICATION_CHANNEL_PRIMARY); // Channel ID
}
return builder;
}
/**
* Send a notification.
*
* @param id The ID of the notification
* @param notification The notification object
*/
public void notify(int id, Notification.Builder notification)
{
getManager().notify(id, notification.build());
}
/**
* Get the notification manager.
* <p>
* Utility method as this helper works with it a lot.
*
* @return The system service NotificationManager
*/
private NotificationManager getManager()
{
if (manager == null) {
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
return manager;
}
/**
* Get the small icon for this app
*
* @return The small icon resource id
*/
private int getSmallIcon()
{
return R.drawable.ic_smart_audio_noti_icon;
}
/**
* Get the notification title for this app
*
* @return The notification title as string
*/
private String getTitle()
{
return getString(R.string.notification_title);
}
/**
* Get the notification content for this app
*
* @return The notification content as string
*/
private String getBody()
{
return getString(R.string.notification_content);
}
}
@Override
public void onCreate()
{
...
notificationHelper = new NotificationHelper(this);
notificationHelper.notify(NotificationHelper.NOTIFICATION_ID_PRIMARY, "App is running");
...
}
@Override
public void onDestroy()
{
notificationHelper.remove(NotificationHelper.NOTIFICATION_ID_PRIMARY)
}