【Android】GPS启动流程及数据流向分析(基于2.3(2)

其中有两个重要的地方:
 1) loadProviders(),会new一个GpsLocationProvider,并将本GpsLocationProvider添加一个ArrayList<LocationProviderInterface>的链 表中。
 2) new 一个 SettingsObserver对象,该对象应该是负责在Settings中有数据变化时通知本地程序进行相应处理的功能。其中 SettingsObserver类中实现 了Observer接口,该接口中的update函数应该就是一个回调函数,当Settings中有数据变化时会回调进这个函数:
 
 

[java]

private final class SettingsObserver implements Observer {             public void update(Observable o, Object arg) {                 synchronized (mLock) {                      updateProvidersLocked();                 }             }        }       private void updateProvidersLocked() {             boolean changesMade = false;             for (int i = mProviders.size() - 1; i >= 0; i--) {                  LocationProviderInterface p = mProviders.get(i);                  boolean isEnabled = p.isEnabled();                  String name = p.getName();                  boolean shouldBeEnabled = isAllowedBySettingsLocked(name);                  If (isEnabled && !shouldBeEnabled) {                       updateProviderListenersLocked(name, false);                       changesMade = true;                  } else if (!isEnabled && shouldBeEnabled) {                       updateProviderListenersLocked(name, true);                       changesMade = true;                  }             }             if (changesMade) {                  mContext.sendBroadcast(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION));             }        }       private void updateProviderListenersLocked(String provider, boolean enabled) {           int listeners = 0;               LocationProviderInterface p = mProvidersByName.get(provider);            if (p == null) {                 return;            }               ArrayList<Receiver> deadReceivers = null;                       ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);            if (records != null) {                 final int N = records.size();                 for (int i=0; i<N; i++) {                     UpdateRecord record = records.get(i);                     // Sends a notification message to the receiver                      if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {                         if (deadReceivers == null) {                              deadReceivers = new ArrayList<Receiver>();                         }                         deadReceivers.add(record.mReceiver);                     }                     listeners++;                }            }               if (deadReceivers != null) {                 for (int i=deadReceivers.size()-1; i>=0; i--) {                     removeUpdatesLocked(deadReceivers.get(i));                 }            }                       if (enabled) {                 p.enable();                 if (listeners > 0) {                      p.setMinTime(getMinTimeLocked(provider), mTmpWorkSource);                      p.enableLocationTracking(true);                 }            } else {                 p.enableLocationTracking(false);                 p.disable();            }        }  

可知是在 updateProviderListenersLocked函数中,通过 LocationProviderInterface p调用enable或者disable来开关位置服务。这里会调用到 LocationProviderInterface的子类GpsLocationProvider中的enable或者disable中:
 
 GpsLocationProvider.java

[java]

public void enable() {            synchronized (mHandler) {               sendMessage(ENABLE, 1null);            }         }  

handlenable就是ENABLE的消息处理函数:

[java]

private void handleEnable() {            if (DEBUG) Log.d(TAG, "handleEnable");            if (mEnabled) return;            mEnabled = native_init();                      Intent intent = new Intent(LocationManager.GPS_SETTING_ENABLED_CHANGE_ACTION);            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mEnabled);            mContext.sendBroadcast(intent);               if (mEnabled) {                mSupportsXtra = native_supports_xtra();                if (mSuplServerHost != null) {                     native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);                }                if (mC2KServerHost != null) {                     native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);                }            } else {                Log.w(TAG, "Failed to enable location provider");            }       }  

可见这里就开始与native层通信了。
 native_init对应jni中的Android_location_GpsLocationProvider_init函数,在该函数中调用了
 sGpsInterface->init(&sGpsCallbacks),
 而 sGpsCallbacks定义如下:
 

[java]

GpsCallbacks sGpsCallbacks = {         sizeof(GpsCallbacks),         location_callback,         status_callback,         sv_status_callback,         nmea_callback,         set_capabilities_callback,         acquire_wakelock_callback,         release_wakelock_callback,         create_thread_callback,         request_utc_time_callback,    };  

这是将jni的一些函数作为参数传递到native c 空间中去,这样在native c中如果有可用数据将通过回调的方式调用到jni中的函数。简单的看一下 location_callback的定义:
 

[java]

static void location_callback(GpsLocation* location)    {         JNIEnv* env = AndroidRuntime::getJNIEnv();         env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,                (jdouble)location->latitude, (jdouble)location->longitude,                (jdouble)location->altitude,                (jfloat)location->speed, (jfloat)location->bearing,                (jfloat)location->accuracy, (jlong)location->timestamp);         checkAndClearExceptionFromCallback(env, __FUNCTION__);    }  

其中有定义:
 static jmethodID method_reportLocation;并且:
 method_reportLocation = env->GetMethodID(clazz, "reportLocation","(IDDDFFFJ)V"); 
 可见jni中的callback函数其实又回调掉了java空间(Framework)中的  reportLocation函数,这便是整个GPS框架的数据流向结构了。所有的数据都是通过回调的方式通知上层:
 nativeC通过回调通知JNI,JNI通过回调通知Framework。这应该是gps整个框架最重要的部分吧,理解了数据流向,其他的应该都简单了。
 我们的native c中并没有实现 native_set_agps_server的功能,所以使用agps的数据服务器不在上层指定,而是在c文件中直接指定的。 native_set_agps_server只是一个空函数。

linux

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wygxxx.html