Android 适配---notification led 呼吸灯

题外话:

2010年10月乔帮主在投资人和华尔街分析师的季度收益电话会议结束前,描述了Android是一个低劣的产品。

“消费者很难使用Android,因为每一部Android手机的操作系统都是不一样的。同样的原因,开发者很难为Android开发软件。Android是开放的,IOS是封闭的这个是Android的优势?这对用户和开发者来说都会是一团糟。 ”—《移动风暴》

这个时候我刚刚大学毕业,见到了一部Android手机联想的–乐phone,瞬间感觉Android这个平台是解救沉陷在kjava、塞班、黑莓等等这些机型的海洋里福音。

四年过去了,发现历史在重复。程序员的宿命从来没有改变,google宣称为开发者创造了天堂,地狱就是在创造天堂的过程中产生的,程序员在这个轮回里没有出来过。

当google看到iphone发展形式,拉里佩奇,和安迪鲁宾他们感到焦虑,ios构建了一个完整的系统,Android提供了一个更为广阔的平台–开放手机联盟。

开放,允许厂商可以定制系统上面系统级app,桌面、电话短信、图库、相机等等。Android平台提供系统级别的接口,这样手机厂商有了很大的自由度,这种自由度造成了现在Android系统“百花齐放”的景象,这个给广大用户带来了一定的困扰,广大开发者更是“菊花残,满地伤”。

对于Android App,业务功能实现后还有很大一部分工作需要放在软件测试和适配开发中,这是个痛苦的过程。每当看到miui等国内厂商开始鼓吹深度定制rom之类的字眼时,真想过去掴他几个大嘴巴子(我不是米黑,就事论事),这种所谓的深度定制就是修改包括launcher在内的很多系统级应用和一部分底层优化开发。这些所谓的深度定制给开发者带来极大的困然。定制、优化rom的团队希望大家有些节操。

适配开发的困境:

Android SDK 差异   x    手机硬件差异   x   无良厂商   x   rom修改    x     用户实际环境(所谓杀毒软件等会干扰程序运行) =  适配开发是个无底洞。

结果:

即使是BAT这些大厂子,不可能适配所有的情况,只能尽可能覆盖机型。对于广大中小开发者来说这个更是噩梦一般,很多比较优秀的个人app出了ios版本,当问作者或者是团队为什么不做Android版本?答案是:适配开发工作量太大,个人\小团队负担不起。

notification

 sdk版本的适配:

3.0 版本的notification做了改版,4.0 、5.0又做了比较大的改动。

3.0主要升级了pad相关的东西(google面临ipad带来的压力)

4.0 在加入了更多的新特性详细见设计文档

5.0多屏升级。

不知道这两次调整和屏幕的尺寸有多少相关关系。

Google 官方的文档是最好的学习材料—-第一手的。

国内出版的一些书的质量确实不敢恭维,加上Android这个变态的更新节奏,书籍往往跟不上节奏,网络信息又比较零散,看文档吧,英文不行慢慢看。

notification是什么?

A notification is a message you can display to the user outside of your application’s normal UI. When you tell the system to issue a notification, it first appears as an icon in the notification area. To see the details of the notification, the user opens the notification drawer. Both the notification area and the notification drawer are system-controlled areas that the user can view at any time.

notification和app的ui不在一个体系里,notification是系统级的组件,app向系统发送通知系统通过通知栏通知用户消息,通过通知栏下拉提供通知的详细信息和通知相关的跳转。

通知:提醒用户注意某个事件,比如:QQ收到消息、音乐下载(进度)完成等等

——————————————————————————————————–

设计:

http://developer.android.com/design/patterns/notifications.html#interacting-with-notifications

文档里面的内容比较多,除了讲notification的构成还讲了很多交互设计的东西,notification毕竟是要打断用户的操作的一个行为,为了不伤害用户体验,产品设计必须明确自己是否真的需要一个notification,Android设备上各种notification确实相当烦人,个人最反感的是那些应用升级的提醒。建议大家还是有些节操,遵守些规则。

———————————————————————————————————————————————————–

Api:

http://developer.android.com/guide/topics/ui/notifiers/notifications.html


——————————————————————————————————–

源码:

Notification源码:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.2_r1/android/app/Notification.java?av=f

类主要是一个数据结构的的封装,app层封装后使用NotificationManager发出:NotificationManager.notify()

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.2_r1/android/app/NotificationManager.java?av=f

Android 系统架构中:一个manager类对应一个aidl接口,一个manager对应一个底层的服务,notification也是这个架构

NotificationManager  —-  INotificationManager  —- com.android.server.NotificationManagerService

Manager中调用notify方法

117    public void notify(String tag, int id, Notification notification)
118    {
119        int[] idOut = new int[1];
120        INotificationManager service = getService();
121        String pkg = mContext.getPackageName();
122        if (localLOGV) Log.v(TAG, pkg + “: notify(” + id + “, ” + notification + “)”);
123        try {
124            service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut);
125            if (id != idOut[0]) {
126                Log.w(TAG, “notify: id corrupted: sent ” + id + “, got back ” + idOut[0]);
127            }
128        } catch (RemoteException e) {
129        }
130    }

通过aidl接口调用到  NotificationManagerService中的enqueueNotificationWithTag方法中。

enqueue说明notification的内部维护着一个“队列”

MAX_PACKAGE_NOTIFICATIONS = 50;  这个final变量限制了单个app发送通知的次数为50个,如果达到了这个阀值,这个方法直接return掉了。

 public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid,String tag, int id, Notification notification, int[] idOut)这个方法一路走下去终于看到了led呼吸灯的处理。中间做了很多if处理,响铃和震动提醒

 updateLightsLocked();

 private LightsService.Light

这个Service 主要负责管灯,机器里可以控制的灯光都在这里处理

34     static final int LIGHT_ID_BACKLIGHT = 0;  背景灯
35     static final int LIGHT_ID_KEYBOARD = 1;   键盘灯
36     static final int LIGHT_ID_BUTTONS = 2;    
37     static final int LIGHT_ID_BATTERY = 3;
38     static final int LIGHT_ID_NOTIFICATIONS = 4;   通知灯
39     static final int LIGHT_ID_ATTENTION = 5;
40     static final int LIGHT_ID_BLUETOOTH = 6;
41     static final int LIGHT_ID_WIFI = 7;
42     static final int LIGHT_ID_COUNT = 8;
43 
44     static final int LIGHT_FLASH_NONE = 0;
45     static final int LIGHT_FLASH_TIMED = 1;
46     static final int LIGHT_FLASH_HARDWARE = 2;


116        private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
117            if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {
118                if (DEBUG) Slog.v(TAG, “setLight #” + mId + “: color=#”
119                        + Integer.toHexString(color));
120                mColor = color;
121                mMode = mode;
122                mOnMS = onMS;
123                mOffMS = offMS;
124                setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
125            }
126        }

最终调用了一个native方法,到底层去了。

private static native void setLight_native(int ptr, int light, int color, int mode,int onMS, int offMS, int brightnessMode);

public static final int LIGHT_ID_NOTIFICATIONS = 4; 

底层怎么处理这个东西的,学完这段开始搞c++   看看Android底层相关的支持。


    原文作者:你去了我想去的巴黎
    原文地址: https://blog.csdn.net/harry211/article/details/38089671
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞