Android LBS中网络定位服务的实现方法

来源:互联网 发布:sql判断count的值大于 编辑:程序博客网 时间:2024/05/22 11:48

由于大陆禁止使用Google定位服务。因此我们需要自己研发一款基于网络与基站的LBS应用。

但是由于Google并没有开放networklocation.apk的源码。因此我们需要自己动手山寨一个偷笑


既然是山寨了,那肯定要走反向工程了。

我们先看看LBS服务的基础LocationManagerService是如何启动网络定位服务的


先看LocationManagerService 的构造方法

 public LocationManagerService(Context context) {     super();     mContext = context;     Resources resources = context.getResources();     mNetworkLocationProviderPackageName =                                         resources.getString(         com.android.internal.R.string.config_networkLocationProviderPackageName);     mGeocodeProviderPackageName = resources.getString(  com.android.internal.R.string.config_geocodeProviderPackageName);     mPackageMonitor.register(context, null, true);     if (LOCAL_LOGV) {         Slog.v(TAG, "Constructed LocationManager Service");     }  }

mNetworkLocationProviderPackageName 这个就是网络定位服务APK的name.如果用的是国际版的ROM的话 这个name应该是networklocation

我们继续
其实,LocationManagerService 是一个线程类,除了构造函数以外,在其 run 方法中又完成了另外一部分的初始化工作,主要是调用其 initialize 方法。 在 initialize 方法中调用了 loadProviders 方法,loadProviders 这个方法中完成了 Location Provider 的加载工作。 该方法又经过同步加锁以及异常的包装,最终的实现方法是 _loadProvidersLocked。 _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.         // The initial value of mNetworkLocationProviderPackageName and         // mGeocodeProviderPackageName is just used to determine what         // signatures future mNetworkLocationProviderPackageName and         // mGeocodeProviderPackageName packages must have. So alternate         // providers can be installed under a different package name         // so long as they have the same signature as the original         // provider packages.         if (mNetworkLocationProviderPackageName != null) {             String packageName = findBestPackage(                    LocationProviderProxy.SERVICE_ACTION,                     mNetworkLocationProviderPackageName);             if (packageName != null) {                 mNetworkLocationProvider = new LocationProviderProxy(                         mContext,                         LocationManager.NETWORK_PROVIDER,                         packageName, mLocationHandler);                 mNetworkLocationProviderPackageName = packageName;                 addProvider(mNetworkLocationProvider);             }         }         if (mGeocodeProviderPackageName != null) {             String packageName = findBestPackage(                     GeocoderProxy.SERVICE_ACTION,                     mGeocodeProviderPackageName);             if (packageName != null) {                 mGeocodeProvider =                       new GeocoderProxy(mContext, packageName);                 mGeocodeProviderPackageName = packageName;             }         }         updateProvidersLocked();     }   


mNetworkLocationProvider 这个就是我们要找的

代码里是根据 mNetworkLocationProviderPackageName 字段创建 LocationProviderProxy 对象。(在创建 LocationProviderProxy 的时候,packageName 参数是依赖于 mNetworkLocationProviderPackageName 的。这个字段是在 LocationManagerService 的构造函数中初始化的。)


既然提到了LocationProviderProxy,那我们就继续跟踪下去

    public LocationProviderProxy(Context context, String name, StringpackageName,
            Handler handler) {
        mContext = context;
        mName = name;
        mIntent = new Intent(SERVICE_ACTION);
        mHandler = handler;
       reconnect(packageName);
    }


    /** Bind to service. Will reconnect if already connected */
    public void reconnect(String packageName) {
        synchronized (mMutex) {
            if (mServiceConnection != null) {
                mContext.unbindService(mServiceConnection);
            }
            mServiceConnection = new Connection();
            mIntent.setPackage(packageName);
            mContext.bindService(mIntent, mServiceConnection,
                    Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND |
                    Context.BIND_ALLOW_OOM_MANAGEMENT);
        }
    }

bindService   o(∩∩)o...哈哈  看到这里我们就大概上知道该怎么办了。

我们自己要实现的networklocation首先需要是一个service,并且需要实现onBind接口。

那下面的问题是IBinder在那里呢

我们继续看LocationProviderProxy

private class Connection implements ServiceConnection, Runnable {        private ILocationProvider mProvider;        // for caching requiresNetwork, requiresSatellite, etc.        private DummyLocationProvider mCachedAttributes;  // synchronized by mMutex        public void onServiceConnected(ComponentName className, IBinder service) {            synchronized (this) {                mProvider = ILocationProvider.Stub.asInterface(service);                if (mProvider != null) {                    mHandler.post(this);                }            }        }

ILocationProvider 这个就是我们要实现的IBinder,也是我们与

LocationManagerService通信的接口类

但是我们不能直接使用ILocationProvider。我们为了编码方便可以使用android提供给我们的gift

frameworks/base/location/lib/java/com/android/location/provider/LocationProvider.java


现在我们可以开始架构我们自己的networklocation.apk了。权且叫它NewLBSLocation.apk吧

我们需要以下几个类(以下只是简单实现)

NewLBSLocationService------------继承自android service,这个是整个APK的入口类,实现onBind接口

NewLBSLocationProvider------------继承自LocationProvider,这个主要是实现与

LocationManagerService的通信接口
NewLBSLocationUtil--------------通过handler与NewLBSLocationProvider通信,在这个类中监听基站与WIFI热点的变化,然后将相关信息发送给定位服务器获取相关位置location,然后通过一系列算法优化location.


0 0