Reputation: 2461
I am working on a Flutter project to syntehsise an string to an audio file. For this reason, I have added flutter_tts
as a dependency and implemented the following method with different approaches in order to check the existence of the generated file:
/// Synthesises the current audio cue into an audio file
static Future<void> synthesiseStringToAudioFile() async {
Future<String> finalPath;
Future<File> finalFile;
Uri uriToFile;
String absolutePath;
bool existsPath;
bool existsManually;
bool exists3;
await flutterTts
.synthesizeToFile("This is my first audio synthesizer in Flutter",
audioFileName)
.then((value) => {
// File has been successfully created
if (value == 1)
{
// Gets the path to the generated audio file
finalPath = pathToFile,
finalPath.then((path) async => {
print('AFile :Path to audio file: $path'),
// Check if exists
existsPath = FileSystemEntity.typeSync(path) != FileSystemEntityType.notFound,
print("AFile : Exists? $existsPath"),
existsManually = await File('/storage/emulated/0/Android/data/mypath/files/temp_audio_cue.wav').exists(), // Requieres async function
print("AFile : Exists2? $existsManually"), // RETURNS TRUE
exists3 = await File(path).exists(),
print("AFile : Exists3? $exists3")
}),
// Gets the generated file
finalFile = localFile,
finalFile.then((file) => {
// Absolute path
absolutePath = file.absolute.path,
print('AFile : AbsolutePath: $absolutePath'),
// Check the URI
uriToFile = file.uri,
print('AFile : URI to audio file: $uriToFile'),
}),
}
else
{print('There was an error during the synthezisation')}
});
}
static void setAudioFileName() {
audioFileName = Platform.isAndroid ? "temp_audio_cue.wav" : "temp_audio_cue.caf";
}
/// Gets the path to the file to be accessed
static Future<String> get pathToFile async {
final path = await localPath;
return '$path/$audioFileName';
}
/// Gets the path to the local directory
static Future<String> get localPath async {
final dir = await getApplicationDocumentsDirectory();
return dir.path;
}
Once the synthesisation is completed, flutterTts.synthesizeToFile()
logs in console the following message:
D/TTS (10335): Successfully created file : /storage/emulated/0/Android/data/mypath/files/temp_audio_cue.wav
so if I check the existence of the file manually (as I do with existManually
) will get a true value, but I am not able to do it trying to get dynamically the path as in the other examples I am trying but the ones I am getting are:
/data/user/0/mypath/app_flutter/temp_audio_cue.wav
so it is missing the beginning
/storage/emulated/0/Android/
I was wondering what is the correct way to get the path to the file (missing)?
Upvotes: 0
Views: 16368
Reputation: 21
I am using filesystem_picker to return absolute paths from storage and then using File('path_string') or Directory('path_string') to get the actual file.
Using manageExternalStorage
permissions allows this work, but keep in mind:
"The Google Play store has a policy that limits usage of MANAGE_EXTERNAL_STORAGE".
This also may not work depending on the SDK you are using and/or conflicts from other packages.
import 'package:filesystem_picker/filesystem_picker.dart';
import 'package:permission_handler/permission_handler.dart';
Directory? rootDir;
late String tempDir;
_getFile(){
await _pickFile();
String path = tempDir;
var file = File(path);
// Do stuff with file
}
// Call this before _pickFile(), ideally inside initState()
Future<void> _prepareStorage() async {
rootDir = Directory('/storage/emulated/0/');
var storageExternal = await Permission.manageExternalStorage.status;
if (storageExternal != PermissionStatus.granted) {
await Permission.manageExternalStorage.request();
}
bool b = storageExternal == PermissionStatus.granted;
//mPrint("STORAGE ACCESS IS : $b");
}
Future<void> _pickFile(BuildContext context) async {
await FilesystemPicker.open(
title: 'Select file',
context: context,
rootDirectory: rootDir!,
fsType: FilesystemType.file,
pickText: 'Select file to add',
folderIconColor: Colors.teal,
requestPermission: () async => await Permission.manageExternalStorage.request().isGranted,
).then((value){
if (value != null){
tempDir = value.toString();
}
else{
tempDir = "";
}
//mPrint(tempDir);
});
}
Add the following to AndroidManifest.xml:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:minSdkVersion="30" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:label="test_flutter"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true"
>
Upvotes: 1
Reputation: 59
you can use path_provider package of flutter
Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
https://pub.dev/packages/path_provider
Upvotes: 0
Reputation: 11
I tried and it worked
import 'package:path_provider/path_provider.dart';
Future<File> getImageFileFromAssets(Asset asset) async {
final byteData = await asset.getByteData();
final tempFile =
File("${(await getTemporaryDirectory()).path}/${asset.name}");
final file = await tempFile.writeAsBytes(
byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes),
);
return file;
}
Upvotes: 0
Reputation: 347
With path_provider in Android save in getExternalStorageDirectory and in iOS save in getApplicationDocumentsDirectory..
Upvotes: 2
Reputation: 680
If you want to get this path : /storage/emulated/0
Use path_provider_ex package, which provides root and app files directory for both "external storage" (internal flash) and SD card (if present), as well as available space for each storage.
Upvotes: 2