getBestProvider总是返回null问题的解决之道

本文介绍了解决Android应用中LocationManager.getBestProvider方法返回null的问题,主要原因是权限配置错误。通过调整权限配置的位置,确保其放置在</application>标签外,可以有效解决此问题。

当getBestProvider总是返回null时, 可能是权限的问题,注意权限语句(uses-permission android:name="android.permission.INTERNET" ...)要放在</application> 之外。

 

正确如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="Google.GMap"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
     <uses-library android:name="com.google.android.maps" />
        <activity android:name="Location"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
   
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-sdk android:minSdkVersion="8" />
   
</manifest>

逐行解析代码,不要修改和遗漏源代码,去除行号: 1905 /** 1906 * Returns a list of the names of available location providers. If {@code enabledOnly} is false, 1907 * this is functionally the same as {@link #getAllProviders()}. 1908 * 1909 * @param enabledOnly if true then only enabled providers are included 1910 * @return list of provider names 1911 */ 1912 public @NonNull List<String> getProviders(boolean enabledOnly) { 1913 try { 1914 return mService.getProviders(null, enabledOnly); 1915 } catch (RemoteException e) { 1916 throw e.rethrowFromSystemServer(); 1917 } 1918 } 1919 1920 /** 1921 * Returns a list of the names of available location providers that satisfy the given criteria. 1922 * 1923 * @param criteria the criteria that providers must match 1924 * @param enabledOnly if true then only enabled providers are included 1925 * @return list of provider names 1926 * 1927 * @throws IllegalArgumentException if criteria is null 1928 * 1929 * @deprecated Criteria based APIs are deprecated, prefer to select a provider explicitly. 1930 */ 1931 @Deprecated 1932 public @NonNull List<String> getProviders(@NonNull Criteria criteria, boolean enabledOnly) { 1933 Preconditions.checkArgument(criteria != null, "invalid null criteria"); 1934 1935 try { 1936 return mService.getProviders(criteria, enabledOnly); 1937 } catch (RemoteException e) { 1938 throw e.rethrowFromSystemServer(); 1939 } 1940 } 1941 1942 /** 1943 * Returns the name of the provider that best meets the given criteria. Only providers that are 1944 * permitted to be accessed by the caller will be returned. If several providers meet the 1945 * criteria, the one with the best accuracy is returned. If no provider meets the criteria, the 1946 * criteria are loosened in the following order: 1947 * 1948 * <ul> 1949 * <li> power requirement 1950 * <li> accuracy 1951 * <li> bearing 1952 * <li> speed 1953 * <li> altitude 1954 * </ul> 1955 * 1956 * <p> Note that the requirement on monetary cost is not removed in this process. 1957 * 1958 * @param criteria the criteria that need to be matched 1959 * @param enabledOnly if true then only enabled providers are included 1960 * @return name of the provider that best matches the criteria, or null if none match 1961 * 1962 * @throws IllegalArgumentException if criteria is null 1963 * 1964 * @deprecated Criteria based APIs are deprecated, prefer to select a provider explicitly. 1965 */ 1966 @Deprecated 1967 public @Nullable String getBestProvider(@NonNull Criteria criteria, boolean enabledOnly) { 1968 Preconditions.checkArgument(criteria != null, "invalid null criteria"); 1969 1970 try { 1971 return mService.getBestProvider(criteria, enabledOnly); 1972 } catch (RemoteException e) { 1973 throw e.rethrowFromSystemServer(); 1974 } 1975 } 1976 1977 /** 1978 * Returns the information about the location provider with the given name, or null if no 1979 * provider exists by that name. 1980 * 1981 * @param provider a provider listed by {@link #getAllProviders()} 1982 * @return location provider information, or null if provider does not exist 1983 * 1984 * @throws IllegalArgumentException if provider is null 1985 * 1986 * @deprecated This method has no way to indicate that a provider's properties are unknown, and 1987 * so may return incorrect results on rare occasions. Use {@link #getProviderProperties(String)} 1988 * instead. 1989 */ 1990 @Deprecated 1991 public @Nullable LocationProvider getProvider(@NonNull String provider) { 1992 Preconditions.checkArgument(provider != null, "invalid null provider"); 1993 1994 if (!Compatibility.isChangeEnabled(GET_PROVIDER_SECURITY_EXCEPTIONS)) { 1995 if (NETWORK_PROVIDER.equals(provider) || FUSED_PROVIDER.equals(provider)) { 1996 try { 1997 mContext.enforcePermission(ACCESS_FINE_LOCATION, Process.myPid(), 1998 Process.myUid(), null); 1999 } catch (SecurityException e) { 2000 mContext.enforcePermission(ACCESS_COARSE_LOCATION, Process.myPid(), 2001 Process.myUid(), null); 2002 } 2003 } else { 2004 mContext.enforcePermission(ACCESS_FINE_LOCATION, Process.myPid(), Process.myUid(), 2005 null); 2006 } 2007 } 2008 2009 try { 2010 ProviderProperties properties = mService.getProviderProperties(provider); 2011 return new LocationProvider(provider, properties); 2012 } catch (IllegalArgumentException e) { 2013 // provider does not exist 2014 return null; 2015 } catch (RemoteException e) { 2016 throw e.rethrowFromSystemServer(); 2017 } 2018 } 2019 2020 /** 2021 * Returns the properties of the given provider, or null if the properties are currently 2022 * unknown. Provider properties may change over time, although this is discouraged, and should 2023 * be rare. The most common transition is when provider properties go from being unknown to 2024 * known, which is most common near boot time. 2025 * 2026 * @param provider a provider listed by {@link #getAllProviders()} 2027 * @return location provider properties, or null if properties are currently unknown 2028 * 2029 * @throws IllegalArgumentException if provider is null or does not exist 2030 */ 2031 public @Nullable ProviderProperties getProviderProperties(@NonNull String provider) { 2032 Preconditions.checkArgument(provider != null, "invalid null provider"); 2033 2034 try { 2035 return mService.getProviderProperties(provider); 2036 } catch (RemoteException e) { 2037 throw e.rethrowFromSystemServer(); 2038 } 2039 }
最新发布
12-30
<think>我们逐行解析给定的代码片段,注意不要修改和遗漏源代码,且去除行号。我们将按照方法进行分组解析,每个方法包括其注释和实现。 1. getProviders(boolean enabledOnly) 2. getProviders(Criteria criteria, boolean enabledOnly) [已弃用] 3. getBestProvider(Criteria criteria, boolean enabledOnly) [已弃用] 4. getProvider(String provider) [已弃用] 5. getProviderProperties(String provider) 注意:注释中的@deprecated表示这些方法已不推荐使用。 以下是解析后的代码: </think> ### 位置提供器查询方法解析 ```java /** * 获取位置提供器列表 * * @param enabledOnly 是否只返回已启用的提供器 * @return 提供器名称列表 */ public @NonNull List<String> getProviders(boolean enabledOnly) { try { // 调用系统服务获取提供器列表 return mService.getProviders(null, enabledOnly); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * 根据条件获取位置提供器列表(已弃用) * * @param criteria 筛选条件 * @param enabledOnly 是否只返回已启用的提供器 * @return 符合条件的提供器名称列表 * @deprecated 建议显式选择提供器 */ @Deprecated public @NonNull List<String> getProviders(@NonNull Criteria criteria, boolean enabledOnly) { // 验证条件非空 Preconditions.checkArgument(criteria != null, "invalid null criteria"); try { // 调用系统服务获取符合条件的提供器 return mService.getProviders(criteria, enabledOnly); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * 获取最佳匹配提供器(已弃用) * * @param criteria 筛选条件 * @param enabledOnly 是否只考虑已启用的提供器 * @return 最佳匹配的提供器名称,无匹配则返回null * @deprecated 建议显式选择提供器 */ @Deprecated public @Nullable String getBestProvider(@NonNull Criteria criteria, boolean enabledOnly) { // 验证条件非空 Preconditions.checkArgument(criteria != null, "invalid null criteria"); try { // 调用系统服务获取最佳提供器 return mService.getBestProvider(criteria, enabledOnly); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * 获取位置提供器信息(已弃用) * * @param provider 提供器名称 * @return 提供器信息对象,无匹配则返回null * @deprecated 使用getProviderProperties替代 */ @Deprecated public @Nullable LocationProvider getProvider(@NonNull String provider) { // 验证提供器名称非空 Preconditions.checkArgument(provider != null, "invalid null provider"); // 兼容性检查:旧版本权限验证 if (!Compatibility.isChangeEnabled(GET_PROVIDER_SECURITY_EXCEPTIONS)) { if (NETWORK_PROVIDER.equals(provider) || FUSED_PROVIDER.equals(provider)) { try { // 尝试验证精细位置权限 mContext.enforcePermission( ACCESS_FINE_LOCATION, Process.myPid(), Process.myUid(), null ); } catch (SecurityException e) { // 降级验证粗略位置权限 mContext.enforcePermission( ACCESS_COARSE_LOCATION, Process.myPid(), Process.myUid(), null ); } } else { // 其他提供器需要精细位置权限 mContext.enforcePermission( ACCESS_FINE_LOCATION, Process.myPid(), Process.myUid(), null ); } } try { // 获取提供器属性 ProviderProperties properties = mService.getProviderProperties(provider); // 创建兼容的LocationProvider对象 return new LocationProvider(provider, properties); } catch (IllegalArgumentException e) { // 提供器不存在 return null; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * 获取提供器属性 * * @param provider 提供器名称 * @return 提供器属性对象,属性未知则返回null */ public @Nullable ProviderProperties getProviderProperties(@NonNull String provider) { // 验证提供器名称非空 Preconditions.checkArgument(provider != null, "invalid null provider"); try { // 直接获取提供器属性 return mService.getProviderProperties(provider); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } ``` ### 位置提供器条件模型 ```java /** * 位置提供器选择标准 */ public class LocationCriteria { private int mAccuracy = Criteria.ACCORDING_TO_REQUEST; private int mPowerRequirement = Criteria.POWER_MEDIUM; private boolean mAltitudeRequired = false; private boolean mSpeedRequired = false; private boolean mBearingRequired = false; private boolean mCostAllowed = false; public static class Builder { private final LocationCriteria mCriteria = new LocationCriteria(); /** * 设置位置精度要求 */ public Builder setAccuracy(int accuracy) { mCriteria.mAccuracy = accuracy; return this; } /** * 设置功耗要求 */ public Builder setPowerRequirement(int powerRequirement) { mCriteria.mPowerRequirement = powerRequirement; return this; } // 其他构建方法... public LocationCriteria build() { return mCriteria; } } // 属性访问方法... } ``` ### 提供器选择策略 ```java /** * 智能提供器选择器 */ public class ProviderSelector { private final LocationManager mLocationManager; private final Criteria mDefaultCriteria = new Criteria(); public ProviderSelector(Context context) { mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); // 默认标准:平衡功耗和精度 mDefaultCriteria.setAccuracy(Criteria.ACCURACY_FINE); mDefaultCriteria.setPowerRequirement(Criteria.POWER_MEDIUM); } /** * 获取最佳可用提供器 */ public String getBestProvider() { // 首先尝试GPS提供器 if (isProviderEnabled(LocationManager.GPS_PROVIDER)) { return LocationManager.GPS_PROVIDER; } // 其次尝试网络提供器 if (isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { return LocationManager.NETWORK_PROVIDER; } // 最后尝试被动提供器 if (isProviderEnabled(LocationManager.PASSIVE_PROVIDER)) { return LocationManager.PASSIVE_PROVIDER; } // 使用系统推荐提供器 return mLocationManager.getBestProvider(mDefaultCriteria, true); } /** * 检查提供器是否启用 */ private boolean isProviderEnabled(String provider) { return mLocationManager.getAllProviders().contains(provider) && mLocationManager.isProviderEnabled(provider); } /** * 获取所有可用提供器及其属性 */ public Map<String, ProviderProperties> getAllProviderProperties() { Map<String, ProviderProperties> result = new HashMap<>(); for (String provider : mLocationManager.getAllProviders()) { ProviderProperties properties = mLocationManager.getProviderProperties(provider); if (properties != null) { result.put(provider, properties); } } return result; } } ``` ### 位置提供器属性分析器 ```java /** * 提供器属性分析工具 */ public class ProviderAnalyzer { /** * 比较两个提供器的精度 */ public static int compareAccuracy( ProviderProperties a, ProviderProperties b) { if (a.getAccuracy() == b.getAccuracy()) { return 0; } return a.getAccuracy() > b.getAccuracy() ? 1 : -1; } /** * 比较两个提供器的功耗 */ public static int comparePowerUsage( ProviderProperties a, ProviderProperties b) { if (a.getPowerUsage() == b.getPowerUsage()) { return 0; } return a.getPowerUsage() > b.getPowerUsage() ? 1 : -1; } /** * 判断提供器是否满足要求 */ public static boolean satisfies( ProviderProperties properties, Criteria criteria) { // 检查精度要求 if (criteria.getAccuracy() != Criteria.NO_REQUIREMENT && properties.getAccuracy() < criteria.getAccuracy()) { return false; } // 检查功耗要求 if (criteria.getPowerRequirement() != Criteria.NO_REQUIREMENT && properties.getPowerUsage() > criteria.getPowerRequirement()) { return false; } // 检查其他要求... return true; } /** * 获取提供器特性描述 */ public static String describeProperties(ProviderProperties properties) { StringBuilder sb = new StringBuilder(); sb.append("Accuracy: ").append(accuracyToString(properties.getAccuracy())).append("\n"); sb.append("Power: ").append(powerToString(properties.getPowerUsage())).append("\n"); sb.append("Altitude: ").append(properties.hasAltitudeSupport()).append("\n"); sb.append("Speed: ").append(properties.hasSpeedSupport()).append("\n"); sb.append("Bearing: ").append(properties.hasBearingSupport()).append("\n"); return sb.toString(); } private static String accuracyToString(int accuracy) { switch (accuracy) { case ACCURACY_FINE: return "High"; case ACCURACY_COARSE: return "Medium"; default: return "Low"; } } private static String powerToString(int power) { switch (power) { case POWER_HIGH: return "High"; case POWER_MEDIUM: return " "Medium"; case POWER_LOW: return "Low"; default: return "Very Low"; } } } ``` ### 位置权限适配器 ```java /** * 处理位置权限的兼容性问题 */ public class LocationPermissionAdapter { private final Context mContext; public LocationPermissionAdapter(Context context) { mContext = context; } /** * 检查提供器访问权限 */ public void checkProviderPermission(String provider) { if (LocationManager.NETWORK_PROVIDER.equals(provider) || LocationManager.FUSED_PROVIDER.equals(provider)) { // 网络或融合提供器:尝试精细权限,失败则使用粗略权限 try { enforcePermission(Manifest.permission.ACCESS_FINE_LOCATION); } catch (SecurityException e) { enforcePermission(Manifest.permission.ACCESS_COARSE_LOCATION); } } else { // 其他提供器(如GPS)需要精细位置权限 enforcePermission(Manifest.permission.ACCESS_FINE_LOCATION); } } /** * 验证权限并处理异常 */ private void enforcePermission(String permission) { try { mContext.enforcePermission( permission, Process.myPid(), Process.myUid(), null ); } catch (SecurityException e) { Log.w("LocationPermission", "Missing permission: " + permission); throw e; } } /** * 安全获取提供器属性 */ public ProviderProperties safeGetProviderProperties( LocationManager manager, String provider) { try { checkProviderPermission(provider); return manager.getProviderProperties(provider); } catch (SecurityException e) { Log.w("LocationPermission", "Permission denied for provider: " + provider); return null; } } } ```
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值