Android에서 '개방 실패 : EACCES (권한 거부)'예외


297

나는 얻고있다

열지 못했습니다 : EACCES (Permission denied)

줄에 OutputStream myOutput = new FileOutputStream(outFileName);

나는 뿌리를 확인하고 시도했다 android.permission.WRITE_EXTERNAL_STORAGE.

이 문제를 어떻게 해결할 수 있습니까?

try {
    InputStream myInput;

    myInput = getAssets().open("XXX.db");

    // Path to the just created empty db
    String outFileName = "/data/data/XX/databases/"
            + "XXX.db";

    // Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);

    // Transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length;
    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }

    // Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();
    buffer = null;
    outFileName = null;
}
catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

Android 태블릿에서도 같은 문제가 있었지만 상황이 독특 할 수 있으므로 여기에 내 솔루션을 의견으로보고하십시오. 앱이 50 개가 넘는 xml 파일을 가진 / data / data / myapp / foo 디렉토리에 액세스하려고 할 때 오류가 발생했습니다. 버그로 인해 앱이 폴더를 정리하지 않았습니다. 일부 오래된 파일이 삭제 된 후 오류가 사라졌습니다. 이유를 모르겠습니다. 일반 Android 기기의 문제 일 수 있습니다.
Hong

이 문제가 해결되었습니다 : stackoverflow.com/questions/33666071/…
partho

답변:


236

나는 같은 문제가 있었다 ... <uses-permission잘못된 장소에 있었다. 이것은 맞다 :

 <manifest>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        ...
        <application>
            ...
            <activity> 
                ...
            </activity>
        </application>
    </manifest> 

uses-permission태그는 외부에 있어야 application태그입니다.


2
사용 허가는 응용 프로그램 외부에 있어야합니다.
user462990

3
경고 : " <uses-permission>태그 뒤에 <application>태그 가 표시됨 "
mr5

11
경고 안드로이드 4.4.4에서는 매개 변수를 사용하지 마십시오 android:maxSdkVersion="18". 이 예외가 발생했습니다
guisantogui

1
이 권한은 API 레벨 19부터 시작됩니다. API 레벨 19 이전에는이 ​​권한이 적용되지 않으며 모든 앱은 여전히 ​​외부 저장소에서 읽을 수 있습니다.
Zar E Ahmer

1
메신저 OTG USB 스틱에 파일을 이동하는 동안 메신저 오류가 발생, 15 LVL API를 사용하여
라비 메타

330

API 23+의 경우 이미 매니페스트에있는 경우에도 읽기 / 쓰기 권한을 요청해야합니다.

// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};

/**
 * Checks if the app has permission to write to device storage
 *
 * If the app does not has permission then the user will be prompted to grant permissions
 *
 * @param activity
 */
public static void verifyStoragePermissions(Activity activity) {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}

AndroidManifest.xml

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

API 23+에 대한 권한 요청에 대한 공식 문서는 https://developer.android.com/training/permissions/requesting.html을 확인 하십시오.


13
명확히하기 위해, 이것이 작동하려면 활동이 활동 권한 요청 응답을 처리해야합니다. 자세한 내용은 developer.android.com/training/permissions/… 를 참조하십시오.
kldavis4


1
이것은 나쁜 것이 아닌가? 사용자 경험과 관련하여.
M. Usman Khan

5
그러나 어디서 사용합니까? 예를 들어 사진을 찍으려면 startActivityForResult 전에 또는 onActivityResult에서 verifyStoragePermissions를 실행해야합니까? 정말 혼란 스럽습니다.
Kiwi Lee

3
이 문제를 해결해 주셔서 감사합니다. 참고 : 누군가 "Manifest.permission"을 해결할 수없는 경우 "import android.Manifest"를 가져와야합니다.
Oubaida AlQuraan

167

Google은 Android Q 의 새로운 기능인 외부 저장소를위한 필터링 된보기를 제공합니다. 빠른 수정 방법은 AndroidManifest.xml 파일에이 코드를 추가하는 것입니다.

<manifest ... >
    <!-- This attribute is "false" by default on apps targeting Android Q. -->
    <application android:requestLegacyExternalStorage="true" ... >
     ...
    </application>
</manifest>

https://developer.android.com/training/data-storage/compatibility 에서 자세한 내용을 읽을 수 있습니다.


@Billy 내가 파일 제공자의 변화를 검색 그래서 그것은 단지 API (29)와 장치에서 발생되는주의
우리엘 프랭클

마지막으로 androidtest 매니페스트에 추가 된이 줄을 사용하여 cloudtestingscreenshotter_lib.aar를 얻었습니다.이 찾기에 대해 대단히 감사합니다.
bko

6
당신은 시간을 많이 절약했습니다. Q에서 개발자에게는 많은 문제가 발생했습니다.이 답변은 별도의 질문으로 게시해야하며 더 많은지지를 받아야합니다.
sanjeev

좀 더이 좋은 작은 마술 트릭에 대해 읽고 싶은,하지만 불행히도 링크 어쨌든 404 오류 ... 감사를 반환
SadSido

android:requestLegacyExternalStorage="true"이것은 이것이 더 낮은 버전 ryt을 깨뜨리지 않을 것이라는 경고를 주는가? @ UrielFrankel
산타

58

에뮬레이터 내에서 응용 프로그램을 실행할 때 이것을 한 번 관찰했습니다. 에뮬레이터 설정에서 외부 저장소 ( "SD 카드")의 크기를 올바르게 지정해야합니다. 기본적으로 "외부 스토리지"필드는 비어 있으며 이는 아마도 그러한 장치가없고 매니페스트에 권한이 부여 된 경우에도 EACCES가 발생 함을 의미합니다.


51

모든 답변 외에도 휴대 전화를 USB 저장소로 사용하지 않아야합니다.

USB 저장 모드를 사용하는 HTC Sensation에서 동일한 문제가 발생했습니다. 여전히 앱을 디버깅 / 실행할 수 있지만 외부 저장소에 저장할 수 없습니다.


고맙습니다. 런타임에 사용자에게 권한을 요청했지만. 이 오류는 에뮬레이터에서 발생했습니다.
Sharp Edge

1
Samsung Galaxy S6 장치를 연결하면 먼저 "DENY"또는 "ALLOW"를 사용하여 "장치 데이터에 대한 액세스 허용"옵션을 제공하며 알림 표시 줄에서도 USB 사용 옵션이 나타납니다. MTP 2. PTP 3. MIDI 장치 4. 충전. 어느 것을 선택해야합니까?
testsingh

34

Android Manifest에 android : requestLegacyExternalStorage = "true" 추가 SDK 29
이상 또는 Android X 마이그레이션 후 Android 10 (Q)에서 작동 합니다.

 <application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:hardwareAccelerated="true"
    android:icon=""
    android:label=""
    android:largeHeap="true"
    android:supportsRtl=""
    android:theme=""
    android:requestLegacyExternalStorage="true">

와우 완벽하게 작동, 그것은 내가 찾던 대답이었습니다, 큰, @rhaldar 감사합니다, 당신은 내 하루를 저장
Ayush

29

내 문제는 minSdkVersion이 23 이하인 경우 필요한 "TargetApi (23)"입니다.

그래서 다음 스 니펫으로 권한을 요청했습니다.

protected boolean shouldAskPermissions() {
    return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
}

@TargetApi(23)
protected void askPermissions() {
    String[] permissions = {
            "android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE"
    };
    int requestCode = 200;
    requestPermissions(permissions, requestCode);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
// ...
    if (shouldAskPermissions()) {
        askPermissions();
    }
}

28

Android Q 용 솔루션 :

<application ...
    android:requestLegacyExternalStorage="true" ... >

당신은 내 하루를 저장했습니다. 권한이 부여되었지만 설정하기 전까지 글라이드는 이미지를 읽을 수 없습니다.
leegor

주의 : 안드로이드 (11)는 완전히 애플 리케이션을위한 저장소 액세스 프레임 워크 (SAF)를 사용하는 8 월 2020 년 그래서 더 업그레이드 파일 액세스를 레거시 액세스를 제거합니다
dimib

16

같은 경험이 있습니다. 내가 찾은 것은 설정-> 응용 프로그램 관리자-> 앱-> 권한-> 저장소 사용으로 이동 하면 문제를 해결한다는 것입니다.


1
이 섹션을 찾을 수 없습니까?
Evan Sevy

13

전화가 여전히 데스크톱 PC에 연결되어 있고 이것을 인식하지 못했기 때문에 어리석은 실수였습니다.

그래서 나는 USB 연결을 꺼야했고 모든 것이 잘 작동했습니다.


나를 위해 일했다. 그러나 왜 작동합니까? USB를 PC에 연결하지 않는 차이점은 무엇입니까?
user13107

좋은 질문. 나는 이것을 더 이상 조사하지 않았다. 장치를 연결하는 순간 시스템에서 쓰기 잠금이 있다고 생각합니다 (따라서 컴퓨터의 USB 장치를 에뮬레이트 할 수 있습니다). 일관성이없는 데이터를 피하기위한 것일 수 있습니다. 그래도 확실하지 않습니다.
Tobias Reich


13

CM 12.1을 실행하는 Samsung Galaxy Note 3에서도 동일한 문제가 발생했습니다. 나를 위해 문제는 내가 가지고 있었다

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18"/>

사용자 사진을 찍고 저장하는 데 사용해야했습니다. ImageLoader에서 동일한 사진을로드하려고 할 때 (Permission denied)오류가 발생했습니다. 해결책은 명시 적으로 추가하는 것이 었습니다

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

위의 권한은 쓰기 권한을 API 버전 18까지로 제한하며 읽기 권한 만 허용합니다.


나를 도와주지 않았다! 시도할만한 가치가 있습니다! 감사.
Sakiboy

9

모든 답변 외에도 클라이언트가 Android 6.0을 사용하는 경우 Android 는 (Marshmallow)에 대한 새로운 권한 모델 을 추가했습니다 .

트릭 : 버전 22 이하를 대상으로하는 경우 응용 프로그램은 설치시 Marshmallow 미만의 OS를 실행하는 모든 장치에서와 마찬가지로 모든 권한을 요청합니다. 에뮬레이터에서 시도하는 경우 Android 6.0부터 설정-> 앱-> YOURAPP-> 권한을 명시 적으로 지정하고 권한을 부여해야합니다.


2
믿을 수 없을 정도로, 나는 이것을 알아 내려고 노력하는 데 이틀을 보냈습니다. Android에서 원활하게 실행되고 있다고 느낄 때마다 이와 같은 일이 발생합니다.
Jaime Ivan Cervantes

7

newFile 앞에 슬래시 "/" 를 넣으면 이상하게도 내 문제가 해결되었습니다. 나는 이것을 바꿨다.

File myFile= new File(Environment.getExternalStorageDirectory() + "newFile");

이에:

File myFile= new File(Environment.getExternalStorageDirectory() + "/newFile");

1
여기서 이상한 것은 없습니다. 첫 번째 행에서는 외부 스토리지 디렉토리가 포함 된 디렉토리와 동일한 디렉토리에 파일을 작성하려고합니다. 즉 /storage/.../something/newfile 대신 /storage/.../somethingnewfile
Stéphane

@ Stéphane 광범위한 답변을 보면 오류 자체가 이상합니다.
Darush

3
올바른 방법은 File (dir, file) cosntructor
Nick Cardoso

@NickCardoso File (String pathname)을 사용할 수도 있습니다. 여기에 요점이없는 것 같습니다. 문제는 File 클래스를 사용하는 방법에 관한 것이 아닙니다. 이 글타래의 답변 범위는이 오류의 오도 및 오류 해결 방법을 보여줍니다. 필자의 경우 오류는 슬래시 누락입니다. 어떤 사람들은 유용하다고 생각했습니다. 물론 파일에 액세스하는 고유 한 방법을 사용할 수 있습니다. 계속해서 답을 게시하십시오. 누군가의 문제를 해결할 수 있습니다.
Darush

당신 은 요점을 얻지 못했습니다. 올바른 생성자를 사용하면 해킹이 필요하지 않습니다. 내 의견이 추가되어 미래의 독자가 실수로 잘못 인도하는 데 도움이 될 수 있습니다. 개인적인 비평이 아니었고 답글이 필요하지 않았습니다.
Nick Cardoso 08

6

나는 같은 문제가 있었고 어떤 제안도 도움이되지 않았다. 그러나 실제 장치 인 Galaxy Tab 에서 흥미로운 이유를 발견했습니다 .

USB 저장소가 켜져 있으면 외부 저장소 읽기 및 쓰기 권한이 영향을 미치지 않습니다. USB 저장 장치를 끄면 올바른 권한으로 문제가 해결됩니다.


2
젠장, 나는 단지 3 시간을 일하는 것처럼 보냈습니다. 또한 장치를 재부팅해야 작동했습니다. 대단히 감사합니다
crgarridos

5

아래의 모든 것이 /data"내부 저장소"에 속할 것으로 기대 합니다. 그러나에 쓸 수 있어야합니다 /sdcard.


5
<uses-permission android : name = "android.permission.WRITE_INTERNAL_STORAGE"/> 시도했습니다. 여전히 같은.
Mert

1
/ data-partition은 일반적으로 일반 파일 액세스를 시도하는 일반 (루트가 아닌) 사용자에게 쓰기 방지되어 있습니다. 내부 저장소의 경우 특히 데이터베이스에 액세스하려는 경우 특별한 방법이 있습니다. 이 문제에 대한 Android 개발자 페이지 가 도움이 될 것입니다.
ovenror

5

귀하 /system/etc/permission/platform.xml
와 그룹 의 권한 속성을 아래와 같이 변경 해야합니다.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
    <group android:gid="sdcard_rw" />
    <group android:gid="media_rw" />    
</uses-permission>

platform.xml이 바로 잠겨있어 adb 쉘을 통해이 작업을 시도하지만 ADB가 mod에 사용할 수있는 스크립트가 필요합니다.
John

불합격. 내 장치를 부팅 루프에 넣습니다.
Tobse

5

Galaxy S5 (Android 6.0.1)의 DCIM / camera 폴더에 이미지를 쓰려고 할 때 동일한 오류가 발생 했으며이 폴더 만 제한된다는 것을 알았습니다. DCIM / 폴더에는 쓸 수 있지만 카메라에는 쓸 수 없습니다. 이는 브랜드 기반 제한 / 사용자 정의 여야합니다.


4

응용 프로그램이 시스템 응용 프로그램에 속해 있으면 SD 카드에 액세스 할 수 없습니다.


4

매니페스트에서 올바른 권한을 모두 설정하더라도 외부 카드에 써드 파티 앱에서 쓸 수있는 유일한 장소는 "자신의 디렉토리"(예 : / sdcard / Android / data /)입니다. 다른 곳 : 예외 : EACCES (허가 거부)


3

아마 대답은 이것입니다 :

API> = 23 디바이스에서 앱을 설치하는 경우 (앱이 시스템 앱이 아님) "설정-애플리케이션"에서 저장 권한을 확인해야합니다. 모든 앱에 대한 권한 목록이 있으므로 확인해야합니다! 시험


3

제 경우에는 외부 저장 장치에 대한 경로를 반환 하는 파일 선택기 라이브러리 를 사용하고 있었지만 시작했습니다 /root/. 그리고 런타임에 부여 된 WRITE_EXTERNAL_STORAGE 권한이 있어도 여전히 EACCES (Permission denied) 오류가 발생했습니다 .
따라서 Environment.getExternalStorageDirectory()외부 저장소에 대한 올바른 경로를 얻는 데 사용하십시오.

예 :
쓸 수 없음 : /root/storage/emulated/0/newfile.txt
쓸 수 있음 : /storage/emulated/0/newfile.txt

boolean externalStorageWritable = isExternalStorageWritable();
File file = new File(filePath);
boolean canWrite = file.canWrite();
boolean isFile = file.isFile();
long usableSpace = file.getUsableSpace();

Log.d(TAG, "externalStorageWritable: " + externalStorageWritable);
Log.d(TAG, "filePath: " + filePath);
Log.d(TAG, "canWrite: " + canWrite);
Log.d(TAG, "isFile: " + isFile);
Log.d(TAG, "usableSpace: " + usableSpace);

/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

출력 1 :

externalStorageWritable: true
filePath: /root/storage/emulated/0/newfile.txt
isFile: false
usableSpace: 0

출력 2 :

externalStorageWritable: true
filePath: /storage/emulated/0/newfile.txt
isFile: true
usableSpace: 1331007488

나는 똑같은 문제가있었습니다. root경로 에서 부품을 제거하면 문제가 해결되었습니다.
xabush


3

검색 결과에서 여기에 와서 Android 10을 대상으로하는 사람 : Android 10 (API 29)은 저장소와 관련된 일부 권한을 변경합니다.

이전 인스턴스 Environment.getExternalStorageDirectory()(API 29에서 더 이상 사용되지 않음)를 로 대체하면 문제가 해결 되었습니다 context.getExternalFilesDir(null).

참고 context.getExternalFilesDir(type)저장 위치를 사용할 수없는 경우 외부 권한이 있는지 검사 할 때마다 확인해야하므로, 널 (null)을 반환 할 수 있습니다.

자세한 내용은 여기를 참조 하십시오 .


2

init.rc에서 / data / 아래에 폴더를 만들고 있는데 (Nexus 7의 aosp와 관련이 있습니다) 정확히이 문제가 있습니다.

폴더 rw (666) 권한을 부여하는 것만으로는 충분하지 않았으며 rwx (777) 여야했습니다.


2

다음 adb 명령을 통해 루팅 된 장치가있는 경우 6.0 이후 스토리지 권한 적용을 무시할 수 있습니다.

root@msm8996:/ # getenforce
getenforce
Enforcing
root@msm8996:/ # setenforce 0
setenforce 0
root@msm8996:/ # getenforce
getenforce
Permissive

1

매니페스트에 권한을 추가하십시오.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

3
권한이 없습니다android.permission.READ_INTERNAL_STORAGE
Ryan R

0

나는 같은 문제가 있었다 (API> = 23).

솔루션 https://stackoverflow.com/a/13569364/1729501 이 저에게 효과적이지만 디버깅을 위해 앱의 연결을 끊는 것은 실용적이지 않았습니다.

내 솔루션은 Windows에 적절한 adb 장치 드라이버를 설치하는 것이 었습니다. 기기에서 Google USB 드라이버가 작동하지 않았습니다.

1 단계 : 장치 브랜드에 맞는 adb 드라이버를 다운로드하십시오.

2 단계 : 기기 관리자로 이동-> 다른 기기-> 단어 "adb"가있는 항목 찾기-> 드라이버 업데이트 선택-> 1 단계에서 위치 지정


0

권한을 추가 한 후 내 문제가 해결되었습니다.

<uses-permission android:name="android.permission.INTERNET"/>

0

gradle 의존성 추가

implementation 'com.karumi:dexter:4.2.0'

주요 활동에 아래 코드를 추가하십시오.

import com.karumi.dexter.Dexter;
import com.karumi.dexter.MultiplePermissionsReport;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);

    new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {


                checkMermission();
            }
        }, 4000);
    }

    private void checkMermission(){
        Dexter.withActivity(this)
                .withPermissions(
                        android.Manifest.permission.READ_EXTERNAL_STORAGE,
                        android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        android.Manifest.permission.ACCESS_NETWORK_STATE,
                        Manifest.permission.INTERNET
                ).withListener(new MultiplePermissionsListener() {
            @Override
            public void onPermissionsChecked(MultiplePermissionsReport report) {
                if (report.isAnyPermissionPermanentlyDenied()){
                    checkMermission();
                } else if (report.areAllPermissionsGranted()){
                    // copy some things
                } else {
                    checkMermission();
                }

            }
            @Override
            public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                token.continuePermissionRequest();
            }
        }).check();
    }

0

제 경우에는 오류가 줄에 나타났습니다.

      target.createNewFile();

SD 카드에서 새 파일을 만들 수 없으므로 DocumentFile 접근 방식을 사용해야했습니다.

      documentFile.createFile(mime, target.getName());

위의 질문에 대해이 접근법으로 문제를 해결할 수 있습니다.

    fos=context.getContentResolver().openOutputStream(documentFile.getUri());

이 스레드도 참조하십시오. Android 5.0 (Lollipop) 용으로 제시된 새로운 SD 카드 액세스 API를 사용하는 방법은 무엇입니까?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.