Android运行时权限-如何实现
Android runtime permissions- how to implement
Android Developer Documentation 给出了这个在运行时请求权限的例子:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an expanation 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(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
这个例子中的 "MY_PERMISSIONS_REQUEST_READ_CONTACTS" 是什么?它说这是一个应用程序定义的 int 常量,但这是否意味着我应该创建一个 Constants.java 并声明一个 public static int?值应该是多少?
在其他示例中,我看到人们在这里使用 1,或者 0 或 0xFFEEDDCC,但我找不到关于它是什么的解释。有人可以向我解释这里需要做什么以及为什么吗? (在我的例子中,我需要确保该应用程序有权访问正确的位置)
ActivityCompat 文档说 "Application specific request code to match with a result reported to onRequestPermissionsResult"?这对我没有帮助。
再往下看 "Handle the permissions request response" 下的文档,您就会明白它的用途。
一个名为 onRequestPermissionsResult
的回调方法被发送回与参数相同的代码,因此您知道哪个权限是 requested/granted:
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
由于常量仅供您使用,因此您可以给它任何您喜欢的值作为 public static final int
。请求的每个权限都需要有自己的常量。
What is "MY_PERMISSIONS_REQUEST_READ_CONTACTS" in this example?
这是一个 int
,将特定的 requestPermissions()
调用绑定到相应的 onRequestPermissionsResult()
回调。
在幕后,requestPermissions()
使用 startActivityForResult()
;此 int
与 startActivityForResult()
.
中的作用相同
does that mean I should make a Constants.java and declare a public static int?
我只想将其设为 activity 中的 private static final int
。但是,您可以在任何地方声明它。
What should the value be?
我好像记得要在0x8000000以下,除此之外可以随便。您在 activity 中为每个 requestPermissions()
调用使用的值应该得到一个不同的 int
,但实际数字无关紧要。
如果您的 activity 只有一个 requestPermissions()
调用,那么 int
值真的无关紧要。但是许多应用程序会在 activity 中进行多次 requestPermissions()
调用。在那种情况下,开发人员可能需要知道,在 onRequestPermissionsResult()
中,这是针对什么请求的结果。
public class SplashActivity extends RuntimePermissionsActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
SplashActivity.super.requestAppPermissions(new
String[]{android.Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE}, R.string.app_name
, 20);
}
@Override
public void onPermissionsGranted(int requestCode) {
try {
TelephonyManager tele = (TelephonyManager) getApplicationContext()
.getSystemService(Context.TELEPHONY_SERVICE);
String imei =tele.getDeviceId()
} catch (Exception e) {
e.printStackTrace();
}
}
public abstract class RuntimePermissionsActivity extends AppCompatActivity {
private SparseIntArray mErrorString;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mErrorString = new SparseIntArray();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
int permissionCheck = PackageManager.PERMISSION_GRANTED;
for (int permission : grantResults) {
permissionCheck = permissionCheck + permission;
}
if ((grantResults.length > 0) && permissionCheck == PackageManager.PERMISSION_GRANTED) {
onPermissionsGranted(requestCode);
} else {
finish();
}
}
public void requestAppPermissions(final String[] requestedPermissions,
final int stringId, final int requestCode) {
mErrorString.put(requestCode, stringId);
int permissionCheck = PackageManager.PERMISSION_GRANTED;
boolean shouldShowRequestPermissionRationale = false;
for (String permission : requestedPermissions) {
permissionCheck = permissionCheck + ContextCompat.checkSelfPermission(this, permission);
shouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale || ActivityCompat.shouldShowRequestPermissionRationale(this, permission);
}
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale) {
ActivityCompat.requestPermissions(RuntimePermissionsActivity.this, requestedPermissions, requestCode);
/*Snackbar.make(findViewById(android.R.id.content), stringId,
Snackbar.LENGTH_INDEFINITE).setAction("GRANT",
new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityCompat.requestPermissions(RuntimePermissionsActivity.this, requestedPermissions, requestCode);
}
}).show();*/
} else {
ActivityCompat.requestPermissions(this, requestedPermissions, requestCode);
}
} else {
onPermissionsGranted(requestCode);
}
}
public abstract void onPermissionsGranted(int requestCode);
}
我浏览了所有答案,但没有满足我确切需要的答案,所以这是我写的一个完美运行的示例,甚至用户点击 不再询问复选框。
创建一个方法,当您想要请求运行时权限时将被调用,例如 readContacts()
或者您也可以 openCamera()
如下所示:
private void readContacts() {
if (!askContactsPermission()) {
return;
} else {
queryContacts();
} }
现在我们需要制作 askContactsPermission()
,您也可以将其命名为 askCameraPermission()
或您要请求的任何权限。
private boolean askContactsPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
return true;
}
if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
Snackbar.make(parentLayout, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
.setAction(android.R.string.ok, new View.OnClickListener() {
@Override
@TargetApi(Build.VERSION_CODES.M)
public void onClick(View v) {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
}
}).show();
} else if (contactPermissionNotGiven) {
openPermissionSettingDialog();
} else {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
contactPermissionNotGiven = true;
}
return false;
}
在编写此函数之前,请确保您已经定义了以下实例变量,如下所示:
private View parentLayout;
private boolean contactPermissionNotGiven;;
/**
* Id to identity READ_CONTACTS permission request.
*/
private static final int REQUEST_READ_CONTACTS = 0;
现在是覆盖 onRequestPermissionsResult
方法的最后一步,如下所示:
/**
* Callback received when a permissions request has been completed.
*/
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_READ_CONTACTS) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
queryContacts();
}
}
}
这里我们完成了运行时权限,插件是 openPermissionSettingDialog()
如果用户通过单击 不再询问 [=] 永久禁用了权限,只需打开设置屏幕63=] 复选框。下面是方法:
private void openPermissionSettingDialog() {
String message = getString(R.string.message_permission_disabled);
AlertDialog alertDialog =
new AlertDialog.Builder(MainActivity.this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
.setMessage(message)
.setPositiveButton(getString(android.R.string.ok),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
dialog.cancel();
}
}).show();
alertDialog.setCanceledOnTouchOutside(true);
}
我们错过了什么?
1.定义strings.xml
中使用的字符串
<string name="permission_rationale">"Contacts permissions are needed to display Contacts."</string>
<string name="message_permission_disabled">You have disabled the permissions permanently,
To enable the permissions please go to Settings -> Permissions and enable the required Permissions,
pressing OK you will be navigated to Settings screen</string>
正在初始化 onCreate
方法中的 parentLayout
变量
parentLayout = findViewById(R.id.content);
在AndroidManifest.xml
中定义所需的权限
<uses-permission android:name="android.permission.READ_CONTACTS" />
queryContacts
方法,根据您的需要或运行时权限,您可以在需要 permission
之前调用您的方法。在我的例子中,我只是使用加载程序来获取联系人,如下所示:
private void queryContacts() {
getLoaderManager().initLoader(0, null, this);}
这工作非常愉快编码:)
Android Developer Documentation 给出了这个在运行时请求权限的例子:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an expanation 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(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
这个例子中的 "MY_PERMISSIONS_REQUEST_READ_CONTACTS" 是什么?它说这是一个应用程序定义的 int 常量,但这是否意味着我应该创建一个 Constants.java 并声明一个 public static int?值应该是多少?
在其他示例中,我看到人们在这里使用 1,或者 0 或 0xFFEEDDCC,但我找不到关于它是什么的解释。有人可以向我解释这里需要做什么以及为什么吗? (在我的例子中,我需要确保该应用程序有权访问正确的位置)
ActivityCompat 文档说 "Application specific request code to match with a result reported to onRequestPermissionsResult"?这对我没有帮助。
再往下看 "Handle the permissions request response" 下的文档,您就会明白它的用途。
一个名为 onRequestPermissionsResult
的回调方法被发送回与参数相同的代码,因此您知道哪个权限是 requested/granted:
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
由于常量仅供您使用,因此您可以给它任何您喜欢的值作为 public static final int
。请求的每个权限都需要有自己的常量。
What is "MY_PERMISSIONS_REQUEST_READ_CONTACTS" in this example?
这是一个 int
,将特定的 requestPermissions()
调用绑定到相应的 onRequestPermissionsResult()
回调。
在幕后,requestPermissions()
使用 startActivityForResult()
;此 int
与 startActivityForResult()
.
does that mean I should make a Constants.java and declare a public static int?
我只想将其设为 activity 中的 private static final int
。但是,您可以在任何地方声明它。
What should the value be?
我好像记得要在0x8000000以下,除此之外可以随便。您在 activity 中为每个 requestPermissions()
调用使用的值应该得到一个不同的 int
,但实际数字无关紧要。
如果您的 activity 只有一个 requestPermissions()
调用,那么 int
值真的无关紧要。但是许多应用程序会在 activity 中进行多次 requestPermissions()
调用。在那种情况下,开发人员可能需要知道,在 onRequestPermissionsResult()
中,这是针对什么请求的结果。
public class SplashActivity extends RuntimePermissionsActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
SplashActivity.super.requestAppPermissions(new
String[]{android.Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE}, R.string.app_name
, 20);
}
@Override
public void onPermissionsGranted(int requestCode) {
try {
TelephonyManager tele = (TelephonyManager) getApplicationContext()
.getSystemService(Context.TELEPHONY_SERVICE);
String imei =tele.getDeviceId()
} catch (Exception e) {
e.printStackTrace();
}
}
public abstract class RuntimePermissionsActivity extends AppCompatActivity {
private SparseIntArray mErrorString;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mErrorString = new SparseIntArray();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
int permissionCheck = PackageManager.PERMISSION_GRANTED;
for (int permission : grantResults) {
permissionCheck = permissionCheck + permission;
}
if ((grantResults.length > 0) && permissionCheck == PackageManager.PERMISSION_GRANTED) {
onPermissionsGranted(requestCode);
} else {
finish();
}
}
public void requestAppPermissions(final String[] requestedPermissions,
final int stringId, final int requestCode) {
mErrorString.put(requestCode, stringId);
int permissionCheck = PackageManager.PERMISSION_GRANTED;
boolean shouldShowRequestPermissionRationale = false;
for (String permission : requestedPermissions) {
permissionCheck = permissionCheck + ContextCompat.checkSelfPermission(this, permission);
shouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale || ActivityCompat.shouldShowRequestPermissionRationale(this, permission);
}
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale) {
ActivityCompat.requestPermissions(RuntimePermissionsActivity.this, requestedPermissions, requestCode);
/*Snackbar.make(findViewById(android.R.id.content), stringId,
Snackbar.LENGTH_INDEFINITE).setAction("GRANT",
new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityCompat.requestPermissions(RuntimePermissionsActivity.this, requestedPermissions, requestCode);
}
}).show();*/
} else {
ActivityCompat.requestPermissions(this, requestedPermissions, requestCode);
}
} else {
onPermissionsGranted(requestCode);
}
}
public abstract void onPermissionsGranted(int requestCode);
}
我浏览了所有答案,但没有满足我确切需要的答案,所以这是我写的一个完美运行的示例,甚至用户点击 不再询问复选框。
创建一个方法,当您想要请求运行时权限时将被调用,例如
readContacts()
或者您也可以openCamera()
如下所示:private void readContacts() { if (!askContactsPermission()) { return; } else { queryContacts(); } }
现在我们需要制作 askContactsPermission()
,您也可以将其命名为 askCameraPermission()
或您要请求的任何权限。
private boolean askContactsPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
return true;
}
if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
Snackbar.make(parentLayout, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
.setAction(android.R.string.ok, new View.OnClickListener() {
@Override
@TargetApi(Build.VERSION_CODES.M)
public void onClick(View v) {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
}
}).show();
} else if (contactPermissionNotGiven) {
openPermissionSettingDialog();
} else {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
contactPermissionNotGiven = true;
}
return false;
}
在编写此函数之前,请确保您已经定义了以下实例变量,如下所示:
private View parentLayout;
private boolean contactPermissionNotGiven;;
/**
* Id to identity READ_CONTACTS permission request.
*/
private static final int REQUEST_READ_CONTACTS = 0;
现在是覆盖 onRequestPermissionsResult
方法的最后一步,如下所示:
/**
* Callback received when a permissions request has been completed.
*/
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_READ_CONTACTS) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
queryContacts();
}
}
}
这里我们完成了运行时权限,插件是 openPermissionSettingDialog()
如果用户通过单击 不再询问 [=] 永久禁用了权限,只需打开设置屏幕63=] 复选框。下面是方法:
private void openPermissionSettingDialog() {
String message = getString(R.string.message_permission_disabled);
AlertDialog alertDialog =
new AlertDialog.Builder(MainActivity.this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
.setMessage(message)
.setPositiveButton(getString(android.R.string.ok),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
dialog.cancel();
}
}).show();
alertDialog.setCanceledOnTouchOutside(true);
}
我们错过了什么?
1.定义strings.xml
<string name="permission_rationale">"Contacts permissions are needed to display Contacts."</string>
<string name="message_permission_disabled">You have disabled the permissions permanently,
To enable the permissions please go to Settings -> Permissions and enable the required Permissions,
pressing OK you will be navigated to Settings screen</string>
正在初始化
onCreate
方法中的parentLayout
变量parentLayout = findViewById(R.id.content);
在
AndroidManifest.xml
中定义所需的权限
<uses-permission android:name="android.permission.READ_CONTACTS" />
queryContacts
方法,根据您的需要或运行时权限,您可以在需要permission
之前调用您的方法。在我的例子中,我只是使用加载程序来获取联系人,如下所示:private void queryContacts() { getLoaderManager().initLoader(0, null, this);}
这工作非常愉快编码:)