android Notification分析——你可能遇到的各种问题

通知的使用网上有各种总结,csdn上也有很多总结非常到位,在此就不做重复的总结了,需要的同学可以自行搜索或者参考下面给出的链接。开始学习的时候认真的读了一些,现在功能开发完毕,把自己最近遇到的一些问题和心得分享给大家。

一、很难逃避de兼容问题

1、直接new Notification()这种方式已经过时,因此自己也没有去细究这种方式,直接使用的是new NotificationCompat.Builder(context).build()(这个在support v4包中,下面的内容全是以这种方式来实现的)

2、自定义布局的兼容

使用NotificationCampat来做自定义布局我们可以这样做:

RemoteViews rvMain = new RemoteViews(context.getPackageName(), R.layout.notification_layout);
//TODO rvMain...
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
				.setContent(rvMain);
// TOOD ...

在4.0以上,这样是没问题,但是在2.3的时候,你会发现这样根本无效,因此我们需要换一种方式:

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;
}

3、通知栏上的操作事件

先说说我们可以处理的通知事件:

setContentIntent():用户点击通知时触发

setFullScreenIntent()://TODO 这个在通知显示的时候会被调用

setDeleteIntent():用户清除通知时触发,可以是点击清除按钮,也可以是左右滑动删除(当然了,前提是高版本)

2.3及以下是无法处理自定义布局中的操作事件的,这样我们就不要去考虑增加自定义按钮了。

二、可能会遇到的问题

1、Ticker图标显示只有中间一部分

new NotificationCompat.Builder(context).setSmallIcon(R.drawable.ic_notice_small, 0)

我们可以通过这样的方式来设置Ticker时显示的图标。在我们测试的时候小米和sony的机器上出现过,解决办法是把之前的大图标(我们最初是72×72)替换成现在的32×32的小图标,并把它从之前的xxhdpi移到hdpi文件夹中。

2、Ticker不显示:直接显示通知的图标,中间的Ticker过程没有显示

这个没有找到是什么原因,直接把setFullScreenIntent(mPIFullScreen, false)这行注销即可

3、点击通知,通知列表不消失

这个只在华为的一个机器上遇到过,解决办法是在点击事件之后发一个关闭的广播:

sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));

参考:http://stackoverflow.com/questions/18261969/clicking-android-notification-actions-does-not-close-notification-drawer

4、出现各种乱

这里说的混乱是指通知没有显示出来、多条通知点击触发的事件相同、多条通知的Intent相同等等。这个时候你可能需要去检查通知的ID和PendingIntent的requestCode。

5、各种机型的适配

这个是相当混乱的,比如大多数是黑底白字,但是部分华为机型是灰底黑字;有些不支持设置自定义布局中的字体颜色;有些会屏蔽自定义布局的背景颜色和透明度,有些甚至你只能自定义通知栏的部分布局(左面的图标是改不了的):

曾经为了追求自定义布局的左侧图标和默认通知的左侧图标宽度相同,大小相仿,做了很多适配,比如各种dimens,但是仅仅是适配,还是不能支持所有机型,遂放弃了。到目前为止没找到一个完美的解决方案,市面上很多优秀的应用做的也不是非常好,对比下左侧图标宽度你就知道。最近在墨迹天气中发现这个功能:

这算不算对混乱的一种妥协呢?

三、自定义的一些扩展

从开始处理通知中的操作事件,到实现一个比现有通知更高的通知,我们的欲望在不断的增加。虽然美好的东西总是来得晚一些,但是目前来看,这些想法我们都可以实现了。

4.1中默认的三种big style可以满足我们很多时候的需求,比如:

从左到右依次应该为BigTextStyle、BigPictureStyle、InboxStyle,这个就不多说了,照着demo就能弄出来。下面是百度音乐播放器的通知效果,在此简单实现下,效果如图:

知道怎么做了,其实是很容易实现的,但关键的是不知道怎么做。首先看到这个效果,自己去尝试了各种方法,比如指定视图的高度,在不同的机器(主要是高版本的)机器上运行,发现都不行,google一下,没有结果。怎么办?反编译吧,在资源文件中发现了layout-v16文件夹下有个布局,这个布局就是我们上图的布局,在一大堆java文件中找到这样一行代码:

notification.bigContentView = *****;

怎么样?明白了吧~~就是关键句,查看api,这个属性需要16及以上才支持,因此我们在实现的时候可以这样写:

if(Build.VERSION.SDK_INT >= 16){
	notification.bigContentView = rvMain;
}

将我们自己的RemoteView付给bigContentView。真正实现的时候你可能会发现,这个高度不是我们任意指定的,是的,却是如此,他的高度是100dp。这样我们就可以通过自定义RemoteView来实现各种绚丽的通知了。

四、通知NotificationManager的源码

本想在分析下NotificationManager,但是发现他的代码很少,只要完成自己的Notification然后调用它的方法就可以。具体的实现就是底层的事情了,又到软肋的

不过简单浏览还是发现了一点点——和Toast的关联,他们都使用了INotificationManager:

    static private INotificationManager getService() {
        if (sService != null) {
            return sService;
        }
        sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification"));
        return sService;
    }

Toast的show():

    /**
     * Show the view for the specified duration.
     */
    public void show() {
        if (mNextView == null) {
            throw new RuntimeException("setView must have been called");
        }

        INotificationManager service = getService();
        String pkg = mContext.getPackageName();
        TN tn = mTN;
        tn.mNextView = mNextView;

        try {
            service.enqueueToast(pkg, tn, mDuration);
        } catch (RemoteException e) {
            // Empty
        }
    }

NotificatioManager的notify():

    /**
     * Post a notification to be shown in the status bar. If a notification with
     * the same tag and id has already been posted by your application and has not yet been
     * canceled, it will be replaced by the updated information.
     *
     * @param tag A string identifier for this notification.  May be {@code null}.
     * @param id An identifier for this notification.  The pair (tag, id) must be unique
     *        within your application.
     * @param notification A {@link Notification} object describing what to
     *        show the user. Must not be null.
     */
    public void notify(String tag, int id, Notification notification)
    {
        int[] idOut = new int[1];
        INotificationManager service = getService();
        String pkg = mContext.getPackageName();
        if (notification.sound != null) {
            notification.sound = notification.sound.getCanonicalUri();
            if (StrictMode.vmFileUriExposureEnabled()) {
                notification.sound.checkFileUriExposed("Notification.sound");
            }
        }
        if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
        try {
            service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
                    notification, idOut, UserHandle.myUserId());
            if (id != idOut[0]) {
                Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
            }
        } catch (RemoteException e) {
        }
    }

参考(引用):

http://blog.csdn.net/vipzjyno1/article/details/25248021

http://blog.csdn.net/feng88724/article/details/6259071

android Notification分析——你可能遇到的各种问题

时间: 2024-10-11 05:34:30

android Notification分析——你可能遇到的各种问题的相关文章

android Notification 的使用(锁定通知栏)

最近一直在研究 android ,并一边研究一边做应用.其中遇到了把程序通知常驻在 Notification 栏,并且不能被 clear 掉(就像android QQ一样)的问题.经过研究实现了其功能,现把 Notification 的使用总结如下: Notification 的使用需要导入 3 个类 1 2 3 import android.app.PendingIntent; import android.app.NotificationManager; import android.app

Android Volley分析(二)——实现

在Android Volley分析(一)--结构中主要分析了Volley的基本组件和框架结构,组件主要是定义的接口,也就是说我们可以实现这些接口来定制自己的Volley版本,比如NetWork.Cache.Request等等.Android Volley在com.android.volley.toolbox下已经做了这些工作,下面就看看这些具体的实现内容 先看一个Volley使用的例子 final TextView mTextView = (TextView) findViewById(R.id

Android多线程分析之四:MessageQueue的实现

罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 在前面两篇文章<Android多线程分析之二:Thread的实现>,<Android多线程分析之三:Handler,Looper的实现>中分别介绍了 Thread 的创建,运行,销毁的过程以及 Thread与 Handler,Looper 之间的关联:Thread 在其 run() 方法中创建和运行消息处理循环 Looper,而 Looper::loop() 方法不断地从 Messag

Android多线程分析之二:Thread的实现

Android多线程分析之二:Thread 罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 在前文<Android多线程分析之一:使用Thread异步下载图像>中演示了如何使用 Thread 处理异步事务.示例中这个 Java Thread 类都是位于 Framework 层的类,它自身是通过 JNI 转调 dalvik 里面的 Thread 相关方法实现的.因此要分析 Androd 中的线程,就需要分析这两层中的与线程相关的代码,这就是本文要

Android多线程分析之一:使用Thread异步下载图像

罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 打算整理一下对 Android Framework 中多线程相关知识的理解,主要集中在 Framework 层的 Thread, Handler, Looper, MessageQueue, Message, AysncTask,当然不可避免地要涉及到 native 方法,因此也会分析 dalvik 中和线程以及消息处理相关的代码:如 dalvik 中的 C++ Thread 类以及 Message

Android Framework 分析---消息机制Native层

在Android的消息机制中,不仅提供了供Application 开发使用的java的消息循环.其实java的机制最终还是靠native来实现的.在native不仅提供一套消息传递和处理的机制,还提供了自定义文件描述符的I/O时间的监听机制.下面我们从具体代码中分析一下. Native层的关键类: Looper.cpp.该类中提供了pollOnce 和wake的休眠和唤醒机制.同时在构造函数中也创建 管道 并加入epoll的机制中,来监听其状态变化. Looper::Looper(bool al

Android多线程分析之五:使用AsyncTask异步下载图像

Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<Android多线程分析之中的一个:使用Thread异步下载图像>中.曾演示了怎样使用 Thread 来完毕异步任务. Android 为了简化在 UI 线程中完毕异步任务(毕竟 UI 线程是 app 最重要的线程).实现了一个名为 AysncTask 的模板类.使用 AysncTask 能够在异步任务进行的同

android Notification和NotificationManager的使用

Notification和NotificationManager 1.Broadcast Receiver组件没有提供可视化的界面来显示广播信息.这里我们可以使用Notification和NotificationManager来实现可视化的信息显示.通过使用它们我们可以显示广播信息的内容,图标 以及震动等信息. 2.使用Notification和NotificationManager也比较简单,一般获得系统级的服务NotificationManager,然后实例化Notification,设置其

Android Binder分析二:Natvie Service的注冊

这一章我们通过MediaPlayerService的注冊来说明怎样在Native层通过binder向ServiceManager注冊一个service,以及client怎样通过binder向ServiceManager获得一个service,并调用这个Service的方法. Native Service的注冊 这里以MediaPlayerService举例来说明怎样在Native层注冊Service,首先来看main_mediaservice.cpp的main方法: int main(int a