Chinaunix首页 | 论坛 | 博客
  • 博客访问: 228694
  • 博文数量: 29
  • 博客积分: 1477
  • 博客等级: 上尉
  • 技术积分: 451
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-06 14:48
文章分类
文章存档

2012年(1)

2011年(14)

2010年(14)

我的朋友

分类: 嵌入式

2010-12-24 11:25:30

Android GPS架构分析
Daniel Wood 20101222
转载时请注明出处和作者
文章出处:http://danielwood.cublog.cn
作者:Daniel Wood
--------------------------------------------------------------------------------

在底层得到gps的接口之后, if (GpsLocationProvider.isSupported())(在文件LocationManagerService.java中调用)语句得到true,然后进行下一步操作,在这里new了一个GpsLocationProvider对象。代码如下:

GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);


注意GpsLocationProvider构造函数里面的两个参数:mContext, this。下面来看看GpsLocationProvider的构造函数的前面几句:

public GpsLocationProvider(Context context, ILocationManager locationManager) {
        mContext = context;
        mLocationManager = locationManager;
        mNIHandler = new GpsNetInitiatedHandler(context, this);

       ...

}


    在GpsLocationProvider类里面的成员变量mLocationManager是构造函数的第二个参数,就是说是LocationManagerService对象。这一点在这里先明确。

接着看_loadProvidersLocked函数。

private void _loadProvidersLocked() {
        // Attempt to load "real" providers first
        if (GpsLocationProvider.isSupported()) {
            // Create a gps location provider
            GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
            mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
            mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
            addProvider(gpsProvider);
            mGpsLocationProvider = gpsProvider;
        }
        // create a passive location provider, which is always enabled
        PassiveProvider passiveProvider = new PassiveProvider(this);
        addProvider(passiveProvider);
        mEnabledProviders.add(passiveProvider.getName());
        // initialize external network location and geocoder services
        Resources resources = mContext.getResources();
        String serviceName = resources.getString(
                com.android.internal.R.string.config_networkLocationProvider);
        if (serviceName != null) {
            mNetworkLocationProvider =
                new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER,
                        serviceName, mLocationHandler);
            addProvider(mNetworkLocationProvider);
        }
        serviceName = resources.getString(com.android.internal.R.string.config_geocodeProvider);
        if (serviceName != null) {
            mGeocodeProvider = new GeocoderProxy(mContext, serviceName);
        }
        updateProvidersLocked();
    }

在构造完GpsLocationProvider之后将其add到全局变量ArrayList mProviders中,备以后调用。

在2.2中采取了一种PassiveProvider的类,而在2.1中是通过LocationProviderProxy代理类的方式。2.1中LocationProviderProxy作为GpsLocationProvider的代理作用在LocationManagerService中,而2.2中的PassiveProvider感觉这个类是个空壳。。。。。。。。有待研究。

然后启动了nerwork location和geocoder 两个service。但是可惜的是这两个服务都无法启动,因为他们是通过配置文件conifg.xml [framework\base\core\res\res\values]得到服务的名字,然后启动服务的。但是在这个配置文件中,两个服务的名字都是null

conifg.xml [framework\base\core\res\res\values]

<!-- Component name of the service providing network location support. -->
    <string name="config_networkLocationProvider">@null</string>
    <!-- Component name of the service providing geocoder API support. -->
    <string name="config_geocodeProvider">@null</string>

其实这也导致了,在调用GetFromLocationName和GetFromLocation两个函数时提示“Service not Available”,这个google Android 2.2的bug。

_loadProvidersLocked函数的最后一句是调用updateProvidersLocked函数,仍然在LocationManagerServic.java文件中。

LocationManagerServic.java

private void updateProvidersLocked() {
        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);
            } else if (!isEnabled && shouldBeEnabled) {
                updateProviderListenersLocked(name, true);
            }
        }
    }

   从上面_loadProvidersLocked函数的代码来看,在mProviders这个ArrayList中有两个元素(这一点未求证),一个是gpsProvider,另一个是passiveProvider。gpsProvider是GpsLocationProvider类型的,它的isEnabled函数返回的是false,因为它并没有被enable。而passiveProvider是PassiveProvider类型,它总是enable的。所以gpsProvider会调用else语句中的updateProviderListenersLocked(name, true)函数。我们主要分析这个else语句,对于passiveProvider不做分析。

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) { //enabled 的值是true
            p.enable();
            if (listeners > 0) {
                p.setMinTime(getMinTimeLocked(provider));
                p.enableLocationTracking(true);
            }
        } else {
            p.enableLocationTracking(false);
            p.disable();
        }
    }


我们只关注主体部分代码,就是在if(enabled)这个语句段里面,启动了gps的服务,具体将在下一篇进行分析。
阅读(5909) | 评论(8) | 转发(1) |
给主人留下些什么吧!~~

chinaunix网友2011-03-29 18:59:03

我與一樓有相同的疑問~ 启nerwork location和geocoder 两个service两个服务都无法启动, 是否更改他们是通过配置文件conifg.xml 就能解决这个问题??? 這個問題與GoogleMobileService有關係嗎? 我的邮箱wwwpopop@gmail.com非常期待你的回信

chinaunix网友2011-03-27 10:06:46

版主,您好,您对GPS研究的很深。在android2.3上是不是没有实现基站定位,我使用GOOGLEmap无法进行基站定位。您说conifg.xml [framework\base\core\res\res\values] @null @null 这是空,与这有关心没有?是不是在google的代码中需要修改conifg.xml 。NetworkLocation.apk我也已经拷贝到/system/app下面了,不能进行定位?怎样解决,我的邮箱是:z1516

chinaunix网友2011-01-21 18:31:55

看了你关于gps的文章感觉非常棒,想请教一个问题,关于gps定位服务的。 你有说过-------------------------- 然后启动了nerwork location和geocoder 两个service。但是可惜的是这两个服务都无法启动,因为他们是通过配置文件conifg.xml [framework\base\core\res\res\values]得到服务的名字,然后启动服务的。但是在这个配置文件中,两个服务的名字都是null。 怎样解决这个问题???我的邮箱wujiangming_520@163.com非常期待你的回信