Пытаюсь поделиться образом через классический Intent. Я добавил следующие элементы:
file_paths.xml:
<?xml version = "1.0" encoding = "utf-8"?>
<paths>
<files-path name = "my_images" path = "." />
</paths>
Манифест:
<provider
android:name = "android.support.v4.content.FileProvider"
android:authorities = "com.example.android.fileprovider"
android:exported = "false"
android:grantUriPermissions = "true">
<meta-data
android:name = "android.support.FILE_PROVIDER_PATHS"
android:resource = "@xml/file_paths" />
</provider>
И напоследок MainActivity.java:
private void shareFile(String fileName) {
Intent share = new Intent(Intent.ACTION_SEND);
Uri uri = FileProvider.getUriForFile(this, "com.example.android.fileprovider", new File(this.getApplicationInfo().dataDir + "/app_flutter/userphotos", fileName));
share.setData(uri);
share.setType("image/png");
share.putExtra(Intent.EXTRA_STREAM, uri);
share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(share, "Share"));
}
Проблема, с которой я столкнулся, заключается в том, что изображение, которым я пытаюсь поделиться, имеет следующий путь:
/data/user/0/shoedrobe.innovativeproposals.com.shoedrobe/app_flutter/userphotos/receipt20181101094430.jpg
Однако FileProvider пытается получить к нему доступ отсюда:
java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/shoedrobe.innovativeproposals.com.shoedrobe/app_flutter/userphotos/receipt20181101094430.jpg
Для сохранения изображений я использую пакет path_provider, и я сохраняю элементы в
getApplicationDocumentsDirectory(), который в Android является каталогом AppData.
Я не уверен, почему FileProvider решил внезапно перейти с /data/user/0/ в папку /data/data/, поэтому любая помощь или советы по этому поводу были бы очень признательны.
Обновлять:
Я обновил код в соответствии с рекомендациями и заменил Uri в разделе MainActivity.java следующей строкой:
Uri uri = FileProvider.getUriForFile(this, "com.example.android.fileprovider", new File(this.getDir("flutter", Context.MODE_PRIVATE).getPath() + "/app_flutter/userphotos", path));
Тем не менее, проблема все еще сохраняется (то же самое исключение, что файл должен находиться в /data/data/<package>, а не в /data/user/0. Я также попытался добавить дополнительные разрешения в свой AndroidManifest:
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE"/>
но это не сработало. Может ли проблема быть в моем файле file_paths.xml?
Под капотом, getApplicationDocumentsDirectory() Flutter использует getDir() вместо dataDir, который может быть другим.
Из документации Android на getDataDir(), что эквивалентно this.getApplicationInfo().dataDir:
Returns the absolute path to the directory on the filesystem where all private files belonging to this app are stored. Apps should not use this path directly; they should instead use getFilesDir(), getCacheDir(), getDir(String, int), or other storage APIs on this class.
The returned path may change over time if the calling app is moved to an adopted storage device, so only relative paths should be persisted.
Следовательно, для обеспечения согласованности между каталогом, используемым Flutter для сохранения изображений, и каталогом, используемым для получения файлов через FileProvider, строку getUriForFile в MainActivity.java можно изменить следующим образом:
FileProvider.getUriForFile(this, "com.example.android.fileprovider", new File(<your application context>.getDir("flutter", Context.MODE_PRIVATE).getPath() + "/app_flutter/userphotos", fileName));
... заменяя <your application context> переменной, хранящей контекст вашего приложения, если таковой имеется.
Я внес в ответ возможное исправление, которое включает в себя изменение каталога, используемого для получения изображений с вашего существующего dataDir, на Context.getDir(), как в исходном коде Flutter.
Я обновил свой код предложенными изменениями (см. Обновления в публикациях), но проблема сохраняется (с разными путями). Поскольку проблема с путями сохраняется, следует ли мне использовать другой путь для хранения предметов? Или мне, возможно, стоит обновить мой файл file_paths?
В итоге ни одно из предложенных решений не сработало; ни с помощью extenal-path, ни другого решения.
Способ, которым мне удалось в конце концов поделиться файлом, заключался в том, чтобы сначала скопировать его во временный (кеш) каталог (в flutter path_provider это getTemporaryDirectory()) и обновить file_paths.xml следующим образом:
<cache-path name = "image" path = "."/>
и наконец под MainActivity.java:
Uri uri = FileProvider.getUriForFile(this, "com.example.android.fileprovider", new File(this.getCacheDir(), path));
Можно ли будет поделиться необходимыми изменениями кода, чтобы исправить приложение?