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.
Я проверил, что файл существует, и он не является нулевой длиной.
У кого-нибудь есть решение для этого?
Ответы
Ответ 1
Одно из ограничений системы разрешений для работы с Android 6.0 заключается в том, что будут проблемы с углами, которые вызывают проблемы. То, с чем вы столкнулись, - это одно: попытка поделиться файлом на внешнем хранилище с приложением, которое не имеет проверок разрешения времени выполнения для этого конкретного пути пользовательского интерфейса.
Я говорю, что это "угловой случай", потому что, поскольку эта ошибка в принимающем приложении влияет на пользователя, пользователь не может ранее использовать это приложение и предоставил необходимое разрешение. Или:
-
Пользователь никогда не использовал это приложение раньше, но все же пытается поделиться им с ним, или
-
Пользователь отменил разрешение с помощью настроек, но не понял, что он сломает этот бит функциональности
Оба из них - события с низкой вероятностью.
Вы, как отправитель, имеете два основных варианта:
-
Отключите использование значений file://
Uri
в пользу файлового обслуживания ContentProvider
, например FileProvider
, поэтому разрешение больше не требуется или
-
Просто живу с угловым футляром
Ответ 2
Я решил это, реализовав 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>
-
second, определите ваши пути к файлам в отдельном файле XML, я назвал его " file_provider_paths.xml"
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="share" path="/" />
</paths>
вы можете найти полное объяснение на этой странице документации
после того, как вы настроили поставщика файлов в 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));
Ответ 3
Кроме того, вам не нужно иметь ContentProvider/FileProvider. Вы можете просто добавить флаг, который предоставляет разрешение на чтение для общего ресурса uri.
В частности, share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
должен сделать трюк.
Ответ 4
Другим способом, который я использовал для решения этой проблемы, было получение 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
}
});
Это может быть более короткое решение для ваших нужд.