上一篇我们记录了 GPS 的定位流程,这一篇记录下 NLP(Network Location Provider)的定位流程,因为在国内,无法使用谷歌提供的NLP,所以国内我们一般会使用三方提供的NLP,比如:百度、高德、腾讯等。
这里我们假设一个app发起 NLP 定位,首先调用 LocationManager 接口,通过AIDL最终调用到 LocationManagerService 里面的 requestLocationUpdates 方法:
554 public void requestLocationUpdates(String provider, long minTime, float minDistance, 555 LocationListener listener) { 556 checkProvider(provider); 557 checkListener(listener); 558 559 LocationRequest request = LocationRequest.createFromDeprecatedProvider( 560 provider, minTime, minDistance, false); 561 requestLocationUpdates(request, listener, null, null); 562 }
到这里我们就知道了,不管是GPS还是NLP,调用的都是这个接口,区别就是传进去的参数不一样,例如:provider,在Android 里面我们有以下几种provider:
Gps_provider、Network_provider、Passive_provider、Fused_provider、Mock_provider,其中前三种比较常用,Fused_provider依赖三方,比如谷歌GMS包。Mock_provider就是我们常说的伪造位置,一些虚拟定位软件就是基于这个开发的,这里我们暂时不记录,需要的后续单独详细讲。
继续看流程调用:
2061 public void requestLocationUpdates(LocationRequest request, ILocationListener listener, 2062 PendingIntent intent, String packageName) { 2063 if (request == null) request = DEFAULT_LOCATION_REQUEST; 2064 checkPackageName(packageName); 2065 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 2066 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 2067 request.getProvider()); 2068 WorkSource workSource = request.getWorkSource(); 2069 if (workSource != null && !workSource.isEmpty()) { 2070 checkDeviceStatsAllowed(); 2071 } 2072 boolean hideFromAppOps = request.getHideFromAppOps(); 2073 if (hideFromAppOps) { 2074 checkUpdateAppOpsAllowed(); 2075 } 2076 boolean callerHasLocationHardwarePermission = 2077 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE) 2078 == PERMISSION_GRANTED; 2079 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel, 2080 callerHasLocationHardwarePermission); 2081 2082 final int pid = Binder.getCallingPid(); 2083 final int uid = Binder.getCallingUid(); 2084 // providers may use public location API's, need to clear identity 2085 long identity = Binder.clearCallingIdentity(); 2086 try { 2087 // We don't check for MODE_IGNORED here; we will do that when we go to deliver 2088 // a location. 2089 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel); 2090 2091 synchronized (mLock) { 2092 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid, 2093 packageName, workSource, hideFromAppOps); 2094 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName); 2095 } 2096 } finally { 2097 Binder.restoreCallingIdentity(identity); 2098 } 2099 }
这个流程其实都是一样的和GPS,最终到 applyRequirementsLocked 方法里这个地方,之前讲过:P指的是 LocationProviderInterface接口,而所有的provider要实现它,而这里我们请求的是网络 provider,此时网络的provider是三方实现的,就会走到具体实现的地方
1816 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest); 1817 p.setRequest(providerRequest, worksource);
而 LocationManagerService 在 systemRunning 的时候就去bind 三方的包,这样在请求Network_provider的时候就是走到绑定的三方接口里
636 // bind to network provider 637 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind( 638 mContext, 639 LocationManager.NETWORK_PROVIDER, 640 NETWORK_LOCATION_SERVICE_ACTION, 641 com.android.internal.R.bool.config_enableNetworkLocationOverlay, 642 com.android.internal.R.string.config_networkLocationProviderPackageName, 643 com.android.internal.R.array.config_locationProviderPackageNames, 644 mLocationHandler); 645 if (networkProvider != null) { 646 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider); 647 mProxyProviders.add(networkProvider); 648 addProviderLocked(networkProvider); 649 } else { 650 Slog.w(TAG, "no network location provider found"); 651 }
至此,大致流程梳理完毕。
文章同步来自微信公众号,更多内容关注公众号:蘑菇君先生