1

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

user3602803
  • 99
  • 5
  • 12
  • 1
    "*To get the internal storage(?) path, I found this code ... But I can't understand how it works, so I can't even use it.*" - it doesn't help you in this situation anyway. All it is doing is enumerating the `/storage/` folder itself displaying the names of files and subfolders in a `TMemo`. – Remy Lebeau Jul 25 '19 at 01:26
  • So far I am studying why ScanFile is not working and so far I have not found an answer. If anyone can help me I would be grateful – user3602803 Jul 30 '19 at 00:33

1 Answers1

5

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;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • This works perfectly for creating the folder and file, but the big problem is that it creates the folder inside the "Documents" folder and this folder is not visible through the USB cable. Ideally create a folder in the same location as the documents folder and not inside it. Is it possible to do this? – user3602803 Jul 25 '19 at 15:16
  • If I can't, that's fine, I was able to create the folder and file I wanted in the "Downloads" folder. When I access by phone I can find the created folder and the file, but when I access by computer I can't find them ... Do you know what may be happening? On my phone it's in "/storage/emulated/0/Downloads/myfolder/test.txt" but if I go to my computer, the Downloads folder is empty – user3602803 Jul 25 '19 at 15:44
  • After 1 day the folder appeared .. Why is it taking so long? – user3602803 Jul 26 '19 at 16:29
  • @user3602803 [Folder added in android not visible via USB](https://stackoverflow.com/questions/13507789/) – Remy Lebeau Jul 26 '19 at 18:07
  • But how can I use "mediaScannerConnection.scanFile" if it's not a Delphi code? In fact, I never understood this relationship of using other codes. Is there any unit I can declare to use it? – user3602803 Jul 26 '19 at 18:23
  • i found this (https://stackoverflow.com/questions/25832698/delphi-android-jmediascannerconnection/26266446) but not work :( – user3602803 Jul 26 '19 at 19:18
  • @user3602803 saying something does not work is not helpful info. You need to be more specific. – Remy Lebeau Jul 26 '19 at 19:20
  • The code that is marked as "resolved", I tried to use it inside a button on my Form. The intention was to start a new scan of the available files, but this simply do not work. What I wanted was to use this "MediaScannerConnection.scanFile(this, new String[] {path.toString()}, null, null);" code line, but I'm trying to "convert" it to delphi – user3602803 Jul 27 '19 at 15:46
  • @user3602803 then you are likely not using it correctly. Please edit your question to include your latest code. – Remy Lebeau Jul 27 '19 at 18:58
  • Since I think I drifted too far from the subject of the main question, I will mark your answer as "Solved," because after all, you really solved the main problem. Already this secondary problem I think fits another issue. I will leave the link in the thread if anyone having this same secondary question can redirect to a specific post. Thanks a lot for the help. – user3602803 Jul 30 '19 at 22:03