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

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

Caused by:java.lang.IllegalArgumentException: provider “network“ does not exist_第1张图片

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

---------------------------------分析---------------------------------------------------------------

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

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

/**
      * @param provider 由 {@link #getAllProviders()} 列出的提供者
      * @param locationRequest 包含位置参数的位置请求
      * @param executor 处理监听器回调的执行器
      * @param Listener 接收位置更新的监听器
      *
      * 如果提供者为 null 或不存在,则抛出 IllegalArgumentException
      * 如果 locationRequest 为 null,则抛出 IllegalArgumentException
      * 如果侦听器为空,则@抛出 IllegalArgumentException
      * 如果没有合适的权限,则抛出@抛出SecurityException
      */

 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
    public void requestLocationUpdates(@NonNull String provider,
            @NonNull LocationRequest locationRequest,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull LocationListener listener) {
        Preconditions.checkArgument(provider != null, "invalid null provider");
        Preconditions.checkArgument(locationRequest != null, "invalid null location request");

        try {
            synchronized (sLocationListeners) {
                WeakReference reference = sLocationListeners.get(
                        listener);
                LocationListenerTransport transport = reference != null ? reference.get() : null;
                if (transport == null) {
                    transport = new LocationListenerTransport(listener, executor);
                } else {
                    Preconditions.checkState(transport.isRegistered());
                    transport.setExecutor(executor);
                }

                //调用LocationManagerService的方法
                mService.registerLocationListener(provider, locationRequest, transport,
                        mContext.getPackageName(), mContext.getAttributionTag(),
                        AppOpsManager.toReceiverId(listener));

                sLocationListeners.put(listener, new WeakReference<>(transport));
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

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

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

  @Override
    public void registerLocationListener(String provider, LocationRequest request,
            ILocationListener listener, String packageName, @Nullable String attributionTag,
            String listenerId) {
        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
                listenerId);
        int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(),
                identity.getPid());
        LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel,
                PERMISSION_COARSE);

        // clients in the system process should have an attribution tag set
        if (identity.getPid() == Process.myPid() && attributionTag == null) {
            Log.w(TAG, "system location request with no attribution tag",
                    new IllegalArgumentException());
        }

        request = validateLocationRequest(provider, request, identity);

        LocationProviderManager manager = getLocationProviderManager(provider);
        //当provider不存在时,抛出异常
        Preconditions.checkArgument(manager != null,
                "provider \"" + provider + "\" does not exist");

        manager.registerLocationRequest(request, identity, permissionLevel, listener);
    }

(3)上面源码上可以看到,当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());
    }

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

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

/**
      * @param provider 由 {@link #getAllProviders()} 列出的提供者
      * @param locationRequest 包含位置参数的位置请求
      * @param executor 处理监听器回调的执行器
      * @param Listener 接收位置更新的监听器
      *
      * 如果提供者为 null 或不存在,则抛出 IllegalArgumentException
      * 如果 locationRequest 为 null,则抛出 IllegalArgumentException
      * 如果侦听器为空,则@抛出 IllegalArgumentException
      * 如果没有合适的权限,则抛出@抛出SecurityException
      */

 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
    public void requestLocationUpdates(@NonNull String provider,
            @NonNull LocationRequest locationRequest,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull LocationListener listener) {
        Preconditions.checkArgument(provider != null, "invalid null provider");
        Preconditions.checkArgument(locationRequest != null, "invalid null location request");

        try {
            synchronized (sLocationListeners) {
                WeakReference reference = sLocationListeners.get(
                        listener);
                LocationListenerTransport transport = reference != null ? reference.get() : null;
                if (transport == null) {
                    transport = new LocationListenerTransport(listener, executor);
                } else {
                    Preconditions.checkState(transport.isRegistered());
                    transport.setExecutor(executor);
                }

      //当名字为NETWORK_PROVIDER的provider不可用时,不更新定位信息
      
   +           if(!isProviderEnabled(NETWORK_PROVIDER))
   +             return ;

                //调用LocationManagerService的方法
                mService.registerLocationListener(provider, locationRequest, transport,
                        mContext.getPackageName(), mContext.getAttributionTag(),
                        AppOpsManager.toReceiverId(listener));

                sLocationListeners.put(listener, new WeakReference<>(transport));
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

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