LocationManager的Android检查权限

我正在尝试获取GPS坐标以在我的活动布局中单击button时显示。 以下是当我点击button时被调用的方法:

public void getLocation(View view) { TextView tv = (TextView) findViewById(R.id.gps_coord_view); LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE); Location loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER); tv.setText("Latitude: " + loc.getLatitude() + "\nLongitude: " + loc.getLongitude()); } 

我收到一个错误,说

通话需要用户可能会拒绝的权限。 代码应明确检查是否有权限。

我已经在AndroidManifest授予了这些权限。 在调用lm.getLastKnownLocation之前,我添加了以下内容,这个错误已经被处理,应用程序会编译:

 if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return; } 

然而,当我点击button调用getLocation时,应用程序崩溃。 到底是怎么回事? 有更好/更简单的方法来抓住设备的GPS坐标?

使用Android API级别(23),我们需要检查权限。 https://developer.android.com/training/permissions/requesting.html

我有你的同样的问题,但以下为我工作,我能够成功地检索位置数据:

(1)确保您拥有在清单中列出的权限:

 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 

(2)确保您向用户请求权限:

 if ( ContextCompat.checkSelfPermission( this, android.Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions( this, new String[] { android.Manifest.permission.ACCESS_COARSE_LOCATION }, LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION ); } 

(3)确保您使用ContextCompat,因为这与旧API级别兼容。

(4)在您的位置服务或初始化LocationManager并获取最后一个已知位置的类中,我们需要检查权限:

 if ( Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission( context, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission( context, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return ; } 

(5)在我的initLocationService方法的顶部包含@TargetApi(23)之后,这个方法只对我有效。

(6)我也join到我的gradle构build中:

 compile 'com.android.support:support-v4:23.0.1' 

这是我的LocationService供参考:

 public class LocationService implements LocationListener { //The minimum distance to change updates in meters private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 10 meters //The minimum time beetwen updates in milliseconds private static final long MIN_TIME_BW_UPDATES = 0;//1000 * 60 * 1; // 1 minute private final static boolean forceNetwork = false; private static LocationService instance = null; private LocationManager locationManager; public Location location; public double longitude; public double latitude; /** * Singleton implementation * @return */ public static LocationService getLocationManager(Context context) { if (instance == null) { instance = new LocationService(context); } return instance; } /** * Local constructor */ private LocationService( Context context ) { initLocationService(context); LogService.log("LocationService created"); } /** * Sets up location service after permissions is granted */ @TargetApi(23) private void initLocationService(Context context) { if ( Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission( context, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission( context, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return ; } try { this.longitude = 0.0; this.latitude = 0.0; this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); // Get GPS and network status this.isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); this.isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); if (forceNetwork) isGPSEnabled = false; if (!isNetworkEnabled && !isGPSEnabled) { // cannot get location this.locationServiceAvailable = false; } //else { this.locationServiceAvailable = true; if (isNetworkEnabled) { locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); if (locationManager != null) { location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); updateCoordinates(); } }//end if if (isGPSEnabled) { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); if (locationManager != null) { location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); updateCoordinates(); } } } } catch (Exception ex) { LogService.log( "Error creating location service: " + ex.getMessage() ); } } @Override public void onLocationChanged(Location location) { // do stuff here with location object } } 

我只用一个Android棒棒糖设备进行testing。 希望这对你有用。

简单的解决scheme

我想支持应用程序的pre api 23,而不是使用checkSelfPermission我用try / catch

 try { location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); } catch (SecurityException e) { dialogGPS(this.getContext()); // lets the user know there is a problem with the gps } 

您引用的错误消息的最后一部分指出: ...with ("checkPermission") or explicitly handle a potential "SecurityException"

检查你是否有权限的更快更简单的方法是用try { ... } catch (SecurityException e) { [insert error handling code here] }来包围你的代码。 如果你有权限,'try'部分将执行,如果你不这样做,'catch'部分将会执行。

如果您正在使用dynamic权限以及ACCESS_FINE_LOCATION等任何权限,则ACCESS_COARSE_LOCATION会提供错误“无法parsingPERMISSION_NAME”方法 ,请使用权限名称编写代码,然后重新生成项目,这将重新生成清单(Manifest.permission)文件。