1. 背景
先看上集
https://blog.csdn.net/xuyongqz/article/details/140774690
app 调用mLocationManager.registerGnssStatusCallback(mCallback) 的时候,接受返回值,如果返回false,delay 500ms,执行retry动作。后期测试的时候,发现goolge这个返回值默认是true,因此要注册的时候,默认delay 500ms处理。
2. bug分析
通过log发现app注册gnss status callback的时间很早,在initializeGnss—mGnssManagerService初始化时间点之前,因为这个时间点mGnssManagerService还未初始化,导致初始化失败。
通过分析log可以知道,上集中的修改仍有问题,那么究竟问题出在哪里呢?为什么app接收了LocationManager::registerGnssStatusCallback的返回值是true,但是仍没有注册成功呢?唯一的解释是android这个接口的返回值异常了,接下来我们从源码出发,一探究竟。
LocationManager::registerGnssStatusCallback的源码如下:按照api说明来看,add成功返回true,而不是注册成功,莫非这里面有坑?
/**
* Registers a GNSS status callback.
*
* @param callback GNSS status callback object to register
* @param handler a handler with a looper that the callback runs on
* @return true if the listener was successfully added
*
* @throws IllegalArgumentException if callback is null
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
*/
@RequiresPermission(ACCESS_FINE_LOCATION)
public boolean registerGnssStatusCallback(
@NonNull GnssStatus.Callback callback, @Nullable Handler handler) {
if (handler == null) {
handler = new Handler();
}
try {
return mGnssStatusListenerManager.addListener(callback, handler);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
public boolean addListener(@NonNull GpsStatus.Listener listener, @NonNull Executor executor)
throws RemoteException {
return addInternal(null, listener, executor);
}
```java
public boolean addListener(@Nullable TRequest request, @NonNull TListener listener,
@NonNull Executor executor) throws RemoteException {
return addInternal(request, listener, executor);
}
protected final boolean addInternal(@Nullable TRequest request, @NonNull Object listener,
@NonNull Handler handler) throws RemoteException {
return addInternal(request, listener, new HandlerExecutor(handler));
}
protected final boolean addInternal(@Nullable TRequest request, @NonNull Object listener,
@NonNull Executor executor)
throws RemoteException {
Preconditions.checkArgument(listener != null, "invalid null listener/callback");
return addInternal(listener, new Registration<>(request, executor, convertKey(listener)));
}
private boolean addInternal(Object key, Registration<TRequest, TListener> registration)
throws RemoteException {
Preconditions.checkNotNull(registration);
synchronized (mLock) {
boolean initialRequest = mListeners.isEmpty();
ArrayMap<Object, Registration<TRequest, TListener>> newListeners = new ArrayMap<>(
mListeners.size() + 1);
newListeners.putAll(mListeners);
Registration<TRequest, TListener> oldRegistration = newListeners.put(key,
registration);
mListeners = newListeners;
if (oldRegistration != null) {
oldRegistration.unregister();
}
TRequest merged = mergeRequests();
if (initialRequest || !Objects.equals(merged, mMergedRequest)) {
mMergedRequest = merged;
if (!initialRequest) {
unregisterService();
}
registerService(mMergedRequest);---这里才会调用LocationManagerService的registerGnssStatusCallback,但是没有接收返回值。
}
return true;---问题出在这里,直接返回了true
}
}
分析到这里,我们终于明白了,LocationManager的registerGnssStatusCallback的返回值,并没有接收LocationManagerService的registerGnssStatusCallback的返回值,而是默认返回的true。所以上集中解决方案有问题。经过和app模块讨论,最终我们决定app注册的时候,延迟500ms注册。
3. 经验总结
Android Framework提供的很多binder接口都是有返回值的,app在使用这些binder接口的时候,要充分利用这些返回值,不能简单的认为,调用了框架接口,就一定能成功。但是google的某些接口也是存在问题的,我们不要迷信google这种大公司一定不会有问题,要用审视的眼光去看待问题,从源码出发,源码是不会骗人的。