Pengecualian 'gagal terbuka: EACCES (Izin ditolak)' di Android

297

Saya mendapatkan

gagal terbuka: EACCES (Permission denied)

di telepon OutputStream myOutput = new FileOutputStream(outFileName);

Saya memeriksa root, dan saya mencoba android.permission.WRITE_EXTERNAL_STORAGE.

Bagaimana saya bisa memperbaiki masalah ini?

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();
}
Mert
sumber
Saya memiliki masalah yang sama pada tablet Android, tetapi situasi saya mungkin unik, jadi saya melaporkan solusi saya di sini dalam komentar. Kesalahan terjadi ketika aplikasi mencoba mengakses direktori / data / data / myapp / foo yang memiliki lebih dari 50 file xml. Aplikasi tidak membersihkan folder karena bug. Setelah beberapa file lama dihapus, kesalahannya hilang. Saya tidak tahu kenapa. Ini bisa menjadi masalah perangkat Android generik.
Hong
Ini menyelesaikan saya: stackoverflow.com/questions/33666071/…
partho

Jawaban:

236

Saya memiliki masalah yang sama ... Itu <uses-permissiondi tempat yang salah. Ini benar:

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

The uses-permissiontag harus luar applicationtag.

pengguna462990
sumber
2
itu adalah bahwa izin penggunaan harus di luar aplikasi
user462990
3
Saya mendapat peringatan: " <uses-permission>tag muncul setelah <application>tag"
mr5
11
PERINGATAN Di android 4.4.4 jangan gunakan parameter android:maxSdkVersion="18". Itu menghasilkan pengecualian ini
guisantogui
1
Izin ini diberlakukan mulai API level 19. Sebelum API level 19, izin ini tidak diberlakukan dan semua aplikasi masih memiliki akses untuk membaca dari penyimpanan eksternal.
Zar E Ahmer
1
saya menggunakan API lvl 15, saya mendapatkan kesalahan saat mencoba untuk memindahkan file ke OTG USB Stick
Ravi Mehta
330

Untuk API 23+ Anda perlu meminta izin baca / tulis meskipun sudah ada dalam manifes Anda.

// 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" />

Untuk dokumentasi resmi tentang meminta izin untuk API 23+, periksa https://developer.android.com/training/permissions/requesting.html

Justin Fiedler
sumber
13
Hanya untuk memperjelas, agar ini berfungsi, aktivitas harus menangani respons permintaan izin aktivitas. Lihat developer.android.com/training/permissions/… untuk lebih jelasnya.
kldavis4
Tautan praktis
Paul Alexander
1
bukankah ini hal yang buruk? sehubungan dengan pengalaman pengguna.
M. Usman Khan
5
Tapi di mana saya menggunakannya? misalnya, jika saya ingin mengambil gambar, apakah saya harus menjalankan verifikasiStoragePermissions sebelum startActivityForResult, atau di onActivityResult? itu benar-benar membingungkan saya.
Kiwi Lee
3
Terima kasih ini menyelesaikan masalah saya. hanya sebuah catatan: jika seseorang tidak dapat menyelesaikan "Manifest.permission" Anda hanya perlu mengimpor "import android.Manifest".
Oubaida AlQuraan
167

Google memiliki fitur baru di Android Q : tampilan berfilter untuk penyimpanan eksternal. Perbaikan cepat untuk itu adalah dengan menambahkan kode ini di file AndroidManifest.xml:

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

Anda dapat membaca lebih lanjut tentang ini di sini: https://developer.android.com/training/data-storage/compatibility

Uriel Frankel
sumber
@ Billy saya perhatikan itu hanya terjadi pada perangkat dengan api 29. Jadi saya mencari perubahan pada penyedia file
Uriel Frankel
Akhirnya ada cloudtestingscreenshotter_lib.aar untuk bekerja dengan baris ini ditambahkan ke manifes androidTest, terima kasih banyak atas penemuan ini.
bko
6
Anda Tuan, menyelamatkan saya banyak waktu. Banyak hal telah menjadi masalah bagi pengembang di Q. Saya pikir jawaban ini harus diposting sebagai pertanyaan terpisah dan layak mendapat lebih banyak upvotes.
sanjeev
Saya ingin membaca lebih lanjut tentang trik sulap hitam kecil yang bagus ini, tetapi sayangnya tautan mengembalikan kesalahan 404 ... Terima kasih
SadSido
ini memberikan peringatan android:requestLegacyExternalStorage="true"ini tidak akan merusak ryt versi yang lebih rendah? @UrielFrankel
Santanu Sur
58

Saya telah mengamati ini sekali ketika menjalankan aplikasi di dalam emulator. Dalam pengaturan emulator, Anda perlu menentukan ukuran penyimpanan eksternal ("Kartu SD") dengan benar. Secara default, bidang "penyimpanan eksternal" kosong, dan itu mungkin berarti tidak ada perangkat seperti itu dan EACCES dilemparkan bahkan jika izin diberikan dalam manifes.

Audrius Meskauskas
sumber
51

Selain semua jawaban, pastikan Anda tidak menggunakan ponsel sebagai penyimpanan USB.

Saya mengalami masalah yang sama pada HTC Sensation pada mode penyimpanan USB yang diaktifkan. Saya masih dapat men-debug / menjalankan aplikasi, tetapi saya tidak dapat menyimpan ke penyimpanan eksternal.

john
sumber
Terima kasih kawan, Meskipun saya telah meminta izin dari pengguna saat runtime. Kesalahan ini terjadi pada emulator.
Sharp Edge
1
Ketika saya menghubungkan perangkat Samsung Galaxy S6 pertama kali memberikan opsi "Izinkan akses ke data perangkat" dengan "DENY" atau "ALLOW" dan juga dari bilah notifikasi saya mendapatkan opsi Gunakan USB untuk 1. MTP 2. PTP 3. MIDI Perangkat 4. Pengisian daya. Yang mana yang harus dipilih?
tes 13h 16
34

Menambahkan android: requestLegacyExternalStorage = "true" ke Android Manifest Hal ini bekerja dengan Android 10 (Q) di SDK 29+
atau Setelah bermigrasi Android X .

 <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
sumber
Wow berfungsi dengan baik, itulah jawaban yang saya cari, bagus, terima kasih @rhaldar, Anda menyelamatkan hari saya
Ayush Katuwal
29

Masalah saya adalah "TargetApi (23)" yang diperlukan jika minSdkVersion Anda di bawah 23.

Jadi, saya minta izin dengan cuplikan berikut

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();
    }
}
Piroxiljin
sumber
28

Solusi untuk Android Q :

<application ...
    android:requestLegacyExternalStorage="true" ... >
mubin986
sumber
Anda telah menyelamatkan hari saya. Izin diberikan tetapi Glide tidak dapat membaca gambar sampai saya mengatur ini.
leegor
Perhatian: Android 11 akan sepenuhnya menghapus akses lawas pada Agustus 2020, jadi lebih baik
perbarui
16

Saya mengalami hal yang sama. Apa yang saya temukan adalah bahwa jika Anda pergi ke Pengaturan -> Manajer Aplikasi -> Aplikasi Anda -> Izin -> Aktifkan Penyimpanan , itu memecahkan masalah.

Atul Kaushik
sumber
1
Saya tidak dapat menemukan bagian ini?
Evan Sevy
13

Ternyata, itu adalah kesalahan bodoh karena ponsel saya masih terhubung ke PC desktop dan tidak menyadarinya.

Jadi saya harus mematikan koneksi USB dan semuanya bekerja dengan baik.

Tobias Reich
sumber
bekerja untuk saya juga. Tapi mengapa itu berhasil? apa bedanya tidak menghubungkan USB ke PC.
user13107
Pertanyaan bagus. Saya tidak pernah menyelidiki ini lebih jauh. Saya kira ada kunci tulis dari sistem saat Anda menghubungkan perangkat (sehingga mungkin meniru perangkat usb di komputer Anda). Mungkin ini untuk menghindari data yang tidak konsisten. Namun tidak yakin.
Tobias Reich
Saya menemukan alasannya di sini stackoverflow.com/questions/7396757/… juga melihat jawaban saya stackoverflow.com/a/43863548/1729501
user13107
13

Saya memiliki masalah yang sama pada Samsung Galaxy Note 3, menjalankan CM 12.1. Masalahnya bagi saya adalah bahwa saya punya

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

dan harus menggunakannya untuk mengambil dan menyimpan foto pengguna. Ketika saya mencoba memuat foto-foto yang sama di ImageLoader saya mendapat (Permission denied)kesalahan. Solusinya adalah menambahkan secara eksplisit

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

karena izin di atas hanya membatasi izin tulis hingga API versi 18, dan dengan itu izin baca.

Kebun binatang
sumber
Tidak membantu saya! Pantas untuk dicoba! Terima kasih.
Sakiboy
9

Selain semua jawaban, jika klien menggunakan Android 6.0, Android menambahkan model izin baru untuk (Marshmallow).

Trik: Jika Anda menargetkan versi 22 atau lebih rendah, aplikasi Anda akan meminta semua izin pada waktu pemasangan seperti pada perangkat yang menjalankan OS di bawah Marshmallow. Jika Anda mencoba emulator maka dari Android 6.0 dan seterusnya Anda perlu secara eksplisit pergi pengaturan-> aplikasi-> YOURAPP -> izin dan ubah izin jika Anda telah memberikannya.

Nourdine Alouane
sumber
2
Luar biasa, saya menghabiskan 2 hari mencoba mencari tahu ini. Setiap kali saya merasa semuanya berjalan lancar di Android, hal seperti ini terjadi.
Jaime Ivan Cervantes
7

Anehnya setelah meletakkan garis miring "/" sebelum file baru saya masalah saya terpecahkan. Saya mengubah ini:

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

untuk ini:

File myFile= new File(Environment.getExternalStorageDirectory() + "/newFile");
Darush
sumber
1
Tidak ada yang aneh di sini. Dengan baris pertama Anda mencoba membuat file di direktori yang sama dengan yang berisi direktori penyimpanan eksternal Anda. yaitu /storage/.../somethingnewfile bukan /storage/.../something/newfile
Stéphane
@ Stéphane Kesalahan itu sendiri aneh jika Anda melihat berbagai jawaban.
Darush
3
Cara yang benar untuk melakukan ini adalah dengan menggunakan File (dir, file) cosntructor
Nick Cardoso
@NickCardoso Anda juga dapat menggunakan File (String pathname). Sepertinya Anda tidak mengerti maksudnya di sini. Pertanyaannya bukan tentang bagaimana menggunakan kelas File. Rentang jawaban di utas ini menunjukkan seberapa menyesatkan kesalahan ini dan berapa banyak cara yang mungkin untuk menyelesaikannya. Dalam kasus saya kesalahannya adalah garis miring yang hilang. Beberapa orang menganggapnya bermanfaat. Tentu Anda bisa menggunakan metode Anda sendiri dalam mengakses file. Silakan dan kirim jawaban Anda. Mungkin memecahkan masalah seseorang.
Darush
Anda tidak mengerti maksudnya. Jika Anda menggunakan konstruktor yang benar, maka retasan Anda tidak diperlukan. Komentar saya telah ditambahkan sehingga dapat membantu setiap pembaca di masa depan yang disesatkan oleh kesalahan Anda. Itu bukan kritik pribadi dan tidak perlu balasan
Nick Cardoso
6

Saya memiliki masalah yang sama dan tidak ada saran yang membantu. Tapi saya menemukan alasan yang menarik untuk itu, pada perangkat fisik, Galaxy Tab .

Ketika penyimpanan USB aktif, izin baca dan tulis penyimpanan eksternal tidak memiliki efek apa pun. Matikan penyimpanan USB, dan dengan izin yang benar, masalah Anda akan terpecahkan.

Hamlet Kraskian
sumber
2
Sial, saya hanya menghabiskan waktu 3 jam untuk bekerja. Adatively, saya harus reboot perangkat dan itu berhasil. Terima kasih banyak
crgarridos
5

Saya harapkan semua yang ada di bawah ini /datamenjadi "penyimpanan internal". Namun, Anda harus bisa menulis /sdcard.

ovenror
sumber
5
Saya mencoba <menggunakan-izin android: name = "android.permission.WRITE_INTERNAL_STORAGE" /> juga. masih sama.
Mert
1
Partisi / data umumnya dilindungi dari penulisan untuk pengguna biasa (non-root) yang mencoba mengakses file biasa. Untuk penyimpanan internal, ada metode khusus untuk melakukannya, terutama jika Anda ingin mengakses database. The Android halaman pengembang akan membantu Anda dalam masalah ini.
ovenror
5

Ubah properti izin di /system/etc/permission/platform.xml
dan grup Anda perlu disebutkan seperti di bawah ini.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
    <group android:gid="sdcard_rw" />
    <group android:gid="media_rw" />    
</uses-permission>
Prabakaran
sumber
platform.xml dikunci, mencoba ini melalui adb shell tetapi perlu skrip apa pun yang akan saya gunakan untuk mod oleh ADB.
John
Gagal. Masukkan perangkat saya ke loop boot.
Tobse
5

Saya memiliki kesalahan yang sama ketika mencoba untuk menulis gambar di folder DCIM / kamera pada Galaxy S5 (android 6.0.1) dan saya tahu bahwa hanya folder ini yang dibatasi. Saya hanya bisa menulis ke DCIM / folder apa pun tetapi tidak di kamera. Ini harus pembatasan / penyesuaian berdasarkan merek.

Mahdi Mehrizi
sumber
4

Ketika aplikasi Anda milik aplikasi sistem, itu tidak dapat mengakses kartu SD.

akan
sumber
4

perlu diingat bahwa meskipun Anda mengatur semua izin yang benar dalam manifes: Satu-satunya tempat aplikasi pihak ketiga diizinkan untuk menulis pada kartu eksternal Anda adalah "direktori mereka sendiri" (yaitu / sdcard / Android / data /) mencoba menulis ke di tempat lain: Anda akan mendapatkan pengecualian: EACCES (Izin ditolak)

Elad
sumber
3

Mungkin jawabannya adalah ini:

pada API> = 23 perangkat, jika Anda menginstal aplikasi (aplikasi bukan aplikasi sistem), Anda harus memeriksa izin penyimpanan di "Pengaturan - aplikasi", ada daftar izin untuk setiap aplikasi, Anda harus memeriksanya! mencoba

Jason Zhu
sumber
3

Dalam kasus saya, saya menggunakan perpustakaan file picker yang mengembalikan path ke penyimpanan eksternal tetapi itu dimulai dari /root/. Dan bahkan dengan izin WRITE_EXTERNAL_STORAGE yang diberikan saat runtime saya masih mendapatkan kesalahan EACCES (Izin ditolak) .
Jadi gunakan Environment.getExternalStorageDirectory()untuk mendapatkan jalur yang benar ke penyimpanan eksternal.

Contoh:
Tidak bisa menulis: /root/storage/emulated/0/newfile.txt
Dapat menulis: /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;
}

Output 1:

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

Output 2:

externalStorageWritable: true
filePath: /storage/emulated/0/newfile.txt
isFile: true
usableSpace: 1331007488
vovahost
sumber
Saya memiliki masalah yang sama persis. Menghapus rootbagian dari jalur menyelesaikan masalah saya.
xabush
3

Bagi siapa pun yang datang ke sini dari hasil pencarian dan menargetkan Android 10: Android 10 (API 29) mengubah beberapa izin yang terkait dengan penyimpanan.

Saya memperbaiki masalah ini ketika saya mengganti contoh sebelumnya Environment.getExternalStorageDirectory()(yang tidak digunakan lagi dengan API 29)context.getExternalFilesDir(null) .

Catat itu context.getExternalFilesDir(type) dapat mengembalikan nol jika lokasi penyimpanan tidak tersedia, jadi pastikan untuk memeriksa setiap kali Anda memeriksa apakah Anda memiliki izin eksternal.

Baca lebih lanjut di sini .

jacoballenwood
sumber
2

Saya membuat folder di bawah / data / di init.rc saya (bercanda dengan aosp pada Nexus 7) dan memiliki masalah ini.

Ternyata memberi izin folder rw (666) tidak cukup dan harus rwx (777) maka semuanya bekerja!

jalur
sumber
2

Posting 6.0 penegakan izin penyimpanan dapat dilewati jika Anda memiliki perangkat yang di-rooting melalui perintah adb ini:

root@msm8996:/ # getenforce
getenforce
Enforcing
root@msm8996:/ # setenforce 0
setenforce 0
root@msm8996:/ # getenforce
getenforce
Permissive
Zakir
sumber
1

Tambahkan Izin dalam manifes.

<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"/>
Harman Khera
sumber
3
Tidak ada izinandroid.permission.READ_INTERNAL_STORAGE
Ryan R
0

Saya memiliki masalah yang sama (API> = 23).

Solusinya https://stackoverflow.com/a/13569364/1729501 bekerja untuk saya, tetapi tidak praktis untuk memutuskan koneksi aplikasi untuk debugging.

solusi saya adalah menginstal driver perangkat adb yang tepat di Windows. Google USB driver tidak berfungsi untuk perangkat saya.

LANGKAH 1: Unduh driver adb untuk merek perangkat Anda.

LANGKAH 2: Buka manajer perangkat -> perangkat lain -> cari entri dengan kata "adb" -> pilih Perbarui driver -> berikan lokasi di langkah 1

pengguna13107
sumber
0

setelah menambahkan izin memecahkan masalah saya

<uses-permission android:name="android.permission.INTERNET"/>
Sai Gopi N
sumber
0

Tambahkan dependensi gradle

implementation 'com.karumi:dexter:4.2.0'

Tambahkan kode di bawah ini dalam aktivitas utama Anda.

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();
    }
ethemsulan
sumber
0

Dalam kasus saya kesalahan muncul di telepon

      target.createNewFile();

karena saya tidak dapat membuat file baru pada kartu sd, jadi saya harus menggunakan pendekatan DocumentFile.

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

Untuk pertanyaan di atas masalah dapat diselesaikan dengan pendekatan ini,

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

Lihat utas ini juga, Bagaimana cara menggunakan API akses kartu SD baru yang disajikan untuk Android 5.0 (Lollipop)?

Tarasantan
sumber