현재 몇 가지 "위험한"권한이 필요한 응용 프로그램을 개발 중입니다. 따라서 Android Marshmallow (API 레벨 23)에서 필요에 따라 "허가 요청"을 추가하려고 시도했지만이를 수행하는 방법을 찾지 못했습니다.
앱에서 새 권한 모델을 사용하여 권한을 요청하려면 어떻게해야합니까?
현재 몇 가지 "위험한"권한이 필요한 응용 프로그램을 개발 중입니다. 따라서 Android Marshmallow (API 레벨 23)에서 필요에 따라 "허가 요청"을 추가하려고 시도했지만이를 수행하는 방법을 찾지 못했습니다.
앱에서 새 권한 모델을 사용하여 권한을 요청하려면 어떻게해야합니까?
답변:
아래 코드를 사용하여 대화 상자를 엽니 다.
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
1);
아래와 같이 활동 결과를 얻으십시오.
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
// 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.
Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
추가 정보 : https://developer.android.com/training/permissions/requesting.html
ActivityCompat.requestPermissions
사용되지? (Nugat에서)
이 구조는 앱에 권한이 있는지 확인하고 권한이없는 경우 요청보다 확인하는 데 사용합니다. 그래서 내 주요 코드에서 다음과 같이 쓰기를 확인하고 싶습니다.
int MyVersion = Build.VERSION.SDK_INT;
if (MyVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
if (!checkIfAlreadyhavePermission()) {
requestForSpecificPermission();
}
}
모듈 checkIfAlreadyhavePermission ()은 다음과 같이 구현됩니다.
private boolean checkIfAlreadyhavePermission() {
int result = ContextCompat.checkSelfPermission(this, Manifest.permission.GET_ACCOUNTS);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
requestForSpecificPermission () 모듈은 다음과 같이 구현됩니다.
private void requestForSpecificPermission() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.GET_ACCOUNTS, Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 101);
}
활동 재정의 :
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 101:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//granted
} else {
//not granted
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
자세한 내용은이 링크를 참조하십시오 : http://revisitingandroid.blogspot.in/2017/01/how-to-check-and-request-for-run-time.html
checkIfAlreadyhavePermission
을return result == PackageManager.PERMISSION_GRANTED;
Google 개발자가 작성한이 래퍼 (권장)를 사용했습니다. 사용하기 매우 쉽습니다.
https://github.com/googlesamples/easypermissions
확인을 다루고 필요한 경우 허가를 요청하는 기능
public void locationAndContactsTask() {
String[] perms = { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_CONTACTS };
if (EasyPermissions.hasPermissions(this, perms)) {
// Have permissions, do the thing!
Toast.makeText(this, "TODO: Location and Contacts things", Toast.LENGTH_LONG).show();
} else {
// Ask for both permissions
EasyPermissions.requestPermissions(this, getString(R.string.rationale_location_contacts),
RC_LOCATION_CONTACTS_PERM, perms);
}
}
행복한 코딩 :)
Android Marshmallow부터는 사용자에게 특정 권한을 요청해야합니다. 권한이 이미 부여되었는지 코드를 통해 확인할 수도 있습니다. 일반적으로 필요한 권한 목록은 다음과 같습니다.
android.permission_group.CALENDAR
- android.permission.READ_CALENDAR
- android.permission.WRITE_CALENDAR
android.permission_group.CAMERA
- android.permission.CAMERA
android.permission_group.CONTACTS
- android.permission.READ_CONTACTS
- android.permission.WRITE_CONTACTS
- android.permission.GET_ACCOUNTS
android.permission_group.LOCATION
- android.permission.ACCESS_FINE_LOCATION
- android.permission.ACCESS_COARSE_LOCATION
android.permission_group.MICROPHONE
- android.permission.RECORD_AUDIO
android.permission_group.PHONE
- android.permission.READ_PHONE_STATE
- android.permission.CALL_PHONE
- android.permission.READ_CALL_LOG
- android.permission.WRITE_CALL_LOG
- android.permission.ADD_VOICEMAIL
- android.permission.USE_SIP
- android.permission.PROCESS_OUTGOING_CALLS
android.permission_group.SENSORS
- android.permission.BODY_SENSORS
android.permission_group.SMS
- android.permission.SEND_SMS
- android.permission.RECEIVE_SMS
- android.permission.READ_SMS
- android.permission.RECEIVE_WAP_PUSH
- android.permission.RECEIVE_MMS
- android.permission.READ_CELL_BROADCASTS
android.permission_group.STORAGE
- android.permission.READ_EXTERNAL_STORAGE
- android.permission.WRITE_EXTERNAL_STORAGE
권한을 확인하는 샘플 코드는 다음과 같습니다.
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.WRITE_CALENDAR)) {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
alertBuilder.setCancelable(true);
alertBuilder.setMessage("Write calendar permission is necessary to write event!!!");
alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.WRITE_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR);
}
});
} else {
ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.WRITE_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR);
}
}
Activity
또는의 요청 런타임 권한에 대한 수업Fragment
또한 사용자가 권한이 있거나 없는 옵션을 쉽게 거부 한 후 권한을 활성화하는 이론적 근거 나 열린 설정 을 표시하는 데 도움이됩니다.Never ask again
class RequestPermissionHandler(private val activity: Activity? = null,
private val fragment: Fragment? = null,
private val permissions: Set<String> = hashSetOf(),
private val listener: Listener? = null
) {
private var hadShowRationale: Boolean = false
fun requestPermission() {
hadShowRationale = showRationaleIfNeed()
if (!hadShowRationale) {
doRequestPermission(permissions)
}
}
fun retryRequestDeniedPermission() {
doRequestPermission(permissions)
}
private fun showRationaleIfNeed(): Boolean {
val unGrantedPermissions = getPermission(permissions, Status.UN_GRANTED)
val permanentDeniedPermissions = getPermission(unGrantedPermissions, Status.PERMANENT_DENIED)
if (permanentDeniedPermissions.isNotEmpty()) {
val consume = listener?.onShowSettingRationale(unGrantedPermissions)
if (consume != null && consume) {
return true
}
}
val temporaryDeniedPermissions = getPermission(unGrantedPermissions, Status.TEMPORARY_DENIED)
if (temporaryDeniedPermissions.isNotEmpty()) {
val consume = listener?.onShowPermissionRationale(temporaryDeniedPermissions)
if (consume != null && consume) {
return true
}
}
return false
}
fun requestPermissionInSetting() {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val packageName = activity?.packageName ?: run {
fragment?.requireActivity()?.packageName
}
val uri = Uri.fromParts("package", packageName, null)
intent.data = uri
activity?.apply {
startActivityForResult(intent, REQUEST_CODE)
} ?: run {
fragment?.startActivityForResult(intent, REQUEST_CODE)
}
}
fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
grantResults: IntArray) {
if (requestCode == REQUEST_CODE) {
for (i in grantResults.indices) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
markNeverAskAgainPermission(permissions[i], false)
} else if (!shouldShowRequestPermissionRationale(permissions[i])) {
markNeverAskAgainPermission(permissions[i], true)
}
}
var hasShowRationale = false
if (!hadShowRationale) {
hasShowRationale = showRationaleIfNeed()
}
if (hadShowRationale || !hasShowRationale) {
notifyComplete()
}
}
}
fun onActivityResult(requestCode: Int) {
if (requestCode == REQUEST_CODE) {
getPermission(permissions, Status.GRANTED).forEach {
markNeverAskAgainPermission(it, false)
}
notifyComplete()
}
}
fun cancel() {
notifyComplete()
}
private fun doRequestPermission(permissions: Set<String>) {
activity?.let {
ActivityCompat.requestPermissions(it, permissions.toTypedArray(), REQUEST_CODE)
} ?: run {
fragment?.requestPermissions(permissions.toTypedArray(), REQUEST_CODE)
}
}
private fun getPermission(permissions: Set<String>, status: Status): Set<String> {
val targetPermissions = HashSet<String>()
for (p in permissions) {
when (status) {
Status.GRANTED -> {
if (isPermissionGranted(p)) {
targetPermissions.add(p)
}
}
Status.TEMPORARY_DENIED -> {
if (shouldShowRequestPermissionRationale(p)) {
targetPermissions.add(p)
}
}
Status.PERMANENT_DENIED -> {
if (isNeverAskAgainPermission(p)) {
targetPermissions.add(p)
}
}
Status.UN_GRANTED -> {
if (!isPermissionGranted(p)) {
targetPermissions.add(p)
}
}
}
}
return targetPermissions
}
private fun isPermissionGranted(permission: String): Boolean {
return activity?.let {
ActivityCompat.checkSelfPermission(it, permission) == PackageManager.PERMISSION_GRANTED
} ?: run {
ActivityCompat.checkSelfPermission(fragment!!.requireActivity(), permission) == PackageManager.PERMISSION_GRANTED
}
}
private fun shouldShowRequestPermissionRationale(permission: String): Boolean {
return activity?.let {
ActivityCompat.shouldShowRequestPermissionRationale(it, permission)
} ?: run {
ActivityCompat.shouldShowRequestPermissionRationale(fragment!!.requireActivity(), permission)
}
}
private fun notifyComplete() {
listener?.onComplete(getPermission(permissions, Status.GRANTED), getPermission(permissions, Status.UN_GRANTED))
}
private fun getPrefs(context: Context): SharedPreferences {
return context.getSharedPreferences("SHARED_PREFS_RUNTIME_PERMISSION", Context.MODE_PRIVATE)
}
private fun isNeverAskAgainPermission(permission: String): Boolean {
return getPrefs(requireContext()).getBoolean(permission, false)
}
private fun markNeverAskAgainPermission(permission: String, value: Boolean) {
getPrefs(requireContext()).edit().putBoolean(permission, value).apply()
}
private fun requireContext(): Context {
return fragment?.requireContext() ?: run {
activity!!
}
}
enum class Status {
GRANTED, UN_GRANTED, TEMPORARY_DENIED, PERMANENT_DENIED
}
interface Listener {
fun onComplete(grantedPermissions: Set<String>, deniedPermissions: Set<String>)
fun onShowPermissionRationale(permissions: Set<String>): Boolean
fun onShowSettingRationale(permissions: Set<String>): Boolean
}
companion object {
const val REQUEST_CODE = 200
}
}
Activity
같은 사용
class MainActivity : AppCompatActivity() {
private lateinit var smsAndStoragePermissionHandler: RequestPermissionHandler
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
smsAndStoragePermissionHandler = RequestPermissionHandler(this@MainActivity,
permissions = setOf(Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_EXTERNAL_STORAGE),
listener = object : RequestPermissionHandler.Listener {
override fun onComplete(grantedPermissions: Set<String>, deniedPermissions: Set<String>) {
Toast.makeText(this@MainActivity, "complete", Toast.LENGTH_SHORT).show()
text_granted.text = "Granted: " + grantedPermissions.toString()
text_denied.text = "Denied: " + deniedPermissions.toString()
}
override fun onShowPermissionRationale(permissions: Set<String>): Boolean {
AlertDialog.Builder(this@MainActivity).setMessage("To able to Send Photo, we need SMS and" + " Storage permission")
.setPositiveButton("OK") { _, _ ->
smsAndStoragePermissionHandler.retryRequestDeniedPermission()
}
.setNegativeButton("Cancel") { dialog, _ ->
smsAndStoragePermissionHandler.cancel()
dialog.dismiss()
}
.show()
return true // don't want to show any rationale, just return false here
}
override fun onShowSettingRationale(permissions: Set<String>): Boolean {
AlertDialog.Builder(this@MainActivity).setMessage("Go Settings -> Permission. " + "Make SMS on and Storage on")
.setPositiveButton("Settings") { _, _ ->
smsAndStoragePermissionHandler.requestPermissionInSetting()
}
.setNegativeButton("Cancel") { dialog, _ ->
smsAndStoragePermissionHandler.cancel()
dialog.cancel()
}
.show()
return true
}
})
button_request.setOnClickListener { handleRequestPermission() }
}
private fun handleRequestPermission() {
smsAndStoragePermissionHandler.requestPermission()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
smsAndStoragePermissionHandler.onRequestPermissionsResult(requestCode, permissions,
grantResults)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
smsAndStoragePermissionHandler.onActivityResult(requestCode)
}
}
Android-M, 즉 API 23 은 안드로이드 장치의 보안 결함을 줄이기 위해 런타임 권한 을 도입 하여 사용자가 런타임시 앱 권한을 직접 관리 할 수 있습니다. 따라서 사용자가 애플리케이션의 특정 권한을 거부하는 경우 권한 대화 상자를 통해 권한을 얻어야합니다 당신이 당신의 쿼리에서 언급했다.
따라서 조치 전에 확인하십시오. 즉, 자원 링크 에 액세스 할 수있는 권한이 있는지 확인 하십시오. 응용 프로그램에 해당 특정 권한이없는 경우 권한 링크를 요청하고 다음과 같이 권한 요청 응답을 처리 할 수 있습니다.
@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
}
}
Android Marshmallow (API 23) 이상에서는 기본적으로 모든 위험한 권한 (공식 문서 공식 문서에 따라 )이 비활성화되어 있습니다. 앱을 처음 열 때 설치 한 후 런타임에 권한을 부여해야합니다.
나는 다음과 같은 방법으로 달성했다.
public class MarshMallowPermission {
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_GALLERY = 0;
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_CAMERA = 1;
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE = 2;
public static final int CAMERA_PERMISSION_REQUEST_CODE = 3;
public static final int LOCATION_PERMISSION_REQUEST_CODE = 4;
Activity activity;
Context mContext;
public MarshMallowPermission(Activity activity) {
this.activity = activity;
this.mContext = activity;
}
public boolean checkPermissionForExternalStorage(){
int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
public boolean checkPermissionForCamera(){
int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
public boolean checkLocationPermission(){
int result = ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
public void requestPermissionForExternalStorage(int requestCode){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(mContext.getApplicationContext(), "External Storage permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},requestCode);
}
}
public void requestPermissionForCamera(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA)){
Toast.makeText(mContext.getApplicationContext(), "Camera permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.CAMERA},CAMERA_PERMISSION_REQUEST_CODE);
}
}
public void requestPermissionForLocation(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_FINE_LOCATION) && ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_COARSE_LOCATION)){
Toast.makeText(mContext.getApplicationContext(), "Location permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE);
}
}
}
활동 수업에서 :
public class MainActivity extends AppCompatActivity{
private MarshMallowPermission marshMallowPermission;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d("NavHome", "Oncreate_nav");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
marshMallowPermission = new MarshMallowPermission(MainActivity.this);
if (!marshMallowPermission.checkPermissionForExternalStorage()) {
marshMallowPermission.requestPermissionForExternalStorage(MarshMallowPermission.EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case MarshMallowPermission.EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//permission granted successfully
} else {
//permission denied
}
break;
}
}
}
AndroidManifest.xml에 권한 추가
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application ...>
....
</application>
런타임 권한이 필요한지 Android 버전을 확인합니다.
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
askForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, 1);
}
권한이 부여되지 않은 경우 사용자에게 권한을 부여하도록 요청하십시오.
private void askForPermission(String permission, int requestCode) {
if (ContextCompat.checkSelfPermission(c, permission)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, permission)) {
Toast.makeText(c, "Please grant the requested permission to get your task done!", Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
} else {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
}
}
}
권한이 부여되었는지 여부를 결정하십시오.
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//permission with request code 1 granted
Toast.makeText(this, "Permission Granted" , Toast.LENGTH_LONG).show();
} else {
//permission with request code 1 was not granted
Toast.makeText(this, "Permission was not Granted" , Toast.LENGTH_LONG).show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
이것을 기본 Fragment 클래스로 사용하고 있습니다. 조각의 권한 만 요청하지만 조각을 리팩터링하고 유사한 활동 버전을 만들 수 있습니다.
public class BaseFragment extends Fragment {
private static final int PERMISSION_REQUEST_BLOCK_INTERNAL = 555;
private static final String PERMISSION_SHARED_PREFERENCES = "permissions";
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_BLOCK_INTERNAL) {
boolean allPermissionsGranted = true;
for (int iGranting : grantResults) {
if (iGranting != PermissionChecker.PERMISSION_GRANTED) {
allPermissionsGranted = false;
break;
}
}
if (allPermissionsGranted && permissionBlock != null) {
permissionBlock.run();
}
permissionBlock = null;
}
}
public void runNowOrAskForPermissionsFirst(String permission, Runnable block) {
if (hasPermission(permission)) {
block.run();
} else if (!hasPermissionOrWillAsk(permission)) {
permissionBlock = block;
askForPermission(permission, PERMISSION_REQUEST_BLOCK_INTERNAL);
}
}
public boolean hasPermissionOrWillAsk(String permission) {
boolean hasPermission = hasPermission(permission);
boolean hasAsked = hasPreviouslyAskedForPermission(permission);
boolean shouldExplain = shouldShowRequestPermissionRationale(permission);
return hasPermission || (hasAsked && !shouldExplain);
}
private boolean hasPermission(String permission) {
return (ContextCompat.checkSelfPermission(getContext(), permission) == PackageManager.PERMISSION_GRANTED);
}
private boolean hasPreviouslyAskedForPermission(String permission) {
SharedPreferences prefs = getContext().getSharedPreferences(PERMISSION_SHARED_PREFERENCES, Context.MODE_PRIVATE);
return prefs.getBoolean(permission, false);
}
private void askForPermission(String permission, int requestCode) {
SharedPreferences.Editor editor = getContext().getSharedPreferences(PERMISSION_SHARED_PREFERENCES, Context.MODE_PRIVATE).edit();
editor.putBoolean(permission, true);
editor.apply();
requestPermissions(new String[] { permission }, requestCode);
}
}
사용해야하는 두 가지 주요 방법이 있습니다.
hasPermissionOrWillAsk-다시 요청하지 않는 사용자가 권한을 요청하고 거부했는지 여부를 확인하려면이 옵션을 사용하십시오. 사용자가 기능을 원하지 않는 것에 대한 최종 답변을 제공 한 경우 UI를 비활성화하는 데 유용합니다.
runNowOrAskForPermissionsFirst-권한이 필요한 일부 코드를 실행하려면이 옵션을 사용하십시오. 사용자가 이미 권한을 부여한 경우 코드가 즉시 실행됩니다. 그렇지 않으면 사용자가 권한을 부여하면 코드가 나중에 실행됩니다. 아니면 전혀. 한곳에서 코드를 지정하기 때문에 좋습니다.
예를 들면 다음과 같습니다.
mFragment.runNowOrAskForPermissionsFirst(Manifest.permission.ACCESS_FINE_LOCATION, new Runnable() {
@Override
public void run() {
...do something if we have permission...
}
});
이에 대한 의견을 보내 주셔서 감사합니다. 이 특정 예제는 장치에서 위치 서비스가 활성화되어 있는지 확인해야한다는 점에서 약간 단순화 된 것은 아닙니다. (권한과는 다릅니다.) 또한 한 번에 하나의 권한 만 지원하지만 한 번에 여러 권한을 지원해야하는 경우 수정하는 것이 간단합니다.
더 깨끗한 방법 일 수 있습니다. 다음과 같은 배열로 모든 권한을 추가하십시오.
private static final String[] INITIAL_PERMS={
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION
};
private static final int INITIAL_REQUEST=1337;
당신의 박해가 무엇이든 각 박해에 대한 방법을 만들
@RequiresApi(api = Build.VERSION_CODES.M)
private boolean canAccessFineLocation() {
return(hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
@RequiresApi(api = Build.VERSION_CODES.M)
private boolean canAccessCoarseLocation() {
return(hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION));
}
@RequiresApi(api = Build.VERSION_CODES.M)
private boolean hasPermission(String perm) {
return(PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm));
}
onCreate 에서이 메소드를 호출하십시오.
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(!canAccessCoarseLocation() || !canAccessFineLocation()){
requestPermissions(INITIAL_PERMS, INITIAL_REQUEST);
}
}
이제 onRequestPermissionsResult를 재정의하십시오 .
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if(requestCode == INITIAL_REQUEST){
if (canAccessFineLocation() && canAccessCoarseLocation()) {
//call your method
}
else {
//show Toast or alert that this permissions is neccessary
}
}
}
한 번에 여러 권한을 사용하려면 이것을 사용할 수 있습니다. 이것은 나를 위해 일한다. 나는 다른 해결책을 얻었다. targetSdkVersion을 22로 지정하면 효과가 있습니다. 그리고 manifest.xml에서 권한을 얻는 것처럼 작동합니다. 테스트하고 나를 위해 작동합니다.
final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
private void insertDummyContactWrapper() {
List<String> permissionsNeeded = new ArrayList<String>();
final List<String> permissionsList = new ArrayList<String>();
if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
permissionsNeeded.add("GPS");
if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS))
permissionsNeeded.add("Read Contacts");
if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS))
permissionsNeeded.add("Write Contacts");
if (permissionsList.size() > 0) {
if (permissionsNeeded.size() > 0) {
// Need Rationale
String message = "You need to grant access to " + permissionsNeeded.get(0);
for (int i = 1; i < permissionsNeeded.size(); i++)
message = message + ", " + permissionsNeeded.get(i);
showMessageOKCancel(message,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
});
return;
}
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
return;
}
insertDummyContact();
}
private boolean addPermission(List<String> permissionsList, String permission) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
// Check for Rationale Option
if (!shouldShowRequestPermissionRationale(permission))
return false;
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS:
{
Map<String, Integer> perms = new HashMap<String, Integer>();
// Initial
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.READ_CONTACTS, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.WRITE_CONTACTS, PackageManager.PERMISSION_GRANTED);
// Fill with results
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for ACCESS_FINE_LOCATION
if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
// All Permissions Granted
insertDummyContact();
} else {
// Permission Denied
Toast.makeText(MainActivity.this, "Some Permission is Denied", Toast.LENGTH_SHORT)
.show();
}
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
상세 사항은. 벨로우즈 링크 확인
Google은 런타임 권한을 처리하기 위해 라이브러리 프로젝트를 제공했습니다. https://github.com/googlesamples/easypermissions 에서 확인할 수 있습니다.
EasyPermissions는 build.gradle 파일에 다음 종속성을 추가하여 설치됩니다.
dependencies {
compile 'pub.devrel:easypermissions:0.3.0'
}
EasyPermissions를 사용하려면 Activity (또는 Fragment)가 onRequestPermissionsResult 메소드를 대체하도록하십시오.
public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// Forward results to EasyPermissions
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
@Override
public void onPermissionsGranted(int requestCode, List<String> list) {
// Some permissions have been granted
// ...
}
@Override
public void onPermissionsDenied(int requestCode, List<String> list) {
// Some permissions have been denied
// ...
}
}
여기이 라이브러리의 작동 방식에 대한 실제 예제가 있습니다. https://github.com/milon87/EasyPermission
백그라운드 서비스에서 권한이 필요할 때 권한을 요청해야하는 경우 사용할 수있는 좋은 라이브러리가 있습니다. 라이브러리의 제한 사항은 현재 앱에 권한이 부여되었는지 여부를 결정하는 데 사용할 수 없다는 것입니다. 앱에 아직 앱이 없는지 항상 사용자에게 묻습니다.
인생을 더 간단하게 만들어보십시오 .Android 권한
아래 코드는 완벽하게 작동합니다. 예를 들어 설명하고 있습니다.
필자의 경우 권한 검사를 util 클래스에 별도로 배치하고 적절한 클래스에서 확인 해야하는 특정 권한을 전달했습니다.이를 통해 전체 응용 프로그램에서 권한 검사 util 파일을 다시 사용할 수 있습니다.
아래 코드 부분은 함수 호출을 보여줍니다.이 경우 android.Manifest.permission.READ_EXTERNAL_STORAGE
권한을 요청하고 있습니다.
//the below call is from a fragment
@OnClick(R.id.button)//butterknife implementation
public void attachPressed() {
if (PermissionUtils.hasThisPermission(getContext(), android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
onAttachPressed();
} else {
PermissionUtils.isPermissionRequestNeeded(getActivity(), this, android.Manifest.permission.READ_EXTERNAL_STORAGE, PermissionUtils.REQUEST_GROUP_STORAGE);
}
}
위의 경우 권한이 허용되면 권한이 확인되고 onAttachPressed();
함수가 호출 되면 요청 권한을 확인합니다.
아래는 필자의 경우 util 클래스에있는 코드입니다. PermissionUtils
public final class PermissionUtils {
public static final int REQUEST_GROUP_STORAGE = 1508;
private PermissionUtils() {
}
public static boolean hasThisPermission(Context context, String permission) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return ActivityCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
} else {
return true;
}
}
public static boolean isPermissionRequestNeeded(Activity activity, Fragment fragment, String permission, int requestCode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !hasThisPermission(activity, permission)) {
final String[] permissions = new String[]{permission};
if (fragment == null) {
activity.requestPermissions(permissions, requestCode);
} else {
fragment.requestPermissions(permissions, requestCode);
}
return true;
}
return false;
}
}
요청 후 함수를 호출하려는 경우 onRequestPermissionsResult
또는 함수 호출을 위해 버튼을 다시 눌러야합니다.
그냥 전화 해 onRequestPermissionsResult
//the below call is from a fragment
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PermissionUtils.REQUEST_GROUP_STORAGE && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
onAttachPressed();
} else {
Log.e("value", "Permission Denied, You cannot use local drive .");
}
}
권한을 요청 하기 위해 RxPermission 라이브러리 라이브러리를 사용합니다. 우리가 허락을 구하기 위해 작성해야하는 긴 코드이기 때문입니다.
RxPermissions rxPermissions = new RxPermissions(this); // where this is an Activity instance // Must be done during an initialization phase like onCreate
rxPermissions
.request(Manifest.permission.CAMERA)
.subscribe(granted -> {
if (granted) { // Always true pre-M
// I can control the camera now
} else {
// Oups permission denied
}
});
귀하의 이러한 의존성을 추가하십시오 build.gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.tbruyelle:rxpermissions:0.10.1'
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
}
이 시도
이것은 Marshmallow 버전에서 허가를 요청하는 가장 간단한 방법입니다.
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED&&ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
//TO do here if permission is granted by user
}
else
{
//ask for permission if user didnot given
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
requestPermissions(new String[]{Manifest.permission.CAMERA,Manifest.permission.ACCESS_FINE_LOCATION}, 0);
}
}
참고 :- 매니페스트 파일에도 동일한 권한을 추가하는 것을 잊지 마십시오
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
권한 확인을위한 두 번째 방법 코드가 부여됩니까?
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA}, 1);
그리고 메소드를 재정의하십시오.
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
if (grantResults.length > 0 && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
// grantResult[0] means it will check for the first postion permission which is READ_EXTERNAL_STORAGE
// grantResult[1] means it will check for the Second postion permission which is CAMERA
Toast.makeText(this, "Permission Granted", Toast.LENGTH_SHORT).show();
}
else
Toast.makeText(this, "Permission not Granted", Toast.LENGTH_SHORT).show();
return;
}
}
}
많은 코드를 작성하지 않고 권한을 요청하는 간단한 방법,
https://github.com/sachinvarma/EasyPermission
추가하는 방법 :
repositories {
maven { url "https://jitpack.io" }
}
implementation 'com.github.sachinvarma:EasyPermission:1.0.1'
허가를 요청하는 방법 :
List<String> permission = new ArrayList<>();
permission.add(EasyPermissionList.READ_EXTERNAL_STORAGE);
permission.add(EasyPermissionList.ACCESS_FINE_LOCATION);
new EasyPermissionInit(MainActivity.this, permission);
누군가에게 도움이되기를 바랍니다.
나는 모든 답변을 겪었지만 정확한 답변을 만족시키지 못하므로 여기에 내가 작성하고 완벽하게 작동하는 예가 있습니다. 사용자가 다시 묻지 않음 확인란을 클릭하더라도 .
다음과 같이 런타임 권한을 요청 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();
}
}
}
여기서 우리는 RunTime 권한으로 완료됩니다. 애드온은 openPermissionSettingDialog()
사용자가 다시 묻지 않음 확인란 을 클릭하여 권한을 영구적으로 비활성화 한 경우 설정 화면을 여는 것 입니다. 아래는 방법입니다.
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>
parentLayout
내부 변수 초기화onCreate
메소드
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);}
이것은 큰 행복 코딩을 작동합니다 :)
당신이 사용하는 경우 AndroidX 활동 1.2.0 또는 AndroidX 조각 1.3.0 :
권한을 요청하는 데 사용할 수있는 새로운 활동 결과 API가 있습니다.
val launcher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
// Permission granted. Do the tasks.
}
}
launcher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
if (CommonMethod.isNetworkAvailable(MainActivity.this)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int permissionCheck = ContextCompat.checkSelfPermission(MainActivity.this,
android.Manifest.permission.CAMERA);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
//showing dialog to select image
callFacebook();
Log.e("permission", "granted MarshMallow");
} else {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.CAMERA}, 1);
}
} else {
Log.e("permission", "Not Required Less than MarshMallow Version");
callFacebook();
}
} else {
CommonMethod.showAlert("Internet Connectivity Failure", MainActivity.this);
}
내 라이브러리를 사용할 수 있습니다 — NoPermission (단 하나의 클래스)
compile 'ru.alexbykov:nopermission:1.1.1'
견본
PermissionHelper permissionHelper = new PermissionHelper(this); //don't use getActivity in fragment!
permissionHelper.check(Manifest.permission.READ_CONTACTS)
.onSuccess(this::onSuccess)
.onDenied(this::onDenied)
.onNeverAskAgain(this::onNeverAskAgain)
.run();
onRequestPermissionResult :
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
permissionHelper.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
EasyPermissions
Google 보다 API가 더 편리하다고 생각 합니다.
응용 프로그램의 어느 곳 에서나 런타임 권한 예제는 다음과 같습니다.
use dependency
maven { url 'https://jitpack.io' }
dependencies {
implementation 'com.github.irshadsparky:PermissionLib:master-SNAPSHOT'
}
다음과 같은 코드를 호출하십시오.
PermissionHelper.requestCamera(new PermissionHelper.OnPermissionGrantedListener() {
@Override
public void onPermissionGranted() {
}
});
더 많은 Github를 찾을 수 있습니다
런타임 권한은 활동적으로 많은 상용구 코드를 생성하며이 코드는 밀접하게 결합되어 있습니다. 코드를 줄이고 일을 쉽게하기 위해 Dexter 라이브러리를 사용할 수 있습니다 .
안드로이드 런타임 퍼미션
public void onClick(View view) {
if (view.getId() == shareButton.getId()) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
this.shareLog();
} else {
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, LogConstants.PERMISSION_REQ_WRITE_EXTERNAL_STORAGE);
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == LogConstants.PERMISSION_REQ_WRITE_EXTERNAL_STORAGE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
this.shareLog();
}
}
}
OnClick 방법은 런타임 권한을 확인하는 것입니다
권한이 제한되면 권한을 요청합니다.