无法授予 FINE_LOCATION 权限

Posted

技术标签:

【中文标题】无法授予 FINE_LOCATION 权限【英文标题】:Can not grant FINE_LOCATION Permission 【发布时间】:2017-10-30 17:19:47 【问题描述】:

您好,我正在构建一个应用程序,我想访问手机的位置。但是,我似乎无法授予访问精细位置权限,因此我的应用无法在我正在测试的 android M 手机中运行。 这是我的代码的一部分:

 public class LocationMainActivity extends AppCompatActivity 

private ListView listView;
private static final String EXTERNAL_PERMISSIONS[] = new String[]
        Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.INTERNET;
private static final int EXTERNAL_CODE=1;
private boolean perm;
private Cursor cursor;
private DatabaseAdapt dbAdapt;
@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_location_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar4);
    setSupportActionBar(toolbar);
    ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    listView = (ListView)findViewById(R.id.locationContainer);

    dbAdapt = new DatabaseAdapt(this);
    dbAdapt.open();
    cursor =dbAdapt.loadLocationTitles();
    String [] from = new String[]DatabaseAdapt.LOCATION_TITLE;
    int [] to = new int[] android.R.id.text1;
    CursorAdapter cursorAdapter = new SimpleCursorAdapter(this,android.R.layout.simple_list_item_1,cursor,
            from,to,0);
    listView.setAdapter(cursorAdapter);


public void onDestroy()
    super.onDestroy();
    cursor.close();
    dbAdapt.close();


@Override
public boolean onCreateOptionsMenu(Menu menu) 
    getMenuInflater().inflate(R.menu.menu_main,menu);
    return super.onCreateOptionsMenu(menu);


@Override
public boolean onOptionsItemSelected(MenuItem item) 
    int id = item.getItemId();
    if(id==R.id.add_button);
        askForPerm();
        if(perm)
            Intent intent = new Intent(LocationMainActivity.this,LocationSecondActivity.class);
            startActivity(intent);
        
        else 
            askForPerm();
        
    
    return super.onOptionsItemSelected(item);


private void askForPerm () 

    // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
    int w = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
    int r = ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET);

    if (w != PackageManager.PERMISSION_GRANTED && r != PackageManager.PERMISSION_GRANTED) 
        ActivityCompat.requestPermissions(this, EXTERNAL_PERMISSIONS, EXTERNAL_CODE);
     else 
        Toast.makeText(this, "Permissions already granted", Toast.LENGTH_SHORT).show();
        perm=true;
    


@Override
public void onRequestPermissionsResult(int requestCode,String[] permissions, int[] grantResults) 
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode)
        case EXTERNAL_CODE:
            if(ActivityCompat.checkSelfPermission(this,permissions[0])==PackageManager.PERMISSION_GRANTED)
            
                perm=true;
            
            else 
                Toast.makeText(this,"Permissions denied",Toast.LENGTH_LONG).show();
                perm=false;
            
            break;
    


在此活动中,我要求获得权限,然后才能添加新位置。该应用程序会定期移动到下一个活动,即使我是第一次安装该应用程序,也会显示授予 toast 的权限,这似乎有点奇怪。我使用相同的代码在应用程序的另一个功能中请求写入外部和相机权限,它工作正常。

我还包含了我想要获取位置坐标的第二个活动的代码

 private EditText editTitleLocation, addressText, latText,longText;
private Button saveLocationButton, deleteLocationButton, navigateButton,findLocationButton;
private static final int UPDATE_TIME = 15000;
private static final int FASTER_UPDATE_TIME = 10000;
private GoogleApiClient myGoogleApi;
private Location location;
private LocationRequest myLocationRequest;
private static final int CHECK_CODE=1;
private double longitude,latitude;
@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_location_second);
    ActionBar actionBar = getSupportActionBar();
    actionBar.setHomeButtonEnabled(true);
    actionBar.setDisplayHomeAsUpEnabled(true);
    actionBar.setDisplayShowHomeEnabled(true);
    initializeViews();
    buildGoogleApi();



private void initializeViews()
    editTitleLocation = (EditText)findViewById(R.id.editTitleLocation);
    addressText = (EditText)findViewById(R.id.addressText);
    latText = (EditText)findViewById(R.id.latitudeText);
    longText=(EditText)findViewById(R.id.longitudeText);
    saveLocationButton = (Button)findViewById(R.id.saveLocation);
    deleteLocationButton = (Button)findViewById(R.id.deleteLocation);
    findLocationButton = (Button)findViewById(R.id.findLocation);
    navigateButton= (Button)findViewById(R.id.navigateLocation);
    saveLocationButton.setOnClickListener(this);
    deleteLocationButton.setOnClickListener(this);
    findLocationButton.setOnClickListener(this);
    navigateButton.setOnClickListener(this);



public void onStart()
    super.onStart();
    if(myGoogleApi!=null)
        myGoogleApi.connect();
    


public void onPause()
    super.onPause();
   if(myGoogleApi!=null)
    LocationServices.FusedLocationApi.removeLocationUpdates(myGoogleApi,LocationSecondActivity.this);


public void onStop()
    super.onStop();
    myGoogleApi.disconnect();


private synchronized void buildGoogleApi()
    myGoogleApi = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API).build();


private void createRequest ()

    myLocationRequest = new LocationRequest();
    myLocationRequest.setInterval(UPDATE_TIME)
                    .setFastestInterval(FASTER_UPDATE_TIME)
                    .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(myLocationRequest);
    PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(myGoogleApi,builder.build());

    result.setResultCallback(new ResultCallback<LocationSettingsResult>() 
        @Override
        public void onResult(LocationSettingsResult result) 
            final Status status = result.getStatus();
            switch (status.getStatusCode())
                case LocationSettingsStatusCodes.SUCCESS:
                    retrieveLocation();
                    break;
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    try
                        status.startResolutionForResult(LocationSecondActivity.this,CHECK_CODE);
                    catch (IntentSender.SendIntentException e)
                        e.printStackTrace();
                    
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                    Toast.makeText(LocationSecondActivity.this,"Settings Change Unavailable",Toast.LENGTH_SHORT).show();
                    break;
            
        
    );


private void retrieveLocation()
    try 
        location = LocationServices.FusedLocationApi.getLastLocation(myGoogleApi);
    catch (SecurityException ex)
        ex.printStackTrace();
    



@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
   switch (requestCode)
       case CHECK_CODE:
           switch (requestCode)
               case Activity.RESULT_OK:
               retrieveLocation();
                   break;
               case Activity.RESULT_CANCELED:
                   break;
           
           break;
   


@Override
public void onConnected(Bundle bundle) 
    createRequest();


@Override
public void onConnectionSuspended(int i) 



@Override
public void onConnectionFailed(ConnectionResult connectionResult) 
    Toast.makeText(this,"Google Api can not connect",Toast.LENGTH_LONG).show();


@Override
public void onLocationChanged(Location location) 
    this.location=location;
    longitude=location.getLongitude();
    latitude=location.getLatitude();


@Override
public void onClick(View v) 
    int id = v.getId();

    switch (id)
        case R.id.saveLocation:
            break;
        case R.id.deleteLocation:
            break;
        case R.id.navigateLocation:
            break;
        case R.id.findLocation:

            if(location!=null)
                latitude = location.getLatitude();
                Log.e("MALAKIS",String.valueOf(latitude));
                longitude=location.getLongitude();
                latText.setText(String.valueOf(latitude));
                longText.setText(String.valueOf(longitude));
            else 
                if(!myGoogleApi.isConnected())
                    myGoogleApi.connect();
                    Log.e("ELSE","fdsfddsd");
                
               try 

                   LocationServices.FusedLocationApi.requestLocationUpdates(myGoogleApi, myLocationRequest, this);
               catch (SecurityException ex)
                   ex.printStackTrace();
               
            

            break;
    


这里的位置是对象为空,安全位置被触发指向我没有精细的位置权限。所以请有人能指出我正确的方向吗?我是否在第二个活动中再次请求权限?

日志显示如下:

    W/System.err: java.lang.SecurityException: Client must have 
  ACCESS_FINE_LOCATION permission to request PRIORITY_HIGH_ACCURACY 
 locations.
 05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad 
 W/System.err:     at android.os.Parcel.readException(Parcel.java:1602)
 05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad 
 W/System.err:     at android.os.Parcel.readException(Parcel.java:1555)
 05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad 
W/System.err:     at 
com.google.android.gms.internal.zzase$zza$zza.zza(Unknown Source)
05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad 
W/System.err:     at com.google.android.gms.internal.zzasg.zza(Unknown 
Source)
05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad 
W/System.err:     at com.google.android.gms.internal.zzash.zza(Unknown 
Source)
05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad 
W/System.err:     at com.google.android.gms.internal.zzary$1.zza(Unknown 
Source)
05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad 
W/System.err:     at com.google.android.gms.internal.zzary$1.zza(Unknown 
Source)
05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad 
W/System.err:     at com.google.android.gms.internal.zzaad$zza.zzb(Unknown 
Source)

【问题讨论】:

安全位置被触发,指向我没有良好的位置权限 ...是运行时异常或 IDE/Lint 警告...我赌警告。 ..这与 getLastLocation 可能返回 null 而你必须忍受这一事实无关 要检查一件小事,你的 元素需要在 之外。它们应该是根 元素的直接子元素。有时,当您在应用程序启动时将它们放入其中时,例如该位置已经在使用中并导致这样的麻烦。 我已经编辑了我的问题并包含了日志。权限在 之外。在 Android 5.0 上测试时我可以获取坐标,但在 Android 6.0 中无法获取 你的targetsdkversion是什么 24.我需要在retrieveLocation 方法中请求权限并且它起作用了。 【参考方案1】:

在你的 askForPerm() 方法中加入以下代码:-

LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(30 * 1000);
    locationRequest.setFastestInterval(5 * 1000);
    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
            .addLocationRequest(locationRequest);
    builder.setAlwaysShow(true); //this is the key ingredient

    PendingResult<LocationSettingsResult> result =
            LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
    result.setResultCallback(new ResultCallback<LocationSettingsResult>() 
        @Override
        public void onResult(LocationSettingsResult result) 
            final Status status = result.getStatus();
            final LocationSettingsStates state = result.getLocationSettingsStates();
            switch (status.getStatusCode()) 
                case LocationSettingsStatusCodes.SUCCESS:
                    // All location settings are satisfied. The client can initialize location
                    // requests here.
                    break;
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    // Location settings are not satisfied. But could be fixed by showing the user
                    // a dialog.
                    try 
                        // Show the dialog by calling startResolutionForResult(),
                        // and check the result in onActivityResult().
                        status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
                     catch (IntentSender.SendIntentException e) 
                        // Ignore the error.
                    
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                    // Location settings are not satisfied. However, we have no way to fix the
                    // settings so we won't show the dialog.
                    break;
            
        
    );

试试这个!!它适用于我的应用程序。

【讨论】:

我修改了我的代码并询问了第二个活动中的权限,它可以工作。我也想问一个问题。是否可以检查用户是否连接到wifi或网络并提示他启用互联网连接?因为我使用的设置 api 只提示用户允许访问他的位置 是的,您可以通过以下方式进行检查:- public boolean isConnected() ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Activity.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); if (networkInfo != null && networkInfo.isConnected()) 返回真;否则返回假;

以上是关于无法授予 FINE_LOCATION 权限的主要内容,如果未能解决你的问题,请参考以下文章

如果没有GPS,则无法使用navigator.geolocation进行反应原生的当前位置

在没有 GPS 的情况下,使用 navigator.geolocation 在 react-native 上无法获取当前位置

Android 11 用户无法授予后台位置权限?

PLSQL 授予用户权限,但仍无法修改数据

无法通过 Facebook 登录。授予权限后黑屏

无法在 TestFlight 上为设备授予构建权限