我无法改变这种感觉:再次,Android开发人员想出了一些新的东西,让所有人都不知道他们会如何看待这个功能。
我在谈论Android O中的通知频道。
多年来,我一直在使用兼容性支持库来避免处理特定的平台细节。即:NotificationCompat
。
现在,Builder
要求我提供一个通知通道ID,这很好,但完全不用我创建这样一个频道。我找不到任何compat支持创建频道。我也找不到合适的方法来在正确的点上创建它们。
文档只是声明它应该“在某处”和“在发出通知时可能不会”。但究竟我应该做什么?我讨厌为简单的任务编写特定版本的东西 - 这就是我使用compat库的原因。
有没有人建议如何处理它?当我想要显示通知时,每次创建是否“昂贵”?
这是我在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());
它并不像你想象的那么贵!您需要做的就是创建一个通知通道并将其绑定到通知。
您可以通过两种方式解决此问题,但对于这两种方法,您需要创建具有特定通道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()设置通道
Notification notification = new Notification.Builder(MainActivity.this).setContentTitle("Title").
setChannelId(id);
mNotificationManager.notify("your_notification_id", notification);
希望这可以帮助
以下是使用反射创建通知通道的替代解决方案,因此您可以设置低于26的compileSdkVersion
。
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);
}
}
然后,当您构建通知时,只需调用.setChannelId()
的NotificationCompat.Builder
方法:
builder.setChannelId("myChannelId");
注意:您需要将appcompat-v7
库更新为26.x.x
中的build.gradle
版本:
compile 'com.android.support:appcompat-v7:26.1.0'
如果您的通知代码每次都具有相同的结构,那么您应该创建一个静态方法并传递所需的所有内容,并将检查API级别的代码放在此方法中。
如果您想支持以前版本的Android(<Oreo)。我们可以将NotificationManager
包装在Notification.Builder
中创建和构建NotificationHelper
实例,如下所示:
/**
* Helper class to manage notification channels, and create notifications.
* <p>
* Created by teocci.
*
* @author [email protected] 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)
}
使用NotificationChannnel非常简单。
NotificationChannel实际上将多个通知分组到通道中。它基本上可以更好地控制用户的通知行为。您可以在Working with Notification Channel | With Example上阅读有关Notification Channel及其实现的更多信息
创建通知渠道
// 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);
现在,在创建Notification时,只需将Channel ID传递给Notification Builder构造函数,如下所示
//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());
以上通知成为第一步中创建的通知通道的一部分,其行为现在将与通道设置有关