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

由于大陆禁止使用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.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值