在国内无法使用谷歌GMS包,我们选择NLP(network location provider)有提供商有: 百度、高德、腾讯等可以选择,那这一块初始化流程是怎样的呢?我们代码梳理下:
我们知道,LocationManagerService 是由 SystemServer 启动的,然后在 SystemServer 里面执行:locationF.systemRunning(),locationF 就是 LocationManagerService,那看下具体代码:
276 public void systemRunning() { 277 synchronized (mLock) { 278 if (D) Log.d(TAG, "systemRunning()");
…………
345 // prepare providers 346 loadProvidersLocked(); ---> 主要看下这个
在 loadProvidersLocked 方法中,我们仅看和网络相关的,重点是下面的这个bind
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, ---> 这几个都是在这里配置:/frameworks/base/core/res/res/values/config.xml 642 com.android.internal.R.string.config_networkLocationProviderPackageName, ---> 三方包名,比如百度Nlp:com.baidu.map.location 643 com.android.internal.R.array.config_locationProviderPackageNames, ---> 添加三方包名,比如百度Nlp:com.baidu.map.location 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 }
58 public static LocationProviderProxy createAndBind( ---> 先去根据config去启动初始包 59 Context context, String name, String action, 60 int overlaySwitchResId, int defaultServicePackageNameResId, 61 int initialPackageNamesResId, Handler handler) { 62 LocationProviderProxy proxy = new LocationProviderProxy(context, name, action, 63 overlaySwitchResId, defaultServicePackageNameResId, initialPackageNamesResId, 64 handler); 65 if (proxy.bind()) { ---> 然后才去bind 66 return proxy; 67 } else { 68 return null; 69 }
看下对应参数:
name:NETWORK_PROVIDER
action:"com.android.location.service.v3.NetworkLocationProvider"
overlaySwitchResId:config_enableNetworkLocationOverlay ---> 一般是 false
defaultServicePackageNameResId:三方包名
initialPackageNamesResId:配置的包含三方包名
72 private LocationProviderProxy(Context context, String name, String action, 73 int overlaySwitchResId, int defaultServicePackageNameResId, 74 int initialPackageNamesResId, Handler handler) { 75 mContext = context; 76 mName = name; 77 mServiceWatcher = new ServiceWatcher(mContext, TAG + "-" + name, action, overlaySwitchResId, 78 defaultServicePackageNameResId, initialPackageNamesResId, 79 mNewServiceWork, handler); 80 }
107 public ServiceWatcher(Context context, String logTag, String action, 108 int overlaySwitchResId, int defaultServicePackageNameResId, 109 int initialPackageNamesResId, Runnable newServiceWork, 110 Handler handler) { 111 mContext = context; 112 mTag = logTag; 113 mAction = action; 114 mPm = mContext.getPackageManager(); 115 mNewServiceWork = newServiceWork; 116 mHandler = handler; 117 Resources resources = context.getResources(); 118 119 // Whether to enable service overlay. 120 boolean enableOverlay = resources.getBoolean(overlaySwitchResId); 121 ArrayList<String> initialPackageNames = new ArrayList<String>(); 122 if (enableOverlay) { ---> 一般是false,所以走 else 的逻辑 123 // A list of package names used to create the signatures. 124 String[] pkgs = resources.getStringArray(initialPackageNamesResId); 125 if (pkgs != null) initialPackageNames.addAll(Arrays.asList(pkgs)); 126 mServicePackageName = null; 127 if (D) Log.d(mTag, "Overlay enabled, packages=" + Arrays.toString(pkgs)); 128 } else { 129 // The default package name that is searched for service implementation when overlay is 130 // disabled. 131 String servicePackageName = resources.getString(defaultServicePackageNameResId); 132 if (servicePackageName != null) initialPackageNames.add(servicePackageName); 133 mServicePackageName = servicePackageName; 134 if (D) Log.d(mTag, "Overlay disabled, default package=" + servicePackageName); --->配置的三方包名 135 } 136 mSignatureSets = getSignatureSets(context, initialPackageNames); 137 }
走完后,我们再看上面提到的 proxy.bind 方法:
82 private boolean bind () { 83 return mServiceWatcher.start(); 84 }
148 public boolean start() { 149 if (isServiceMissing()) return false; 150 151 synchronized (mLock) { 152 bindBestPackageLocked(mServicePackageName, false); ---> 注意这个方法,false 传下去,会用到 153 } 154 155 // listen for user change 156 IntentFilter intentFilter = new IntentFilter(); 157 intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 158 intentFilter.addAction(Intent.ACTION_USER_UNLOCKED); 159 mContext.registerReceiverAsUser(new BroadcastReceiver() { 160 @Override 161 public void onReceive(Context context, Intent intent) { 162 final String action = intent.getAction(); 163 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 164 UserHandle.USER_NULL); 165 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 166 switchUser(userId); 167 } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) { 168 unlockUser(userId); 169 } 170 } 171 }, UserHandle.ALL, intentFilter, null, mHandler); 172 173 // listen for relevant package changes if service overlay is enabled. 174 if (mServicePackageName == null) { 175 mPackageMonitor.register(mContext, null, UserHandle.ALL, true); 176 } 177 178 return true; 179 }
192 /** 193 * Searches and binds to the best package, or do nothing if the best package 194 * is already bound, unless force rebinding is requested. 195 * 196 * @param justCheckThisPackage Only consider this package, or consider all 197 * packages if it is {@code null}. 198 * @param forceRebind Force a rebinding to the best package if it's already 199 * bound. 200 * @returns {@code true} if a valid package was found to bind to. 201 */ 202 @GuardedBy("mLock") 203 private boolean bindBestPackageLocked(String justCheckThisPackage, boolean forceRebind) { 204 Intent intent = new Intent(mAction); 205 if (justCheckThisPackage != null) { 206 intent.setPackage(justCheckThisPackage); 207 } 208 final List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(intent, 209 PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 210 mCurrentUserId); ---> 查找 211 int bestVersion = Integer.MIN_VALUE; 212 ComponentName bestComponent = null; 213 boolean bestIsMultiuser = false; 214 if (rInfos != null) { 215 for (ResolveInfo rInfo : rInfos) { 216 final ComponentName component = rInfo.serviceInfo.getComponentName(); 217 final String packageName = component.getPackageName(); 218 219 // check signature 220 try { 221 PackageInfo pInfo; 222 pInfo = mPm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES 223 | PackageManager.MATCH_DEBUG_TRIAGED_MISSING); 224 if (!isSignatureMatch(pInfo.signatures)) { 225 Log.w(mTag, packageName + " resolves service " + mAction 226 + ", but has wrong signature, ignoring"); 227 continue; 228 } 229 } catch (NameNotFoundException e) { 230 Log.wtf(mTag, e); 231 continue; 232 } 233 234 // check metadata --> NLP中service需要配置metadata属性,因为下面会和默认最小值比对 235 int version = Integer.MIN_VALUE; 236 boolean isMultiuser = false; 237 if (rInfo.serviceInfo.metaData != null) { 238 version = rInfo.serviceInfo.metaData.getInt( 239 EXTRA_SERVICE_VERSION, Integer.MIN_VALUE); 240 isMultiuser = rInfo.serviceInfo.metaData.getBoolean(EXTRA_SERVICE_IS_MULTIUSER); 241 } 242 243 if (version > bestVersion) { 244 bestVersion = version; 245 bestComponent = component; 246 bestIsMultiuser = isMultiuser; 247 } 248 } 249 250 if (D) { 251 Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction, 252 (justCheckThisPackage == null ? "" 253 : "(" + justCheckThisPackage + ") "), rInfos.size(), 254 (bestComponent == null ? "no new best component" 255 : "new best component: " + bestComponent))); 256 } 257 } else { 258 if (D) Log.d(mTag, "Unable to query intent services for action: " + mAction); 259 } 260 261 if (bestComponent == null) { 262 Slog.w(mTag, "Odd, no component found for service " + mAction); 263 unbindLocked(); 264 return false; 265 } 266 267 final int userId = bestIsMultiuser ? UserHandle.USER_SYSTEM : mCurrentUserId; 268 final boolean alreadyBound = Objects.equals(bestComponent, mBoundComponent) 269 && bestVersion == mBoundVersion && userId == mBoundUserId; 270 if (forceRebind || !alreadyBound) { ---> forceRebind 传下来的参数是 false,第一次,alreadyBound 也为false 271 unbindLocked(); --> 执行 272 bindToPackageLocked(bestComponent, bestVersion, userId); 273 } 274 return true; 275 }
292 @GuardedBy("mLock") 293 private void bindToPackageLocked(ComponentName component, int version, int userId) { 294 Intent intent = new Intent(mAction); 295 intent.setComponent(component); 296 mBoundComponent = component; 297 mBoundPackageName = component.getPackageName(); 298 mBoundVersion = version; 299 mBoundUserId = userId; 300 if (D) Log.d(mTag, "binding " + component + " (v" + version + ") (u" + userId + ")"); 301 mContext.bindServiceAsUser(intent, this, ---> bind,成功后回调该 onServiceConnected 方法,失败回调 onServiceDisconnected 302 Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE, 303 new UserHandle(userId)); 304 }
绑定成功后回调:
367 @Override 368 public void onServiceConnected(ComponentName component, IBinder binder) { 369 synchronized (mLock) { 370 if (component.equals(mBoundComponent)) { 371 if (D) Log.d(mTag, component + " connected"); 372 mBoundService = binder; 373 if (mHandler !=null && mNewServiceWork != null) { 374 mHandler.post(mNewServiceWork); ---> 这个是之前传下来的,现在执行这个 375 } 376 } else { 377 Log.w(mTag, "unexpected onServiceConnected: " + component); 378 } 379 } 380 }
95 private Runnable mNewServiceWork = new Runnable() { 96 @Override 97 public void run() { 98 if (D) Log.d(TAG, "applying state to connected service"); 99 100 boolean enabled; 101 final ProviderProperties[] properties = new ProviderProperties[1]; 102 ProviderRequest request; 103 WorkSource source; 104 synchronized (mLock) { 105 enabled = mEnabled; 106 request = mRequest; 107 source = mWorksource; 108 } 109 110 111 mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() { 112 @Override 113 public void run(IBinder binder) { 114 ILocationProvider service = ILocationProvider.Stub.asInterface(binder); ---> 这个service实际上就是bind三方的NLP 115 try { 116 // load properties from provider 117 properties[0] = service.getProperties(); 118 if (properties[0] == null) { 119 Log.e(TAG, mServiceWatcher.getBestPackageName() + 120 " has invalid location provider properties"); 121 } 122 123 // apply current state to new service 124 if (enabled) { 125 service.enable(); 126 if (request != null) { 127 service.setRequest(request, source); 128 } 129 } 130 } catch (RemoteException e) { 131 Log.w(TAG, e); 132 } catch (Exception e) { 133 // never let remote service crash system server 134 Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e); 135 } 136 } 137 }); 138 139 synchronized (mLock) { 140 mProperties = properties[0]; 141 } 142 } 143 };
至此,整个bind流程记录完毕,另外如何集成三方NLP呢?这个我们可以参考公众号:蘑菇君先生