理解Android6权限方法
Understanding the Android 6 permission method
我正在尝试从图库中获取图像并将其设置为图像视图,但在 Android6 中存在一些权限问题。下面是请求权限的方法。我应该请求读取外部存储还是写入外部存储?
这是我到目前为止所做的:
private static final int READ_CONTACTS_PERMISSIONS_REQUEST = 1;
public void getPermissionToReadExternalStorage() {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(
Manifest.permission.READ_EXTERNAL_STORAGE)) {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
READ_CONTACTS_PERMISSIONS_REQUEST);
}}}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String permissions[],
@NonNull int[] grantResults){
// Make sure it's our original READ_CONTACTS request
if (requestCode == READ_CONTACTS_PERMISSIONS_REQUEST) {
if (grantResults.length == 1 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getActivity(), "Read Contacts permission granted", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(), "Read Contacts permission denied", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
现在我的点击侦听器从图库中选取数据:
pro.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
if (android.os.Build.VERSION.SDK_INT >= 23) {
getPermissionToReadExternalStorage();
if (getPermissionToReadExternalStorage () this???? <==)
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0);
} else {
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0);
}}
});
return v;
}
现在我想获得方法 getPermissionToReadExternalStorage()
的结果,这样我就可以启动 Activity 来为 Android 挑选图库 6. 如何获得无效 class?
另一件事是我是否必须为我的应用程序请求的每个权限编写方法?
编辑
我已经重写了代码并发布在另一个答案中。
旧答案:
是的,你每次都要检查并征求许可。
通常我这样写代码:
private int requestPermissionCode;
private Runnable requestPermissionRunnable;
private void runPermissionCode(String requestPermission, int requestCode, Runnable codeToRun) {
if (android.os.Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissionCode = requestCode;
requestPermissionRunnable = codeToRun;
requestPermissions(new String[]{requestPermission},
requestCode);
}
} else {
codeToRun.run();
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String permissions[],
@NonNull int[] grantResults) {
if (requestCode == requestPermissionCode) {
if (grantResults.length == 1 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (requestPermissionRunnable != null)
requestPermissionRunnable.run();
} else {
Toast.makeText(getActivity(), "Permission denied", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
和运行它是这样的:
runPermissionCode(Manifest.permission.READ_EXTERNAL_STORAGE, READ_CONTACTS_PERMISSIONS_REQUEST, new Runnable() {
@Override
public void run() {
// your code here
}
});
我敢肯定这不是最好的方法,但至少它提供了请求许可并使操作更容易的可能性。
所以我已经完全重写了请求权限的代码。
现在它支持请求多个权限和 运行 代码以得到正确的结果。
它还适用于 preMarshmallow 设备,因此在这种情况下您不必检查和复制代码。
首先,用这段代码创建一个Activity class(你可以扩展任何你需要的activity,例如AppCompatActivity):
public abstract class PermissionActivity extends AppCompatActivity {
private final ArrayList<PermissionListener> permissionListeners = new ArrayList<>();
@SuppressWarnings("unused")
public void requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener) {
requestPermissions(requestCode, requestPermissions, null, permissionListener);
}
@SuppressWarnings("unused")
public void requestPermissions(final int requestCode, String[] requestPermissions, String message, final PermissionListener permissionListener) {
final int[] grantResults = new int[requestPermissions.length];
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ArrayList<String> list_notGranted = new ArrayList<>();
for (String requestPermission : requestPermissions)
if (ContextCompat.checkSelfPermission(this, requestPermission) != PackageManager.PERMISSION_GRANTED)
list_notGranted.add(requestPermission);
if (list_notGranted.size() > 0) {
permissionListeners.add(permissionListener);
requestPermissions = list_notGranted.toArray(new String[list_notGranted.size()]);
if (message != null) {
boolean shouldShowRequestPermissionRationale = false;
for (String permission : requestPermissions)
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
shouldShowRequestPermissionRationale = true;
break;
}
if (shouldShowRequestPermissionRationale) {
final String[] f_requestPermissions = requestPermissions;
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message);
DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
PermissionActivity.super.requestPermissions(f_requestPermissions, requestCode);
break;
default:
for (int i = 0; i < grantResults.length; i++)
grantResults[i] = PackageManager.PERMISSION_DENIED;
if (permissionListener != null)
permissionListener.onResult(requestCode, f_requestPermissions, grantResults);
break;
}
}
};
builder.setPositiveButton("OK", onClickListener);
builder.setNegativeButton("Cancel", onClickListener);
builder.show();
} else {
super.requestPermissions(requestPermissions, requestCode);
}
} else {
super.requestPermissions(requestPermissions, requestCode);
}
} else {
for (int i = 0; i < grantResults.length; i++)
grantResults[i] = PackageManager.PERMISSION_GRANTED;
if (permissionListener != null)
permissionListener.onResult(requestCode, requestPermissions, grantResults);
}
} else {
if (permissionListener != null) {
for (int i = 0; i < grantResults.length; i++)
grantResults[i] = PackageManager.PERMISSION_GRANTED;
permissionListener.onResult(requestCode, requestPermissions, grantResults);
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
for (Iterator<PermissionListener> it = permissionListeners.iterator(); it.hasNext(); ) {
PermissionListener permissionListener = it.next();
if (permissionListener.onResult(requestCode, permissions, grantResults)) {
it.remove();
}
}
}
public interface PermissionListener {
boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults);
}
}
如果你想从 Fragments 请求权限,添加这个 class:
public class PermissionFragment extends Fragment {
@SuppressWarnings("unused")
public void requestPermissions(int requestCode, String[] requestPermissions, PermissionActivity.PermissionListener permissionListener) {
requestPermissions(requestCode, requestPermissions, null, permissionListener);
}
@SuppressWarnings("unused")
public void requestPermissions(final int requestCode, String[] requestPermissions, String message, PermissionActivity.PermissionListener permissionListener) {
((PermissionActivity) getActivity()).requestPermissions(requestCode, requestPermissions, message, permissionListener);
}
}
您的 Activity 和 Fragment 应该扩展这些 class 而不是标准的。
现在您已准备好通过调用以下方法请求权限:
requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener)
如果应用程序需要权限才能运行,您应该调用此方法并指定说明为什么需要权限的消息。
requestPermissions(int requestCode, String[] requestPermissions, String message, PermissionListener permissionListener)
不要误调用默认方法,即
// DON'T USE THIS ONE!
requestPermissions(String[] requestPermissions, int requestCode)
// DON'T USE THIS ONE!
这里是请求联系人的例子:
private void requestAndLoadContacts() {
String[] permissions = new String[]{Manifest.permission.READ_CONTACTS};
requestPermissions(REQUEST_PERMISSIONS_CONTACTS, permissions, "Read contacts permission is required for the app to work!", new PermissionListener() {
@Override
public boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults) {
// Check if the requestCode is ours
if (requestCode == REQUEST_PERMISSIONS_CONTACTS) {
// Check if the permission is correct and is granted
if (requestPermissions[0].equals(Manifest.permission.READ_CONTACTS) && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted
// Calling a method to actually load the contacts
loadContacts();
} else {
// Permission not granted
Toast.makeText(MainActivity.this, "Access denied!", Toast.LENGTH_SHORT).show();
}
return true;
}
return false;
}
});
}
注意:
当您实现 PermissionListener 时,不要忘记 return true 当 requestCode 是正确的 时,否则 PermissionListener 不会从 ArrayList 中删除,您很可能会发生小的内存泄漏。
初始化您的权限
private static final int INITIAL_REQUEST = 1337;
private static final int GET_ACCOUNTS = INITIAL_REQUEST+2;
private static final int LOCATION_REQUEST =INITIAL_REQUEST+3;
private static final String[] INITIAL_PERMS = {
Manifest.permission.GET_ACCOUNTS,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_FINE_LOCATION
};
检查设备并请求权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!canAccessAccounts()|| !canAccessLocation() ||!canAccessInternet()) {
requestPermissions(INITIAL_PERMS, INITIAL_REQUEST);
}
}
检查是否授予权限
private boolean canAccessAccounts() {
return (hasPermission(Manifest.permission.GET_ACCOUNTS));
}
private boolean canAccessLocation() {
return (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
private boolean canAccessInternet() {
return (hasPermission(Manifest.permission.INTERNET));
}
private boolean hasPermission(String perm) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return (PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm));
}
return (true);
}
在 RequestPermissionsResult 上更新权限和检查权限的方法
void UpdatePermissions(){
canAccessInternet();
canAccessLocation();
canAccessInternet();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
UpdatePermissions();
switch(requestCode) {
case GET_ACCOUNTS:
if (canAccessAccounts()) {
}
else {
}
break;
case LOCATION_REQUEST:
if (canAccessLocation()) {
}
else {
}
break;
case INITIAL_REQUEST:
if(canAccessInternet()){
}else {
}
break;
}
}
我正在尝试从图库中获取图像并将其设置为图像视图,但在 Android6 中存在一些权限问题。下面是请求权限的方法。我应该请求读取外部存储还是写入外部存储?
这是我到目前为止所做的:
private static final int READ_CONTACTS_PERMISSIONS_REQUEST = 1;
public void getPermissionToReadExternalStorage() {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(
Manifest.permission.READ_EXTERNAL_STORAGE)) {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
READ_CONTACTS_PERMISSIONS_REQUEST);
}}}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String permissions[],
@NonNull int[] grantResults){
// Make sure it's our original READ_CONTACTS request
if (requestCode == READ_CONTACTS_PERMISSIONS_REQUEST) {
if (grantResults.length == 1 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getActivity(), "Read Contacts permission granted", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(), "Read Contacts permission denied", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
现在我的点击侦听器从图库中选取数据:
pro.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
if (android.os.Build.VERSION.SDK_INT >= 23) {
getPermissionToReadExternalStorage();
if (getPermissionToReadExternalStorage () this???? <==)
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0);
} else {
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0);
}}
});
return v;
}
现在我想获得方法 getPermissionToReadExternalStorage()
的结果,这样我就可以启动 Activity 来为 Android 挑选图库 6. 如何获得无效 class?
另一件事是我是否必须为我的应用程序请求的每个权限编写方法?
编辑
我已经重写了代码并发布在另一个答案中。
旧答案:
是的,你每次都要检查并征求许可。
通常我这样写代码:
private int requestPermissionCode;
private Runnable requestPermissionRunnable;
private void runPermissionCode(String requestPermission, int requestCode, Runnable codeToRun) {
if (android.os.Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissionCode = requestCode;
requestPermissionRunnable = codeToRun;
requestPermissions(new String[]{requestPermission},
requestCode);
}
} else {
codeToRun.run();
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String permissions[],
@NonNull int[] grantResults) {
if (requestCode == requestPermissionCode) {
if (grantResults.length == 1 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (requestPermissionRunnable != null)
requestPermissionRunnable.run();
} else {
Toast.makeText(getActivity(), "Permission denied", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
和运行它是这样的:
runPermissionCode(Manifest.permission.READ_EXTERNAL_STORAGE, READ_CONTACTS_PERMISSIONS_REQUEST, new Runnable() {
@Override
public void run() {
// your code here
}
});
我敢肯定这不是最好的方法,但至少它提供了请求许可并使操作更容易的可能性。
所以我已经完全重写了请求权限的代码。 现在它支持请求多个权限和 运行 代码以得到正确的结果。 它还适用于 preMarshmallow 设备,因此在这种情况下您不必检查和复制代码。
首先,用这段代码创建一个Activity class(你可以扩展任何你需要的activity,例如AppCompatActivity):
public abstract class PermissionActivity extends AppCompatActivity {
private final ArrayList<PermissionListener> permissionListeners = new ArrayList<>();
@SuppressWarnings("unused")
public void requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener) {
requestPermissions(requestCode, requestPermissions, null, permissionListener);
}
@SuppressWarnings("unused")
public void requestPermissions(final int requestCode, String[] requestPermissions, String message, final PermissionListener permissionListener) {
final int[] grantResults = new int[requestPermissions.length];
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ArrayList<String> list_notGranted = new ArrayList<>();
for (String requestPermission : requestPermissions)
if (ContextCompat.checkSelfPermission(this, requestPermission) != PackageManager.PERMISSION_GRANTED)
list_notGranted.add(requestPermission);
if (list_notGranted.size() > 0) {
permissionListeners.add(permissionListener);
requestPermissions = list_notGranted.toArray(new String[list_notGranted.size()]);
if (message != null) {
boolean shouldShowRequestPermissionRationale = false;
for (String permission : requestPermissions)
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
shouldShowRequestPermissionRationale = true;
break;
}
if (shouldShowRequestPermissionRationale) {
final String[] f_requestPermissions = requestPermissions;
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message);
DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
PermissionActivity.super.requestPermissions(f_requestPermissions, requestCode);
break;
default:
for (int i = 0; i < grantResults.length; i++)
grantResults[i] = PackageManager.PERMISSION_DENIED;
if (permissionListener != null)
permissionListener.onResult(requestCode, f_requestPermissions, grantResults);
break;
}
}
};
builder.setPositiveButton("OK", onClickListener);
builder.setNegativeButton("Cancel", onClickListener);
builder.show();
} else {
super.requestPermissions(requestPermissions, requestCode);
}
} else {
super.requestPermissions(requestPermissions, requestCode);
}
} else {
for (int i = 0; i < grantResults.length; i++)
grantResults[i] = PackageManager.PERMISSION_GRANTED;
if (permissionListener != null)
permissionListener.onResult(requestCode, requestPermissions, grantResults);
}
} else {
if (permissionListener != null) {
for (int i = 0; i < grantResults.length; i++)
grantResults[i] = PackageManager.PERMISSION_GRANTED;
permissionListener.onResult(requestCode, requestPermissions, grantResults);
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
for (Iterator<PermissionListener> it = permissionListeners.iterator(); it.hasNext(); ) {
PermissionListener permissionListener = it.next();
if (permissionListener.onResult(requestCode, permissions, grantResults)) {
it.remove();
}
}
}
public interface PermissionListener {
boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults);
}
}
如果你想从 Fragments 请求权限,添加这个 class:
public class PermissionFragment extends Fragment {
@SuppressWarnings("unused")
public void requestPermissions(int requestCode, String[] requestPermissions, PermissionActivity.PermissionListener permissionListener) {
requestPermissions(requestCode, requestPermissions, null, permissionListener);
}
@SuppressWarnings("unused")
public void requestPermissions(final int requestCode, String[] requestPermissions, String message, PermissionActivity.PermissionListener permissionListener) {
((PermissionActivity) getActivity()).requestPermissions(requestCode, requestPermissions, message, permissionListener);
}
}
您的 Activity 和 Fragment 应该扩展这些 class 而不是标准的。
现在您已准备好通过调用以下方法请求权限:
requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener)
如果应用程序需要权限才能运行,您应该调用此方法并指定说明为什么需要权限的消息。
requestPermissions(int requestCode, String[] requestPermissions, String message, PermissionListener permissionListener)
不要误调用默认方法,即
// DON'T USE THIS ONE!
requestPermissions(String[] requestPermissions, int requestCode)
// DON'T USE THIS ONE!
这里是请求联系人的例子:
private void requestAndLoadContacts() {
String[] permissions = new String[]{Manifest.permission.READ_CONTACTS};
requestPermissions(REQUEST_PERMISSIONS_CONTACTS, permissions, "Read contacts permission is required for the app to work!", new PermissionListener() {
@Override
public boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults) {
// Check if the requestCode is ours
if (requestCode == REQUEST_PERMISSIONS_CONTACTS) {
// Check if the permission is correct and is granted
if (requestPermissions[0].equals(Manifest.permission.READ_CONTACTS) && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted
// Calling a method to actually load the contacts
loadContacts();
} else {
// Permission not granted
Toast.makeText(MainActivity.this, "Access denied!", Toast.LENGTH_SHORT).show();
}
return true;
}
return false;
}
});
}
注意: 当您实现 PermissionListener 时,不要忘记 return true 当 requestCode 是正确的 时,否则 PermissionListener 不会从 ArrayList 中删除,您很可能会发生小的内存泄漏。
初始化您的权限
private static final int INITIAL_REQUEST = 1337;
private static final int GET_ACCOUNTS = INITIAL_REQUEST+2;
private static final int LOCATION_REQUEST =INITIAL_REQUEST+3;
private static final String[] INITIAL_PERMS = {
Manifest.permission.GET_ACCOUNTS,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_FINE_LOCATION
};
检查设备并请求权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!canAccessAccounts()|| !canAccessLocation() ||!canAccessInternet()) {
requestPermissions(INITIAL_PERMS, INITIAL_REQUEST);
}
}
检查是否授予权限
private boolean canAccessAccounts() {
return (hasPermission(Manifest.permission.GET_ACCOUNTS));
}
private boolean canAccessLocation() {
return (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
private boolean canAccessInternet() {
return (hasPermission(Manifest.permission.INTERNET));
}
private boolean hasPermission(String perm) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return (PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm));
}
return (true);
}
在 RequestPermissionsResult 上更新权限和检查权限的方法
void UpdatePermissions(){
canAccessInternet();
canAccessLocation();
canAccessInternet();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
UpdatePermissions();
switch(requestCode) {
case GET_ACCOUNTS:
if (canAccessAccounts()) {
}
else {
}
break;
case LOCATION_REQUEST:
if (canAccessLocation()) {
}
else {
}
break;
case INITIAL_REQUEST:
if(canAccessInternet()){
}else {
}
break;
}
}