首页 > 代码库 > 各种Notification详解,含工具类

各种Notification详解,含工具类

                                                           

    

  

 

 

昨天一天只写了两篇文章,效率超低。追其原因呢,其实我一直在研究notification的实现方式,今天研究完了给大家分享一下。本来想写个工具类来封装一下代码的,但是我发现notification的个性化元素太多了,做成一个方法的话参数又多的要死,于是我就将比较常见的方法做了封装,写了个不是很规整的工具类,至于内部的逻辑啊,点击跳转的事件啊,大家下载demo后看看代码应该就能明白了,最重要的是根据自己的需要选择好的方法。还有一点需要建议的是,如果你发的通知都是用同一个ID的话可能会出现通知叠加的情况,这点需要注意一下。还是那句话根据实际需要吧,如果我的通知类型都是一样的,用同一个ID叠加就让他叠加吧。好啦,下面我们来看代码。

 

首先还是布局文件,这里用的全是button,在布局界面直接绑定了监听器。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.kale.notification.MainActivity"     android:orientation="vertical">    <Button        android:id="@+id/normal_button_id"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="普通的通知"         android:onClick="buttonListener"/>    <Button        android:id="@+id/view_button_id"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="较为特别的通知"         android:onClick="buttonListener"/>    <Button        android:id="@+id/private_button_id"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="自定义布局的通知"         android:onClick="buttonListener"/>    <Button        android:id="@+id/big_button_id"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="可以显示多行信息的通知"         android:onClick="buttonListener"/>    <Button        android:id="@+id/progress_button_id"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="有进度条的通知"         android:onClick="buttonListener"/>    <Button        android:id="@+id/pic_button_id"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="有大图片的通知"         android:onClick="buttonListener"/>    <Button        android:id="@+id/btn_button_id"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="有两个按钮的通知"         android:onClick="buttonListener"/>            <Button        android:id="@+id/clear_button_id"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="40dp"        android:text="清除所有的通知"         android:onClick="buttonListener"/></LinearLayout>

 

自定义的通知布局

notification.xml

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"     android:background="#000000">    <ImageView        android:id="@+id/image"        android:layout_width="45dp"        android:layout_height="45dp"        android:layout_alignParentLeft="true"        android:layout_marginTop="8dp"        android:layout_marginBottom="8dp"        android:layout_marginLeft="8.0dip"        android:layout_marginRight="10dp"         android:src="@drawable/ic_launcher"/>    <TextView        android:id="@+id/text"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_below="@id/title"        android:layout_marginTop="3.0dip"        android:layout_toLeftOf="@+id/button"        android:layout_toRightOf="@id/image"        android:text="This is the text"        android:textColor="#ffffff"        android:textSize="16sp" />    <TextView        android:id="@+id/title"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignLeft="@+id/text"        android:layout_alignTop="@+id/image"        android:textStyle="bold"        android:text="title"        android:textColor="#ffffff"        android:textSize="16sp" />    <Button        android:id="@+id/button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignBottom="@+id/image"        android:layout_alignParentRight="true"        android:gravity="center_vertical"        android:text="跳转"        android:textColor="#ffffff" /></RelativeLayout>

 

点击通知信息,跳转的activity界面

other.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="horizontal" >    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_weight="0.50"        android:layout_gravity="center"        android:gravity="center_horizontal"        android:text="用PendingIntent跳转到的界面"        android:textAppearance="?android:attr/textAppearanceLarge" /></LinearLayout>

这个界面对应的activity就是个空的activity——OtherActivity.java,代码就不贴了。

 

主界面

MainAcitivity.java

package com.kale.notification;import android.app.Activity;import android.app.PendingIntent;import android.content.Intent;import android.os.Bundle;import android.os.SystemClock;import android.view.View;import android.widget.RemoteViews;public class MainActivity extends Activity {    NotificationAdmain admain;    static int NOTIFICATION_ID = 13565400;    Intent intent;    int smallIcon = R.drawable.ic_launcher;    String ticker = "来了条新的通知";    int LargeIcon = R.drawable.kale;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // 设置点击后启动的activity        intent = new Intent(MainActivity.this, OtherActivity.class);        admain = new NotificationAdmain(this,NOTIFICATION_ID);    }    public void buttonListener(View v) {        switch (v.getId()) {        case R.id.normal_button_id:            admain.normal_notification(intent, smallIcon, ticker, "普通的通知",                    "采用默认配置,这里的文字只能显示一行,会将多余的字影藏");            break;        case R.id.view_button_id:            admain.special_notification(intent, smallIcon, ticker, LargeIcon,                    "特殊的通知", "这里面大小图标同时存在,并且有数字");            break;        case R.id.private_button_id:            //设置自定义布局中按钮的跳转界面            Intent btnIntent = new Intent(MainActivity.this,OtherActivity.class);            btnIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);            //如果是启动activity,那么就用PendingIntent.getActivity,如果是启动服务,那么是getService            PendingIntent Pintent = PendingIntent.getActivity(this,                     (int) SystemClock.uptimeMillis(), btnIntent, PendingIntent.FLAG_UPDATE_CURRENT);                         // 自定义布局            RemoteViews remoteViews = new RemoteViews(getPackageName(),                    R.layout.notification);            remoteViews.setImageViewResource(R.id.image, R.drawable.kale);            remoteViews.setTextViewText(R.id.title, "自定义通知视图");            remoteViews.setTextViewText(R.id.text, "这个自定义通知栏只能这么高了,不能有再多的内容了");            remoteViews.setOnClickPendingIntent(R.id.button, Pintent);//定义按钮点击后的动作            admain.view_notification(remoteViews, intent, smallIcon, ticker);            break;        case R.id.big_button_id:            admain.big_notification(intent, smallIcon, ticker, "可以随内容变长的通知",                    "《天之界线》是Jack.Tony在2009年3月开始动笔的一本小说。"                            + "其内容包涵了悬疑,穿越,魔法,冒险等元素。 Jack.Tony于2009年秋季完成了"                            + "《天之界线》的序章——沉睡的容器。");            break;        case R.id.progress_button_id:            admain.progress_notification(intent, smallIcon, ticker, "有进度条的通知信息","正在下载中……");            break;        case R.id.pic_button_id:            admain.pic_notification(intent, smallIcon, ticker, "有大图片的通知信息", LargeIcon);            break;        case R.id.btn_button_id:            admain.btn_notification(intent,smallIcon, ticker, "有按钮的通知", "下面的按钮可点击");            break;        case R.id.clear_button_id:            admain.clear();            break;        default:            break;        }    }}

 

好,现在重头戏来了。

NotificationAdmain.java

package com.kale.notification;import android.app.Activity;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.content.Context;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.SystemClock;import android.support.v4.app.NotificationCompat;import android.widget.RemoteViews;public class NotificationAdmain {    private static int NOTIFICATION_ID;    private NotificationManager nm;    private Notification notification;    private NotificationCompat.Builder cBuilder;    private Notification.Builder nBuilder;    private Context mContext;    int requestCode = (int) SystemClock.uptimeMillis();    private static final int FLAG = Notification.FLAG_INSISTENT;    public NotificationAdmain(Context context, int ID) {        this.NOTIFICATION_ID = ID;        mContext = context;        // 获取系统服务来初始化对象        nm = (NotificationManager) mContext                .getSystemService(Activity.NOTIFICATION_SERVICE);        cBuilder = new NotificationCompat.Builder(mContext);    }    /**     * 设置在顶部通知栏中的各种信息     *      * @param intent     * @param smallIcon     * @param ticker     */    private void setCompatBuilder(Intent intent, int smallIcon, String ticker,            String title, String msg) {        // 如果当前Activity启动在前台,则不开启新的Activity。        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);        // 当设置下面PendingIntent.FLAG_UPDATE_CURRENT这个参数的时候,常常使得点击通知栏没效果,你需要给notification设置一个独一无二的requestCode        // 将Intent封装进PendingIntent中,点击通知的消息后,就会启动对应的程序        PendingIntent pIntent = PendingIntent.getActivity(mContext,                requestCode, intent, FLAG);        cBuilder.setContentIntent(pIntent);// 该通知要启动的Intent        cBuilder.setSmallIcon(smallIcon);// 设置顶部状态栏的小图标        cBuilder.setTicker(ticker);// 在顶部状态栏中的提示信息        cBuilder.setContentTitle(title);// 设置通知中心的标题        cBuilder.setContentText(msg);// 设置通知中心中的内容        cBuilder.setWhen(System.currentTimeMillis());        /*         * 将AutoCancel设为true后,当你点击通知栏的notification后,它会自动被取消消失,         * 不设置的话点击消息后也不清除,但可以滑动删除         */        cBuilder.setAutoCancel(true);        // 将Ongoing设为true 那么notification将不能滑动删除        // notifyBuilder.setOngoing(true);        /*         * 从Android4.1开始,可以通过以下方法,设置notification的优先级,         * 优先级越高的,通知排的越靠前,优先级低的,不会在手机最顶部的状态栏显示图标         */        cBuilder.setPriority(NotificationCompat.PRIORITY_MAX);        /*         * Notification.DEFAULT_ALL:铃声、闪光、震动均系统默认。         * Notification.DEFAULT_SOUND:系统默认铃声。         * Notification.DEFAULT_VIBRATE:系统默认震动。         * Notification.DEFAULT_LIGHTS:系统默认闪光。         * notifyBuilder.setDefaults(Notification.DEFAULT_ALL);         */        cBuilder.setDefaults(Notification.DEFAULT_ALL);    }    /**     * 设置builder的信息,在用大文本时会用到这个     *      * @param intent     * @param smallIcon     * @param ticker     */    private void setBuilder(Intent intent, int smallIcon, String ticker) {        nBuilder = new Notification.Builder(mContext);        // 如果当前Activity启动在前台,则不开启新的Activity。        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);        PendingIntent pIntent = PendingIntent.getActivity(mContext,                requestCode, intent, FLAG);        nBuilder.setContentIntent(pIntent);        nBuilder.setSmallIcon(smallIcon);        nBuilder.setTicker(ticker);        nBuilder.setWhen(System.currentTimeMillis());        nBuilder.setPriority(NotificationCompat.PRIORITY_MAX);        nBuilder.setDefaults(Notification.DEFAULT_ALL);    }    /**     * 普通的通知     *      * @param intent     * @param smallIcon     * @param ticker     * @param title     * @param msg     */    public void normal_notification(Intent intent, int smallIcon,            String ticker, String title, String msg) {        setCompatBuilder(intent, smallIcon, ticker, title, msg);        sent();    }    /**     * 进行多项设置的通知(在小米上似乎不能设置大图标,系统默认大图标为应用图标)     *      * @param intent     * @param smallIcon     * @param ticker     * @param LargeIcon     * @param title     * @param msg     */    public void special_notification(Intent intent, int smallIcon,            String ticker, int LargeIcon, String title, String msg) {        setCompatBuilder(intent, smallIcon, ticker, title, msg);        // 如果不设置LargeIcon,那么系统会默认将上面的SmallIcon作为主要图标,显示在通知选项的最左侧,右下角的小图标将不再显示        Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(),                LargeIcon);        cBuilder.setLargeIcon(bitmap);                // 将Ongoing设为true 那么notification将不能滑动删除        cBuilder.setOngoing(true);        // 删除时        Intent deleteIntent = new Intent(mContext, DeleteService.class);        int deleteCode = (int) SystemClock.uptimeMillis();        // 删除时开启一个服务        PendingIntent deletePendingIntent = PendingIntent.getService(mContext,                deleteCode, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT);        cBuilder.setDeleteIntent(deletePendingIntent);        cBuilder.setDefaults(Notification.DEFAULT_SOUND | // 设置使用默认的声音                Notification.DEFAULT_LIGHTS);// 设置使用默认的LED        cBuilder.setVibrate(new long[] { 0, 100, 200, 300 });// 设置自定义的振动        cBuilder.setAutoCancel(true);        // builder.setSound(Uri.parse("file:///sdcard/click.mp3"));        // 设置通知样式为收件箱样式,在通知中心中两指往外拉动,就能出线更多内容,但是很少见        cBuilder.setNumber(3);        cBuilder.setStyle(new NotificationCompat.InboxStyle()                .addLine("M.Lynn 你好,我是kale").addLine("M.Lynn 已收到,保证完成任务")                .addLine("M.Lynn 哈哈,明白了~").setSummaryText("+3 more")); // 设置在细节区域底端添加一行文本        sent();    }    /**     * 自定义视图的通知     *      * @param remoteViews     * @param intent     * @param smallIcon     * @param ticker     */    public void view_notification(RemoteViews remoteViews, Intent intent,            int smallIcon, String ticker) {        setCompatBuilder(intent, smallIcon, ticker, null, null);        notification = cBuilder.build();        notification.contentView = remoteViews;        // 发送该通知        nm.notify(NOTIFICATION_ID, notification);    }    /**     * 可以容纳多行提示文本的通知信息 (因为在高版本的系统中才支持,所以要进行判断)     *      * @param intent     * @param smallIcon     * @param ticker     * @param title     * @param msg     */    public void big_notification(Intent intent, int smallIcon, String ticker,            String title, String msg) {        final int sdk = android.os.Build.VERSION.SDK_INT;        if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {            normal_notification(intent, smallIcon, ticker, title, msg);        } else {            setBuilder(intent, smallIcon, ticker);            nBuilder.setContentTitle(title);            nBuilder.setPriority(Notification.PRIORITY_HIGH);            notification = new Notification.BigTextStyle(nBuilder).bigText(msg)                    .build();            // 发送该通知            nm.notify(NOTIFICATION_ID, notification);        }    }    /**     * 有进度条的通知,可以设置为模糊进度或者精确进度     *      * @param intent     * @param smallIcon     * @param ticker     * @param title     * @param msg     */    public void progress_notification(Intent intent, int smallIcon,            String ticker, String title, String msg) {        setCompatBuilder(intent, smallIcon, ticker, title, msg);        /*         * 因为进度条要实时更新通知栏也就说要不断的发送新的提示,所以这里不建议开启通知声音。         * 这里是作为范例,给大家讲解下原理。所以发送通知后会听到多次的通知声音。         */        new Thread(new Runnable() {            @Override            public void run() {                int incr;                for (incr = 0; incr <= 100; incr += 10) {                    // 参数:1.最大进度, 2.当前进度, 3.是否有准确的进度显示                    cBuilder.setProgress(100, incr, false);                    // cBuilder.setProgress(0, 0, true);                    sent();                    try {                        Thread.sleep(1 * 500);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }                // 进度满了后,设置提示信息                cBuilder.setContentText("下载完成~").setProgress(0, 0, false);                sent();            }        }).start();    }    /**     * 容纳大图片的通知     *      * @param intent     * @param smallIcon     * @param ticker     * @param title     * @param bigPic     */    public void pic_notification(Intent intent, int smallIcon, String ticker,            String title, int bigPic) {        setCompatBuilder(intent, smallIcon, ticker, title, null);        NotificationCompat.BigPictureStyle picStyle = new NotificationCompat.BigPictureStyle();        Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(),                bigPic);        picStyle.bigPicture(bitmap);        cBuilder.setStyle(picStyle);        sent();    }    /**     * 里面有两个按钮的通知     *      * @param intent     * @param smallIcon     * @param ticker     * @param title     * @param msg     */    public void btn_notification(Intent intent, int smallIcon, String ticker,            String title, String msg) {        Intent notifyIntent = new Intent(mContext, OtherActivity.class);        int requestCode = (int) SystemClock.uptimeMillis();        PendingIntent pendIntent = PendingIntent.getActivity(mContext,                requestCode, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);        setCompatBuilder(intent, smallIcon, ticker, title, msg);        cBuilder.addAction(android.R.drawable.ic_media_previous,                mContext.getString(R.string.previous), pendIntent);        cBuilder.addAction(android.R.drawable.ic_media_next,                mContext.getString(R.string.next), pendIntent);        sent();    }    /**     * 发送通知     */    private void sent() {        notification = cBuilder.build();        // 发送该通知        nm.notify(NOTIFICATION_ID, notification);    }    /**     * 根据id清除通知     */    public void clear() {        // 取消通知        nm.cancelAll();    }}

 

点击通知,或者是删除通知的时候都可以用intent触发一个service或者是activity,这里是删除时候触发的service

DeleteService

package com.kale.notification;import android.app.IntentService;import android.content.Intent;import android.util.Log;public class DeleteService extends IntentService{    public DeleteService() {        super("");        // TODO Auto-generated constructor stub    }    @Override    protected void onHandleIntent(Intent intent) {        Log.i("LOG", "===========deleteService");    }}

 

最后,记得注册activity和service,把需要的权限也写上

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.kale.notification"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="8"        android:targetSdkVersion="18" />    <!-- 闪光灯的权限 -->    <uses-permission android:name="android.permission.FLASHLIGHT"/>    <!-- 振动的权限 -->    <uses-permission android:name="android.permission.VIBRATE"/>    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name=".MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <activity android:name="com.kale.notification.OtherActivity"/>        <service android:name="com.example.notificationtest.DeleteService" />    </application></manifest>