Erro de permissão de armazenamento no Marshmallow


159

No Lollipop, a funcionalidade de download funciona bem no meu aplicativo, mas quando atualizei para o Marshmallow, meu aplicativo falha e gera esse erro quando tento fazer o download da Internet para o cartão SD:

Neither user  nor current process has android.permission.WRITE_EXTERNAL_STORAGE

Ele reclama dessa linha de código:

DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);

Eu tenho as permissões no manifesto fora do aplicativo:

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

Limpei e reconstruí o projeto, mas ele ainda falha.


Tente isso, pode ser ajuda para: - stackoverflow.com/a/41221852/5488468
Bipin Bharti

Eu preparei uma biblioteca que ajudará a lidar com permissões de tempo de execução facilmente. github.com/nabinbhandari/Android-Permissions
Nabin Bhandari

Respostas:


357

Você deve verificar se o usuário concedeu permissão de armazenamento externo usando:

if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
    Log.v(TAG,"Permission is granted");
    //File write logic here
    return true;
}

Caso contrário, você precisa pedir ao usuário para conceder uma permissão ao seu aplicativo:

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);

É claro que estes são apenas para dispositivos marshmallow, então você precisa verificar se o aplicativo está sendo executado no Marshmallow:

 if (Build.VERSION.SDK_INT >= 23) {
      //do your check here
 }

Certifique-se também de que sua atividade implemente OnRequestPermissionResult

A permissão inteira é assim:

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

Retorno de chamada do resultado da permissão:

@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
    }
}

2
@Houssem feliz em ajudar.!
MetaSnarf 23/06

14
Isso não funciona para a API> = 23, solicitando permissão para Manifest.permission.WRITE_EXTERNAL_STORAGEsempre retorna '-1', ou seja, permissão negada. Verifique a nova documentação, que diz que para a API 19 em diante, você não precisa da WRITE_EXTERNAL_STORAGEpermissão. Como alguns dos comentários acima mencionado, você deve fazer tudo isso com aManifest.permission.READ_EXTERNAL_STORAGE
AmeyaB

3
@VSB: Está em um lugar estranho, mas aqui está: developer.android.com/guide/topics/manifest/…
AmeyaB 18/16

3
@AmeyB Como a documentação disse, para API> = 19, não é necessário declarar a permissão para escrever no armazenamento externo, se o aplicativo usar seu próprio diretório específico no armazenamento externo, retornado por getExternalFilesDir(). Em outros casos, a permissão ainda android.permission.WRITE_EXTERNAL_STORAGEdeve ser declarada da maneira mais manifesta.
VSB

1
Sim, consertou. O problema estava relacionado à biblioteca de aplicativos de hóquei. esta biblioteca substituiu minha permissão de gravação. @MetaSnarf
Selin

38

O sistema de permissões do Android é uma das maiores preocupações de segurança desde o início, pois essas permissões são solicitadas no momento da instalação. Uma vez instalado, o aplicativo poderá acessar todas as coisas concedidas sem que o usuário reconheça o que exatamente o aplicativo faz com a permissão.

O Android 6.0 Marshmallow apresenta uma das maiores alterações no modelo de permissões com a adição de permissões de tempo de execução, um novo modelo de permissão que substitui o modelo de permissões de tempo de instalação existente quando você segmenta a API 23 e o aplicativo está sendo executado em um dispositivo Android 6.0+

A cortesia vai para Solicitar permissões no tempo de execução .

Exemplo

Declare isso como Global

private static final int PERMISSION_REQUEST_CODE = 1;

Adicione isso na sua onCreate()seção

Após setContentView (R.layout.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
    }

Agora adicionando checkPermission () e 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;
    }
}

Para sua informação

onRequestPermissionsResult

Essa interface é o contrato para receber os resultados para solicitações de permissão.


28

Verifique várias permissões no nível da API 23 Etapa 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,
};

Passo 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;
}

Etapa 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;
    }
}

Etapa 4: em onCreate of Activity checkPermissions ();


2
Obrigado. Parece uma resposta promissora para várias permissões. Mas está faltando um pouco em exemplos. Como ele lida never ask againe perde algumas permissões? O usuário recebe algum feedback? Seria bom ver um exemplo real deste ou mais comentários nos seus trechos de código.
Not2qubit

Para lidar com não perguntar novamente cercar o suplemento de permissões se bloco com if (shouldshowpermissionrationale ()) {} ... é verdade se a permissão é necessária e não para sempre rejeitou
me_

Essa deve ser a resposta correta e otimizada.
VikaS GuttE 25/10/19

21

A menos que haja um requisito definido de gravação no armazenamento externo, você sempre pode optar por salvar os arquivos no diretório do aplicativo. No meu caso, tive que salvar arquivos e, depois de desperdiçar 2 a 3 dias, descobri se alterei o caminho de armazenamento de

Environment.getExternalStorageDirectory()

para

getApplicationContext().getFilesDir().getPath() //which returns the internal app files directory path

funciona como charme em todos os dispositivos. Isso ocorre porque para escrever no armazenamento externo, você precisa de permissões extras, mas a escrita no diretório interno do aplicativo é simples.


onde você escreve esse código? Eu não consigo lembrar usando Environment.getExternalStorageDiretory () no meu código
royjavelosa

5

você precisa usar a permissão de tempo de execução no marshmallow https://developer.android.com/training/permissions/requesting.html

você pode verificar as informações do aplicativo -> permissão

é seu aplicativo obter permissão para gravar armazenamento externo ou não


2
na verdade, essa informação do aplicativo de resposta -> permissão resolveu o acidente :), mas aceitei a outra resposta para obter detalhes do que fazer. Eu desejo que eu posso aceitar tanto Thank u muito
Badr

Graças que fixa o navegador cair em um problema de download no emulador Android
sdaffa23fdsf

4

Parece que o usuário recusou a permissão e o aplicativo tenta gravar no disco externo, causando erro.

@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

Verifique https://developer.android.com/training/permissions/requesting.html

Este vídeo lhe dará uma idéia melhor sobre o UX, tratando das permissões de tempo de execução https://www.youtube.com/watch?v=iZqDdvhTZj0


1

Na versão marshmallow, os desenvolvedores precisam solicitar permissões de tempo de execução ao usuário. Deixe-me dar todo o processo para solicitar permissões de tempo de execução.

Eu estou usando referência a partir daqui: permissões de tempo de execução do marshmallow android .

Primeiro, crie um método que verifique se todas as permissões são concedidas ou não

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

Agora, aqui está o código que é executado após o método acima. Substituiremos o onRequestPermissionsResult()método:

 @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.
                        }
                    }
                }
            }
        }

    }

Se o usuário clicar na opção Negar , o showDialogOK()método será usado para mostrar o diálogo

Se o usuário clicar em Negar e também clicar em uma caixa de seleção dizendo "nunca perguntar novamente" , o explain()método será usado para mostrar a caixa de diálogo.

métodos para mostrar diálogos:

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

O trecho de código acima solicita quatro permissões por vez. Você também pode solicitar qualquer número de permissões em qualquer atividade, conforme seus requisitos.


0

Após muita pesquisa, este código funciona para mim:

Verifique se a permissão já possui: Verifique a permissão WRITE_EXTERNAL_STORAGE Permitida ou não?

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

Implementar o método onRequestPermissionsResult Override para verificar se o usuário permite ou nega

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

0

funcionou para mim

 boolean hasPermission = (ContextCompat.checkSelfPermission(AddContactActivity.this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
    if (!hasPermission) {
        ActivityCompat.requestPermissions(AddContactActivity.this,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_WRITE_STORAGE);
    }

   @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode)
    {
        case REQUEST_WRITE_STORAGE: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                //reload my activity with permission granted or use the features what required the permission
            } else
            {
                Toast.makeText(AddContactActivity.this, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
            }
        }
    }

}

0
   Try this



int permission = ContextCompat.checkSelfPermission(MainActivity.this,
                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE);

     if (permission != PackageManager.PERMISSION_GRANTED) {
                Log.i("grant", "Permission to record denied");

                if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                        android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(this);
                    builder.setMessage(getString(R.string.permsg))
                            .setTitle(getString(R.string.permtitle));

                    builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {

                        public void onClick(DialogInterface dialog, int id) {
                            Log.i("grant", "Clicked");
                            makeRequest();
                        }
                    });

                    AlertDialog dialog = builder.create();
                    dialog.show();

                } else {

                    //makeRequest1();
                    makeRequest();
                }
            }


     protected void makeRequest() {
            ActivityCompat.requestPermissions(this,
                    new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    500);
        }



     @Override
        public void onRequestPermissionsResult(int requestCode,
                                               String permissions[], int[] grantResults) {
            switch (requestCode) {
                case 500: {

                    if (grantResults.length == 0
                            || grantResults[0] !=
                            PackageManager.PERMISSION_GRANTED) {

                        Log.i("1", "Permission has been denied by user");

                    } else {

                        Log.i("1", "Permission has been granted by user");

                    }
                    return;
                }

            }
        }

0

Antes de iniciar o download, verifique suas permissões de tempo de execução e, se você não tiver permissão, solicite permissões como este método

requestStoragePermission ()

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

0

De uma maneira simples, a permissão pode ser concedida usando o arquivo manifest.xml, mas foi aprovado até o nível 23 da API 23 sdk versão 6, depois daqui em diante, se quisermos obter a permissão, precisamos solicitar o uso para permitir a permissão que são necessários.

Basta adicionar este código no mainActivity.java

Override
            public void onClick(View view) {
                // Request the permission
                ActivityCompat.requestPermissions(MainActivity.this,
                        new String[]{Manifest.permission.CAMERA},
                        PERMISSION_REQUEST_CAMERA);

Substitua CAMERA ou adicione com WRITE_EXTERNAL_STORAGE, se desejar, e com o código exclusivo.

                            new String[]{Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    101);

Este é o código simples para obter permissão.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.