Android'de 'açık başarısız oldu: EACCES (İzin reddedildi)'


298

alıyorum

açık başarısız: EACCES (Permission denied)

çizgide OutputStream myOutput = new FileOutputStream(outFileName);

Kökü kontrol ettim ve denedim android.permission.WRITE_EXTERNAL_STORAGE.

Bu sorunu nasıl düzeltebilirim?

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 tablette de aynı sorunu yaşadım, ancak durumum benzersiz olabilir, bu yüzden burada bir yorumda çözümümü bildiriyorum. Hata, uygulama 50'den fazla xml dosyasına sahip olan dizin / veri / veri / myapp / foo'ya erişmeye çalıştığında meydana geldi. Uygulama, bir hata nedeniyle klasörü temizlemedi. Bazı eski dosyalar silindikten sonra hata kayboldu. Sebebini bilmiyorum. Genel Android cihazında bir sorun olabilir.
Hong

Yanıtlar:


236

Aynı sorunu yaşadım ... <uses-permissionYanlış yerdeydim. Bu doğru:

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

uses-permissionEtiketi dışında olması gerekir applicationetiketi.


2
Kullanım izninin uygulamanın dışında olması gerekiyor
user462990

3
Bir uyarı alıyorum: " <uses-permission>tag tag sonra görünür <application>"
mr5

11
UYARI android 4.4.4'te parametreyi kullanmayın android:maxSdkVersion="18". Bu istisnayı
guisantogui

1
Bu izin, API düzey 19'dan başlayarak zorunlu kılınmıştır. API düzey 19'dan önce bu izin zorunlu değildir ve tüm uygulamaların harici depolama biriminden okumaya hala erişimi vardır.
Zar E Ahmer

1
im lvl 15 API kullanarak, im OTG USB Stick dosya taşımak için çalışırken hata alıyorum
Ravi Mehta

330

API 23+ için, bildiriminizde olsalar bile okuma / yazma izinlerini istemeniz gerekir.

// 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+ için izin istemeyle ilgili resmi belgeler için https://developer.android.com/training/permissions/requesting.html adresini ziyaret edin.


13
Bunun açıklığa kavuşturulması için, faaliyetin etkinlik izinleri istek yanıtını işlemesi gerekir. Daha fazla bilgi için developer.android.com/training/permissions/… adresine bakın.
kldavis4

Burada açıklama ve örnekler ile kullanışlı bağlantı inthecheesefactory.com/blog/…
Paul Alexander

1
bu kötü bir şey değil mi? kullanıcı deneyimi açısından.
M. Usman Khan

5
Ama nerede kullanırım? örneğin, bir resim çekmek istersem, startActivityForResult öğesinden önce veya onActivityResult öğesinde verifyStoragePermissions öğesini çalıştırmam gerekir mi? beni gerçekten şaşırtıyor.
Kiwi Lee

3
Teşekkürler bu sorunumu çöz. sadece bir not: Birisi "Manifest.permission" çözemezse, sadece "ithalat android.Manifest" almak gerekir.
Oubaida AlQuraan

170

Google'ın Android Q'da yeni bir özelliği var : harici depolama için filtrelenmiş görünüm. Bunun için hızlı bir düzeltme bu kodu AndroidManifest.xml dosyasına eklemektir:

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

Bununla ilgili daha fazla bilgiyi buradan edinebilirsiniz: https://developer.android.com/training/data-storage/compatibility


@Billy sadece api 29 ile cihazlarda olduğunu fark ettim. Bu yüzden dosya sağlayıcı değişiklikleri aradım
Uriel Frankel

Sonunda androidTest manifestine eklenen bu hatla çalışmak için cloudtestingscreenshotter_lib.aar var, bu bulmak için çok teşekkür ederim.
bko

6
Siz efendim, çok zaman kazandınız. Q'da bir geliştirici için bir çok şey acı çekti. Bence bu cevap ayrı bir soru olarak gönderilmeli ve daha fazla oyu hak ediyor.
sanjeev

Bu güzel küçük kara sihir hakkında daha fazla okumak istiyorum, ama ne yazık ki bağlantı 404 hatası döndürür ... Neyse teşekkürler
SadSido

onun android:requestLegacyExternalStorage="true"bu alışkanlık alt sürüm ryt kırmak bir uyarı veriyor? @UrielFrankel
Santanu Sur

58

Uygulamayı öykünücü içinde çalıştırırken bunu bir kez gözlemledim. Emülatör ayarlarında, harici depolama biriminin boyutunu ("SD Kart") doğru bir şekilde belirtmeniz gerekir. Varsayılan olarak, "harici depolama" alanı boştur ve bu muhtemelen böyle bir aygıtın olmadığı ve manifest'te izinler verildiğinde bile EACCES'in atıldığı anlamına gelir.


51

Tüm yanıtlara ek olarak, telefonunuzu USB depolama birimi olarak kullanmadığınızdan emin olun.

USB depolama modundaki HTC Sensation'da da aynı sorunu yaşıyordum. Yine de uygulamada hata ayıklayabilir / çalıştırabilirim, ancak harici depolama birimine kaydedemiyorum.


Teşekkürler adamım, çalışma zamanında kullanıcıdan izin istesem de. Bu hata emülatörde meydana geldi.
Sharp Edge

1
Samsung Galaxy S6 cihazını bağladığımda, önce "DENY" veya "ALLOW" ile "Cihaz verilerine erişime izin ver" seçeneği sunuyor ve ayrıca bildirim çubuğundan 1 için USB kullan seçeneği alıyorum. MTP 2. PTP 3. MIDI Cihazlar 4. Şarj etme. Hangisini seçmeli?
testsingh

35

Android Manifest'e android: requestLegacyExternalStorage = "true" ekle SDK 29+
veya Android X'i taşıdıktan sonra Android 10 (Q) ile çalıştı .

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

Vay be mükemmel çalışıyor, aradığım cevap buydu, harika, teşekkürler @rhaldar, günümü kurtardın
Ayush Katuwal

29

Benim sorunum minSdkVersion 23 feryat ise gerekli olan "TargetApi (23)" ile oldu.

Bu yüzden, aşağıdaki snippet ile istek iznim var

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 için çözüm :

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

Sen benim günümü kurtardın. İzin verilir, ancak Glide bunu ayarlayana kadar görüntüleri okuyamaz.
19:19

Dikkat: Android 11, Ağustos 2020'de eski erişimi tamamen kaldıracak, bu nedenle uygulamalarınız için Depolama Erişimi Çerçevesi'ni (SAF) kullanmak üzere dosya erişimini daha iyi yükseltin
dimib

16

Ben de aynısını yaşıyorum. Bulduğum şey, Ayarlar -> Uygulama Yöneticisi -> Uygulamanız -> İzinler -> Depolamayı Etkinleştir'e giderseniz sorunu çözmesidir.


1
Bu bölümü bulamıyorum?
Evan Sevy

13

Görünüşe göre, telefonum hala masaüstü PC'ye bağlıyken ve bunu fark etmediğim için aptalca bir hataydı.

Bu yüzden USB bağlantısını kapatmak zorunda kaldım ve her şey yolunda gitti.


benim için de çalıştı. Ama neden çalışıyor? USB'yi PC'ye bağlamayan fark nedir?
user13107

İyi soru. Bunu daha fazla araştırmadım. Cihazı bağladığınız anda sistemden bir yazma kilidi olduğunu tahmin ederim (böylece bilgisayarınızda bir usb cihazını taklit edebilir). Belki bu tutarsız verilerin önüne geçmek içindir. Yine de emin değilim.
Tobias Reich


13

CM 12.1 çalıştıran Samsung Galaxy Note 3'te de aynı sorunu yaşadım. Benim için sorun vardı

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

ve kullanıcı fotoğrafları çekmek ve saklamak için kullanmak zorundaydı. ImageLoader aynı fotoğrafları yüklemeye çalıştığımda (Permission denied)hatayı aldım . Çözüm açıkça eklemekti

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

çünkü yukarıdaki izin, yazma iznini yalnızca API sürüm 18'e ve onunla birlikte okuma iznine sınırlar.


Bana yardım etmedi! Denemeye değer tho! Teşekkürler.
Sakiboy

9

Tüm yanıtlara ek olarak, istemciler Android 6.0 kullanıyorsa, Android (Marshmallow) için yeni izin modeli ekledi .

Hile: Sürüm 22 veya daha düşük bir sürümünü hedefliyorsanız, uygulamanız, Marshmallow'un altında işletim sistemi çalıştıran herhangi bir cihazda olduğu gibi yükleme sırasında tüm izinleri isteyecektir. Emülatör üzerinde çalışıyorsanız o zaman android 6.0'dan itibaren ayarlar-> uygulamalar-> YOURAPP -> izinlerine gitmeniz ve varsa izinleri değiştirmeniz gerekir.


2
İnanılmaz, bunu anlamaya çalışırken 2 gün geçirdim. Android'de her şeyin yolunda gittiğini hissettiğimde, böyle bir şey olur.
Jaime Ivan Cervantes

7

Garip bir şekilde "/" eğik çizgi koymak benim newFile önce sorunum çözüldü. Bunu değiştirdim:

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

buna:

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

1
Burada tuhaf bir şey yok. İlk satırla, harici depolama dizininizi içeren dizinde aynı dizinde bir dosya oluşturmaya çalışıyorsunuz. /storage/.../something/newfile yerine /storage/.../somethingnewfile
Stéphane

@ Stéphane Çok çeşitli yanıtlara bakarsanız hatanın kendisi tuhaftır.
Darush

3
Bunu yapmanın doğru yolu File (dir, file) cosntructor'ı kullanmaktır
Nick Cardoso

@NickCardoso Dosya (Dize yolu adı) da kullanabilirsiniz. Burada konuya değinmiyormuşsunuz gibi görünüyor. Soru File sınıfının nasıl kullanılacağı ile ilgili değildir. Bu iş parçacığındaki yanıt aralığı, bu hatanın ne kadar yanıltıcı olduğunu ve çözümün kaç olası yolunu gösterir. Benim durumumda hata eksik eğik çizgi oldu. Bazı insanlar bunu faydalı buldu. Bir dosyaya erişmek için kendi yönteminizi kullanabilirsiniz. Devam et ve cevabını gönder. Birinin sorununu çözebilir.
Darush

Sen anlamýyorsun. Doğru yapıcıyı kullanırsanız, hackiniz gerekli değildir. Benim yorumum eklendi, böylece gelecekteki okuyucuların hatanız tarafından yanıltılmasına yardımcı olabilir. Kişisel bir eleştiri değildi ve bir cevaba gerek yoktu
Nick Cardoso

6

Aynı sorunu yaşadım ve hiçbir öneri yardımcı olmadı. Ama bunun için ilginç bir neden buldum, fiziksel bir cihazda Galaxy Tab .

USB depolama birimi açıkken, harici depolama okuma ve yazma izinlerinin bir etkisi yoktur. USB depolama birimini kapatmanız yeterlidir ve doğru izinlerle sorunu çözersiniz.


2
Kahretsin, sadece 3 saat çalışıyordum. Buna ek olarak, cihazı yeniden başlatmak zorunda kaldım ve işe yaradı. Çok teşekkür ederim
crgarridos

5

Aşağıdaki her şeyin /data"dahili depolamaya" ait olmasını beklerdim . Ancak, yazabilmeniz gerekir /sdcard.


5
<Kullanımlar-izin android: isim = "android.permission.WRITE_INTERNAL_STORAGE" /> da denedim. hala aynı.
Mert

1
/ Data-bölümü genellikle sıradan dosya erişimi yapmaya çalışan sıradan (root olmayan) kullanıcılara yazma korumalıdır. Dahili depolama için, özellikle veritabanlarına erişmek istiyorsanız bunu yapmak için özel yöntemler vardır. Android geliştirici sayfaları bu konuda size yardımcı olacaktır.
Ocak'ta

5

Sizin /system/etc/permission/platform.xml
ve grubunuzun ihtiyacı olan bir izin özelliğini aşağıdaki gibi belirtin.

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

platform.xml, adb kabuğu aracılığıyla denenir, ancak ADB mod için kullanmama izin verecek herhangi bir komut dosyasına ihtiyaç duyar.
John

Başarısız. Cihazımı bir önyükleme döngüsüne koy.
Aralık'ta Tobse

5

Galaxy S5'teki (android 6.0.1) DCIM / kamera klasörüne bir resim yazmaya çalışırken aynı hatayla karşılaştım ve sadece bu klasörün kısıtlandığını anladım. Sadece DCIM / herhangi bir klasöre yazabilirim ama kamerada yazamadım. Bu marka temelli kısıtlama / özelleştirme olmalıdır.


4

Uygulamanız sistem uygulamasına ait olduğunda, SD karta erişemez.


4

manifest'te tüm doğru izinleri ayarlasanız bile: 3. taraf uygulamaların harici kartınıza yazmasına izin verilen tek yer "kendi dizinleri" dir (yani / sdcard / Android / data /) başka bir yerde: istisna alacaksınız: EACCES (İzin reddedildi)


3

Belki de cevap şudur:

API> = 23 cihazda, uygulama yüklerseniz (uygulama sistem uygulaması değilse) "Ayar - uygulamalar" bölümündeki depolama iznini kontrol etmelisiniz, her uygulama için izin listesi vardır, kontrol etmelisiniz! Deneyin


3

Benim durumumda , harici depolamanın yolunu döndüren bir dosya seçici kitaplığı kullanıyordum , ancak başladı /root/. Ve çalışma zamanında verilen WRITE_EXTERNAL_STORAGE izni ile bile hala EACCES hatası aldım (İzin reddedildi) . Harici depolama için doğru yolu almak için
kullanın Environment.getExternalStorageDirectory().

Örnek:
Yazamaz: /root/storage/emulated/0/newfile.txt
Yazabilir: /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;
}

Çıkış 1:

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

Çıkış 2:

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

Aynı problemi yaşıyordum. Parçayı rootyoldan kaldırmak sorunumu çözdü.
xabush


3

Arama sonuçlarından buraya gelen ve Android 10'u hedefleyen herkes için: Android 10 (API 29), depolama ile ilgili bazı izinleri değiştirir.

Önceki örneklerini Environment.getExternalStorageDirectory()(API 29 ile kullanımdan kaldırıldı) ile değiştirdiğimde sorunu çözdüm context.getExternalFilesDir(null).

context.getExternalFilesDir(type)Depolama konumu kullanılamıyorsa null değeri döndürülebileceğini unutmayın , bu nedenle harici izinlerinizin olup olmadığını kontrol ettiğinizde emin olun.

Daha fazlasını buradan okuyun .


2

/ İnit.rc altında (Nexus 7 aosp ile mucking) / data / altında bir klasör oluşturuyorum ve tam olarak bu sorun vardı.

Klasöre rw (666) izni vermenin yeterli olmadığı ve rwx (777) olması gerektiği ortaya çıktı!


2

Şu adb komutları aracılığıyla köklü bir cihazınız varsa, depolama sonrası izinlerin 6.0 sonrası uygulaması atlanabilir:

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

1

Manifest'te İzin Ekle.

<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
İzin yokandroid.permission.READ_INTERNAL_STORAGE
Ryan R

0

Aynı sorunu yaşadım (API> = 23).

Çözüm https://stackoverflow.com/a/13569364/1729501 benim için çalıştı, ancak hata ayıklama için uygulamanın bağlantısını kesmek pratik değildi.

benim çözüm Windows uygun adb aygıt sürücüsü yüklemek oldu. Google USB sürücüsü cihazım için çalışmadı.

ADIM 1: Cihaz markanız için adb sürücülerini indirin.

ADIM 2: Cihaz yöneticisine gidin -> diğer cihazlar -> "adb" kelimesi ile girişleri arayın -> Sürücüyü güncelle -> 1. adımda yer verin


0

izin ekledikten sonra sorunumu çözdüm

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

0

Sınıf bağımlılıkları ekleme

implementation 'com.karumi:dexter:4.2.0'

Ana etkinliğinize aşağıdaki kodu ekleyin.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.