2015-10-06 1 views
29

Я делюсь изображением, и этот код работает правильно для устройств перед Android 6:Android 6: больше не могут делиться файлами?

Intent shareIntent = new Intent(Intent.ACTION_SEND); 
shareIntent.setType("image/*"); 
Uri uri = Uri.fromFile(new File(mFilename)); 
shareIntent.putExtra(Intent.EXTRA_STREAM, uri); 
mContext.startActivity(Intent.createChooser(shareIntent, mChooserTitle)); 

Однако я получаю ошибку тоста «не может прикреплять пустые файлы», когда я пытаюсь поделиться с помощью Android 6 .

Я проверял, что файл существует, и это не нулевая длина.

У кого-нибудь есть решение для этого?

+0

Вы получаете этот «тост» до или после выбора? Если после, какое приложение вы выбрали? Кроме того, где именно указывается «mFilename»? – CommonsWare

+0

После выбора, это происходит с каждым приложением, которое я пробовал. По крайней мере, с Gmail и Hangouts. –

+0

mFilename находится внутри 'getExternalCacheDir()', начиная с '/ storage/emulated/0/Android/data /' –

ответ

22

Одно из ограничений системы разрешений для работы с Android 6.0 заключается в том, что будут проблемы с углами, которые вызывают проблемы. То, с чем вы столкнулись, - это одно: попытка поделиться файлом на внешнем хранилище с приложением, которое не имеет проверок разрешения времени выполнения для этого конкретного пути пользовательского интерфейса.

Я говорю, что это «угловой случай», потому что эта ошибка в принимающем приложении влияет на пользователя, пользователь не мог ранее использовать это приложение и предоставил необходимое разрешение. Либо:

  • Пользователь никогда не использовал это приложение раньше, но он все еще пытается разделить содержание к нему, или

  • Пользователь отменил разрешение через настройки, но не понял, что это нарушило бы этот бит функциональности

Оба эти события с низкой вероятностью.

Вы, как отправитель, есть два основных варианта:

  1. Меняет от использования file://Uri значения, в пользу файл-служа ContentProvider как FileProvider, поэтому разрешение больше не требуется, или

  2. Просто жить с угловой случае

+1

Хорошо, я реализовал FileProvider, и он отлично работает! –

+8

@ DanieleB: FWIW, я написал [сообщение в блоге] (https://commonsware.com/blog/2015/10/07/runtime-permissions-files-action-send.html) об этом. – CommonsWare

33

Я решил ее осущ ementing в FileProvider, как это было предложено @CommonsWare

Сначала необходимо настроить FileProvider:

  • первым, добавьте <provider> в файл манифеста XML

    <provider 
        android:name="android.support.v4.content.FileProvider" 
        android:authorities="com.myfileprovider" 
        android:exported="false" 
        android:grantUriPermissions="true"> 
        <meta-data 
         android:name="android.support.FILE_PROVIDER_PATHS" 
         android:resource="@xml/file_provider_paths" /> 
    </provider> 
    
  • вторых, определить ваш путь к файлу в отдельном файле XML, я назвал его «file_provider_paths.XML "

    <paths xmlns:android="http://schemas.android.com/apk/res/android"> 
        <external-path name="share" path="/" /> 
    </paths> 
    

вы можете найти полное объяснение в этом documentation page

после того, как вы настроили ваш провайдер файла в XML, это код, чтобы разделить файл изображения:

Intent shareIntent = new Intent(Intent.ACTION_SEND); 
shareIntent.setType("image/*"); 
Uri fileUri = FileProvider.getUriForFile(mContext, "com.myfileprovider", new File(mFilename)); 
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 
shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri); 
mContext.startActivity(Intent.createChooser(shareIntent, mChooserTitle)); 
+0

хорошее решение. –

+0

отлично работает на android 6.0 – Soham

+0

perfect thank u ... –

0

Другим способом, который я использовал для решения этой проблемы, было получение URL-адреса URI поставщика контента с использованием MediaScannerConnection сразу после того, как вы написали файл в общий каталог :

 MediaScannerConnection.scanFile(context, new String[] {imageFile.toString()}, yourMimeType, new OnScanCompletedListener() { 
      @Override 
      public void onScanCompleted(String path, Uri uri) { 
       //uri = "content://" style URI that is safe to attach to share intent 
      } 
     }); 

Это может быть более короткое решение для ваших нужд.

2

В качестве альтернативы, вам не нужно иметь ContentProvider/FileProvider. Вы можете просто добавить флаг, который предоставляет разрешение на чтение для общего ресурса uri. В частности, share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); должен сделать трюк.

+0

, предполагая, что приложение уже открыто, то есть. – yrizk