在用户输入之前 Android 权限请求 运行 代码出现问题
Trouble with Android permissions request running code before user input
我有以下辅助方法来检查权限:
private boolean canAccessLocation() {
return(hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
private boolean hasPermission(String perm) {
return(PackageManager.PERMISSION_GRANTED==checkCallingOrSelfPermission(perm));
}
我有一个请求方法来提示用户访问他们的位置
public void requestLocationPermissions(){
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
Log.d("permissions",
"Displaying contacts permission rationale to provide additional context.");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_LOCATION);
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_LOCATION);
}
}
在需要位置权限的地方,我写
if(!canAccessLocation()){
requestLocationPermissions();
} else {
}
startActivity(new Intent(MyActivity.this, MyOtherActivity.class));
我遇到的问题是,在向用户显示允许或拒绝权限的对话框之前,新的 activity 是通过意图启动的。因此,如果我在下一个 activity 中有代码要求用户授予或拒绝权限,它将崩溃,然后 然后 询问用户是否要授予权限。我很难让 API 23 权限系统在此应用程序上正常工作,我真的需要一些帮助。
所以我的问题是:在用户选择是否拒绝或允许权限之前,如何阻止后续代码行的执行?
如果发布的片段正是您在项目中尝试的片段,那么解决方案很简单 :D
if(!canAccessLocation()){
requestLocationPermissions();
} else {
//start only if permission is granted
startActivity(new Intent(MyActivity.this, MyOtherActivity.class));
}
您确实需要在请求权限的 Activity 中实现此回调
void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults);
在该回调中,只需验证 requestCode 是否是您请求的,如果 grantResults[0] == PackageManager.PERMISSION_GRANTED,如果是,则在授予权限后执行您需要执行的操作,例如生成一个新的 [=20] =].
此外,如果 ActivityCompat.shouldShowRequestPermissionRationale 调用 returns 为真,您应该向用户显示一条提示,说明请求权限的理由。一旦用户按下 'Ok',您将再次请求权限。
我为此苦苦挣扎了几个小时,所以我只是想把它放在那里以防它对某人有用。
我改编了以下代码:
https://developer.android.com/training/permissions/requesting.html
在我的例子中,应用程序需要请求多个 ('dangerous') 权限。我会在应用程序启动时执行此操作,然后再显示启动画面。
P.S。我应该提到我没有运气同时请求所有权限,因此递归。希望这是可能的,并且有人可以解决这个问题。另外,我已经注释掉了 'Should we show an explanation' 块。下面的逻辑不适合这种行为,但我把它留给了后代,因为它来自上面的 link。
package a.dangerous.app;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
public class AskMultiplePermsThenSpashActivity extends Activity {
static final String[] _requestPermissions = {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_SMS,
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS
};
@Override
protected void onStart() {
super.onStart();
this.checkPermissions(0); //start at zero, of course
}
private void checkPermissions(int permissionIndex) {
if(permissionIndex >= _requestPermissions.length) {
//i.e. we have requested all permissions, so show the splash screen
this.showSplash();
}
else {
this.askForPermission(_requestPermissions[permissionIndex], permissionIndex);
}
}
private void askForPermission(String permission, int permissionIndex) {
if (ContextCompat.checkSelfPermission(
this,
permission)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
// if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
//} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(
this,
new String[]{permission},
permissionIndex //permissionIndex will become the requestCode on callback
);
}
else {
this.checkPermissions(permissionIndex+1); //check the next permission
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//Regardless of whether the permission was granted we carry on.
//If perms have been denied then the app must cater for it
this.checkPermissions(requestCode+1); //check the next permission
}
private void showSplash() {
//(ta da)
//once splashed, start the main activity
this.startMainActivity();
}
private void startMainActivity() {
Intent mainIntent = new Intent(
this,
MainActivity.class
);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
this.startActivity(mainIntent);
this.finish();
}
}
我有以下辅助方法来检查权限:
private boolean canAccessLocation() {
return(hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
private boolean hasPermission(String perm) {
return(PackageManager.PERMISSION_GRANTED==checkCallingOrSelfPermission(perm));
}
我有一个请求方法来提示用户访问他们的位置
public void requestLocationPermissions(){
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
Log.d("permissions",
"Displaying contacts permission rationale to provide additional context.");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_LOCATION);
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_LOCATION);
}
}
在需要位置权限的地方,我写
if(!canAccessLocation()){
requestLocationPermissions();
} else {
}
startActivity(new Intent(MyActivity.this, MyOtherActivity.class));
我遇到的问题是,在向用户显示允许或拒绝权限的对话框之前,新的 activity 是通过意图启动的。因此,如果我在下一个 activity 中有代码要求用户授予或拒绝权限,它将崩溃,然后 然后 询问用户是否要授予权限。我很难让 API 23 权限系统在此应用程序上正常工作,我真的需要一些帮助。
所以我的问题是:在用户选择是否拒绝或允许权限之前,如何阻止后续代码行的执行?
如果发布的片段正是您在项目中尝试的片段,那么解决方案很简单 :D
if(!canAccessLocation()){
requestLocationPermissions();
} else {
//start only if permission is granted
startActivity(new Intent(MyActivity.this, MyOtherActivity.class));
}
您确实需要在请求权限的 Activity 中实现此回调
void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults);
在该回调中,只需验证 requestCode 是否是您请求的,如果 grantResults[0] == PackageManager.PERMISSION_GRANTED,如果是,则在授予权限后执行您需要执行的操作,例如生成一个新的 [=20] =].
此外,如果 ActivityCompat.shouldShowRequestPermissionRationale 调用 returns 为真,您应该向用户显示一条提示,说明请求权限的理由。一旦用户按下 'Ok',您将再次请求权限。
我为此苦苦挣扎了几个小时,所以我只是想把它放在那里以防它对某人有用。
我改编了以下代码: https://developer.android.com/training/permissions/requesting.html
在我的例子中,应用程序需要请求多个 ('dangerous') 权限。我会在应用程序启动时执行此操作,然后再显示启动画面。
P.S。我应该提到我没有运气同时请求所有权限,因此递归。希望这是可能的,并且有人可以解决这个问题。另外,我已经注释掉了 'Should we show an explanation' 块。下面的逻辑不适合这种行为,但我把它留给了后代,因为它来自上面的 link。
package a.dangerous.app;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
public class AskMultiplePermsThenSpashActivity extends Activity {
static final String[] _requestPermissions = {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_SMS,
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS
};
@Override
protected void onStart() {
super.onStart();
this.checkPermissions(0); //start at zero, of course
}
private void checkPermissions(int permissionIndex) {
if(permissionIndex >= _requestPermissions.length) {
//i.e. we have requested all permissions, so show the splash screen
this.showSplash();
}
else {
this.askForPermission(_requestPermissions[permissionIndex], permissionIndex);
}
}
private void askForPermission(String permission, int permissionIndex) {
if (ContextCompat.checkSelfPermission(
this,
permission)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
// if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
//} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(
this,
new String[]{permission},
permissionIndex //permissionIndex will become the requestCode on callback
);
}
else {
this.checkPermissions(permissionIndex+1); //check the next permission
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//Regardless of whether the permission was granted we carry on.
//If perms have been denied then the app must cater for it
this.checkPermissions(requestCode+1); //check the next permission
}
private void showSplash() {
//(ta da)
//once splashed, start the main activity
this.startMainActivity();
}
private void startMainActivity() {
Intent mainIntent = new Intent(
this,
MainActivity.class
);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
this.startActivity(mainIntent);
this.finish();
}
}