标签:
一直用的android手机,用过这么多的app,平时也会遇到有趣的通知提醒,在这里先总结两种吧,notification和图标数字,有的以后看到再研究。还有,推广一下哈,刚刚建立一个Q群544645972,有兴趣的加一下,一起成长。
Notification应该算是最常见的app通知方式了,网上资料也很多,各种使用方法官方文档也已经写的非常详细了:http://developer.android.com/intl/zh-cn/guide/topics/ui/notifiers/notifications.html。这里就介绍一下几种特殊的用法:
将一个notification的setOngoing属性设置为true之后,notification就能够一直停留在系统的通知栏直到cancel或者应用退出。所以有的时候需要实时去根据情景动态改变notification,这里以一个定时器的功能为例,需要每隔1s去更新一下notification,具体效果:
非常简单的功能,代码也很简单:
private Timer timer;
private TimerTask task;
...
if (timer != null)
return;
timer = new Timer("time");
task = new TimerTask() {
@Override
public void run() {
showDynamicNotification();
}
};
timer.scheduleAtFixedRate(task, 0, 1000);
private void showDynamicNotification() {
L.i("show dynamic notification");
mBuilder = new NotificationCompat.Builder(NotificationActivity.this);
RemoteViews view = new RemoteViews(getPackageName(), R.layout.layout_notification);
view.setTextViewText(R.id.tv_number, parseDate());
view.setImageViewResource(R.id.iv_icon, R.mipmap.ic_launcher);
Intent intent = new Intent(NOTIFY_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(NotificationActivity.this,
1000, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.setTicker("you got a new message")
.setOngoing(true)
.setContent(view);
notification = mBuilder.build();
notificationManager.notify(NOTIFY_ID2, notification);
}
private String parseDate() {
SimpleDateFormat format = new SimpleDateFormat("yyyy hh:mm:ss", Locale.getDefault());
return format.format(System.currentTimeMillis());
}
需要注意的是Notification.Builder 是 Android 3.0 (API 11) 引入的,为了兼容低版本,我们一般使用 Support V4 包提供的 NotificationCompat.Builder 来构建 Notification。要想动态更新notification,需要利用 NotificationManager.notify() 的 id 参数,该 id 在应用内需要唯一(如果不唯一,在有些4.x的手机上会出现pendingIntent无法响应的问题,在红米手机上出现过类似情况),要想更新特定 id 的通知,只需要创建新的 notification,并触发与之前所用 id 相同的 notification,如果之前的通知仍然可见,则系统会根据新notification 对象的内容更新该通知,相反,如果之前的通知已被清除,系统则会创建一个新通知。
在这个例子中使用的是完全自定义的remoteViews,remoteViews和普通view的更新机制不一样,网上资料很多,感兴趣的可以去仔细了解。还有一个就是PendingIntent,这就不详细介绍了,这里简单列一下PendingIntent的4个flag的作用
Notification有两种视觉风格,一种是标准视图(Normal view)、一种是大视图(Big view)。标准视图在Android中各版本是通用的,但是对于大视图而言,仅支持Android4.1+的版本,比如邮件,音乐等软件就会使用到这种大视图样式的扩展通知栏,系统提供了setStyle()函数用来设置大视图模式,一般情况下有三种模式提供选择:
RemoteViews smallView = new RemoteViews(getPackageName(), R.layout.layout_notification);
smallView.setTextViewText(R.id.tv_number, parseDate());
smallView.setImageViewResource(R.id.iv_icon, R.mipmap.ic_launcher);
mBuilder = new NotificationCompat.Builder(NotificationActivity.this);
mBuilder.setSmallIcon(R.mipmap.ic_launcher)
.setNumber((int) (Math.random() * 1000))
//No longer displayed in the status bar as of API 21.
.setTicker("you got a new message")
.setDefaults(Notification.DEFAULT_SOUND
| Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS)
// .setDeleteIntent()
.setAutoCancel(true)
.setWhen(0)
.setPriority(NotificationCompat.PRIORITY_LOW);
intent = new Intent(NOTIFY_ACTION);
pendingIntent = PendingIntent.getBroadcast(NotificationActivity.this,
1000, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(pendingIntent);
//在5.0版本之后,可以支持在锁屏界面显示notification
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
mBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
}
notification = mBuilder.build();
notification.contentView = smallView;
//如果系统版本 >= Android 4.1,设置大视图 RemoteViews
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
RemoteViews view = new RemoteViews(getPackageName(), R.layout.layout_big_notification);
view.setTextViewText(R.id.tv_name, "我是名字1我是名字2我是名字3我是名字4我是名字5我是名字6我是名字7我是名字");
view.setOnClickPendingIntent(R.id.btn_click_close,
PendingIntent.getBroadcast(NotificationActivity.this, 1001,
new Intent(CLICK_ACTION), PendingIntent.FLAG_UPDATE_CURRENT));
//textview marquee property is useless for bigContentView
notification.bigContentView = view;
}
notificationManager.notify(NOTIFY_ID3, notification);
xml布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:background="#ef222222">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="150dp">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@mipmap/ic_launcher"
android:layout_gravity="center_vertical"/>
<LinearLayout
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView android:id="@+id/tv_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:layout_gravity="center"
android:gravity="center_horizontal|center_vertical"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="false"
android:focusable="true"
android:focusableInTouchMode="true"
android:singleLine="true"
android:textSize="15sp"
android:textStyle="bold"
android:textColor="#fff">
<requestFocus/>
</TextView>
<Button
android:id="@+id/btn_click_close"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="10dp"
android:layout_gravity="center_horizontal"
android:textSize="30sp"
android:background="#ef222222"
android:text="X"/>
</LinearLayout>
</FrameLayout>
</LinearLayout>
这里有几点需要着重说明一下
这种效果大家应该在微信中看的很多,其实实现也很简单:
代码:
RemoteViews headsUpView = new RemoteViews(getPackageName(), R.layout.layout_heads_up_notification);
intent = new Intent(NOTIFY_ACTION);
pendingIntent = PendingIntent.getBroadcast(NotificationActivity.this,
1000, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder = new NotificationCompat.Builder(NotificationActivity.this);
mBuilder.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("this is notification title test")
.setContentText("this is notification text test")
.setNumber((int) (Math.random() * 1000))
.setTicker("you got a new message")
//must set pendingintent for this notification, or will be crash
.setContentIntent(pendingIntent)
.setDefaults(Notification.DEFAULT_SOUND
| Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS)
.setAutoCancel(true)
.setWhen(0);
notification = mBuilder.build();
if (Build.VERSION.SDK_INT >= 21) {
notification.priority = Notification.PRIORITY_MAX;
notification.headsUpContentView = headsUpView;
}
notificationManager.notify(NOTIFY_ID1, notification);
这个效果非常的方便,用户都不需要直接下拉出通知栏,直接就能够看见,省去了多余操作,google官方文档介绍:http://developer.android.com/intl/zh-cn/guide/topics/ui/notifiers/notifications.html#Heads-up。headsUpContentView属性也只是在21版本时出现,使用的时候需要注意。
1.通过notification打开activity的时候,就要涉及到保存用户导航的问题,这个时候就要使用到activity task的相关内容了,我以前写过一篇博客中有介绍到activity task的内容:android深入解析Activity的launchMode启动模式,Intent Flag,taskAffinity,感兴趣的可以去看看。那么要实现点击notification打开指定activity,就需要设置相关的pendingIntent,有两种特殊的情况需要说明一下:
RemoteViews rvMain = new RemoteViews(context.getPackageName(), R.layout.notification_layout);
//TODO rvMain...
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContent(rvMain);
// TOOD ...
是无效的,需要换一种方式:
RemoteViews rvMain = new RemoteViews(context.getPackageName(), R.layout.notification_layout);
//TODO rmMain...
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContent(rvMain);
// TOOD ...
Notification notification = builder.build();
if(Build.VERSION.SDK_INT <= 10){
notification.contentView = rvMain;
}
4.通知栏上的操作事件:
http://www.tutorialsface.com/2015/08/android-custom-notification-tutorial/
http://developer.android.com/intl/zh-cn/guide/topics/ui/notifiers/notifications.html#Heads-up
http://glgjing.github.io/blog/2015/11/18/android-kai-fa-zhi-notification-xiang-jie/
http://www.codeceo.com/article/android-notification-4-types.html
http://www.itnose.net/detail/6169442.html
http://www.cnblogs.com/over140/p/4249503.html
http://blog.csdn.net/loongggdroid/article/details/17616509/
http://www.2cto.com/kf/201408/327782.html
http://blog.csdn.net/xxbs2003/article/details/19167331
http://www.jianshu.com/p/4d76b2bc8784
http://home.bdqn.cn/thread-42153-1-1.html
虽然说这是iOS上的风格,但是在某些手机上还是支持的,比如三星和HTC(m8t,6.0)的有些手机都可以,小米手机是个特例,它是根据notification的数量来自动生成的。
一般情况下,HTC和三星可以使用下面的函数生成
public static void setBadge(Context context, int count) {
String launcherClassName = getLauncherClassName(context);
if (launcherClassName == null) {
return;
}
Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE");
intent.putExtra("badge_count", count);
intent.putExtra("badge_count_package_name", context.getPackageName());
intent.putExtra("badge_count_class_name", launcherClassName);
context.sendBroadcast(intent);
}
public static String getLauncherClassName(Context context) {
PackageManager pm = context.getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
for (ResolveInfo resolveInfo : resolveInfos) {
String pkgName = resolveInfo.activityInfo.applicationInfo.packageName;
if (pkgName.equalsIgnoreCase(context.getPackageName())) {
String className = resolveInfo.activityInfo.name;
return className;
}
}
return null;
}
由于android碎片化太严重,所以在不同手机上适配起来是非常麻烦,不过还好在github上国人写了一个库可以覆盖挺多机型:ShortcutBadger,也可以参考一下:http://stackoverflow.com/questions/17565307/how-to-display-count-of-notifications-in-app-launcher-icon。
标签:
原文地址:http://blog.csdn.net/self_study/article/details/51055769