Android中 RemoveView的使用和举例 —— 最全面的APP通知栏适配(8.0通知栏适配)
目录
RemoteViews应该是一种远程View,与其这样不如叫远程服务可能比较好理解,但是远程View的确没听说过,其实它和远程Service是一样的,RemoteViews表示的是一个View结构,它可以在其他进程中显示,由于它在其他进程中显示,为了能够更新它的界面,RemoteViews提供了一组基础的操作用于跨进程更新它的界面。
RemoteViews在Android中的使用场景有两种:通知栏和桌面小部件;
主要是通过NotificationManager的notify方法来实现的,它除了默认效果外,还可以另外定义布局。桌面小部件则是通过AppWidgetProvider来实现的AppWidgetProvider本质上是一个广播。通知栏和桌面小部件的开发过程中都会用到RemoteViews,它们在更新界面时无法像在Activity里面那样去直接更新View,这是因为二者的界面都运行在其他进程中,确切来说是系统的SystemServer进程。为了跨进程更新界面,RemoteViews提供了一系列set方法,并且这些方法只是View全部方法的子集,另外RemoteViews中所支持的View类型也是有限的
Notification,俗称通知,是一种具有全局效果的通知,它展示在屏幕的顶端,首先会表现为一个图标的形式,当用户向下滑动的时候,展示出通知具体的内容。
因为Android的快速发展,而Android的版本也快速的升级导致了一些兼容性的问题。对于Notification而言,Android3.0是一个分水岭,在其之前构建Notification推荐使用NotificationCompate.Builder,它位于android.support.v4.app.NotificationCompat.Builder,是一个Android向下版本的兼容包,而在Android3.0之后,一般推荐使用Notification.Builder构建。本博客主要介绍的是Android8.x的开发
使用系统默认的样式弹出一个通知是很简单的简单示例:
/**
* 版本N之前发送通知消息
*/
private void showNotictionN() {
Bitmap btm = BitmapFactory.decodeResource(getResources(),
R.mipmap.image_a2);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
RemoteViewDemoActivity.this).setSmallIcon(R.mipmap.image_a3)
.setContentTitle("a new message title")
.setContentText("the context of the new message");
//第一次提示消息的时候显示在通知栏上
mBuilder.setTicker("New message");
//设置桌面图标红点显示未读消息数为12,如果不需要显示红点请去掉这段代码
mBuilder.setNumber(12);
mBuilder.setLargeIcon(btm);
//自己维护通知的消失
mBuilder.setAutoCancel(true);
//构建一个Intent
Intent resultIntent = new Intent(RemoteViewDemoActivity.this, MainActivity.class);
//封装一个Intent
PendingIntent resultPendingIntent = PendingIntent.getActivity(
RemoteViewDemoActivity.this, 0, resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
// 设置通知主题的意图
mBuilder.setContentIntent(resultPendingIntent);
//获取通知管理器对象
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
}
- PendingIntent
对于一个通知而言,它显示的消息是有限的,一般仅用于提示一些概要信息。但是一般简短的消息,并不能表达需要告诉用户的全部内容,所以需要绑定一个意图,当用户点击通知的时候,调用一个意图展示出一个Activity用来显示详细的内容。而Notification中,并不使用常规的Intent去传递一个意图,而是使用PendingIntent。
先来说说Intent和PendingIntent的区别,PendingIntent可以看做是对Intent的包装,通过名称可以看出PendingIntent用于处理即将发生的意图,而Intent用来用来处理马上发生的意图。而对于通知来说,它是一系统级的全局通知,并不确定这个意图被执行的时间。当在应用外部执行PendingIntent时,因为它保存了触发应用的Context,使得外部应用可以如在当前应用中一样,执行PendingIntent里的Intent,就算执行的时候响应通知的应用已经被销毁了,也可以通过存在PendingIntent里的Context照常执行它,并且还可以处理Intent说带来的额外信息。
PendingIntent提供了多个静态的getXxx()方法,用于获得适用于不同场景的PendingIntent对象。一般需要传递的几个参数都很常规,只介绍一个flag参数,用于标识PendingIntent的构造选择:
| flag参数取值 | 备注 |
|---|---|
| FLAG_CANCEL_CURRENT | 如果构建的PendingIntent已经存在,则取消前一个,重新构建一个。 |
| FLAG_NO_CREATE | 如果前一个PendingIntent已经不存在了,将不再构建它。 |
| FLAG_ONE_SHOT | 表明这里构建的PendingIntent只能使用一次。 |
| FLAG_UPDATE_CURRENT | 如果构建的PendingIntent已经存在,则替换它,常用。 |
实现的效果如下(手头的手机是小米5.1.1的系统)
如果说上面的代码仅仅实现了,通知栏小图的显示,那么,你一定不能错过大图显示的效果
/**
* 在系统版本 android 7.0 之前上面显示大图通知消息
*/
private void showBigNotifitionN() {
Bitmap btm = BitmapFactory.decodeResource(getResources(),
R.mipmap.image_a2);
Intent intent = new Intent(RemoteViewDemoActivity.this,
MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(
RemoteViewDemoActivity.this, 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
Notification noti = new NotificationCompat.Builder(
RemoteViewDemoActivity.this)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(btm)
.setContentTitle("this is small view content title")
.setContentText("this is small view content text")
.setNumber(13)
.setContentIntent(pendingIntent)
.setStyle(
new NotificationCompat.InboxStyle()
.addLine(
"M.Twain (Google+) Haiku is more than a cert...")
.addLine("M.Twain Reminder")
.addLine("M.Twain Lunch?")
.addLine("M.Twain Revised Specs")
.addLine("M.Twain ")
.addLine(
"Google Play Celebrate 25 billion apps with Goo..")
.addLine(
"Stack Exchange StackOverflow weekly Newsl...")
.setBigContentTitle("this is big notifity's title")
.setBigContentTitle("this is big content title")
.setSummaryText("this is big notifity's SummaryText"))
.build();
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, noti);
}
同样的在系统版本是android5.1.1 的小米手机上面得到的小时效果为
- 初始状态是折叠显示的
- 当用户下拉或者是展开消息的时候
相同的代码在华为手机7.0.0系统的显示效果是这样的
- 初始状态是折叠显示的
- 当用户下拉或者是展开消息的时候
上面的代码虽然运行完美但是我们发现,在系统的版本大于7.0的时候就会出现显示不出来的情况。为了解决这个问题,特地查阅了很多的资料,大体原因是这样的
不得不说,通知栏真是一个让人又爱又恨的东西。
通知栏是Android系统原创的一个功能,虽说乔布斯一直认为Android系统是彻彻底底抄袭iOS的一个产品,但是通知栏确实是Android系统原创的,反而苹果在iOS 5之后也加入了类似的通知栏功能。
通知栏的设计确实非常巧妙,它默认情况下不占用任何空间,只有当用户需要的时候用手指在状态栏上向下滑动,通知栏的内容才会显示出来,这在智能手机发展的初期极大地解决了手机屏幕过小,内容展示区域不足的问题。
可是随着智能手机发展的逐渐成熟,通知栏却变得越来越不讨人喜欢了。各个App都希望能抢占通知栏的空间,来尽可能地宣传和推广自己的产品。现在经常是早上一觉醒来拿起手机一看,通知栏上全是各种APP的推送,不胜其烦。
我个人虽然是Android应用开发者,但同时也是Android手机的资深用户。我已经使用了8年的Android手机,目前我对于通知栏的这种垃圾推送是零容忍的。现在每当我安装一个新的App时,我都会先到设置里面去找一找有没有推送开关,如果有的话我会第一时间把它关掉。而如果一个App经常给我推送垃圾信息却又无法关闭时,我会直接将它的通知总开关给关掉,如果还不是什么重要的App的话,那么我可能就直接将它卸载掉了。
为什么一个很好的通知栏功能现在却变得这么遭用户讨厌?很大一部分原因都是因为开发者没有节制地使用导致的。就好像App保活一样,直到今天还是不断有人问我该如何保活App,试想如何每个人都能保活自己的App,那么最终受害的人是谁?还不是使用Android手机的用户。大家的手机只会越来越卡,最后只想把手机丢掉,变成iPhone用户了。也是因为开发者没节制地使用,Android现在的每个版本都会不断收缩后台权限。
回到通知栏上也是一样,每个开发者都只想着尽可能地去宣传自己的App,最后用户的手机就乱得跟鸡窝一样了。但是通知栏又还是有用处的,比如我们收到微信、短信等消息的时候,确实需要通知栏给我们提醒。因此分析下来,通知栏目前最大的问题就是,无法让用户对感兴趣和不感兴趣的消息进行区分。就比如说,我希望淘宝向我推送卖家发货和物流的相关消息,但是我不想收到那些打折促销或者是让我去买衣服的这类消息。那么就目前来说,是没有办法对这些消息做区分的,我要么同意接受所有消息,要么就屏蔽所有消息,这是当前通知栏的痛点。
那么在Android 8.0系统中,Google也是从这个痛点开始下手的。
从Android 8.0系统开始,Google引入了通知渠道这个概念。
什么是通知渠道呢?顾名思义,就是每条通知都要属于一个对应的渠道。每个App都可以自由地创建当前App拥有哪些通知渠道,但是这些通知渠道的控制权都是掌握在用户手上的。用户可以自由地选择这些通知渠道的重要程度,是否响铃、是否振动、或者是否要关闭这个渠道的通知。
拥有了这些控制权之后,用户就再也不用害怕那些垃圾推送消息的打扰了,因为用户可以自主地选择自己关心哪些通知、不关心哪些通知。举个具体的例子,我希望可以即时收到支付宝的收款信息,因为我不想错过任何一笔收益,但是我又不想收到支付宝给我推荐的周围美食,因为我没钱只吃得起公司食堂。这种情况,支付宝就可以创建两种通知渠道,一个收支,一个推荐,而我作为用户对推荐类的通知不感兴趣,那么我就可以直接将推荐通知渠道关闭,这样既不影响我关心的通知,又不会让那些我不关心的通知来打扰我了。
对于每个App来说,通知渠道的划分是非常需要仔细考究的,因为通知渠道一旦创建之后就不能再修改了,因此开发者需要仔细分析自己的App一共有哪些类型的通知,然后再去创建相应的通知渠道。这里我们来参考一下Twitter的通知渠道划分:
可以看到,Twitter就是根据自己的通知类型,对通知渠道进行了非常详细的划分,这样用户的自主选择性就比较高了,也就大大降低了用户不堪其垃圾通知的骚扰而将App卸载的概率。
Google这次对于8.0系统通知渠道的推广态度还是比较强硬的。
首先,如果你升级了appcompat库,那么所有使用appcompat库来构建通知的地方全部都会进行废弃方法提示,如下所示:
上图告诉我们,此方法已废弃,需要使用带有通知渠道的方法才行。
当然,Google也并没有完全做绝,即使方法标为了废弃,但还是可以正常使用的。可是如果你将项目中的targetSdkVersion指定到了26或者更高,那么Android系统就会认为你的App已经做好了8.0系统的适配工作,当然包括了通知栏的适配。这个时候如果还不使用通知渠道的话,那么你的App的通知将完全无法弹出。因此这里给大家的建议就是,一定要适配。
好了,前面向大家介绍了这么多的背景知识,那么现在开始我们就正式进入正题,来学习一下如何进行8.0系统中通知栏的适配。
首先我们使用Android Studio来新建一个项目,就叫它NotificationTest吧。
创建好项目之后,打开app/build.gradle文件检查一下,确保targetSdkVersion已经指定到了26或者更高,如下所示:
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.example.notificationtest"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
可以看到,这里我在创建新项目的时候默认targetSdkVersion就是26,如果你是低于26的话,说明你的Android SDK有些老了,最好还是更新一下。当然如果你懒得更新也没关系,手动把它改成26就可以了。
接下来修改MainActivity中的代码,如下所示:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = "chat";
String channelName = "聊天消息";
int importance = NotificationManager.IMPORTANCE_HIGH;
createNotificationChannel(channelId, channelName, importance);
channelId = "subscribe";
channelName = "订阅消息";
importance = NotificationManager.IMPORTANCE_DEFAULT;
createNotificationChannel(channelId, channelName, importance);
}
}
@TargetApi(Build.VERSION_CODES.O)
private void createNotificationChannel(String channelId, String channelName, int importance) {
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
NotificationManager notificationManager = (NotificationManager) getSystemService(
NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
}
}
代码不长,我来简单解释下。这里我们在MainActivity中创建了两个通知渠道,首先要确保的是当前手机的系统版本必须是Android 8.0系统或者更高,因为低版本的手机系统并没有通知渠道这个功能,不做系统版本检查的话会在低版本手机上造成崩溃。
创建一个通知渠道的方式非常简单,这里我封装了一个createNotificationChannel()方法,里面的逻辑相信大家都看得懂。需要注意的是,创建一个通知渠道至少需要渠道ID、渠道名称以及重要等级这三个参数,其中渠道ID可以随便定义,只要保证全局唯一性就可以。渠道名称是给用户看的,需要能够表达清楚这个渠道的用途。重要等级的不同则会决定通知的不同行为,当然这里只是初始状态下的重要等级,用户可以随时手动更改某个渠道的重要等级,App是无法干预的。
上述代码我是模拟了这样一个场景。想象一下我们正在开发一个类似于微信的App,其中App通知主要可以分为两类,一类是我和别人的聊天消息,这类消息非常重要,因此重要等级我设为了IMPORTANCE_HIGH。另一类是公众号的订阅消息,这类消息不是那么重要,因此重要等级我设为了IMPORTANCE_DEFAULT。除此之外,重要等级还可以设置为IMPORTANCE_LOW、IMPORTANCE_MIN,分别对应了更低的通知重要程度。
现在就可以运行一下代码了,运行成功之后我们关闭App,进入到设置 -> 应用 -> 通知当中,查看NotificationTest这个App的通知界面(手头找到的是一部android8.0.0的华为手机),如下图所示:
刚才我们创建的两个通知渠道这里已经显示出来了。可以看到,由于这两个通知渠道的重要等级不同,通知的行为也是不同的,聊天消息可以发出提示音并在屏幕上弹出通知,而订阅消息只能发出提示音。
当然,用户还可以点击进去对该通知渠道进行任意的修改,比如降低聊天消息的重要等级,甚至是可以完全关闭该渠道的通知。
至于创建通知渠道的这部分代码,你可以写在MainActivity中,也可以写在Application中,实际上可以写在程序的任何位置,只需要保证在通知弹出之前调用就可以了。并且创建通知渠道的代码只在第一次执行的时候才会创建,以后每次执行创建代码系统会检测到该通知渠道已经存在了,因此不会重复创建,也并不会影响任何效率。
触发通知的代码和之前版本基本是没有任何区别的,只是在构建通知对象的时候,需要多传入一个通知渠道ID,表示这条通知是属于哪个渠道的。
那么下面我们就来让通知显示出来。
@OnClick({R.id.btn_appweiget_test})
public void onclick(View view) {
switch (view.getId()) {
case R.id.btn_androido_height:
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
showNotictionN();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = "chat";
String channelName = "聊天消息";
int importance = NotificationManager.IMPORTANCE_HIGH;
createNotificationChannel(channelId, channelName, importance);
sendChatMsg();
}
break;
case R.id.btn_androido_default:
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
showNotictionN();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = "subscribe";
String channelName = "订阅消息";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
createNotificationChannel(channelId, channelName, importance);
sendSubscribeMsg();
}
break;
}
}
-
createNotificationChannel 方法
@TargetApi(Build.VERSION_CODES.O) private void createNotificationChannel(String channelId, String channelName, int importance) { NotificationChannel channel = new NotificationChannel(channelId, channelName, importance); NotificationManager notificationManager = (NotificationManager) getSystemService( NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(channel); } -
sendChatMsg 方法
public void sendChatMsg() { NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); Notification notification = new NotificationCompat.Builder(this, "chat") .setContentTitle("收到一条聊天消息") .setContentText("今天中午吃什么?") .setWhen(System.currentTimeMillis()) .setSmallIcon(R.mipmap.img_cat) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.image_a2)) .setAutoCancel(true) .build(); manager.notify(1, notification); } -
sendSubscribeMsg方法
public void sendSubscribeMsg() { NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); Notification notification = new NotificationCompat.Builder(this, "subscribe") .setContentTitle("收到一条订阅消息") .setContentText("地铁沿线30万商铺抢购中!") .setWhen(System.currentTimeMillis()) .setSmallIcon(R.mipmap.iamge_a4) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.img_cat)) .setAutoCancel(true) .build(); manager.notify(2, notification); }
这里我们分别在sendChatMsg()和sendSubscribeMsg()方法中触发了两条通知,创建通知的代码就不再多做解释了,和传统创建通知的方法没什么两样,只是在NotificationCompat.Builder中需要多传入一个通知渠道ID,那么这里我们分别传入了chat和subscribe这两个刚刚创建的渠道ID。
现在重新运行一下代码,并点击发送聊天消息按钮,效果如下图所示:
由于这是一条重要等级高的通知,因此会使用这种屏幕弹窗的方式来通知用户有消息到来。然后我们可以下拉展开通知栏,这里也能查看到通知的详细信息:
用户可以通过快速向左或者向右滑动来关闭这条通知。
接下来点击发送订阅消息按钮,你会发现现在屏幕上不会弹出一条通知提醒了,只会在状态栏上显示一个小小的通知图标:
因为订阅消息通知的重要等级是默认级别,这就是默认级别通知的展示形式。当然我们还是可以下拉展开通知栏,查看通知的详细信息:
不过上面演示的都是通知栏的传统功能,接下来我们看一看Android 8.0系统中通知栏特有的功能。
刚才提到了,快速向左或者向右滑动可以关闭一条通知,但如果你缓慢地向左或者向右滑动,就会看到这样两个按钮:
其中,左边那个时钟图标的按钮可以让通知延迟显示。比方说这是一条比较重要的通知,但是我暂时没时间看,也不想让它一直显示在状态栏里打扰我,我就可以让它延迟一段后时间再显示,这样我就暂时能够先将精力放在专注的事情上,等过会有时间了这条通知会再次显示出来,我不会错过任何信息。如下所示:
而右边那个设置图标的按钮就可以用来对通知渠道进行屏蔽和配置了,用户对每一个App的每一个通知渠道都有绝对的控制权,可以根据自身的喜好来进行配置和修改。如下所示:
比如说我觉得订阅消息老是向我推荐广告,实在是太烦了,我就可以将订阅消息的通知渠道关闭掉。这样我以后就不会再收到这个通知渠道下的任何消息,而聊天消息却不会受到影响,这就是8.0系统通知渠道最大的特色。
另外,点击上图中的所有类别就可以进入到当前应用程序通知的完整设置界面。
在前面的内容中我们已经了解到,通知渠道一旦创建之后就不能再通过代码修改了。既然不能修改的话那还怎么管理呢?为此,Android赋予了开发者读取通知渠道配置的权限,如果我们的某个功能是必须按照指定要求来配置通知渠道才能使用的,那么就可以提示用户去手动更改通知渠道配置。
只讲概念总是不容易理解,我们还是通过具体的例子来学习一下。想一想我们开发的是一个类似于微信的App,聊天消息是至关重要的,如果用户不小心将聊天消息的通知渠道给关闭了,那岂不是所有重要的信息全部都丢了?为此我们一定要保证用户打开了聊天消息的通知渠道才行。
@OnClick({R.id.btn_appweiget_test})
public void onclick(View view) {
switch (view.getId()) {
case R.id.btn_androido_height:
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
showNotictionN();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = "chat";
String channelName = "聊天消息";
checkNotificationChannel(channelId);
int importance = NotificationManager.IMPORTANCE_HIGH;
createNotificationChannel(channelId, channelName, importance);
sendChatMsg();
}
break;
case R.id.btn_androido_default:
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
showNotictionN();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = "subscribe";
String channelName = "订阅消息";
checkNotificationChannel(channelId);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
createNotificationChannel(channelId, channelName, importance);
sendSubscribeMsg();
}
break;
}
}
/**
* 检测通知权限,在用户关闭时跳转通知权限设置,引导用户打开通知权限
* @param channelld
*/
private void checkNotificationChannel(String channelld) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationChannel channel = manager.getNotificationChannel(channelld);
if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
intent.putExtra(Settings.EXTRA_CHANNEL_ID, channel.getId());
startActivity(intent);
Toast.makeText(this, "请手动将通知打开", Toast.LENGTH_SHORT).show();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
这里我们对两个按钮的点击事件进行了修改,通过getNotificationChannel()方法获取到了NotificationChannel对象,然后就可以读取该通知渠道下的所有配置了。这里我们判断如果通知渠道的importance等于IMPORTANCE_NONE,就说明用户将该渠道的通知给关闭了,这时会跳转到通知的设置界面提醒用户手动打开。
现在重新运行一下程序,效果如下图所示:
可以看到,当我们将聊天消息的通知渠道关闭后,下次再次发送聊天消息将会直接跳转到通知设置界面,提醒用户手动将通知打开。
除了以上管理通知渠道的方式之外,Android 8.0还赋予了我们删除通知渠道的功能,只需使用如下代码即可删除:
/**
* 删除指定编号的渠道,删除后通知设置界面会保留删除记录
*
* @param channelId
*/
private void deleteChannel(String channelId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.deleteNotificationChannel(channelId);
}
}
但是这个功能非常不建议大家使用。因为Google为了防止应用程序随意地创建垃圾通知渠道,会在通知设置界面显示所有被删除的通知渠道数量(当然很遗憾,手头的华为手机没有显示,网上张图吧,自觉捂脸了),如下图所示:
这样是非常不美观的,所以对于开发者来说最好的做法就是仔细规划好通知渠道,而不要轻易地使用删除功能。
前面我们提到过,苹果是从iOS 5开始才引入了通知栏功能,那么在iOS 5之前,iPhone都是怎么进行消息通知的呢?使用的就是未读角标功能,效果如下所示:
实际上Android系统之前是从未提供过这种类似于iOS的角标功能的,但是由于很多国产手机厂商都喜欢跟风iOS,因此各种国产手机ROM都纷纷推出了自己的角标功能。
可是国产手机厂商虽然可以订制ROM,但是却没有制定API的能力,因此长期以来都没有一个标准的API来实现角标功能,很多都是要通过向系统发送广播来实现的,而各个手机厂商的广播标准又不一致,经常导致代码变得极其混杂。
值得高兴的是,从8.0系统开始,Google制定了Android系统上的角标规范,也提供了标准的API,长期让开发者头疼的这个问题现在终于可以得到解决了。
那么下面我们就来学习一下如何在Android系统上实现未读角标的效果。
篇幅限制我把这部分放在自己的另一篇博客进行讲解了,感兴趣的请点击这里哦,使用功能过程中如果有好的建议或者有什么不足的地方留言给我我会持续更新
Android 桌面图标添加未读消息角标APP角标最佳实践
4. 如果你对这pain文章感兴趣,请点击下载完整演示代码哦,同时也欢迎提建议我会持续更细
点击下载 https://github.com/benchegnzhou/AndroidDevelomentArtDemo
参考文章
Android API Level对应Android版本一览表