2015-01-15 2 views
8

Этот вопрос был опубликован раньше, но не было четкого или принятого ответа и всех решений, которые должны были «работать», не для меня. См. Здесь: Gmail 5.0 app fails with "Permission denied for the attachment" when it receives ACTION_SEND intent«Разрешение отклонено для вложения» (в Gmail 5.0), пытающегося прикрепить файл к намерению электронной почты

У меня есть приложение, которое создает данные в текстовом файле и должно отправлять текстовый файл по электронной почте, автоматически прикрепляя его. Я пробовал много способов подключить это приложение, и, по-видимому, он работает для Gmail 4.9 и ниже, но 5.0 имеет некоторые новые функции разрешения, отключающие его от выполнения того, что я хочу.

Intent i = new Intent(Intent.ACTION_SEND); 

    String to = emailRecipient.getText().toString(); 

    i.setType("message/rfc822"); 
    i.putExtra(Intent.EXTRA_EMAIL, new String[] { to }); 
    i.putExtra(Intent.EXTRA_SUBJECT, "Pebble Accelerometer Data"); 
    i.putExtra(Intent.EXTRA_TEXT, "Attached are files containing accelerometer data captured by SmokeBeat Pebble app."); 
    String[] dataPieces = fileManager.getListOfData(getApplicationContext()); 
    for(int i2 = 0; i2 < dataPieces.length; i2++){ 
     i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(getApplicationContext().getFilesDir() + File.separator + dataPieces[i2]))); 
    } 
    i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(getApplicationContext().getFilesDir() + File.separator + fileManager.getCurrentFileName(getApplicationContext())))); 
    Log.e("file loc", getApplicationContext().getFilesDir() + File.separator + fileManager.getCurrentFileName(getApplicationContext())); 
    try { 
     startActivity(Intent.createChooser(i, "Send Email")); 
    } catch (android.content.ActivityNotFoundException ex) { 
     Toast.makeText(Main.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show(); 
    } 

В datapieces может быть пустым, да, но текущая строка файла ниже цикл всегда надежен и всегда придает то.

Я попытался изменить

Uri.fromFile() 

в

Uri.parse() 

Когда я делаю это, он придает, но Gmail затем падает, и когда я проверяю LogCat это из-за нулевого указателя. Скорее всего, это связано с тем, что Gmail не имеет доступа к файлу и поэтому имеет значение null.

Я также попытался с помощью

getCacheDir() 

вместо

getFilesDir() 

и имеет тот же результат.

Что я здесь делаю неправильно, и как мне его исправить? Некоторый пример кода был бы действительно, действительно удобно, потому что я новичок в разработке Android и объясняю, что мне нужно делать без какого-то отталкивания, вероятно, не поможет.

Большое спасибо.

ответ

6

Хорошо, ребята. Взял перерыв и вернулся, понял это.

Вот как это работает, вы должны иметь права на запись/чтение для внешнего хранения, поэтому добавить эти разрешения манифеста:

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

Затем файл должен быть скопирован из внутренней директории для хранения вашего приложения в внешний каталог приложения. Я рекомендую вам использовать внутреннее хранилище, и вот что я здесь делаю, чтобы вы могли самостоятельно найти SD-карты.

Вот блок кода, который делает магию. Журналы включены, но вы можете удалить их всеми способами.

public void writeToExternal(Context context, String filename){ 
    try { 
     File file = new File(context.getExternalFilesDir(null), filename); //Get file location from external source 
     InputStream is = new FileInputStream(context.getFilesDir() + File.separator + filename); //get file location from internal 
     OutputStream os = new FileOutputStream(file); //Open your OutputStream and pass in the file you want to write to 
     byte[] toWrite = new byte[is.available()]; //Init a byte array for handing data transfer 
     Log.i("Available ", is.available() + ""); 
     int result = is.read(toWrite); //Read the data from the byte array 
     Log.i("Result", result + ""); 
     os.write(toWrite); //Write it to the output stream 
     is.close(); //Close it 
     os.close(); //Close it 
     Log.i("Copying to", "" + context.getExternalFilesDir(null) + File.separator + filename); 
     Log.i("Copying from", context.getFilesDir() + File.separator + filename + ""); 
    } catch (Exception e) { 
     Toast.makeText(context, "File write failed: " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); //if there's an error, make a piece of toast and serve it up 
    } 
} 
+4

Существует огромная разница между вопросом и решением - вопрос заключается в совместном использовании личных файлов приложения (из context.getFiles()), и в ответ он стал из общего хранилища (~ context.getExternalFilesDir()) ... Не то же самое ... – Felix

+0

Есть ли хорошее общее решение для устройств, которые не могут иметь внешнее хранилище? Или это сценарий, даже беспокойство сейчас? – dylansturg

+0

Использование внешнего хранилища для хранения вложения стало плохой практикой с Android API 23 и его новой системой разрешений. Если вы не запрашиваете у пользователя разрешения WRITE_EXTERNAL_STORAGE во время выполнения, он не будет работать. –

1

Обнаружили одно и то же прикрепление. Разрешения в манифесте не имели никакого эффекта, скорее уже не имеют никакого эффекта с API 23. Наконец, решили это следующим образом.

первой необходимости проверять и предоставление разрешений на время выполнения, я это сделал в моей основной деятельности:

public static final int MY_PERMISSIONS_REQUEST_READ_STORAGE=10001; 
private void checkPermission(){ 
    if (this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 
     // Should we show an explanation? 
     if (this.shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) { 
      // Show an explanation to the user asynchronously 
     } else { 
      // No explanation needed, we can request the permission. 
      this.requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 
        MY_PERMISSIONS_REQUEST_READ_STORAGE); 
     } 
    } 
} 

Теперь при отправке, создать файл в общедоступном каталоге (пытались сохранение в мою папку приложения - то же самое проблема отрицания)

public File createFile(){ 
String htmlStr="<!DOCTYPE html>\n<html>\n<body>\n<p>my html file</p></body></html>"; 
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "aimexplorersummary.html"); 
try { 
     FileWriter writer = new FileWriter(file ,false); 
     writer.write(htmlStr); 
     } 
     writer.flush(); 
     writer.close(); 
    } catch (IOException e) { 
    e.printStackTrace(); 
    return null; 
    } 
return file; 
} 

Теперь компоновать отправка намерения и putExtra с URI в файл, который находится в общественном хранилище, пользователь должен предоставить разрешения и не вызывает никаких проблем в настоящее время

public void send(){ 
Intent intentSend = new Intent(android.content.Intent.ACTION_SEND); 
intentSend.setType("text/html"); 
File file = createFile(); 
if(file!=null){ 
    intentSend.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file)); 
} 
startActivity(Intent.createChooser(intentSend, "Send using:")); 
} 
Смежные вопросы