How do I create a new folder in the internal storage (?) of Android (I want say, the main folder that has all the subfolders ... Whatsapp, DCIM, pictures, Ringtones, Alarms ..) and create a new .txt
file inside in this folder.
I want to create a .txt
file and I need the user to plug the USB cable into their computer, access the device, enter the folder my application creates, and copy this file to their desktop.
I tried this code to create the file:
procedure TF_start.Button2Click(Sender: TObject);
var
output_text: string;
arquivo: TextFile;
begin
output_text := 'test';
TFile.WriteAllText(TPath.Combine(TPath.GetDocumentsPath, 'test.txt'), 'content');
ReWrite(arquivo);
WriteLn(arquivo, output_text);
CloseFile(arquivo);
end;
But it does not work.
To get the internal storage(?) path, I found this code:
P := '/storage/';
if (FindFirst(P + '*', faAnyFile, Sr) = 0) then
repeat
Memo1.Lines.Add(Sr.Name);
until (FindNext(Sr) <> 0);
FindClose(Sr);
But I can't understand how it works, so I can't even use it.
I also found this link, but I didn't find any function that returns me the "general" directory path I want to create a folder.
The functions System.IOUtils.TPath.GetHomePath()
, and System.IOUtils.TPath.GetDocumentsPath()
do not return me the correct path.
System.SysUtils.GetHomePath()
return -> /data/user/0/com.embarcadero.app/cache
System.IOUtils.TPath.GetDocumentsPath()
return -> /data/com.embarcadero.app-1/lib/arm
@edit
Using the @Remy Lebeau code and this code I managed to get to this point. The problem is that the code to update the directory with the files does nothing
Use System.IOUtils, Androidapi.Helpers, Androidapi.Jni.Media, Androidapi.JNI.JavaTypes, Androidapi.JNI.GraphicsContentViewText;
//Button
procedure TF_start.Button2Click(Sender: TObject);
var
path_file output_text: string;
begin
path_file := TPath.Combine(System.IOUtils.TPath.GetSharedDownloadsPath, 'Folder_app');
output_text := 'test';
if not TDirectory.Exists(path_file) then
TDirectory.CreateDirectory(path_file);
try
TFile.WriteAllText(TPath.Combine(path_file, Nome_Arquivo), Arquivo_saida);
except
ShowMessage('An error occurred while saving the file.');
end;
end;
Another button:
procedure TF_corrida.BTNfinalize_appClick(Sender: TObject);
var
c: Integer;
JMediaScannerCon: Androidapi.Jni.Media.JMediaScannerConnection;
JMediaScannerCon_Client: Androidapi.Jni.Media.JMediaScannerConnection_MediaScannerConnectionClient;
begin
JMediaScannerCon:=TJMediaScannerConnection.JavaClass.init(TAndroidHelper.Context, JMediaScannerCon_Client);
JMediaScannerCon.connect;
c:=0;
while not JMediaScannerCon.isConnected do begin
Sleep(100);
inc(c);
if (c>20) then break;
end;
if (JMediaScannerCon.isConnected) then begin
JMediaScannerCon.scanFile(StringToJString(path_file), nil);
JMediaScannerCon.disconnect;
end;
end;
PS This warning had appeared:
[DCC Warning] u_corrida.pas(682): W1000 Symbol 'SharedActivityContext' is deprecated: 'Use TAndroidHelper.Context'
So I changed the code
Note: I also tried replacing "path_file" with "System.IOUtils.TPath.GetSharedDownloadsPath", but to no avail too
This question has already been answered, the other question (index files and folders) has been moved to: How to index a created file in Android sdcard Delphi
You don't actually want "internal storage", that is private to your app and not even the user can access it (without root access to the device). You want "external storage" instead, so the user (and other apps) can access it.
Per Save files on device storage in Android's documentation:
Internal storage is best when you want to be sure that neither the user nor other apps can access your files.
External storage is the best place for files that don't require access restrictions and for files that you want to share with other apps or allow the user to access with a computer.
Use one of the TPath.GetShared...()
methods to get an "external storage" path, such as TPath.GetSharedDocumentsPath()
. And make sure your app has the WRITE_EXTERNAL_STORAGE
permission enabled.
Also, note that TFile.WriteAllText()
will not create a missing folder (in fact, it will raise an EDirectoryNotFoundException
). You have to create the folder yourself first, such as with TDirectory.CreateDirectory()
or SysUtils.ForceDirectories()
. TPath.Combine()
simply concatenates the input strings together, it does not create the actual folder.
Try this:
procedure TF_start.Button2Click(Sender: TObject);
var
path, output_text: string;
begin
output_text := 'test';
path := TPath.Combine(TPath.GetSharedDocumentsPath, 'myfolder');
if not TDirectory.Exists(path) then
TDirectory.CreateDirectory(path);
TFile.WriteAllText(TPath.Combine(path, 'test.txt'), output_text);
end;