zoukankan      html  css  js  c++  java
  • android6.0锁屏界面接收新通知处理流程

    灭屏状态下,接收新信息,屏幕会半亮显示通知流程

    1,应用构造notification后,传给NotificationManager,而后进入NotificationManagerService处理。 

    NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
    
    nm.notify(NOTIFICATION_ID, notification)

     frameworksasecorejavaandroidappNotificationManager.java

    public void notify(int id, Notification notification)
        {
            notify(null, id, notification);
        }
    public void notify(String tag, int id, Notification notification)
        {
    ……
    
         Notification stripped = notification.clone();
            Builder.stripForDelivery(stripped);
            try {
                service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
                        stripped, idOut, UserHandle.myUserId());
                if (id != idOut[0]) {
                    Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
                }
            } catch (RemoteException e) {
            }
    }

    frameworksaseservicescorejavacomandroidserver otificationNotificationManagerService.java

    public void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
                    Notification notification, int[] idOut, int userId) throws RemoteException {
                enqueueNotificationInternal(pkg, opPkg, Binder.getCallingUid(),
                        Binder.getCallingPid(), tag, id, notification, idOut, userId);
            }

    同一个包名的通知超过50条不会继续处理。

    
    

    if (count >= MAX_PACKAGE_NOTIFICATIONS) {
    Slog.e(TAG, "Package has already posted " + count
    + " notifications. Not showing more. package=" + pkg);
    return;
    }

    private void buzzBeepBlinkLocked(NotificationRecord record) {
    ……
    ……
    // light
            // release the light
            boolean wasShowLights = mLights.remove(record.getKey());
            if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && aboveThreshold) {
                mLights.add(record.getKey());
                updateLightsLocked();
                if (mUseAttentionLight) {
                    mAttentionLight.pulse();
                }
                blink = true;
            } else if (wasShowLights) {
                updateLightsLocked();
            }
            if (buzz || beep || blink) {
                EventLogTags.writeNotificationAlert(record.getKey(),
                        buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);
                mHandler.post(mBuzzBeepBlinked);
            }
    
    }

    屏幕半亮闪烁需要判断 (notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0

    所以在应用构建notification时可以通过给flag赋值来控制是否要屏幕半亮闪烁。 

    先读取设置数据库中的NOTIFICATION_LIGHT_PULSE来判断是否闪烁,如果mNotificationPulseEnabled为true,则先闪烁一次(Light.LIGHT_FLASH_TIMED =1)。

    Settings.System.getInt(resolver, Settings.System.NOTIFICATION_LIGHT_PULSE, 0)
    if (mNotificationPulseEnabled) {
    // pulse repeatedly
    mNotificationLight.setFlashing(ledARGB, Light.LIGHT_FLASH_TIMED,  //Light.LIGHT_FLASH_TIMED =1
    ledOnMS, ledOffMS);
    }
    // let SystemUI make an independent decision //进入SystemUI处理
    mStatusBar.notificationLightPulse(ledARGB, ledOnMS, ledOffMS);


    2,然后进入SystemUi继续处理。
    SystemUI中最终处理在DozeService中,也有一个开关判断,是否要闪烁。
    if (!mDozeParameters.getPulseOnNotifications()) return;//getPulseOnNotifications默认为true

    DozeService.java中调用private void requestPulse(final int reason)执行点亮屏幕。

    private void requestPulse(final int reason, boolean performedProxCheck) {
            if (mHost != null && mDreaming && !mPulsing) {
                // Let the host know we want to pulse.  Wait for it to be ready, then
                // turn the screen on.  When finished, turn the screen off again.
                // Here we need a wakelock to stay awake until the pulse is finished.
                mWakeLock.acquire();
                mPulsing = true;
                if (!mDozeParameters.getProxCheckBeforePulse()) {//这里先判断是否要先执行ProxCheck, proxCheck会检查手机sensor是否正常,如果不正常就退出,不执行点亮屏幕
                    // skip proximity check
                    continuePulsing(reason);
                    return;
                }
                final long start = SystemClock.uptimeMillis();
                if (performedProxCheck) {
                    // the caller already performed a successful proximity check; we'll only do one to
                    // capture statistics, continue pulsing immediately.
                    continuePulsing(reason);
                }
                // perform a proximity check
                new ProximityCheck() {
                    @Override
                    public void onProximityResult(int result) {
                        ……
                                      ……
                    }
                }.check();
            }
        }
        
        private abstract class ProximityCheck implements SensorEventListener, Runnable {
                ……
                ……
                public void check() {
                if (mFinished || mRegistered) return;
                final Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
                if (sensor == null) {//手机sensor无效,直接退出程序。
                    if (DEBUG) Log.d(mTag, "No sensor found");
                    finishWithResult(RESULT_UNKNOWN);
                    return;
                }
                // the pickup sensor interferes with the prox event, disable it until we have a result
                mPickupSensor.setDisabled(true);
    
                mMaxRange = sensor.getMaximumRange();
                mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0,
                        mHandler);
                mHandler.postDelayed(this, TIMEOUT_DELAY_MS);
                mRegistered = true;
            }
                
                ……
                ……
        }

    ----------------------------------------------------------------------------------------------------

    3,SystemUI下拉展开布局中显示通知处理流程

    BaseStatusBar中通过mNotificationListener监听通知更新,获取通知

     private final NotificationListenerService mNotificationListener =
                new NotificationListenerService() {
                
                 public void onListenerConnected() {
                    if (DEBUG) Log.d(TAG, "onListenerConnected");
                    final StatusBarNotification[] notifications = getActiveNotifications();//获取当前所有通知集合
                    final RankingMap currentRanking = getCurrentRanking();
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            for (StatusBarNotification sbn : notifications) {
                                addNotification(sbn, currentRanking, null /* oldEntry */);
                            }
                        }
                    });
                    }
                ……
        }

    NotificationListenerService获取通知
       public StatusBarNotification[] getActiveNotifications() {
            return getActiveNotifications(null, TRIM_FULL);
        }
        
        public StatusBarNotification[] getActiveNotifications(String[] keys, int trim) {
            if (!isBound())
                return null;
            try {
                //这里通过Binder调用NotificationManagerService调用getActiveNotificationsFromListener获取通知
                ParceledListSlice<StatusBarNotification> parceledList = getNotificationInterface().getActiveNotificationsFromListener(mWrapper, keys, trim);
                List<StatusBarNotification> list = parceledList.getList();
                …………
                return list.toArray(new StatusBarNotification[list.size()]);
            } catch (android.os.RemoteException ex) {
                Log.v(TAG, "Unable to contact notification manager", ex);
            }
            return null;
        }
        
        //获取INotificationManager的实例,也就是NotificationManagerService中的mService
        private final INotificationManager getNotificationInterface() {
            if (mNoMan == null) {
                mNoMan = INotificationManager.Stub.asInterface(
                        ServiceManager.getService(Context.NOTIFICATION_SERVICE));
            }
            return mNoMan;
        }
    NotificationManagerService中对Context.NOTIFICATION_SERVICE的映射
    public class NotificationManagerService extends SystemService
        public void onStart() {
                ……
                publishBinderService(Context.NOTIFICATION_SERVICE, mService);//SystemService中定义的方法 publishBinderService(..)
            ……
        }

    通过上述流程已经获取通知数据,将数据显示在SystemUI中在PhoneStatusBar中处理

      //重载父类BaseStatusBar中的方法,mNotificationListener中会直接调用这里添加通知
        public void addNotification(StatusBarNotification notification, RankingMap ranking, Entry oldEntry) {
            if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());
    
            Entry shadeEntry = createNotificationViews(notification);
            if (shadeEntry == null) {
                return;
            }
            ……
            addNotificationViews(shadeEntry, ranking);//
            // Recalculate the position of the sliding windows and the titles.
            setAreThereNotifications();
        }
      protected void addNotificationViews(Entry entry, RankingMap ranking) {
            if (entry == null) {
                return;
            }
            // Add the expanded view and icon.
            mNotificationData.add(entry, ranking);//
            updateNotifications(); //此方法会将新通知添加到SystemUI布局中显示
        }
  • 相关阅读:
    [原]跟我学silverlight系列教程[1]—wpf/silverlight体系架构和运行机制
    [转载]My97DatePicker在Frame中无法打开站点
    sql select的时候按特定的顺序排序
    javascript获取滚动条位置
    sql2005 数据库没有完全关闭,无法重新生成日志
    .Net framework
    输出datagrid的内容到excel
    IIS中网站出错
    [原]跟我学silverlight系列教程
    SharePoint2010 的ADFS2.0设置
  • 原文地址:https://www.cnblogs.com/antoon/p/5549672.html
Copyright © 2011-2022 走看看