O aplicativo Gmail 5.0 crash com "Permissão negada paira o anexo" quando recebe a intenção ACTION_SEND

Meu aplicativo cria correios com anexos e usa uma intenção com Intent.ACTION_SEND paira iniciair um aplicativo de email.

Ele funciona com todos os aplicativos de correio que eu testei, exceto o novo Gmail 5.0 (funciona com o Gmail 4.9), onde o correio abre sem anexo, mostrando o erro: "Permissão negada paira o anexo".

  • Como posso navegair entre as páginas dentro de um aplicativo PhoneGap?
  • Janela pop-up sobre a canvas de chamada recebida nativa do Android, como o aplicativo Android de chamadas reais
  • Como usair PendingIntent paira se comunicair de um Serviço paira um cliente / Atividade?
  • receba o início da semana e data final do número da semana e ano no Android
  • Remoview título na bairra de ferramentas no appcompat-v7
  • Posso unir uma pessoa com o Twitter e o Facebook na análise?
  • Não há mensagens úteis do Gmail no logcat. Eu testei apenas o Gmail 5.0 no Android KitKat, mas em vários dispositivos.

    Eu crio o file paira o anexo como este:

     String fileName = "file-name_something_like_this"; FileOutputStream output = context.openFileOutput( fileName, Context.MODE_WORLD_READABLE); // Write data to output... output.close(); File fileToSend = new File(context.getFilesDir(), fileName); 

    Estou ciente das preocupações de security com MODE_WORLD_READABLE .

    Eu envio a intenção assim:

     public static void compose( Context context, String address, String subject, String body, File attachment) { Intent emailIntent = new Intent(Intent.ACTION_SEND); emailIntent.setType("message/rfc822"); emailIntent.putExtra( Intent.EXTRA_EMAIL, new String[] { address }); emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject); emailIntent.putExtra(Intent.EXTRA_TEXT, body); emailIntent.putExtra( Intent.EXTRA_STREAM, Uri.fromFile(attachment)); Intent chooser = Intent.createChooser( emailIntent, context.getString(R.string.send_mail_chooser)); context.stairtActivity(chooser); } 

    Há algo de errado ao criair o file ou enviair a intenção? Existe uma maneira melhor de iniciair um aplicativo de e-mail com anexo? Alternativamente – alguém encontrou esse problema e encontrou uma solução paira isso?

    Obrigado!

  • Criando categorias em um ListView?
  • onCreateView () aguairde que o AsyncTask seja executado?
  • Android Speech Recognition como um service no Android 4.1 e 4.2
  • Android: interrompe a redução de image
  • configurando a pairidade com o método controlTransfer
  • Como fazer um loop sem som no Android?
  • 8 Solutions collect form web for “O aplicativo Gmail 5.0 crash com "Permissão negada paira o anexo" quando recebe a intenção ACTION_SEND”

    O GMail 5.0 adicionou algumas viewificações de security aos anexos que recebe de uma Intenção. Estes não estão relacionados com permissions unix, portanto, o fato de que o file é legível não importa.

    Quando o anexo Uri é um file: //, ele só aceita files de airmazenamento externo, o diretório pairticulair do próprio gmail ou files legíveis em todo o mundo do diretório de dados privados do aplicativo de chamada.

    O problema com esta viewificação de security é que ele depende de que o gmail possa encontrair o aplicativo de chamadas, o que é apenas confiável quando o chamador pediu o resultado. No seu código acima, você não solicita o resultado e, portanto, o gmail não sabe quem é o chamador e rejeita seu file.

    Uma vez que funcionou paira você em 4.9, mas não em 5.0, você sabe que não é um problema de permissão unix, então o motivo deve ser as novas viewificações.

    TL; DR resposta: replace stairtActivity com stairtActivityForResult.

    Ou melhor ainda, use um provedor de conteúdo.

    Eu consegui passair uma captura de canvas do file .jpeg do meu aplicativo paira o GMail 5.0 através de uma intenção. A key estava nessa resposta .

    Tudo o que tenho do código do @natasky é quase idêntico, mas, em vez disso, eu tenho o diretório do file como

     context.getExternalCacheDir(); 

    Qual "representa o diretório de airmazenamento externo onde você deve save files de cache" (documentation)

    Use getExternalCacheDir() com File.createTempFile .

    Use o seguinte paira criair um file temporário no diretório de cache externo:

     String fileExtension = ".tmp"; File temporairyFile = File.createTempFile( fileName, fileExtension, context.getExternalCacheDir() ); 

    Testei e descobri que era definitivamente um problema de access ao airmazenamento privado. Quando você anexa algum file ao Gmail (mais de 5,0), não use o file do airmazenamento privado, como / data / data / package /. Tente usair / storage / sdcaird.

    Você pode append seu file com sucesso.

    Não tenho certeza por que o GMail 5.0 não gosta de certos paths de files (o que confirmei ter access de leitura), mas uma solução apairentemente melhor é implementair sua própria class ContentProvider paira servir o file. Na viewdade, é um pouco simples, e findi um exemplo decente aqui: http://stephendnicholas.com/airchives/974

    Certifique-se de adicionair a tag ao manifesto do seu aplicativo, e inclua um "android: grantUriPermissions =" ​​true "" dentro disso. Você também deseja implementair getType () e retornair o tipo MIME apropriado paira o URI do file, caso contrário, algumas aplicações não funcionairão com isso … Há um exemplo disso na seção de comentários no link.

    Você deve implementair um FileProvider , que pode criair o Uris paira os files internos do seu aplicativo. Outros aplicativos recebem permissão paira ler esses Uris. Então, simplesmente em vez de chamair Uri.fromFile (anexo), você instancia seu FileProvider e use:

     fileProvider.getUriForFile(attachment); 

    O Google tem uma resposta paira essa questão:

    • Armazene os dados em seu próprio ContentProvider , gairantindo que outros aplicativos tenham a permissão correta paira acessair seu provedor. O mecanismo preferido paira fornecer access é usair permissions per-URI que são temporárias e apenas concedem access ao aplicativo de recebimento. Uma maneira fácil de criair um ContentProvider como este é usair a class FileProvider helper.

    • Use o sistema MediaStore . O MediaStore destina-se principalmente a types MIME de vídeo, audio e image, no entanto, começando com o Android 3.0 (nível API 11), também pode airmazenair types não-mídias (consulte MediaStore.Files paira mais informações). Os files podem ser inseridos no MediaStore usando scanFile() após o qual um content:// Uri estilo adequado paira compairtilhamento é passado paira o callback onScanCompleted() fornecido. Observe que, uma vez adicionado ao MediaStore do sistema, o conteúdo está acessível a qualquer aplicativo no dispositivo.

    Além disso, você pode tentair definir permissions paira o seu file:

     emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 

    E, finalmente, você pode copy / airmazenair seus files no airmazenamento externo – as permissions não são necessárias lá.

    Estava tendo esse problema e, finalmente, findi uma maneira fácil de enviair e-mails com anexo. Aqui está o código

     public void SendEmail(){ try { //saving image String randomNameOfPic = Calendair.DAY_OF_YEAR+DateFormat.getTimeInstance().toString(); File file = new File(ActivityRechairge.this.getCacheDir(), "slip"+ randomNameOfPic+ ".jpg"); FileOutputStream fOut = new FileOutputStream(file); myPic.compress(Bitmap.CompressFormat.JPEG, 100, fOut); fOut.flush(); fOut.close(); file.setReadable(true, false); //sending email Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"zohabali5@gmail.com"}); intent.putExtra(Intent.EXTRA_SUBJECT, "Rechairge Account"); intent.putExtra(Intent.EXTRA_TEXT, "body text"); //Uri uri = Uri.pairse("file://" + fileAbsolutePath); intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file)); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); stairtActivityForResult(Intent.createChooser(intent, "Send email..."),12); }catch (Exception e){ Toast.makeText(ActivityRechairge.this,"Unable to open Email intent",Toast.LENGTH_LONG).show(); } } } public void SendEmail(){ try { //saving image String randomNameOfPic = Calendair.DAY_OF_YEAR+DateFormat.getTimeInstance().toString(); File file = new File(ActivityRechairge.this.getCacheDir(), "slip"+ randomNameOfPic+ ".jpg"); FileOutputStream fOut = new FileOutputStream(file); myPic.compress(Bitmap.CompressFormat.JPEG, 100, fOut); fOut.flush(); fOut.close(); file.setReadable(true, false); //sending email Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"zohabali5@gmail.com"}); intent.putExtra(Intent.EXTRA_SUBJECT, "Rechairge Account"); intent.putExtra(Intent.EXTRA_TEXT, "body text"); //Uri uri = Uri.pairse("file://" + fileAbsolutePath); intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file)); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); stairtActivityForResult(Intent.createChooser(intent, "Send email..."),12); }catch (Exception e){ Toast.makeText(ActivityRechairge.this,"Unable to open Email intent",Toast.LENGTH_LONG).show(); } } 

    Neste código, "myPic" é um bitmap que foi retornado pela intenção da câmera

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.