Caused by:java.lang.IllegalArgumentException: provider “network“ does not exist

问题: 手机定位权限开启,在安装定制化apk时,首次安装正常启动,再次启动,则应用崩溃.根据系统日志,定位到问题是在LocationManager.java中.系统日志如下图:

 问题分析: app中会申请定位的权限,但是系统中,现在network provider不存在,当provider不存在时,调用LocationManagerService.java 的 requestLocationUpdates(),安卓系统会抛出异常.

(1) 当app 获取定位时,会通过LocationManager.java 提供的api,获取定位,

源码路径:frameworks/base/location/java/android/location/LocationManager.java

  @UnsupportedAppUsage
    private void requestLocationUpdates(LocationRequest request, LocationListener listener,
            Looper looper, PendingIntent intent) {

        String packageName = mContext.getPackageName();

        // wrap the listener class
        ListenerTransport transport = wrapListener(listener, looper);

        try {

            //调用LocatonManagerService中的方法
            mService.requestLocationUpdates(request, transport, intent, packageName);

       } catch (RemoteException e) {
           throw e.rethrowFromSystemServer();
       }
    }

(2)接着着调用LocationManagerService 的requestLocationUpdates() 方法.

源码路径:frameworks/base/services/core/java/com/android/server/LocationManagerService.java

 @Override
 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
            PendingIntent intent, String packageName) {


                      ......            

  Receiver receiver;
                if (intent != null) {
                    receiver = getReceiverLocked(intent, pid, uid, packageName, workSource,
                            hideFromAppOps);
                } else {
                    receiver = getReceiverLocked(listener, pid, uid, packageName, workSource,
                            hideFromAppOps);
                }
 
                //进一步调用
                requestLocationUpdatesLocked(sanitizedRequest, receiver, uid, packageName);
            
} finally {
                Binder.restoreCallingIdentity(identity);
            }

                     ......

(3)接着着调用 requestLocationUpdatesLocked()

 @GuardedBy("mLock")
    private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
            int uid, String packageName) {
        // Figure out the provider. Either its explicitly request (legacy use cases), or
        // use the fused provider
        if (request == null) request = DEFAULT_LOCATION_REQUEST;
        //获取需要的provider
        String name = request.getProvider();
        //provider name 不能为空,否则抛出异常
        if (name == null) {
            throw new IllegalArgumentException("provider name must not be null");
        }
       
        //通过provider name 来获取 locationProvider 
        LocationProvider provider = getLocationProviderLocked(name);

        // 当 locationProvider 为null 时,会抛出异常
        if (provider == null) {
            throw new IllegalArgumentException("provider doesn't exist: " + name);
        }

        UpdateRecord record = new UpdateRecord(name, request, receiver);
        if (D) {
            Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
                    + " " + name + " " + request + " from " + packageName + "(" + uid + " "
                    + (record.mIsForegroundUid ? "foreground" : "background")
                    + (isThrottlingExemptLocked(receiver.mCallerIdentity)
                    ? " [whitelisted]" : "") + ")");
        }

        UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
        if (oldRecord != null) {
            oldRecord.disposeLocked(false);
        }

        if (!provider.isUseableLocked() && !isSettingsExemptLocked(record)) {
            // Notify the listener that updates are currently disabled - but only if the request
            // does not ignore location settings
            receiver.callProviderEnabledLocked(name, false);
        }

        applyRequirementsLocked(name);

        // Update the monitoring here just in case multiple location requests were added to the
        // same receiver (this request may be high power and the initial might not have been).
        receiver.updateMonitoring(true);
    }

(4)上面源码上可以看到,当LocationProvider 为 null 时,系统会抛出异常,这就是日志中看到的异常,因此,可以在 locationProvider 不为为 null 的时,才执行后面的步骤,在LocationManager.java中,提供了一个 isProviderEnabled()方法去判断provider是否可用.

源码路径:frameworks/base/location/java/android/location/LocationManager.java

//如果提供程序存在并且已启用返回true;如果provider为null,则抛出 IllegalArgumentException
 
public boolean isProviderEnabled(@NonNull String provider) {
        return isProviderEnabledForUser(provider, Process.myUserHandle());
    }

(5) 因此,最终的解决方案为:

源码路径:frameworks/base/location/java/android/location/LocationManager.java

  @UnsupportedAppUsage
    private void requestLocationUpdates(LocationRequest request, LocationListener listener,
            Looper looper, PendingIntent intent) {

        String packageName = mContext.getPackageName();

        // wrap the listener class
        ListenerTransport transport = wrapListener(listener, looper);

        try {

           //如果名字为NETWORK_PROVIDER的LocationProvider为null,就不继续后面的获取位置的流程
 +           if (!isProviderEnabled(NETWORK_PROVIDER))
 +             retrun ;

            //调用LocatonManagerService中的方法
            mService.requestLocationUpdates(request, transport, intent, packageName);

       } catch (RemoteException e) {
           throw e.rethrowFromSystemServer();
       }
    }

你可能感兴趣的:(Android,10,Android,java,开发语言,android)