LocationProviderProxy 分析

与Android 位置信息相关的分析

1. Android LocationManagerService流程分析
2. Android 从GPS中获取位置信息流程分析
3. Android 从PassiveProvider获取位置信息


LocationManagerService文章中介绍了各个LocationProvider和从各个LocationProvider中获取位置信息和大致流程。
在这篇文章中将会介绍networkProvider怎么获取位置信息。


network:通过网络来获取位置信息的,主要利用手机的基站,和WiFi节点的位置来大致定位。在国内基本使用第三方应用的sdk来实现的。(百度、高德等)


LocationManagerService与networkProvider通信主要是通过LocationProviderProxy 代理类来与networkProvider通信

LocationManagerService.java

private void loadProvidersLocked() {
...
    // bind to network provider
    LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
            mContext,
            LocationManager.NETWORK_PROVIDER,
            NETWORK_LOCATION_SERVICE_ACTION,
            com.android.internal.R.bool.config_enableNetworkLocationOverlay,
            com.android.internal.R.string.config_networkLocationProviderPackageName,
            com.android.internal.R.array.config_locationProviderPackageNames,
            mLocationHandler);
    if (networkProvider != null) {
        mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
        mProxyProviders.add(networkProvider);
        addProviderLocked(networkProvider);
    } else {
        Slog.w(TAG, "no network location provider found");
    }
...
}

使用LocationProviderProxy 的createAndBind方法创建和绑定networkProvider


LocationProviderProxy.java

public static LocationProviderProxy createAndBind(
        Context context, String name, String action,
        int overlaySwitchResId, int defaultServicePackageNameResId,
        int initialPackageNamesResId, Handler handler) {
    // 
    LocationProviderProxy proxy = new LocationProviderProxy(context, name, action,
            overlaySwitchResId, defaultServicePackageNameResId, initialPackageNamesResId, handler);
    if (proxy.bind()) { // 绑定服务 ,会调用ServiceWatcher.start方法
        return proxy;
    } else {
        return null;
    }
}

LocationProviderProxy.java

// action 通过PMS可以找到这个此service,启动并绑定, 该action 为 “com.android.location.service.v3.NetworkLocationProvider”
// mServiceWatcher 会启动这个服务
private LocationProviderProxy(Context context, String name, String action,
        int overlaySwitchResId, int defaultServicePackageNameResId,
        int initialPackageNamesResId, Handler handler) {
    mContext = context;
    mName = name;
    mServiceWatcher = new ServiceWatcher(mContext, TAG + "-" + name, action, overlaySwitchResId,
            defaultServicePackageNameResId, initialPackageNamesResId,
            mNewServiceWork, handler);
}

private boolean bind () {
    return mServiceWatcher.start();
}
ServiceWatcher.java

public class ServiceWatcher implements ServiceConnection {
    public boolean start() {
        if (isServiceMissing()) return false;

        synchronized (mLock) {
            bindBestPackageLocked(mServicePackageName, false); // 启动服务并绑定
        }

    ...}


    private boolean bindBestPackageLocked(String justCheckThisPackage, boolean forceRebind) {
        Intent intent = new Intent(mAction);
        if (justCheckThisPackage != null) {
            intent.setPackage(justCheckThisPackage);
        }
        // 通过intent 查找对应的service
        final List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(intent,
                PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                mCurrentUserId);
        int bestVersion = Integer.MIN_VALUE;
        ComponentName bestComponent = null;
        boolean bestIsMultiuser = false;
        if (rInfos != null) {
            for (ResolveInfo rInfo : rInfos) {
                final ComponentName component = rInfo.serviceInfo.getComponentName();
                final String packageName = component.getPackageName();

                // check signature
                try {
                    PackageInfo pInfo;
                    pInfo = mPm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES
                            | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
                    if (!isSignatureMatch(pInfo.signatures)) { // 判断签名
                        Log.w(mTag, packageName + " resolves service " + mAction
                                + ", but has wrong signature, ignoring");
                        continue;
                    }
                } catch (NameNotFoundException e) {
                    Log.wtf(mTag, e);
                    continue;
                }

                // check metadata
                int version = Integer.MIN_VALUE;
                boolean isMultiuser = false;
                if (rInfo.serviceInfo.metaData != null) {
                    version = rInfo.serviceInfo.metaData.getInt(
                            EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
                    isMultiuser = rInfo.serviceInfo.metaData.getBoolean(EXTRA_SERVICE_IS_MULTIUSER);
                }
                // 判断该service的serviceVersion 是否大于Integer.MIN_VALUE,是则表示有效
                if (version > bestVersion) {
                    bestVersion = version;
                    bestComponent = component;
                    bestIsMultiuser = isMultiuser;
                }
            }
        } 

        if (bestComponent == null) {
            Slog.w(mTag, "Odd, no component found for service " + mAction);
            unbindLocked();
            return false;
        }

        final int userId = bestIsMultiuser ? UserHandle.USER_SYSTEM : mCurrentUserId;
        final boolean alreadyBound = Objects.equals(bestComponent, mBoundComponent)
                && bestVersion == mBoundVersion && userId == mBoundUserId;
        if (forceRebind || !alreadyBound) {
            unbindLocked();
            bindToPackageLocked(bestComponent, bestVersion, userId); //通过compoent绑定服务
        }
        return true;
    }

    // 绑定服务
    private void bindToPackageLocked(ComponentName component, int version, int userId) {
        Intent intent = new Intent(mAction);
        intent.setComponent(component);
        mBoundComponent = component;
        mBoundPackageName = component.getPackageName();
        mBoundVersion = version;
        mBoundUserId = userId;
        if (D) Log.d(mTag, "binding " + component + " (v" + version + ") (u" + userId + ")");
        mContext.bindServiceAsUser(intent, this,
                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
                new UserHandle(userId));
    }

    // 由于当前ServiceWatcher 继承 ServiceConnection,所以当通过bindServiceAsUser 方法绑定成功后会调用onServiceConnected
    public void onServiceConnected(ComponentName component, IBinder binder) {
        synchronized (mLock) {
            if (component.equals(mBoundComponent)) {
                if (D) Log.d(mTag, component + " connected");
                mBoundService = binder; // 保存连接上的service
                if (mHandler !=null && mNewServiceWork != null) {
                    mHandler.post(mNewServiceWork); // 执行mNewServiceWork Runnable方法,此方法在LocationProviderProxy:mNewServiceWork
                }
            } else {
                Log.w(mTag, "unexpected onServiceConnected: " + component);
            }
        }
    }
}
LocationProviderProxy.java

// 当成功获取到第三方应用的LocationProvider 服务会调用此线程
private Runnable mNewServiceWork = new Runnable() {
    @Override
    public void run() {
        boolean enabled;
        final ProviderProperties[] properties = new ProviderProperties[1];
        ProviderRequest request;
        WorkSource source;
        synchronized (mLock) {
            enabled = mEnabled;
            request = mRequest;
            source = mWorksource;
        }

        // 调用runOnBinder 方法会再次调用BinderRunner.run 方法,并且将上一步保存的service通过参数回调过来即binder
        mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
            @Override
            public void run(IBinder binder) {
                ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
                try {
                    // load properties from provider
                    properties[0] = service.getProperties();
                    if (properties[0] == null) {
                        Log.e(TAG, mServiceWatcher.getBestPackageName() +
                                " has invalid location provider properties");
                    }

                    // apply current state to new service
                    if (enabled) { // 如果需要获取位置信息,则调用enable 方法启动第三方应用的locationProvider。并且通过setRequest设置LocationRequest
                        service.enable();
                        if (request != null) {
                            service.setRequest(request, source);
                        }
                    }
                } catch (RemoteException e) {
                    Log.w(TAG, e);
                } catch (Exception e) {
                    // never let remote service crash system server
                    Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
                }
            }
        });

        synchronized (mLock) {
            mProperties = properties[0];
        }
    }
};

到现在,mServiceWatcher中已经存放了三方应用的LocationProvider,本地应用调用requestLocationUpdates方法后的流程(使用network获取位置信息):
LocationManager.requestLocationUpdates() -> LocationManagerService.requestLocationUpdates() -> LocationManagerService.requestLocationUpdatesLocked() -> LocationManagerService.applyRequirementsLocked() ->
LocationProviderProxy.setRequest() -> mServiceWatcher.runOnBinder() -> ServiceWatcher.BinderRunner.run() -> 第三方service的setRequest(request, source)方法。


由于三方LocationProvider会继承 LocationProviderBase 方法。最后在计算出Location信息后会调用LocationProviderBase类的reportLocation()方法将数据传给请求数据的应用。

LocationProviderBase.java

public final void reportLocation(Location location) {
    //  mLocationManager 为 LocationManagerService 实例对象
    try {
        mLocationManager.reportLocation(location, false);
    } catch (RemoteException e) {
        Log.e(TAG, "RemoteException", e);
    } catch (Exception e) {
        // never crash provider, might be running in a system process
        Log.e(TAG, "Exception", e);
    }
}

总结:

1.通过LocationManager.NETWORK_PROVIDER来获取位置信息,LocationManagerService会使用 LocationProviderProxy 与三方SDK的LocationProvide通信获取位置信息。

2.LocationProviderProxy 中通过 ServiceWatcher 来绑定三方SDK的LocationProvide 服务,并且内部会保存此服务

3.LocationProviderProxy 会通过 ServiceWatcher 来调用服务的接口与服务通信。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值