信息提醒之Notification,兼容全部SDK-更新中

简介: 信息提醒之Notification,兼容全部SDK-更新中

概述


Notification与对话框、Toast无论从外观上还是从使用方法上有本质的区别。

Notification是Android中很理想的提示方法,Notification可以在Android桌面上最上方的状态栏显示提示信息,还可以显示图像,甚至可以将控件加载到上面,而且只要用户不清空,这些信息可以永久的保留在状态栏,除了这些还有其他更吸引人的特性,让我们一起发掘下吧。


本篇博文中使用的创建Notification 是通过一个兼容全部SDK的工具类创建的,因为setLatestEventInfo方法在API11中不建议使用了,而且谷歌在API23 (Android6.0)中彻底废弃了该方法。


所以本篇博文中会提供一个创建Notification的工具类,来兼容所有额SDK版本~


NotificationUtils.java

import android.annotation.TargetApi;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.os.Build;
import com.apkfuns.logutils.LogUtils;
import java.lang.reflect.Method;
/**
 * 兼容所有SDK的NotificationUtil
 *
 * @author Mr.Yang on 2016-02-18  20:34.
 * @version 1.0
 * @desc
 */
public class NotificationUtil {
    public static Notification createNotification(Context context, PendingIntent pendingIntent, String title, String text, int iconId) {
        Notification notification;
        if (isNotificationBuilderSupported()) {
            LogUtils.d("isNotificationBuilderSupported");
            notification = buildNotificationWithBuilder(context, pendingIntent, title, text, iconId);
        } else {
            // 低于API 11 Honeycomb
            LogUtils.d("buildNotificationPreHoneycomb");
            notification = buildNotificationPreHoneycomb(context, pendingIntent, title, text, iconId);
        }
        return notification;
    }
    public static boolean isNotificationBuilderSupported() {
        try {
            return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) && Class.forName("android.app.Notification.Builder") != null;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }
    @SuppressWarnings("deprecation")
    private static Notification buildNotificationPreHoneycomb(Context context, PendingIntent pendingIntent, String title, String text, int iconId) {
        Notification notification = new Notification(iconId, "", System.currentTimeMillis());
        try {
            // try to call "setLatestEventInfo" if available
            Method m = notification.getClass().getMethod("setLatestEventInfo", Context.class, CharSequence.class, CharSequence.class, PendingIntent.class);
            m.invoke(notification, context, title, text, pendingIntent);
        } catch (Exception e) {
            // do nothing
        }
        return notification;
    }
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    @SuppressWarnings("deprecation")
    private static Notification buildNotificationWithBuilder(Context context, PendingIntent pendingIntent, String title, String text, int iconId) {
        android.app.Notification.Builder builder = new android.app.Notification.Builder(context)
                .setContentTitle(title)
                .setContentText(text)
                .setContentIntent(pendingIntent)
                .setSmallIcon(iconId);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            return builder.build();
        } else {
            return builder.getNotification();
        }
    }
}

在状态栏上显示通知信息


Notification需要使用NotificationManager来管理,一般来讲创建并显示Notification需要以下5个步骤:


通过getSystemService方法获取一个NotificationManager对象

创建一个Notification对象,在这里我们使用兼容较好的NotificationUtils类来创建

由于Notification可以与应用程序脱离,也就是说,即使应用程序被关闭,Notification仍然会显示在状态栏中,当应用程序再此启动后,又可以重新控制这些Notification,如清除或者替换他们。因此,需要创建一个PendingIntent对象。该对象由Android系统负责维护,因此在应用程序关闭后,该对象仍然不会被释放。

使用Notification类的setLatestEventInfo方法设置详细信息(改方法已经在6.0废弃,可使用提供的工具类来代替)

使用NotificationManager类的notify方法显示Notification。再这一步需要指定标识Notification的唯一ID,改ID必须相对于同一个NotificationManager对象是唯一的,否则就会覆盖相同ID的Notification。

20160302204255874.gif

 /**
     * 全部兼容
     * http://blog.csdn.net/yangshangwei/article/details/50688221
     */
    private void showNotification() {
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, getIntent(), 0);
        // 工具类判断版本,通过不同的方式获取Notification
        Notification notification = NotificationUtil.createNotification(this, pendingIntent, "您有新消息", "消息内容", R.drawable.flag_mark_blue);
        notification.tickerText = "我是提示通知时的文字内容";
        notification.when = System.currentTimeMillis();
        // 使用默认的声音
        notification.defaults = Notification.DEFAULT_SOUND;
        // 使用默认的震动 需要添加uses-permission  android.permission.VIBRATE
        notification.defaults = Notification.DEFAULT_VIBRATE;
        // 使用默认的Light
        notification.defaults = Notification.DEFAULT_LIGHTS;
        // 所有的都是用默认值
        notification.defaults = Notification.DEFAULT_ALL;
        notificationManager.notify(R.drawable.flag_mark_blue, notification);
        // 5S后,执行取消的方法,即5S后 自动清除该通知栏 ,根据需求考虑是否需要这样
//        Handler handler = new Handler();
//        handler.postDelayed(new Runnable() {
//            @Override
//            public void run() {
//                notificationManager.cancel(R.drawable.flag_mark_blue);
//            }
//        },5*1000);
    }


上述代码中的

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, getIntent(), 0);


返回一个PendingIntent对象,这个对象与一个Activity对象关联,这个案例中与当前的Activity关联。将Android状态栏滑下来后,单击Notification,就会显示关联的这个Activity。如果Activity已经显示,仍然会显示一个新的Activity,并覆盖当前显示的Activity。不过这些显示的Activity都是一样的,除了getActivity方法之外,还可以getBroacast和getService方法。 这两个方法用于单击Notification后发出一条广播或者启动一个服务。


设置默认发声、震动、Light效果

   // 使用默认的声音
        notification.defaults = Notification.DEFAULT_SOUND;
        // 使用默认的震动 需要添加uses-permission  android.permission.VIBRATE
        notification.defaults = Notification.DEFAULT_VIBRATE;
        // 使用默认的Light
        notification.defaults = Notification.DEFAULT_LIGHTS;
        // 所有的都是用默认值
        notification.defaults = Notification.DEFAULT_ALL;


注意事项:

  • defaults属性必须在调用notify方法之前调用,否则不起作用
  • 设置震动效果需要在AndroidManifest.xml中添加权限
  • <uses-permission android:name="android.permission.VIBRATE" />


清除指定的Notification


如果要清除某个消息可以使用NotificationManager.cancel方法,该方法只有一个参数,表示要清除的Notification的ID。


20160302205804631.gif

 case 1:// 清除指定的Notification-cancel(id)
                                    cancelNotification(R.drawable.flag_mark_blue);
 /**
     * 清除某个消息,
     *
     * @param id Notification的id
     */
    private void cancelNotification(int id) {
        notificationManager.cancel(id);
    }


清除全部的Notification


使用cancelAll()可以清除当前NotificationManager对象中的所有的Notification。


清除Notification后触发的善后工作


当我们将状态栏下拉下来之后都会看到在屏幕的右上角有一个“清除“按钮或者图标,单击该按钮可以清除所有的Notification, 那么在清除后,往往需要做一些善后的工作,这个就需要通过Notification.deleteIntent来完成。


deleteIntent也需要设置一个PendingIntent类型的变量,由于在清除所有的Notification时调用,可以将这个动作和Activity、Broadcast、Service关联。


20160302210749276.gif

 private void notificationDeleteIntent() {
        // 通过getSystemservice获取NotificationManager
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        // PendingIntent --getAct ,getBrc ,getSev等等
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity_.class), 0);
        // Notification
        Notification notification = NotificationUtil.createNotification(this, pendingIntent, "Title", "text", R.drawable.tag_blue);
        notification.when = System.currentTimeMillis();
        notification.tickerText = "清除Notificaiton的善后工作";
        // 清除通知,触发的操作,这里将清除Notification触发的deleteIntent设置为跳转到ToastDemoListAct,当然了也可以启动广播 服务等等
        PendingIntent deleteIntent = PendingIntent.getActivity(this, 0, new Intent(this, ToastDemoListAct.class), 0);
        notification.deleteIntent = deleteIntent;
        notificationManager.notify(R.drawable.tag_blue, notification);
    }

如果想响应删除动作的Activity传递数据,可以利用被PendingIntent封装的intent。例如

......
Intent intent = new Intent(this,Main.class);
//传递数据
intent.putExtra("msg","what r u  doing ?");
PendingIntent pendingIntent = PendingIntent.getActivity(this,0.intent,0);
.......


这样在Activity中(一般在onCreate方法中)接收解即可

String msg = getIntent().getStringExtra("msg");



永久存在的Notification


我们发现单击”清除“按钮,有些Notification并没有被清除掉,这样无法被清除的Notification被称为永久Notification,这些Notification只能通过他们的程序 来清除。

实现这样的效果很简单,只需要设置Notification.flag即可。

/**
     * FLAG_SHOW_LIGHTS  //控制闪光
     * <p/>
     * FLAG_ONGOING_EVENT  //显示在”正在运行的“一栏中
     * <p/>
     * FLAG_INSISTENT   //重复发出声音,直到用户响应此通知
     * <p/>
     * FLAG_ONLY_ALERT_ONCE  //标记声音或者震动一次
     * <p/>
     * FLAG_AUTO_CANCEL  //在通知栏上点击此通知后自动清除此通知
     * <p/>
     * FLAG_NO_CLEAR    //将flag设置为这个属性那么通知栏的那个清楚按钮就不会出现
     * <p/>
     * FLAG_FOREGROUND_SERVICE//前台服务标记
     * <p/>
     * https://developer.android.com/intl/zh-cn/reference/android/app/Notification.html#FLAG_GROUP_SUMMARY
     * <p/>
     * FLAG_GROUP_SUMMARY
     * <p/>
     * FLAG_LOCAL_ONLY
     */
    private void permanentNotification() {
        // 通过getSystemService获取NotificationManager
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        // PendingIntent
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, getIntent(), 0);
        // Notification
        Notification notification = NotificationUtil.createNotification(this, pendingIntent, "Title", "Content", R.drawable.face);
        notification.tickerText = "清除不掉的Notification";
        notification.when = System.currentTimeMillis();
        notification.flags = Notification.FLAG_NO_CLEAR;
        // 展示Notification
        notificationManager.notify(R.drawable.face, notification);
    }


自定义Notification


我们可以通过Notification.contentView 来自定义Notification。

contentView 并不是一个View,而是RemoteViews类型。

RemoteView只支持有限的几个控件和布局,如下所示


RemoteView支持的布局

  • FrameLayout
  • LinearLayout
  • RelativeLayout


RemoteView支持的控件

  • AnalogClock
  • Button
  • Chronometer
  • ImageButton
  • ImageView
  • ProgressBar
  • TextView

如果使用其他控件,会抛出异常。


实现步骤


activity_custom_notification.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <TextView
        android:id="@+id/textview"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="自定义内容"
        android:textColor="#F00"
        android:textSize="20sp" />
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/tag_green" />
</LinearLayout>
    private void customNotification() {
        // 通过getSystemService()获取NotificationManager
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        //PendingIntent
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,getIntent(),0);
        // Notification
        Notification notification = NotificationUtil.createNotification(this,pendingIntent,"Title","text",R.drawable.flag_mark_yellow);
        // 设置属性...
        notification.tickerText="自定义Notification";
        notification.when = System.currentTimeMillis();
        //自定义Notification布局
        RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.activity_custom_notification);
        remoteViews.setTextViewText(R.id.textview,"666666666");
        notification.contentView = remoteViews ;
        // notifiy
        notificationManager.notify(R.drawable.flag_mark_yellow,notification);
    }

运行效果


20160302212632897.gif


相关文章
|
2月前
|
Kubernetes API 开发工具
【Azure Developer】通过SDK(for python)获取Azure服务生命周期信息
需要通过Python SDK获取Azure服务的一些通知信息,如:K8S版本需要更新到指定的版本,Azure服务的维护通知,服务处于不健康状态时的通知,及相关的操作建议等内容。
46 18
|
3月前
|
Java 开发工具
【Azure Developer】示例: 在中国区调用MSGraph SDK通过User principal name获取到User信息,如Object ID
【Azure Developer】示例: 在中国区调用MSGraph SDK通过User principal name获取到User信息,如Object ID
|
3月前
|
机器学习/深度学习 开发工具 Python
【Azure 应用服务】使用Python Azure SDK 来获取 App Service的访问限制信息(Access Restrictions)
【Azure 应用服务】使用Python Azure SDK 来获取 App Service的访问限制信息(Access Restrictions)
|
3月前
|
开发工具 数据安全/隐私保护 Python
【Azure 环境】通过Python SDK收集所有订阅简略信息,例如订阅id 名称, 资源组及组内资源信息等,如何给Python应用赋予相应的权限才能获取到信息呢?
【Azure 环境】通过Python SDK收集所有订阅简略信息,例如订阅id 名称, 资源组及组内资源信息等,如何给Python应用赋予相应的权限才能获取到信息呢?
|
3月前
|
缓存 JavaScript 前端开发
微信 JS-SDK Demo “分享信息设置” API 及数字签名生成方法(NodeJS版本)
微信 JS-SDK Demo “分享信息设置” API 及数字签名生成方法(NodeJS版本)更新时间(2020-10-29)
|
6月前
|
开发工具 Python
【SLS开源兼容系列】使用ES SDK 访问SLS
本文介绍如何用es sdk访问sls
164 0
|
6月前
|
开发工具 Android开发
Android获取SDK的版本信息
Android获取SDK的版本信息
73 0
|
6月前
|
JSON JavaScript 前端开发
全面的.NET微信网页开发之JS-SDK使用步骤、配置信息和接口请求签名生成详解
全面的.NET微信网页开发之JS-SDK使用步骤、配置信息和接口请求签名生成详解
|
移动开发 JavaScript 前端开发
uniapp在H5获取当前定位信息不需要SDK可直接获取城市(包括经纬度省市区和市区编码)
最近在做获取用户当前定位信息的时候,发现uniapp官方提供的兼容性并不是特别好,光注意事项都是密密麻麻一大堆,在实际使用场景下,效果并不理想,也不是很稳定。于是便重新封装了一下腾讯地图的一些东西,提高了下兼容度!下边我会把我用的封装思路逻辑给大家一一讲解。完整代码可私信我我发给你以上便是基于uni-app框架开发,使用Promise进行异步请求和结果返回,封装的H5获取当前详细定位信息组件希望大家一起交流。
1642 0
|
移动开发 人工智能 文字识别
uniapp 前端实现文字识别,身份证识别,营业执照识别 (兼容APP、H5、小程序 不需要任何SDK)
本文将介绍如何使用uniapp和百度AI开放平台的OCR(光学字符识别)API实现身份证、营业执照等卡证的识别和文字识别功能。以上就是uniapp使用百度AI平台OCR API实现卡证识别和文字识别的整体实现过程全部内容了,有不懂的,或者我代码有误的地方,希望大家多多交流。具体详细代码示例可以私信问我要哈!
684 0