Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
AndroidÉϵÄNotification
 
À´Ô´£ºqiangbo.space ·¢²¼ÓÚ£º 2017-7-27
  2018  次浏览      27
 

ÔÚ±¾ÎÄÖУ¬ÎÒÃÇÀ´ÏêϸÁ˽âÒ»ÏÂAndroidÉϵÄNitificationʵÏÖ¡£

NotificationÊÇ×ÔAndroid·¢²¼ÒÔÀ´¾ÍÓеÄAPI£¬Ò²ÊÇÓ¦ÓóÌÐòÖÐ×î³£ÓõŦÄܵÄÖ®Ò»£¬¿ª·¢Õß¶ÔÆäÓ¦µ±ÊÇÏ൱µÄÊìϤÁË¡£

ÔÚAndroid½ü¼¸ÄêµÄ°æ±¾¸üÐÂÖУ¬¼¸ºõÿ¸ö°æ±¾¶¼»á¶Ôϵͳ֪ͨ½çÃæ£¬ÒÔ¼°Ïà¹ØAPI×öһЩµÄ¸Ä±ä¡£ÕâЩ¸Ä±äʹµÃ¿ª·¢Õß¿ÉÒÔ¸üºÃµÄ¿ØÖÆÓ¦ÓóÌÐòµÄ֪ͨÑùʽ£¬Í¬Ê±Ò²Ê¹µÃ֪ͨ¹¦ÄܸüÒ×ÓÚÓû§Ê¹Óá£

±¾ÎÄÎÒÃÇÀ´Ïêϸ¿´Ò»ÏÂNotification·½ÃæµÄ֪ʶ¡£

¿ª·¢ÕßAPI

ÕâÀï²»´òËã¶ÔNotification»ù±¾µÄʹÓ÷½Ê½×ö¹ý¶à½²½â£¬Õâ·½ÃæÄÚÈݶÔÓںܶ࿪·¢ÕßÀ´Ëµ¶¼ÒѾ­ÊǷdz£ÊìϤµÄÁË£¬²¢ÇÒÍøÂçÉÏÒ²ºÜÈÝÒ×ËÑË÷µ½Ïà¹ØÄÚÈÝ¡£

ÏÂÃæÖ»»á˵Ã÷Notification×ÔAndroid 5.0ÒÔÀ´µÄÐÂÔö¼Ó¹¦ÄÜ¡£

Heads-up Notification

Heads-up Notification ÊÇAndroid 5.0ÉϵÄÐÂÔö¹¦ÄÜ¡£

µ±É豸´¦ÓÚʹÓÃ״̬Ï£¨ÒѾ­½âËø²¢ÇÒÆÁÄ»ÁÁ×Å£©Ê±£¬ÕâÖÖ֪ͨÒÔÒ»¸öСµÄ¸¡¶¯´°¿ÚµÄÐÎʽ³ÊÏÖ³öÀ´£¬¾ÍÏñÏÂÃæÕâÑù£º

Õâ¸öÑùʽ¿´ÆðÀ´ÏñÊǶÔ֪ͨµÄÒ»ÖÖѹËõ£¬µ«ÊÇHeads-up Notification¿ÉÒÔ°üº¬Action Button¡£Óû§¿ÉÒÔµã»÷Action Button½øÐÐÏàÓ¦µÄ²Ù×÷£¬Ò²¿ÉÒÔ½«Õâ¸ö֪ͨ½çÃæÒÆ³ýµôµ«ÊDz»À뿪µ±Ç°Ó¦Óá£

Õâ¶ÔÓÚÓû§ÌåÑéÀ´ËµÊÇÒ»Ïî·Ç³£ºÃµÄ¸Ä½ø£¬ÏµÍ³µÄÀ´µç֪ͨ¾ÍÊÇÕâÖÖÐÎʽµÄ֪ͨ¡£ÔÚÉ豸´¦ÓÚʹÓÃ״̬ÏÂʱ£¬ÕâÖÖ֪ͨ¼È²»»á¸ÉÈÅÓû§µ±Ç°µÄÐÐΪ£¨¿ÉÒÔÖ±½Ó½«Í¨Öª½çÃæÒÆ³ýµô£©£¬ÓÖ·½±ãÁËÓû§¶ÔÓÚ֪ͨµÄ´¦Àí£¨¿ÉÒÔÖ±½Óµã»÷Action ButtonÀ´´¦Àí֪ͨ£©¡£

Ö»ÒªNotificationÂú×ãÏÂÃæµÄÁ½ÖÖÇé¿öÏÂÈκÎÒ»ÖÖ£¬¾Í»á²úÉúHeads-up Notification£º

NotificationÉèÖÃÁËfullScreenIntent

NotificationÊÇÒ»¸öHighÓÅÏȼ¶µÄ֪ͨ²¢ÇÒʹÓÃÁËÁåÉù»òÕð¶¯

ËøÆÁÉϵÄNotification

´ÓAndroid 5.0¿ªÊ¼£¬Í¨Öª¿ÉÒÔÔÚËøÆÁÉÏÏÔʾ¡£¿ª·¢Õß¿ÉÒÔÀûÓÃÕâ¸öÌØÐÔÀ´ÊµÏÖýÌå²¥·Å°´Å¥»òÕ߯äËû³£ÓõIJÙ×÷¡£µ«Í¬Ê±£¬Óû§Ò²¿ÉÒÔͨ¹ýÉèÖÃÀ´¾ö¶¨ÊÇ·ñÔÚËøÆÁ½çÃæÉÏÏÔʾij¸öÓ¦ÓõÄ֪ͨ¡£

¿ª·¢Õß¿ÉÒÔͨ¹ýNotification.Builder.setVisibility(int)·½·¨À´¿ØÖÆÍ¨ÖªÏÔʾµÄÏêϸ¼¶±ð¡£Õâ¸ö·½·¨½ÓÊÕÈý¸ö¼¶±ðµÄ¿ØÖÆ£º

VISIBILITY_PUBLIC ÏÔʾ֪ͨµÄÈ«²¿ÄÚÈÝ

VISIBILITY_PRIVATE ÏÔʾ֪ͨµÄ»ù±¾ÐÅÏ¢£¬ÀýÈç֪ͨµÄiconºÍtitle£¬µ«ÊDz»ÏÔʾÏêϸÄÚÈÝ

VISIBILITY_SECRET ²»ÏÔʾ֪ͨµÄÈκÎÄÚÈÝ

NotificationÖ±½Ó»Ø¸´

´ÓAndroid 7.0¿ªÊ¼£¬Óû§¿ÉÒÔÔÚ֪ͨ½çÃæÉϽøÐÐÖ±½Ó»Ø¸´¡£Ö±½Ó»Ø¸´°´Å¥¸½¼ÓÔÚ֪ͨµÄÏÂÃæ¡£

µ±Óû§Í¨¹ý¼üÅ̻ظ´Ê±£¬ÏµÍ³½«Óû§ÊäÈëµÄÎÄ×Ö¸½ÔÚ¿ª·¢ÕßÖ¸¶¨µÄIntentÉÏ£¬È»ºó·¢Ë͸ø¶ÔÓ¦µÄÓ¦Óá£

´´½¨Ò»¸ö°üº¬Ö±½Ó»Ø¸´°´Å¥µÄ֪ͨ·ÖΪÏÂÃæ¼¸¸ö²½Ö裺

´´½¨Ò»¸öPendingIntent£¬Õâ¸öPendingIntent½«ÔÚÓû§ÊäÈëÍê³Éµã»÷·¢ËͰ´Å¥Ö®ºó´¥·¢¡£Òò´ËÎÒÃÇÐèҪΪÕâ¸öPendingIntentÉèÖÃÒ»¸ö½ÓÊÜÕߣ¬ÎÒÃÇ¿ÉÒÔʹÓÃÒ»¸öBroadcastReceiverÀ´½øÐнÓÊÕ

´´½¨Ò»¸öRemoteInput.Builder¶ÔÏóʵÀý£¬Õâ¸öÀàµÄ¹¹Ô캯Êý½ÓÊÕÒ»¸ö×Ö·û´®×÷ΪKeyÀ´ÈÃϵͳ·ÅÈëÓû§ÊäÈëµÄÎÄ×Ö¡£ÔÚ½ÓÊÕ·½Í¨¹ýÕâ¸ökeyÀ´»ñÈ¡ÊäÈë

ͨ¹ýNotification.Action.Builder.addRemoteInput()·½·¨½«µÚ1²½´´½¨µÄRemoteInput¶ÔÏóÌí¼Óµ½Notification.ActionÉÏ

´´½¨Ò»¸ö֪ͨ°üº¬Ç°Ãæ´´½¨µÄNotification.Action£¬È»ºó·¢ËÍ

Ïà¹Ø´úÂëʾÀýÈçÏ£º

intent = new Intent(context, NotificationBroadcastReceiver.class);
intent.setAction(REPLY_ACTION);
intent.putExtra(KEY_NOTIFICATION_ID, notificationId);
intent.putExtra(KEY_MESSAGE_ID, messageId);
PendingIntent replyPendingIntent = PendingIntent.getBroadcast(
getApplicationContext(), 100, intent,
PendingIntent.FLAG_UPDATE_CURRENT);

// Key for the string that's delivered in the action's intent.
private static final String KEY_TEXT_REPLY = "key_text_reply";
String replyLabel = getResources().getString(R.string.reply_label);
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
.setLabel(replyLabel)
.build();

// Create the reply action and add the remote input.
Notification.Action action =
new Notification.Action.Builder(R.drawable.ic_reply_icon,
getString(R.string.label), replyPendingIntent)
.addRemoteInput(remoteInput)
.build();

// Build the notification and add the action.
Notification newMessageNotification =
new Notification.Builder(mContext)
.setSmallIcon(R.drawable.ic_message)
.setContentTitle(getString(R.string.title))
.setContentText(getString(R.string.content))
.addAction(action)
.build();

// Issue the notification.
NotificationManager notificationManager =
(NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(notificationId, newMessageNotification);

µ±Óû§µã»÷»Ø¸´°´Å¥Ê±£¬ÏµÍ³»áÌáʾÓû§ÊäÈ룺

µ±Óû§ÊäÈëÍê³É²¢µã»÷·¢ËͰ´Å¥Ö®ºó£¬ÎÒÃÇÉèÖõÄreplyPendingIntent±»»á´¥·¢¡£Ç°ÃæÎÒÃÇÉèÖÃÁËÒ»¸öBroadcastReceiverÀ´´¦ÀíÕâ¸öIntent£¬ÓÚÊÇÔÚBroadcastReceiverÖпÉÒÔͨ¹ýÏÂÃæÕâÑùµÄ·½Ê½À´»ñÈ¡Óû§ÊäÈëµÄÎı¾£º

private CharSequence getReplyMessage(Intent intent) {
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput != null) {
return remoteInput.getCharSequence(KEY_REPLY);
}
return null;
}

public void onReceive(Context context, Intent intent) {
if (REPLY_ACTION.equals(intent.getAction())) {
CharSequence message = getReplyMessage(intent);
int messageId = intent.getIntExtra(KEY_MESSAGE_ID, 0);

Toast.makeText(context, "Message ID: " + messageId + "\nMessage: " + message,
Toast.LENGTH_SHORT).show();
}
}

ÕâÀﻹÓÐÁ½µãÐèÒª¿ª·¢Õß×¢ÒâµÄ£º

Óû§µã»÷Íê·¢ËͰ´Å¥Ö®ºó£¬¸Ã°´Å¥»á±ä³ÉÒ»¸öÐýתµÄÑùʽ±íʾÕâ¸ö¶¯×÷»¹ÔÚ½øÐÐÖС£¿ª·¢ÕßÐèÒªÖØÐ·¢ËÍÒ»ÌõеÄ֪ͨÀ´¸üÐÂÕâ¸ö״̬

ͨ¹ýBroadcastReceiverÀ´´¦ÀíÕâ¸ö·¢ËÍʼþµÄͬʱ£¬Çë×¢Ò⽫BroadcastReceiverÔÚAndroidManifest.xmlÖеÄÅäÖÃÉèΪ£ºandroid:exported=¡±false¡±¡£·ñÔòÈκÎÓ¦Óö¼¿ÉÒÔ·¢ËÍÒ»ÌõIntentÀ´´¥·¢ÄãµÄBroadcastReceiver£¬Õâ¿ÉÄܶÔÄãÓ¦ÓÃÔì³ÉΣº¦¡£

Bundling Notifications

´ÓAndroid 7.0¿ªÊ¼£¬ÏµÍ³Ìṩһ¸öеķ½Ê½À´Õ¹Ê¾Á¬ÐøµÄ֪ͨ£ºBundling notifications¡£

ÕâÖÖչʾ·½Ê½ÌرðÊÊÓÃÓÚ¼´Ê±Í¨Ñ¶ÀàÓ¦Óã¬ÒòΪÕâÀàÓ¦Óûá³ÖÐø²»¶ÏµÄÊÕµ½ÐµÄÏûÏ¢²¢·¢ËÍ֪ͨ¡£ÕâÖÖչʾ·½Ê½ÊÇÒÔÒ»ÖÖ²ã´ÎÐԵĽṹÀ´×é֪֯ͨ¡£¶¥²¿ÊÇÏÔʾ×éÄÚ¸ÅÀÀÐÅÏ¢µÄÏûÏ¢£¬µ±Óû§½øÒ»²½Õ¹¿ª×éµÄʱºò£¬ÏµÍ³ÏÔʾ×éÄڵĸü¶àÐÅÏ¢¡£ÈçÏÂͼËùʾ£º

Notification.BuildÀàÖÐÌṩÁËÏàÓ¦µÄAPIÀ´½øÐÐÕâÖÖ֪ͨÑùʽµÄ¹ÜÀí£º

Notification.Builder.setGroup (String groupKey) ͨ¹ýgroupKey½«Í¨Öª¹éΪһ¸ö×é

Notification.Builder.set GroupSummary(boolean isGroupSummary) µ±isGroupSummary = trueʱ±íʾ½«¸ÃÌõ֪ͨÉèΪ×éÄÚµÄSummary֪ͨ

Notification.Builder.setSortKey (String sortKey) ϵͳ½«¸ù¾ÝÕâÀïÉèÖõÄsortKey½øÐÐÅÅÐò

Notification ÏûÏ¢Ñùʽ

´ÓAndroid 7.0¿ªÊ¼£¬ÏµÍ³ÌṩÁËMessagingStyle APIÀ´×Ô¶¨Òå֪ͨµÄÑùʽ¡£¿ª·¢Õß¿ÉÒÔ×Ô¶¨Òå֪ͨµÄ¸÷ÖÖLabel£¬°üÀ¨£º¶Ô»°Title£¬¸½¼ÓÏûÏ¢ÒÔ¼°Í¨ÖªµÄContent viewµÈ¡£ÏÂÃæÊÇÒ»¶Î´úÂëʾÀý£º

Notification notification = new Notification.Builder()
.setSmallIcon(R.drawable.ic_menu_camera)
.setStyle(new Notification.MessagingStyle("Me")
.setConversationTitle("Team lunch")
.addMessage("Hi", timestamp1, null) // Pass in null for user.
.addMessage("What's up?", timestamp2, "Coworker")
.addMessage("Not much", timestamp3, null)
.addMessage("How about lunch?", timestamp4, "Coworker"))
.build();

ÕâÌõ֪ͨÏÔʾ³öÀ´ÊÇÏÂÃæÕâ¸öÑù×Ó£º

֪ͨÀ¸Óë֪ͨ´°¿Ú

Íⲿ½çÃæ

֪ͨÀ¸Î»ÓÚ״̬À¸ÖУ¬ÔÚ״̬À¸µÄ×ó²àͨ¹ýһϵÁÐÓ¦ÓõÄIconÀ´ÏÔʾ֪ͨ£º

Óû§¿ÉÒÔͨ¹ý´ÓÆÁÄ»ÉϲàÏ»¬µÄ·½·¨Õ¹¿ªÍ¨Öª´°¿Ú£¬Í¨Öª´°¿ÚµÄÉÏ·½ÊÇQuick SettingsÇøÓò£¬Ï·½ÊÇ֪ͨÁÐ±í¡£Óû§¿ÉÒÔÕ¹¿ªQuick SettingsÇøÓò¡£

ÄÚ²¿ÊµÏÖ

ÔÚÁ˽âÁË֪ͨ½çÃæµÄÍâ¹ÛÖ®ºó£¬ÎÒÃǾÍÀ´¿´Ò»ÏÂϵͳÊÇÈçºÎʵÏÖÕâ¸ö½çÃæµÄ¡£

ÔÚSystemUIµÄʵÏÖÖУ¬Í¨¹ýXML²¼¾ÖÎļþÒÔ¼°Ò»ÏµÁÐ×Ô¶¨ÒåLayoutÀàÀ´¹ÜÀí֪ͨ½çÃæ¡£

Õû¸öStatus Barͨ¹ýsuper_status_bar.xmlÎļþÀ´½øÐв¼¾Ö£¬Õâ¸ö²¼¾ÖÎļþµÄ¸ùÔªËØÊÇÒ»¸ö×Ô¶¨ÒåµÄFrameLayout£¬ÀàÃûÊÇStatusBarWindowView¡£Õâ¸ö²¼¾ÖÎļþµÄ½á¹¹ÈçÏÂͼËùʾ£º

ÔÚÕâÀÎÒÃÇÖØµãÒª¹Ø×¢µÄ¾ÍÊÇÑ¡ÖеÄÁ½ÐУº

super_status_bar.xmlÖÐincludeÁËÒ»¸öÃû³ÆÎªstatus_barµÄ²¼¾ÖÎļþ

super_status_bar.xmlÖÐincludeÁËÒ»¸öÃû³ÆÎªstatus_bar_expandedµÄ²¼¾ÖÎļþ

ÕâÀïµÄstatus_bar±ãÊÇϵͳ״̬À¸µÄ²¼¾ÖÎļþ£¬status_bar_expanded±ãÊÇÏÂÀ­µÄ֪ͨ´°¿ÚµÄ²¼¾ÖÎļþ¡£

status_bar.xml²¼¾ÖÎļþ½á¹¹ÈçÏÂͼËùʾ¡£Õâ¸ö²¼¾ÖÎļþµÄ¸ùÔªËØÊÇÃû³ÆÎªPhoneStatusBarViewµÄ×Ô¶¨ÒåFrameLayoutÀà¡£

¶ÔÕÕÕâ¸ö²¼¾ÖÎļþºÍÊÖ»úÉϵÄ״̬À¸£¬ÎÒÏàÐŶÁÕßÓ¦¸ÃºÜÈÝÒ×Àí½âÁË£º

notification_icon_area ÕýÊÇϵͳÏÔʾ֪ͨiconµÄÇøÓò

system_icon_area ÊÇÏÔʾϵͳͼ±êµÄÇøÓò£¬ÀýÈ磺Wifi£¬µç»°ÐÅÏ¢ÒÔ¼°µç³ØµÈ

clock ÊÇ״̬À¸ÉÏÏÔʾʱ¼äµÄÇøÓò

ÏÂÃæÎÒÃÇÔÙÀ´¿´Ò»ÏÂstatus_bar_expanded.xmlÕâ¸ö²¼¾ÖÎļþµÄ½á¹¹£¬Õâ¸ö²¼¾ÖÎļþµÄ¸ùÔªËØÊÇÒ»¸öÃû³ÆÎªNotificationPanelViewµÄÀ࣬Õâ¸öÀàͬÑùÊÇÒ»¸ö×Ô¶¨ÒåµÄFrameLayout¡£

ÔÚÕâ¸ö²¼¾ÖÎļþÖУº

¶¥²¿ÊÇÒ»¸öÃû³ÆÎªkeyguard_status_viewµÄÔªËØ¡£Õâ¸ö±ãÊǸýçÃæÉϵÄ״̬À¸²¼¾Ö¡£Õâ¸ö״̬À¸ÏÔʾµÄÄÚÈݺÍͨ³£µÄ״̬À¸µÄÄÚÈÝÊÇÓÐËùÇø±ðµÄ£¬¶ÁÕß¿ÉÒԻص½ÉÏÃæÏàÓ¦µÄ½ØÍ¼¶Ô±Èһϲ»Í¬³¡¾°ÏÂ״̬À¸ÏÔʾµÄÄÚÈÝ

qs_auto_reinflate_container ÊÇÏÔʾQuick SettingsµÄÇøÓò¡£Õâ¸öÇøÓòÆäʵÊÇincludeÁËÒ»¸öÁíÍâ²¼¾ÖÎļþ£ºqs_panel.xml

notification_stack_scroller ±ãÊÇÕæÕýÏÔʾ֪ͨÁбíµÄµØ·½£¬ÕâÊÇÒ»¸öNotificationStackScrollLayoutÀàÐ͵ÄÔªËØ¡£´ÓÃû³ÆÉÏÎÒÃǾͿÉÒÔ¿´³ö£¬Õâ¸öÔªËØÊÇ¿ÉÒÔ¹ö¶¯µÄ£¬ÒòΪ֪ͨµÄÁбí¿ÉÄÜÊǺܳ¤µÄ¡£

ÉÏÃæÎÒÖ»´ó¸Å½²½âÁËÕâЩ½çÃæÖÐ×îÖ÷ÒªµÄÔªËØ£¬¶øÊµ¼ÊÉϲ¼¾ÖÖл¹Óзdz£¶àµÄÆäËûÔªËØ¡£ÕâÀïÎÒÃǾͲ»Ò»Ò»½²½âÁË¡£¶ÁÕß¿ÉÒÔ½èÖúAndroid StudioÉϵÄLayout Inspector¹¤¾ßÑ¡Ôñcom.android.systemui½ø³Ì£¬È»ºóÑ¡ÔñStatusBarÀ´Ïêϸ·ÖÎö¸Ã½çÃæÉϵÄÿһ¸öÔªËØ£¬Layout Inspector½çÃæ¿´ÆðÀ´ÏñÏÂÃæÕâÑù£º

Notification´Ó·¢Ë͵½ÏÔʾ

NotificationµÄ·¢ËÍ

ÓÐÁËÉÏÃæÍ¨Öª½çÃæ²¼¾ÖµÄ֪ʶ֮ºó£¬ÎÒÃÇÔÙ¿´Ò»Ï£¬Ó¦ÓóÌÐòÖз¢Ë͵Ä֪ͨÊÇÈçºÎ×îÖÕÏÔʾµ½ÏµÍ³µÄ֪ͨ½çÃæÉϵġ£

¿ª·¢Õßͨ¹ý´´½¨Notification¶ÔÏóÀ´·¢ËÍ֪ͨ¡£¸Ã¶ÔÏóÖмǼÁËÒ»Ìõ֪ͨµÄËùÓÐÏêϸÐÅÏ¢£¬NotificationÀàͼÈçÏÂËùʾ£º

ÕâÀïµÄºÜ¶à×Ö¶ÎÏàÐÅ¿ª·¢Õß¶¼ºÜÊìϤ£¬ÒòΪÕâЩ×ֶζ¼ÊÇÎÒÃÇ·¢ËÍ֪ͨʱҪÉèÖõġ£ÕâÀïÐèҪ˵Ã÷µÄÊÇBundle extrasÕâ¸ö×ֶΡ£BundleÒÔ¼üÖµ¶ÔµÄÐÎʽ´æ´¢ÁË¿ÉÒÔͨ¹ýIPC´«µÝµÄһϵÁÐÊý¾Ý¡£µ±ÎÒÃÇͨ¹ýNotification.buidler¹¹½¨Notification¶ÔÏóʱ£¬ÓÐһЩ×Ô¶¨ÒåÑùʽµÄÖµ¶¼ÊÇ´æÔÚÕâ¸öextras×Ö¶ÎÖеģ¬ÀýÈçÏÂÃæÕâЩ£º

public Builder setShowWhen(boolean show) {
mN.extras.putBoolean(EXTRA_SHOW_WHEN, show);
return this;
}

public Builder setSmallIcon(Icon icon) {
mN.setSmallIcon(icon);
if (icon != null && icon.getType() == Icon.TYPE_RESOURCE) {
mN.icon = icon.getResId();
}
return this;
}


public Builder setContentTitle(CharSequence title) {
mN.extras.putCharSequence(EXTRA_TITLE, safeCharSequence(title));
return this;
}

public Builder setContentText(CharSequence text) {
mN.extras.putCharSequence(EXTRA_TEXT, safeCharSequence(text));
return this;
}

public Builder setContentInfo(CharSequence info) {
mN.extras.putCharSequence(EXTRA_INFO_TEXT, safeCharSequence(info));
return this;
}

public Builder setProgress(int max, int progress, boolean indeterminate) {
mN.extras.putInt(EXTRA_PROGRESS, progress);
mN.extras.putInt(EXTRA_PROGRESS_MAX, max);
mN.extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, indeterminate);
return this;
}

public Builder setStyle(Style style) {
if (mStyle != style) {
mStyle = style;
if (mStyle != null) {
mStyle.setBuilder(this);
mN.extras.putString(EXTRA_TEMPLATE, style.getClass().getName());
} else {
mN.extras.remove(EXTRA_TEMPLATE);
}
}
return this;
}

NotificationÀàÊÇÒ»¸öParcelableÀ࣬ÕâÒâζ×ÅËü¿ÉÒÔͨ¹ýBinder±»¿ç½ø³Ì´«µÝ¡£

ÎÒÃÇͨ³£²»»áÊÖ¶¯´´½¨Notification£¬¶øÊÇͨ¹ýNotification.BuilderÀàÖеÄsetXXX·½·¨£¨ÉÏÃæÒѾ­ÁгöÁËһЩ£©À´´´½¨Notification¡£ºÜÏÔÈ»£¬Õâ¸öNotification.BuilderÀàʹÓõÄÊǵäÐ͵ÄBuilderÉè¼ÆÄ£Ê½£¬Í¨¹ýÕâ¸öÀ࣬¼ò»¯ÁËÎÒÃÇ´´½¨NotificationµÄ¹ý³Ì£¬ÏÂͼÊÇNotification.BuilderÀàµÄÀàͼ£º

Õâ¸öÀàÌṩÁ˷dz£¶àµÄsetXXX·½·¨ÈÃÎÒÃÇÉèÖÃNotificationµÄÊôÐÔ£¬²¢ÇÒÕâЩ·½·¨»á·µ»ØBuilder¶ÔÏó±¾ÉíÒÔ±ãÎÒÃÇ¿ÉÒÔÁ¬Ðøµ÷Óá£×îÖÕ£¬ÎÒÃÇͨ¹ýÒ»¸öbuild·½·¨»ñÈ¡µ½¹¹ÔìºÃµÄNotification¶ÔÏó¡£

NotificationManagerService

ÔÚ¹¹ÔìºÃÁËNotification¶ÔÏóÖ®ºó£¬ÎÒÃÇͨ¹ýNotificationManagerµÄpublic void notify (int id, Notification notification)£¨¼°ÆäÖØÔØ£©·½·¨ÕæÕý½«Í¨Öª·¢ËͳöÈ¥¡£

ÎÒÏàÐŶÁÕß×ÔÈ»ÄÜÏëµ½£¬Õâ¸öNotificationManagerÒ»¶¨Ò²ÊÇͨ¹ýBinderʵÏֵġ£

ȷʵû´í£¬ÕæÕýʵÏÖ֪ͨ·¢Ë͵ķþÎñ½Ð×öNotificationManagerService£¬Õâ¸öServiceͬÑùλÓÚsystem_server½ø³ÌÖС£

NotificationManager´ú±íÁË·þÎñµÄ¿Í»§¶Ë±»Ó¦ÓóÌÐòËùʹÓ㬶ø NotificationManagerServiceλÓÚϵͳ½ø³ÌÖнÓÊպʹ¦ÀíÇëÇó¡£ AndroidϵͳÖдóÁ¿µÄϵͳ·þÎñ¶¼ÊÇÕâÑùµÄʵÏÖÌ×·¡£

notify½Ó¿Ú×îÖÕ»áµ÷Óõ½NotificationManagerÖеÄÁíÒ»¸ö½Ð×önotifyAsUserµÄ½Ó¿ÚÀ´·¢ËÍ֪ͨ£¬ÆäʵÏÖÈçÏ£º

public void notifyAsUser (String tag, int id, Notification notification, UserHandle user)
{
int[] idOut = new int[1];
INotificationManager service = getService(); ¢Ù
String pkg = mContext.getPackageName();
// Fix the notification as best we can.
Notification.addFieldsFromContext (mContext, notification); ¢Ú
if (notification.sound != null) {
notification.sound = notification.sound.getCanonicalUri();
if (StrictMode.vmFileUriExposureEnabled()) {
notification.sound.checkFileUriExposed ("Notification.sound");
}
}
fixLegacySmallIcon(notification, pkg);
if (mContext.getApplicationInfo() .targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
if (notification.getSmallIcon() == null) {
throw new IllegalArgumentException ("Invalid notification (no valid small icon): "
+ notification); ¢Û
}
}
if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
final Notification copy = Builder.maybeCloneStrippedForDelivery (notification);
try {
service.enqueueNotificationWithTag (pkg, mContext.getOpPackageName(), tag, id,
copy, idOut, user.getIdentifier()); ¢Ü
if (localLOGV && id != idOut[0]) {
Log.v(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

Õâ¶Î´úÂë˵Ã÷ÈçÏ£º

ͨ¹ýgetService·½·¨»ñÈ¡NotificationManagerServiceµÄÔ¶³Ì·þÎñ½Ó¿Ú£¬getService·½·¨µÄʵÏÖÆäʵ¾ÍÊÇͨ¹ýServiceManagerÄõ½NotificationManagerServiceµÄBinder¶ÔÏó

ͨ¹ýmContextΪNotificationÌí¼ÓһЩ¸½¼ÓÊôÐÔ£¬ÕâÀïµÄmContext´ú±íÁ˵÷Ó÷¢ËÍ֪ͨ½Ó¿ÚµÄContext£¬ÏµÍ³·þÎñÖлáͨ¹ýÕâ¸öContextÀ´È·¶¨ÊÇË­ÔÚʹÓ÷þÎñ

ÔÚLOLLIPOP_MR1Ö®Éϵİ汾£¨API Level 22£©ÉÏ£¬·¢ËÍ֪ͨ±ØÐëÉèÖÃSmall Icon£¬·ñÔòÖ±½ÓÅ׳öÒì³£

µ÷ÓÃNotificationManagerServiceµÄÔ¶³Ì½Ó¿ÚÀ´ÕæÕý½øÐÐ֪ͨµÄ·¢ËÍ

½ÓÏÂÀ´ÎÒÃÇÒª¹Ø×¢µÄ×ÔÈ»ÊÇNotificationManagerService. enqueueNotificationWithTag·½·¨µÄʵÏÖ¡£

NotificationManagerServiceÏà¹Ø´úÂëλÓÚÒÔÏ·¾¶£º/frameworks/ base/services/core/java/com/android/server/notification/

ÔÚNotificationManagerService. enqueueNotificationWithTag·½·¨ÖУ¬»á½«Óû§·¢Ë͹ýÀ´µÄNotification¶ÔÏó°ü×°ÔÚÒ»¸öStatusBarNotification¶ÔÏóÖУº

final StatusBarNotification n = new StatusBarNotification(
pkg, opPkg, id, tag, callingUid, callingPid, 0, notification,
user);

È»ºóÓÖ½«StatusBarNotification°ü×°ÔÚNotificationRecord¶ÔÏóÖУº

final NotificationRecord r = new NotificationRecord(getContext(), n);

StatusBarNotification¹¹Ô캯ÊýÖÐµÄÆäËû²ÎÊý£¬ÃèÊöÁË·¢ËÍ֪ͨµÄµ÷ÓÃÕßµÄÉí·Ý£¬°üÀ¨£º°üÃû£¬µ÷ÓÃÕßµÄuid£¬pidµÈµÈ¡£Õâ¸öÉí·ÝµÄ×÷ÓÃÊÇ£ºÏµÍ³¿ÉÒÔÕë¶Ôµ÷ÓÃÕßÉí·ÝµÄ²»Í¬×ö²»Í¬µÄ´¦Àí¡£ÀýÈ磺Óû§¿ÉÄܹرÕÁËijЩӦÓõÄ֪ͨÏÔʾ£¬ÏµÍ³Í¨¹ýµ÷ÓÃÕßµÄÉí·Ý±ã¿ÉÒÔÈ·¶¨Õâ¸öÓ¦ÓõÄ֪ͨÊÇ·ñÐèÒªÏÔʾÔÚ֪ͨ½çÃæÉÏ¡£

¶ø¿´µ½NotificationRecord£¬¶ÁÕßÓ¦¸ÃºÜ×ÔÈ»ÄÜÏëµ½ActivityManagerServiceÖеÄActivityRecord£¬ProcessRecordµÈ½á¹¹¡£ÕâЩ¶¼ÊÇϵͳ·þÎñÖÐÓÃÀ´ÃèÊöÓ¦ÓóÌÐòÖжÔÏóµÄ¶ÔÓ¦½á¹¹¡£

ÏÂͼÃèÊöÁËÉÏÃæÈýÖֽṹµÄ°üº¬¹ØÏµ£º

ϵͳÔÚ´´½¨NotificationRecord¶ÔÏóÖ®ºó£¬»áPostÒ»¸öRunnableµÄTask½øÐÐ֪ͨµÄ·¢ËÍ£º

final NotificationRecord r = new NotificationRecord(getContext(), n);
mHandler.post(new EnqueueNotificationRunnable(userId, r));

ÔÚEnqueueNotificationRunnableÖУ¬ÐèÒª×öÏÂÃæ¼¸¼þÊÂÇ飺

´¦Àí֪ͨµÄ·Ö×é

¼ì²é¸Ã֪ͨÊÇ·ñÒѾ­±»×èÖ¹£¨Í¨¹ýµ÷ÓÃÕßµÄÉí·Ý£º°üÃû¼°uid£©

¶Ô֪ͨ½øÐÐÅÅÐò

Åж϶ÔÒÑÓÐ֪ͨ¸üУ¬»¹ÊÇ·¢ËÍÒ»ÌõеÄ֪ͨ

µ÷ÓÃNotificationListeners.notifyPostedLocked

Èç¹ûÐèÒª£º´¦ÀíÉùÒôºÍÕð¶¯

ÕâÀïÖ»ÓÐNotificationListeners.notifyPostedLockedÐèҪ˵Ã÷һϡ£

Ò»Ìõ֪ͨ·¢Ë͵½ÏµÍ³Ö®ºó£¬ÏµÍ³ÖпÉÄÜ»áÓкܶàÄ£¿é»á¶ÔÆä¸ÐÐËȤ£¨×î»ù±¾µÄ£¬»áÓÐÄ£¿éÒª½«Õâ¸ö֪ͨÏÔʾÔÚ֪ͨ½çÃæÉÏ£©¡£·¢ËÍ֪ͨÊÇÒ»¸öʼþ£¬´¦Àí֪ͨÊÇÒ»¸öÏìÓ¦£¬µ±Ê¼þµÄÏìÓ¦Õß¿ÉÄܲ»Ö¹Ò»¸öµÄʱºò£¬ÎªÁË´ïµ½½âñîÕâÁ½ÕßÖ®¼äµÄ¹ØÏµ£¬ºÜ×ÔÈ»µÄ»áʹÓÃÎÒÃdz£¼ûµÄ¼àÌýÆ÷Ä£ÐÍ£¨»òÕß½Ð×ö£ºObserverÉè¼ÆÄ£Ê½£©¡£

ϵͳÖУ¬¶ÔÓÚ֪ͨ¸ÐÐËȤµÄ¼àÌýÆ÷ͨ¹ýNotificationListenerServiceÀàÀ´±í´ï¡£¶øÕâÀïµÄNotificationListeners.notifyPostedLocked±ãÊǶÔËùÓеÄNotificationListenerService½øÐлص÷֪ͨ¡£

ÕâÆäÖÐÓÐÒ»¸ö×îÖØÒªµÄNotificationListenerService¾ÍÊÇBaseStatusBar¡£ÒòΪËü¾ÍÊǸºÔð½«Í¨ÖªÏÔʾÔÚ֪ͨ½çÃæÉϵļàÌýÆ÷¡£

NotificationµÄÏÔʾ

BaseStatusBarÖжÔÓÚ֪ͨ·¢Ë͵Ļص÷Âß¼­ÈçÏ£º

public void onNotificationPosted(final StatusBarNotification sbn,
final RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
if (sbn != null) {
mHandler.post(new Runnable() {
@Override
public void run() {
processForRemoteInput(sbn.getNotification());
String key = sbn.getKey(); ¢Ù
mKeysKeptForRemoteInput.remove(key);
boolean isUpdate = mNotificationData.get(key) != null; ¢Ú
if (!ENABLE_CHILD_NOTIFICATIONS
&& mGroupManager.isChildInGroupWithSummary(sbn)) {
if (DEBUG) {
Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);
}

// Remove existing notification to avoid stale data.
if (isUpdate) {
removeNotification(key, rankingMap); ¢Û
} else {
mNotificationData.updateRanking(rankingMap);
}
return;
}
if (isUpdate) {
updateNotification(sbn, rankingMap);
} else {
addNotification(sbn, rankingMap, null /* oldEntry */); ¢Ü
}
}
});
}
}

Õâ¶Î´úÂëµÄ˵Ã÷ÈçÏ£º

ÿ¸öStatusBarNotification¶ÔÏó¶¼ÓÐÒ»¸öKeyÖµ£¬Õâ¸öÖµ¸ù¾Ýµ÷ÓÃÕßµÄÉí·ÝÒÔ¼°µ÷ÓÃÕßÉèÖõÄ֪ͨidÉú³É¡£µ±Ó¦ÓóÌÐòͨ¹ýͬһ¸ö֪ͨid·¢ËÍÁ˶à´Î֪ͨ£¬ÕâЩ֪ͨµÄKeyÖµÊÇÒ»ÑùµÄ£¬ÓÉ´Ë¿ÉÒÔ¶Ô֪ͨ½øÐиüÐÂ

mNotificationData£¨ÀàÐÍΪNotificationData£©ÖмǼÁËϵͳËùÓеÄ֪ͨÁбí

Èç¹ûÊÇÒ»¸öÒѾ­´æÔÚµÄ֪ͨÐèÒª¸üУ¬ÔòÏȽ«´æÔÚµÄ֪ͨɾ³ý

addNotificationÊÇÒ»¸ö³éÏó·½·¨£¬ÓÉ×ÓÀàʵÏÖ

ÔÚÊÖ»úÉ豸ÉÏ£¬addNotificationÕâ¸ö·½·¨×ÔÈ»ÊÇÓÉPhoneStatusBarÀ´ÊµÏÖ¡£ÔÚaddNotification·½·¨ÖУ¬»áµ÷ÓÃupdateNotifications·½·¨À´×îÖÕ½«Í¨ÖªÏÔʾÔÚ֪ͨ½çÃæÉÏ£¬Æä´úÂëÈçÏÂËùʾ£º

protected void updateNotifications() {
mNotificationData.filterAndSort();

updateNotificationShade();
mIconController.updateNotificationIcons(mNotificationData);
}

ÕâÀïµÄupdateNotificationShade·½·¨±ãÊǽ«Í¨ÖªµÄÏÔʾÄÚÈÝÌí¼Óµ½Í¨ÖªÃæ°åµÄÏÔÊ¾ÇøÓò£ºNotificationStackScrollLayoutÖС£¶ømIconController.updateNotificationIcons (mNotificationData)ÔòÊÇÔÚnotification_icon_areaÇøÓòÌí¼Ó֪ͨIcon¡£

updateNotificationShade´úÂë±È½Ï³¤£¬µ«ÊÇÂß¼­ÊDZȽϺÃÀí½âµÄ¡£Ö÷ÌåÂß¼­¾ÍÊǶÔÿһ¸öÐèÒªÏÔʾµÄ֪ͨ´´½¨Ò»¸öExpandableNotificationRow£¬È»ºóÉèÖöÔÓ¦µÄÄÚÈݲ¢Ìí¼Óµ½NotificationStackScrollLayout(mStackScroller¶ÔÏó)ÖС£

ä¯ÀÀÒ»ÏÂÕâ¶Î´úÂë±ã¿ÉÒÔ¿´µ½ÎÒÃÇÔÚAPI²¿·Ö½²½âµÄһЩAPIÔÚϵͳ·þÎñÖеÄʵÏÖ£ºÕâÀïÁË´¦Àí֪ͨµÄ·Ö×飬visibilityµÈÏà¹ØÐÅÏ¢¡£

private void updateNotificationShade() {
if (mStackScroller == null) return;

// Do not modify the notifications during collapse.
if (isCollapsing()) {
addPostCollapseAction(new Runnable() {
@Override
public void run() {
updateNotificationShade();
}
});
return;
}

ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
ArrayList<ExpandableNotificationRow> toShow = new ArrayList<>(activeNotifications.size());
final int N = activeNotifications.size();
for (int i=0; i<N; i++) {
Entry ent = activeNotifications.get(i);
int vis = ent.notification.getNotification().visibility;

// Display public version of the notification if we need to redact.
final boolean hideSensitive =
!userAllowsPrivateNotificationsInPublic (ent.notification.getUserId());
boolean sensitiveNote = vis == Notification.VISIBILITY_PRIVATE;
boolean sensitivePackage = packageHasVisibilityOverride (ent.notification.getKey());
boolean sensitive = (sensitiveNote && hideSensitive) || sensitivePackage;
boolean showingPublic = sensitive && isLockscreenPublicMode();
if (showingPublic) {
updatePublicContentView(ent, ent.notification);
}
ent.row.setSensitive (sensitive, hideSensitive);
if (ent.autoRedacted && ent.legacy) {
// TODO: Also fade this? Or, maybe easier (and better), provide a dark redacted form
// for legacy auto redacted notifications.
if (showingPublic) {
ent.row.setShowingLegacyBackground(false);
} else {
ent.row.setShowingLegacyBackground(true);
}
}
if (mGroupManager.isChildInGroupWithSummary (ent.row.getStatusBarNotification())) {
ExpandableNotificationRow summary = mGroupManager.getGroupSummary(
ent.row.getStatusBarNotification());
List<ExpandableNotificationRow> orderedChildren =
mTmpChildOrderMap.get(summary);
if (orderedChildren == null) {
orderedChildren = new ArrayList<>();
mTmpChildOrderMap.put (summary, orderedChildren);
}
orderedChildren.add(ent.row);
} else {
toShow.add(ent.row);
}

}

ArrayList< ExpandableNotificationRow> toRemove = new ArrayList<>();
for (int i=0; i< mStackScroller.getChildCount(); i++) {
View child = mStackScroller.getChildAt(i);
if (!toShow.contains(child) && child instanceof ExpandableNotificationRow) {
toRemove.add ((ExpandableNotificationRow) child);
}
}

for (ExpandableNotificationRow remove : toRemove) {
if (mGroupManager.isChildInGroupWithSummary (remove.getStatusBarNotification())) {
// we are only transfering this notification to its parent, don't generate an animation
mStackScroller.setChildTransferInProgress(true);
}
if (remove.isSummaryWithChildren()) {
remove.removeAllChildren();
}
mStackScroller.removeView(remove);
mStackScroller .setChildTransferInProgress(false);
}

removeNotificationChildren();

for (int i=0; i<toShow.size(); i++) {
View v = toShow.get(i);
if (v.getParent() == null) {
mStackScroller.addView(v);
}
}

addNotificationChildrenAndSort();

// So after all this work notifications still aren't sorted correctly.
// Let's do that now by advancing through toShow and mStackScroller in
// lock-step, making sure mStackScroller matches what we see in toShow.
int j = 0;
for (int i = 0; i < mStackScroller.getChildCount(); i++) {
View child = mStackScroller.getChildAt(i);
if (!(child instanceof ExpandableNotificationRow)) {
// We don't care about non-notification views.
continue;
}

ExpandableNotificationRow targetChild = toShow.get(j);
if (child != targetChild) {
// Oops, wrong notification at this position. Put the right one
// here and advance both lists.
mStackScroller.changeViewPosition(targetChild, i);
}
j++;

}

// clear the map again for the next usage
mTmpChildOrderMap.clear();

updateRowStates();
updateSpeedbump();
updateClearAll();
updateEmptyShadeView();

updateQsExpansionEnabled();
mShadeUpdates.check();
}

ÖÁ´Ë£¬Ò»Ìõз¢Ë͵Ä֪ͨ¾ÍÕæÕýÏÔʾ³öÀ´ÁË¡£

ÏÂÃæÕâ·ùͼÃèÊöÁËÒ»ÌõNotification´Ó·¢Ë͵½ÏÔʾ³öÀ´µÄÁ÷³Ì£º

   
2018 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕÂ

Éî¶È½âÎö£ºÇåÀíÀôúÂë
ÈçºÎ±àд³öÓµ±§±ä»¯µÄ´úÂë
ÖØ¹¹-ʹ´úÂë¸ü¼ò½àÓÅÃÀ
ÍŶÓÏîÄ¿¿ª·¢"±àÂë¹æ·¶"ϵÁÐÎÄÕÂ
Ïà¹ØÎĵµ

ÖØ¹¹-¸ÄÉÆ¼ÈÓдúÂëµÄÉè¼Æ
Èí¼þÖØ¹¹v2
´úÂëÕû½àÖ®µÀ
¸ßÖÊÁ¿±à³Ì¹æ·¶
Ïà¹Ø¿Î³Ì

»ùÓÚHTML5¿Í»§¶Ë¡¢Web¶ËµÄÓ¦Óÿª·¢
HTML 5+CSS ¿ª·¢
ǶÈëʽC¸ßÖÊÁ¿±à³Ì
C++¸ß¼¶±à³Ì