Exceção 'falha ao abrir: EACCES (permissão negada)' no Android

297

estou obtendo

aberto falhou: EACCES (Permission denied)

na linha OutputStream myOutput = new FileOutputStream(outFileName);

Eu verifiquei a raiz e tentei android.permission.WRITE_EXTERNAL_STORAGE.

Como posso resolver este problema?

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
fonte
Eu tive o mesmo problema em um tablet Android, mas minha situação pode ser única, por isso relato minha solução aqui em um comentário. O erro ocorreu quando o aplicativo tentou acessar o diretório / data / data / myapp / foo que tinha mais de 50 arquivos xml. O aplicativo não limpou a pasta devido a um erro. Após a exclusão de alguns arquivos antigos, o erro desapareceu. Eu não sei porque. Pode ser um problema do dispositivo Android genérico.
Hong
Isso me resolveu: stackoverflow.com/questions/33666071/…
partho

Respostas:

236

Eu tive o mesmo problema ... O <uses-permissionestava no lugar errado. Está certo:

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

A uses-permissiontag precisa estar fora da applicationtag.

user462990
fonte
2
é que as necessidades de usos-permissão para estar fora do aplicativo
user462990
3
Recebo um aviso: "a <uses-permission>tag aparece após a <application>tag"
mr5 18/08/14
11
AVISO No Android 4.4.4 não use o parâmetro android:maxSdkVersion="18". Ele estava gerando essa exceção
guisantogui
1
Essa permissão é aplicada a partir do nível 19. da API. Antes do nível 19 da API, essa permissão não é aplicada e todos os aplicativos ainda têm acesso para ler a partir do armazenamento externo.
Zar E Ahmer
1
im usando API lvl 15, im recebendo erro ao tentar mover o arquivo para OTG USB Stick
Ravi Mehta
330

Para a API 23+, você precisa solicitar as permissões de leitura / gravação, mesmo que elas já estejam no seu manifesto.

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

Para documentação oficial sobre como solicitar permissões para a API 23+, consulte https://developer.android.com/training/permissions/requesting.html

Justin Fiedler
fonte
13
Apenas para esclarecer, para que isso funcione, a atividade deve manipular a resposta da solicitação de permissão da atividade. Consulte developer.android.com/training/permissions/… para obter mais detalhes.
precisa
Link útil com explicação e exemplos aqui em inthecheesefactory.com/blog/…
Paul Alexander
1
isso não é uma coisa ruim? com relação à experiência do usuário.
M. Usman Khan
5
Mas onde eu o uso? por exemplo, se eu quiser tirar uma foto, preciso executar confirmStoragePermissions antes de startActivityForResult ou em onActivityResult? isso realmente me confunde.
Kiwi Lee
3
Graças isso resolve meu problema. apenas uma observação: se alguém não conseguir resolver "Manifest.permission", basta importar "import android.Manifest".
Oubaida AlQuraan
167

O Google possui um novo recurso no Android Q : exibição filtrada para armazenamento externo. Uma solução rápida para isso é adicionar esse código no arquivo AndroidManifest.xml:

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

Você pode ler mais sobre isso aqui: https://developer.android.com/training/data-storage/compatibility

Uriel Frankel
fonte
@Billy eu notei é só acontece em dispositivos com api 29. Então eu procurei por mudanças no provedor de arquivos
Uriel Frankel
Finalmente, consegui que o cloudtestingscreenshotter_lib.aar trabalhasse com esta linha adicionada ao manifesto androidTest, muito obrigado por esta descoberta.
BKO
6
Você me salvou muito tempo. Muitas coisas se tornaram um problema para um desenvolvedor no Q. Acho que essa resposta deve ser postada como uma pergunta separada e merece mais votos.
sanjeev 7/01
Eu gostaria de ler mais sobre esse pequeno truque de magia negra, mas infelizmente o link retorna um erro 404 ... Obrigado mesmo assim
SadSido 4/03
está dando um aviso de que android:requestLegacyExternalStorage="true"isso não vai quebrar as versões inferiores ryt? @UrielFrankel
Santanu Sur
58

Eu observei isso uma vez ao executar o aplicativo dentro do emulador. Nas configurações do emulador, você precisa especificar o tamanho do armazenamento externo ("Cartão SD") corretamente. Por padrão, o campo "armazenamento externo" está vazio, e isso provavelmente significa que não existe esse dispositivo e o EACCES é acionado, mesmo que as permissões sejam concedidas no manifesto.

Audrius Meskauskas
fonte
51

Além de todas as respostas, verifique se você não está usando o telefone como armazenamento USB.

Eu estava com o mesmo problema no HTC Sensation no modo de armazenamento USB ativado. Ainda posso depurar / executar o aplicativo, mas não consigo salvar em armazenamento externo.

John
fonte
Obrigado cara, mesmo que eu tenha solicitado permissões do usuário em tempo de execução. Este erro ocorreu no emulador.
Sharp Edge
1
Quando conecto o dispositivo Samsung Galaxy S6, ele primeiro oferece a opção "Permitir acesso aos dados do dispositivo" com "DENY" ou "PERMITIR" e também na barra de notificação. Estou recebendo a opção Usar USB para 1. MTP 2. PTP 3. MIDI Dispositivos 4. Carregamento. Qual escolher?
Testandoh
34

Adicionar android: requestLegacyExternalStorage = "true" para o manifesto Android é ele trabalhou com Android 10 (Q) no SDK 29+
ou Após a migração 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
fonte
Wow funciona perfeitamente, essa foi a resposta que eu estava procurando, ótimo, obrigado @rhaldar, você salvou meu dia
Ayush Katuwal
29

Meu problema foi com "TargetApi (23)", necessário se a sua minSdkVersion for abaixo 23.

Então, eu tenho permissão de solicitação com o seguinte trecho

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
fonte
28

Solução para Android Q :

<application ...
    android:requestLegacyExternalStorage="true" ... >
mubin986
fonte
Você salvou meu dia. A permissão é concedida, mas Glide não pode ler imagens até que eu defina isso.
leegor
Cuidado: o Android 11 removerá completamente o acesso herdado em agosto de 2020, portanto, melhore o acesso ao arquivo para usar o Storage Access Framework (SAF) para seus aplicativos
dimib
16

Estou experimentando o mesmo. O que descobri é que, se você for para Configurações -> Gerenciador de aplicativos -> Seu aplicativo -> Permissões -> Ativar armazenamento , ele resolverá o problema.

Atul Kaushik
fonte
1
Não consigo encontrar esta seção?
Evan Sevy
13

Acabou que foi um erro estúpido, pois eu ainda tinha meu telefone conectado ao PC de mesa e não percebi isso.

Então eu tive que desligar a conexão USB e tudo funcionou bem.

Tobias Reich
fonte
trabalhou para mim também. Mas por que isso funciona? que diferença não conecta USB ao PC faz.
User13107
Boa pergunta. Eu nunca investiguei isso mais. Eu acho que existe um bloqueio de gravação no sistema no momento em que você conecta o dispositivo (para que ele possa emular um dispositivo USB no seu computador). Talvez isso seja para evitar dados inconsistentes. Não tenho certeza.
Tobias Reich
Encontrei o motivo aqui: stackoverflow.com/questions/7396757/… também veja minha resposta stackoverflow.com/a/43863548/1729501
user13107
13

Eu tive o mesmo problema no Samsung Galaxy Note 3, executando o CM 12.1. O problema para mim era que eu tinha

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

e teve que usá-lo para tirar e armazenar fotos do usuário. Quando tentei carregar as mesmas fotos no ImageLoader, recebi o (Permission denied)erro. A solução foi adicionar explicitamente

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

pois a permissão acima limita apenas a permissão de gravação até a API 18 e, com ela, a permissão de leitura.

ZooS
fonte
Não me ajudou! Vale a pena tentar tho! Obrigado.
Sakiboy 5/02
9

Além de todas as respostas, se os clientes estiverem usando o Android 6.0, o Android adicionou um novo modelo de permissão para (Marshmallow).

Truque: se você estiver direcionando a versão 22 ou inferior, seu aplicativo solicitará todas as permissões no momento da instalação, como faria em qualquer dispositivo executando um sistema operacional abaixo do Marshmallow. Se você estiver experimentando o emulador, a partir do Android 6.0 em diante, precisará explicitamente acessar as configurações-> aplicativos-> YOURAPP-> permissões e alterar a permissão, caso tenha dado alguma.

Nourdine Alouane
fonte
2
Inacreditável, passei 2 dias tentando descobrir isso. Sempre que sinto que as coisas estão funcionando sem problemas no Android, algo assim ocorre.
Jaime Ivan Cervantes
7

Estranhamente depois de colocar uma barra "/" antes do meu newFile, meu problema foi resolvido. Eu mudei isso:

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

para isso:

File myFile= new File(Environment.getExternalStorageDirectory() + "/newFile");
Darush
fonte
1
Nada de estranho aqui. Com a primeira linha, você está tentando criar um arquivo no mesmo diretório que contém o diretório de armazenamento externo. /storage/.../somethingnewfile em vez de /storage/.../something/newfile
Stéphane
@ Stéphane O erro em si é estranho se você olhar para a ampla gama de respostas.
Darush
3
A maneira correta de fazer isso é usar o cosntructor Arquivo (dir, arquivo)
Nick Cardoso
@NickCardoso Você também pode usar Arquivo (nome do caminho da String). Parece que você não está entendendo o assunto aqui. A questão não é sobre como usar a classe File. O intervalo de respostas neste tópico mostra como esse erro é enganoso e quantas maneiras possíveis de resolvê-lo. No meu caso, o erro foi a barra ausente. Algumas pessoas acharam útil. Claro que você poderia usar seu próprio método de acessar um arquivo. Vá em frente e poste sua resposta. Pode resolver o problema de alguém.
Darush
Você não está entendendo o ponto. Se você usar o construtor correto, seu hack não será necessário. Meu comentário foi adicionado para ajudar futuros leitores a serem enganados pelo seu erro. Não era uma crítica pessoal e não precisa de uma resposta
Nick Cardoso
6

Eu tive o mesmo problema e nenhuma das sugestões ajudou. Mas eu achei uma razão interessante para isso, em um dispositivo físico, o Galaxy Tab .

Quando o armazenamento USB está ativado, as permissões de leitura e gravação do armazenamento externo não têm efeito. Basta desativar o armazenamento USB e, com as permissões corretas, o problema será resolvido.

Hamlet Kraskian
fonte
2
Droga, eu passei três horas trabalhando. Além disso, tive que reiniciar o dispositivo e funcionou. Muito obrigado
crgarridos
5

Eu esperaria que tudo abaixo /datapertencesse ao "armazenamento interno". Você deve, no entanto, poder escrever para /sdcard.

estufa
fonte
5
Tentei <android de permissão de uso: name = "android.permission.WRITE_INTERNAL_STORAGE" /> também. continua o mesmo.
Mert
1
A partição / data é geralmente protegida contra gravação para usuários comuns (não raiz) que tentam acessar arquivos comuns. Para armazenamento interno, existem métodos especializados para fazer isso, especialmente se você deseja acessar bancos de dados. As páginas de desenvolvedor do Android devem ajudá-lo nessa questão.
ovenror
5

Altere uma propriedade de permissão no seu /system/etc/permission/platform.xml
grupo e que você precisa mencionar como abaixo.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
    <group android:gid="sdcard_rw" />
    <group android:gid="media_rw" />    
</uses-permission>
Prabakaran
fonte
platform.xml está bloqueado, tentando isso através do shell adb, mas precisa de qualquer script que o ADB me permita usar para o mod.
John
Falhou. Coloque meu dispositivo em um loop de inicialização.
Tobse
5

Eu tive o mesmo erro ao tentar escrever uma imagem na pasta DCIM / camera no Galaxy S5 (android 6.0.1) e descobri que apenas essa pasta é restrita. Eu simplesmente poderia escrever em DCIM / qualquer pasta, mas não na câmera. Isso deve ser uma restrição / personalização com base na marca.

Mahdi Mehrizi
fonte
4

Quando seu aplicativo pertence ao aplicativo do sistema, ele não pode acessar o cartão SD.

vai
fonte
4

lembre-se de que, mesmo que você defina todas as permissões corretas no manifesto: o único local em que os aplicativos de terceiros podem gravar no cartão externo são "seus próprios diretórios" (por exemplo, / sdcard / Android / data /) tentando gravar no em qualquer outro lugar: você receberá a exceção: EACCES (permissão negada)

Elad
fonte
3

Talvez a resposta seja esta:

na API> = 23 dispositivos, se você instalar o aplicativo (o aplicativo não é um aplicativo do sistema), verifique a permissão de armazenamento em "Configuração - aplicativos", há uma lista de permissões para cada aplicativo, verifique-a! experimentar

Jason Zhu
fonte
3

No meu caso, eu estava usando uma biblioteca de seletor de arquivos que retornou o caminho para o armazenamento externo, mas começou a partir /root/. E mesmo com a permissão WRITE_EXTERNAL_STORAGE concedida em tempo de execução, ainda recebi o erro EACCES (permissão negada) .
Portanto, use Environment.getExternalStorageDirectory()para obter o caminho correto para o armazenamento externo.

Exemplo:
Não é possível escrever: /root/storage/emulated/0/newfile.txt
Pode escrever: /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;
}

Saída 1:

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

Saída 2:

externalStorageWritable: true
filePath: /storage/emulated/0/newfile.txt
isFile: true
usableSpace: 1331007488
vovahost
fonte
Eu estava tendo o mesmo problema exato. A remoção da rootpeça do caminho resolveu meu problema.
Xbush
3
Environment.getExternalStoragePublicDirectory();

Ao usar esse método descontinuado do Android 29 em diante, você receberá o mesmo erro:

java.io.FileNotFoundException: open failed: EACCES (Permission denied)

Resolução aqui:

getExternalStoragePublicDirectory descontinuado no Android Q

user2965003
fonte
3

Para quem vem aqui dos resultados de pesquisa e está segmentando o Android 10: o Android 10 (API 29) altera algumas permissões relacionadas ao armazenamento.

Corrigi o problema quando substitui minhas instâncias anteriores de Environment.getExternalStorageDirectory()(que foi preterido na API 29) por context.getExternalFilesDir(null).

Observe que context.getExternalFilesDir(type)pode retornar nulo se o local de armazenamento não estiver disponível; verifique isso sempre que estiver verificando se possui permissões externas.

Leia mais aqui .

jacoballenwood
fonte
2

Estou criando uma pasta em / data / no meu init.rc (mexendo com o aosp no Nexus 7) e tive exatamente esse problema.

Descobriu-se que dar permissão à pasta rw (666) não era suficiente e tinha que ser rwx (777), então tudo funcionou!

faixa
fonte
2

A imposição pós-6.0 de permissões de armazenamento pode ser ignorada se você tiver um dispositivo raiz através destes comandos adb:

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

Adicione permissão no manifesto.

<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
fonte
3
Não há permissãoandroid.permission.READ_INTERNAL_STORAGE
Ryan R
0

Eu tive o mesmo problema (API> = 23).

A solução https://stackoverflow.com/a/13569364/1729501 funcionou para mim, mas não era prático desconectar o aplicativo para depuração.

minha solução foi instalar o driver de dispositivo adb adequado no Windows. O driver USB do google não funcionou para o meu dispositivo.

PASSO 1: Faça o download de drivers adb para a marca do seu dispositivo.

PASSO 2: Vá para o gerenciador de dispositivos -> outros dispositivos -> procure entradas com a palavra "adb" -> selecione Atualizar driver -> indique a localização na etapa 1

user13107
fonte
0

depois de adicionar permissão resolveu meu problema

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

Adicionar dependências gradle

implementation 'com.karumi:dexter:4.2.0'

Adicione o código abaixo em sua atividade principal.

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
fonte
0

No meu caso, o erro estava aparecendo na linha

      target.createNewFile();

como não consegui criar um novo arquivo no cartão sd, tive que usar a abordagem DocumentFile.

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

Para a pergunta acima, o problema pode ser resolvido com essa abordagem,

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

Veja também este tópico: Como usar a nova API de acesso ao cartão SD apresentada para o Android 5.0 (Lollipop)?

Tarasantan
fonte