Android 无法授予FINE_位置权限

Android 无法授予FINE_位置权限,android,android-permissions,android-location,Android,Android Permissions,Android Location,你好,我正在构建一个应用程序,我想访问手机的位置。然而,我似乎无法授予访问精细位置权限,因此我的应用程序无法在我正在测试的Android M手机上运行。 以下是我代码的一部分: public class LocationMainActivity extends AppCompatActivity { private ListView listView; private static final String EXTERNAL_PERMISSIONS[] = new String[]{

你好,我正在构建一个应用程序,我想访问手机的位置。然而,我似乎无法授予访问精细位置权限,因此我的应用程序无法在我正在测试的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;
    }

}

将以下代码放入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;
            }
        }
    });
LocationRequest LocationRequest=LocationRequest.create();
locationRequest.setPriority(locationRequest.PRIORITY\u高精度);
位置请求设置间隔(30*1000);
locationRequest.SetFastTestInterval(5*1000);
LocationSettingsRequest.Builder=新建LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true)//这是关键成分
Pendingreult结果=
LocationServices.SettingsApi.checkLocationSettings(GoogleAppClient,builder.build());
result.setResultCallback(新的ResultCallback(){
@凌驾
公共void onResult(位置设置结果){
最终状态状态=result.getStatus();
最终位置SettingsStates状态=结果。getLocationSettingsStates();
开关(status.getStatusCode()){
案例位置设置StatusCodes.SUCCESS:
//满足所有位置设置。客户端可以初始化位置
//请求在这里。
打破
案例位置设置StatusCodes.RESOLUTION_要求:
//不满足位置设置。但可以通过显示用户来修复
//对话。
试一试{
//通过调用startResolutionForResult()显示对话框,
//并在onActivityResult()中检查结果。
status.startResolutionForResult(MainActivity.this,请求检查设置);
}catch(IntentSender.sendtintentexe){
//忽略错误。
}
打破
案例位置设置StatusCodes.SETTINGS\u CHANGE\u不可用:
//位置设置不满意。但是,我们无法修复此问题
//设置,这样我们就不会显示对话框。
打破
}
}
});

试试这个!!它在我的应用程序中工作。

安全位置被触发,指出我没有精细位置权限。。。这是运行时异常还是IDE/Lint警告。。。我敢打赌警告。。。它与getLastLocation可能返回null这一事实无关,您必须接受一件小事来检查,您的and元素需要在它之外。它们应该是根元素的直接子元素。有时,当你在应用程序启动时将它们放在里面时,例如,该位置将已在使用中,并导致类似的问题。我已编辑了我的问题,还包括日志。权限不在许可范围内。在安卓5.0上测试时,我可以得到坐标,但在安卓6.0上无法得到坐标。您的目标版本是什么。我需要在retrieveLocation方法中请求权限,它成功了。我修改了代码,在第二个活动中请求了权限,它成功了。我还想问一个问题。是否可以检查用户是否连接到wifi或网络,并提示他启用internet连接?因为我使用的设置api仅提示用户启用对其位置的访问Yes您可以检查:-public boolean isConnected(){ConnectivityManager connMgr=(ConnectivityManager)getSystemService(Activity.CONNECTIVITY_SERVICE);NetworkInfo NetworkInfo=connMgr.getActiveNetworkInfo();if(NetworkInfo!=null&&NetworkInfo.isConnected())返回true;否则返回false;}
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;
            }
        }
    });