마시멜로의 스토리지 사용 권한 오류
롤리팝에서 다운로드 기능은 내 앱에서 잘 작동하지만 마시멜로로 업그레이드하면 인터넷에서 SD 카드로 다운로드하려고 하면 앱이 충돌하고 다음 오류가 발생합니다.
Neither user nor current process has android.permission.WRITE_EXTERNAL_STORAGE
이 코드 라인에 대해 불만을 표시합니다.
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
매니페스트 외부 응용 프로그램에 대한 권한이 있습니다.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
프로젝트를 청소하고 다시 만들었지만 아직도 고장이 납니다.
사용자가 다음을 사용하여 외부 스토리지에 대한 사용 권한을 부여했는지 확인해야 합니다.
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.v(TAG,"Permission is granted");
//File write logic here
return true;
}
그렇지 않은 경우 사용자에게 앱에 권한을 부여하도록 요청해야 합니다.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
물론 이것들은 마시멜로 장치만을 위한 것이기 때문에 당신은 당신의 앱이 마시멜로에서 실행되고 있는지 확인해야 합니다.
if (Build.VERSION.SDK_INT >= 23) {
//do your check here
}
또한 활동이 구현되는지 확인합니다.OnRequestPermissionResult
전체 권한은 다음과 같습니다.
public boolean isStoragePermissionGranted() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
Log.v(TAG,"Permission is granted");
return true;
} else {
Log.v(TAG,"Permission is revoked");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return false;
}
}
else { //permission is automatically granted on sdk<23 upon installation
Log.v(TAG,"Permission is granted");
return true;
}
}
권한 결과 콜백:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
Log.v(TAG,"Permission: "+permissions[0]+ "was "+grantResults[0]);
//resume tasks needing this permission
}
}
Android의 권한 시스템은 설치 시 해당 권한이 요청되기 때문에 항상 가장 큰 보안 문제 중 하나입니다.설치가 완료되면 응용프로그램은 사용자의 승인 없이 부여된 모든 항목에 액세스할 수 있습니다.
Android 6.0 Mashmallow는 런타임 권한이 추가되어 권한 모델에 가장 큰 변화 중 하나를 도입했습니다. 이는 API 23을 대상으로 하고 앱이 Android 6.0+ 기기에서 실행될 때 기존 설치 시간 권한 모델을 대체하는 새로운 권한 모델입니다.
예
전역으로 선언
private static final int PERMISSION_REQUEST_CODE = 1;
섹션에 추가합니다.
내용 보기를 설정한 후(R. 레이아웃).your_xml);
if (Build.VERSION.SDK_INT >= 23)
{
if (checkPermission())
{
// Code for above or equal 23 API Oriented Device
// Your Permission granted already .Do next code
} else {
requestPermission(); // Code for permission
}
}
else
{
// Code for Below 23 API Oriented Device
// Do next code
}
이제 checkPermission() 및 requestPermission()을 추가하는 중입니다.
private boolean checkPermission() {
int result = ContextCompat.checkSelfPermission(Your_Activity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
private void requestPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(Your_Activity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Toast.makeText(Your_Activity.this, "Write External Storage permission allows us to do store images. Please allow this permission in App Settings.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(Your_Activity.this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.e("value", "Permission Granted, Now you can use local drive .");
} else {
Log.e("value", "Permission Denied, You cannot use local drive .");
}
break;
}
}
참고로
이 인터페이스는 권한 요청에 대한 결과를 수신하기 위한 계약입니다.
API 레벨 23에서 다중 사용 권한 확인 1단계:
String[] permissions = new String[]{
Manifest.permission.INTERNET,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.VIBRATE,
Manifest.permission.RECORD_AUDIO,
};
2단계:
private boolean checkPermissions() {
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p : permissions) {
result = ContextCompat.checkSelfPermission(this, p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), 100);
return false;
}
return true;
}
3단계:
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (requestCode == 100) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// do something
}
return;
}
}
4단계: 활동 만들기에서 권한 확인();
외부 스토리지에 기록해야 하는 명확한 요구 사항이 없는 한 항상 앱 디렉터리에 파일을 저장하도록 선택할 수 있습니다.저의 경우 파일을 저장해야 했고 2~3일의 시간을 허비한 후 스토리지 경로를
Environment.getExternalStorageDirectory()
로.
getApplicationContext().getFilesDir().getPath() //which returns the internal app files directory path
모든 장치에서 매력적으로 작동합니다.외부 저장소에 쓰기 위해서는 추가 권한이 필요하지만 내부 앱 디렉터리에 쓰기는 간단하기 때문입니다.
마시멜로 https://developer.android.com/training/permissions/requesting.html 에서 런타임 권한을 사용해야 합니다.
앱 정보를 확인하실 수 있습니다 -> 권한
앱이 외부 스토리지 쓰기에 대한 권한을 얻는지 여부
마시멜로 버전부터 개발자는 사용자에게 런타임 권한을 요청해야 합니다.런타임 권한을 요청하는 전체 프로세스를 제공합니다.
나는 여기서 참조를 사용하고 있습니다: 마시멜로 런타임 권한 안드로이드.
먼저 모든 권한이 부여되었는지 여부를 확인하는 메서드를 만듭니다.
private boolean checkAndRequestPermissions() {
int camerapermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
int writepermission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int permissionLocation = ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION);
int permissionRecordAudio = ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO);
List<String> listPermissionsNeeded = new ArrayList<>();
if (camerapermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.CAMERA);
}
if (writepermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (permissionLocation != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (permissionRecordAudio != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.RECORD_AUDIO);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
이제 위의 방법 이후에 실행되는 코드가 있습니다.우리는 무시할 것입니다.onRequestPermissionsResult()
방법:
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
Log.d(TAG, "Permission callback called-------");
switch (requestCode) {
case REQUEST_ID_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
// Initialize the map with both permissions
perms.put(Manifest.permission.CAMERA, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.RECORD_AUDIO, PackageManager.PERMISSION_GRANTED);
// Fill with actual results from user
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for both permissions
if (perms.get(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "sms & location services permission granted");
// process the normal flow
Intent i = new Intent(MainActivity.this, WelcomeActivity.class);
startActivity(i);
finish();
//else any one or both the permissions are not granted
} else {
Log.d(TAG, "Some permissions are not granted ask again ");
//permission is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permission
// // shouldShowRequestPermissionRationale will return true
//show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)
|| ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|| ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)
|| ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) {
showDialogOK("Service Permissions are required for this app",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
checkAndRequestPermissions();
break;
case DialogInterface.BUTTON_NEGATIVE:
// proceed with logic by disabling the related features or quit the app.
finish();
break;
}
}
});
}
//permission is denied (and never ask again is checked)
//shouldShowRequestPermissionRationale will return false
else {
explain("You need to give some mandatory permissions to continue. Do you want to go to app settings?");
// //proceed with logic by disabling the related features or quit the app.
}
}
}
}
}
}
사용자가 거부 옵션을 클릭하면showDialogOK()
메소드는 대화 상자를 표시하는 데 사용됩니다.
사용자가 거부를 클릭하고 "다시 묻지 않음" 확인란도 클릭하면explain()
메소드는 대화 상자를 표시하는 데 사용됩니다.
대화 상자를 표시하는 방법:
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", okListener)
.create()
.show();
}
private void explain(String msg){
final android.support.v7.app.AlertDialog.Builder dialog = new android.support.v7.app.AlertDialog.Builder(this);
dialog.setMessage(msg)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
// permissionsclass.requestPermission(type,code);
startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:com.exampledemo.parsaniahardik.marshmallowpermission")));
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
finish();
}
});
dialog.show();
}
위의 코드 조각은 한 번에 4개의 권한을 요청합니다.또한 요구 사항에 따라 활동에서 원하는 수의 권한을 요청할 수 있습니다.
내가 찾은 가장 쉬운 방법은
private boolean checkPermissions(){
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
return true;
}
else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_CODE);
return false;
}
}
MainActivity의 OnCreate() 기능에 아래 코드를 추가합니다. 여기에는 권한을 요청하는 팝업이 표시됩니다.
if (ActivityCompat.shouldShowRequestPermissionRationale(TestActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)){
}
else {
ActivityCompat.requestPermissions(TestActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
100);
}
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Log.d(TAG, "Permission granted");
} else {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
100);
}
fab.setOnClickListener(v -> {
Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.refer_pic);
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(requireActivity().getContentResolver(),
b, "Title", null);
Uri imageUri = Uri.parse(path);
share.putExtra(Intent.EXTRA_STREAM, imageUri);
share.putExtra(Intent.EXTRA_TEXT, "Here is text");
startActivity(Intent.createChooser(share, "Share via"));
});
검색을 많이 한 후 이 코드는 나에게 도움이 됩니다.
권한에 이미 다음이 있는지 확인합니다.WRITE_EXTERNAL_STORAGE 권한 허용 여부를 선택하십시오.
if(isReadStorageAllowed()){
//If permission is already having then showing the toast
//Toast.makeText(SplashActivity.this,"You already have the permission",Toast.LENGTH_LONG).show();
//Existing the method with return
return;
}else{
requestStoragePermission();
}
private boolean isReadStorageAllowed() {
//Getting the permission status
int result = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
//If permission is granted returning true
if (result == PackageManager.PERMISSION_GRANTED)
return true;
//If permission is not granted returning false
return false;
}
//Requesting permission
private void requestStoragePermission(){
if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)){
//If the user has denied the permission previously your code will come to this block
//Here you can explain why you need this permission
//Explain here why you need this permission
}
//And finally ask for the permission
ActivityCompat.requestPermissions(this,new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE},REQUEST_WRITE_STORAGE);
}
RequestPermissions에 Override 구현확인을 위한 결과 메서드가 사용자 허용 또는 거부입니다.
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
//Checking the request code of our request
if(requestCode == REQUEST_WRITE_STORAGE){
//If permission is granted
if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
//Displaying a toast
Toast.makeText(this,"Permission granted now you can read the storage",Toast.LENGTH_LONG).show();
}else{
//Displaying another toast if permission is not granted
Toast.makeText(this,"Oops you just denied the permission",Toast.LENGTH_LONG).show();
}
}
다운로드를 시작하기 전에 런타임 권한을 확인하고 권한이 없는 경우 이 방법과 같은 요청 권한을 확인합니다.
스토리지 사용 권한 요청()
private void requestStoragePermission(){
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
android.Manifest.permission.READ_EXTERNAL_STORAGE))
{
}
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
STORAGE_PERMISSION_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults) {
if(requestCode == STORAGE_PERMISSION_CODE){
if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
}
else{
Toast.makeText(this,
"Oops you just denied the permission",
Toast.LENGTH_LONG).show();
}
}
}
간단한 방법으로 manifest.xml 파일을 사용하여 권한을 부여할 수 있지만, 이후 api 레벨 23 sdk 버전 6까지는 괜찮았습니다. 여기서부터는 권한을 받으려면 필요한 권한을 허용하기 위해 사용을 요청해야 합니다.
메인 Activity.java에 이 코드를 추가하기만 하면 됩니다.
Override
public void onClick(View view) {
// Request the permission
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.CAMERA},
PERMISSION_REQUEST_CAMERA);
원하는 경우 CAMERA를 대체하거나 WRITE_EXTERNAL_STORAGE 및 고유 코드로 추가합니다.
new String[]{Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE},
101);
이것은 허가를 받기 위한 간단한 코드입니다.
언급URL : https://stackoverflow.com/questions/33162152/storage-permission-error-in-marshmallow
'programing' 카테고리의 다른 글
윈도우 기능이 있는 SQL 쿼리에서 그룹화할 수 있습니까? (0) | 2023.08.06 |
---|---|
테이블스페이스 생성 및 삭제 Oracle (0) | 2023.08.06 |
Android Room - 자동 생성으로 삽입된 새 행의 ID 가져오기 (0) | 2023.08.06 |
MariaDB의 동적 피벗 테이블이 php에서 작동하지 않는 쿼리 (0) | 2023.08.06 |
Spring Boot API 게이트웨이에서 이름을 확인할 수 없습니다. (0) | 2023.08.06 |