Прикрепление файла из безопасного хранилища в Gmail из моего приложения

В моем приложении есть возможность отправить журнал, который хранится в безопасном хранилище приложения. Путь к файлу: «/data/data/com.mycompany.myapp/files/log.zip». Права доступа к файлу были изменены на MODE_WORLD_READABLE, и цель запуска электронной почты:

Intent i = new Intent(Intent.ACTION_SEND);
i.setType("application/zip");
i.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///data/data/com.mycompany.myapp/files/log.zip));
startActivity(Intent.createChooser(i, "Send Error Log"));

Если файл находится на SD-карте, проблем нет. Но когда это надежное хранилище, вложений нет. Я почти уверен, что это не проблема премиссии, потому что он отлично работает со стандартным почтовым клиентом и с приложением TouchDown Exchange. Такая проблема только с Gmail. Это глюк Gmail или я что-то упустил?

Спасибо.


person user496854    schedule 30.04.2011    source источник
comment
Можете ли вы получить поток в файл напрямую и таким образом проверить свою теорию?   -  person MJB    schedule 01.05.2011
comment
Я точно знаю, что поток доступен — другие почтовые приложения могут получить к нему доступ и без проблем прикрепить его.   -  person user496854    schedule 02.05.2011


Ответы (4)


Да, мы можем прикрепить внутренние файлы, хранящиеся в каталоге файлов, к Gmail с помощью FileProvider. Используя FileProvider, мы можем предоставить временный доступ к некоторым внутренним файлам нашего приложения (как указано в filepaths.xml).

В манифесте, как указано в документации Android, добавьте FileProvider:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.package.name.fileprovider"
    android:grantUriPermissions="true"
    android:exported="false">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
</provider>

Теперь в папке res/xml вашего приложения создайте filepaths.xml и добавьте следующий код:

 <paths>
 <files-path path="." name="name" />

Примечание. Это даст доступ к корневому каталогу файлов, если вы хотите предоставить конкретный доступ к какому-либо подкаталогу, например изображениям, во внутренней памяти, укажите путь как «images/»

    <paths>
    <files-path path="images/" name="name" />

В коде:

File file=new File(context.getFilesDir(),"test.txt");

Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND_MULTIPLE);

shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
                                 "Test");

shareIntent.setType("text/plain");

shareIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
                             new String[] {"email-address you want to send the file to"});

Uri uri = FileProvider.getUriForFile(context,"com.package.name.fileprovider",
                                               file);

            ArrayList<Uri> uris = new ArrayList<Uri>();
            uris.add(uri);

            shareIntent .putParcelableArrayListExtra(Intent.EXTRA_STREAM,
                                                    uris);


            try {
               context.startActivity(Intent.createChooser(shareIntent , "Email:").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));                                                      


            }
            catch(ActivityNotFoundException e) {
                Toast.makeText(context,
                               "Sorry No email Application was found",
                               Toast.LENGTH_SHORT).show();
            }
        }

Это сработало для меня. Надеюсь, это поможет :)

person Adarsh Chithran    schedule 28.10.2014

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

person user496854    schedule 02.05.2011
comment
Кто-нибудь нашел другой способ обойти эту проблему? (что, если у них нет и SD-карты?) - person TChadwick; 20.10.2012
comment
@TChadwick взгляните на этот ответ stackoverflow.com/a/18332000/1082344. безопасное хранилище в Gmail, используя класс FileProvider из библиотеки поддержки и вручную предоставляя и отзывая разрешения для моих файлов. - person IsaacCisneros; 28.02.2014
comment
Это неправда. Используя FileProvider, вы можете поделиться через Gmail. - person neteinstein; 23.01.2015

Вложения клиентского приложения Gmail, наконец, теперь работают на устройствах Android 4.0+. я проверил на своих устройствах 4.2 и 4.3, и они работают.

Я проверил на своем moto razr 2.3, что клиент Gmail НЕ работает. использование другого почтового клиента работает нормально, поэтому ваш ответ от 2011 года был правильным.

person David T.    schedule 10.10.2013

AndroidManifest.xml

        <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.cummins.faultadvisor.LogFileShare"
        android:exported="false"
        android:grantUriPermissions="true" >
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/log_file_provider" />
    </provider>

рез/xml/path.xml

     <?xml version="1.0" encoding="utf-8"?>
     <paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="files" path=""/>
    </paths>

ваш файл активности должен иметь следующее намерение:

    Uri log_file_uri = null;
    Uri logcat_file_uri = null;
    String log_filePath = activity.getApplicationContext().getFilesDir().getPath()
    + "/"+ activity.getApplicationContext().getResources().getString(R.string.log_file);
    String logcat_filePath = activity.getApplicationContext().getFilesDir()
    .getPath()+ "/"+ activity.getApplicationContext().getResources().getString(R.string.logcat_file);
    File log_file = new File(log_filePath);File logcat_file = new File(logcat_filePath);
    if (log_file.exists() && logcat_file.exists()) {
    log_file_uri = FileProvider.getUriForFile(
    activity.getApplicationContext(),"com.example.LogFileShare",log_file);
    logcat_file_uri = FileProvider.getUriForFile(
    activity.getApplicationContext(),"com.example.LogFileShare",logcat_file);
person Suyog Gunjal    schedule 07.12.2015