Reputation: 1059
I'm developing a mobile app using flutter. For that I used downloads-path-provider to get the download directory of the mobile phone. The emulator returns /storage/emulated/0/Download
. Also when I save a file in this directory the file can be visible in the Download folder.
But on a real devices it also returns the same directory path. /storage/emulated/0/Download
Is this correct for the actual devices? Because on actual devices I cannot see the saved file in the Download folder.
Is there any solution to find the downloads directory on a real device?
Upvotes: 20
Views: 88761
Reputation: 2330
just adding to @live-love answer
This code handles iOS normal way using path_provider
package but for android it uses direct Downloads path, also taking the precaution that on some devices it may be Downloads
with an s
bool dirDownloadExists = true;
var directory;
if (Platform.isIOS) {
directory = await getDownloadsDirectory();
} else {
directory = "/storage/emulated/0/Download/";
dirDownloadExists = await Directory(directory).exists();
if(dirDownloadExists){
directory = "/storage/emulated/0/Download/";
}else{
directory = "/storage/emulated/0/Downloads/";
}
}
Upvotes: 5
Reputation: 31
You can use "flutter_file_dialog" to handle the issue. After succesfully saving file into app you can provide the path of file to this package and save it in another folder of phone. You can use the function below; ** fromDest ** is the path of the saved file.
_saveFileToDest(String fromDest) async {
final params =
SaveFileDialogParams(sourceFilePath: fromDest);
final filePath = await FlutterFileDialog.saveFile(params: params);
if (kDebugMode) {
print(filePath);
}
}
Upvotes: 0
Reputation: 1141
This question and answer is deprecated with flutter 3.0+ : try this one
Future<void> _prepareSaveDir() async {
_localPath = (await _findLocalPath())!;
print(_localPath);
final savedDir = Directory(_localPath);
bool hasExisted = await savedDir.exists();
if (!hasExisted) {
savedDir.create();
}
}
Future<String?> _findLocalPath() async {
if (platform == TargetPlatform.android) {
return "/sdcard/download/";
} else {
var directory = await getApplicationDocumentsDirectory();
return directory.path + Platform.pathSeparator + 'Download';
}
}
one method for create or find directory and other one will find path.
Upvotes: 3
Reputation: 2317
add this to manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
then use these 2 packages:
in pubspec add:
permission_handler: ^5.0.1+1
downloads_path_provider: ^0.1.0
then
Future<File> writeFile(Uint8List data, String name) async {
// storage permission ask
var status = await Permission.storage.status;
if (!status.isGranted) {
await Permission.storage.request();
}
// the downloads folder path
Directory tempDir = await DownloadsPathProvider.downloadsDirectory;
String tempPath = tempDir.path;
var filePath = tempPath + '/$name';
//
// the data
var bytes = ByteData.view(data.buffer);
final buffer = bytes.buffer;
// save the data in the path
return File(filePath).writeAsBytes(buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
}
then use the method:
var file = await writeFile(uint8List, 'name');
Upvotes: 9
Reputation: 52494
path_provider will probably undergo some changes soon, there are some open issues:
https://github.com/flutter/flutter/issues/35783
As of right now, the best way to get the download path on an Android device is to use:
/storage/emulated/0/Download/
No (s) needed.
And to get the external dir path in Android:
/storage/emulated/0/
The "emulated" word does not mean it's the emulator path, it's just a naming convention.
Make sure you have permission to write to the file, add this to manifest.xml file, right under <manifest tag:
<manifest package="..." ... >
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
and also request permission at run time.
See https://pub.dev/packages/permission_handler
Upvotes: 33