AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Cross-Platform-Entwicklung Einfachen String als Datei speichern und via Intent an eine APP übergeben
Thema durchsuchen
Ansicht
Themen-Optionen

Einfachen String als Datei speichern und via Intent an eine APP übergeben

Ein Thema von fisipjm · begonnen am 15. Jan 2024 · letzter Beitrag vom 17. Jan 2024
Antwort Antwort
fisipjm

Registriert seit: 28. Okt 2013
299 Beiträge
 
#1

Einfachen String als Datei speichern und via Intent an eine APP übergeben

  Alt 15. Jan 2024, 16:57
Hi,

Ich glaub ich stehe heute extrem auf dem Schlauch.
Ich versuche folgendes, aus meiner Sicht einfaches, Vorhaben zu realisieren.

Ich entwickle mit FireMonkey (FMX) eine Android App (eigentlich auch iOS, aber so weit will ich ja noch gar nicht gehen).
In dieser APP habe ich einen einfachen String. In dem String eine kleine HTML Datei.
Das einzige was ich jetzt machen möchte, ist den String zu speichern (von mir aus auch ohne speichern, wüsste aber nicht wie das gehen soll) und die Datei per intent an den Android Öffnen dialog zu übergeben. Aber jedes mal wenn ich eine APP zum öffnen auswähle bekomme ich entweder die Meldung, dass die Datei nicht existiert oder der Zugriff nicht möglich ist.

Ich verwende Delphi 12. Ich entwickle auf Android 14. Ich habe in der Berechtigungsliste die sichere Dateifreigabe aktiviert.
Die Datei provider_paths.xml sieht so aus:

Code:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="internal_private_files" path="."/>
<cache-path name="internal_cache_files" path="."/>
<external-path name="external_public_files" path="."/>
<external-files-path name="external_private_files" path="."/>
<external-cache-path name="external_cache_files" path="."/>
<external-media-path name="external_media_files" path="."/>
</paths>
Mein Code mit dem ich das Versuche sieht so aus

Delphi-Quellcode:
procedure Share;
{$IF DEFINED(ANDROID)}
  procedure OpenHTMLFile(const FilePath: string);
  var
    Intent: JIntent;
    arch: JFile;
    Uri: Jnet_Uri;
  begin
    arch := TJFile.JavaClass.init(StringToJString(FilePath));
    arch.setReadable(true, false);

    if TJBuild_VERSION.JavaClass.SDK_INT >= 24 then
    begin
      Uri := TJcontent_FileProvider.JavaClass.getUriForFile(TAndroidHelper.Context,
        StringToJString(System.Concat(JStringToString(TAndroidHelper.Context.getPackageName), '.fileprovider')), arch);
    end
    else
    begin
      Uri := TJnet_Uri.JavaClass.fromFile(arch);
    end;

    Intent := TJIntent.Create;
    Intent.putExtra(TJIntent.JavaClass.EXTRA_NOT_UNKNOWN_SOURCE, true);
    Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
    Intent.setDataAndType(Uri, StringToJString('text/html'));

    TAndroidHelper.Context.startActivity(Intent);
  end;
{$ENDIF}

var
  Filename: String;
  lHTML: String;
begin
  lHTML:='<HTML><HEAD></HEAD><BODY><h1>Hallo World!</h1></BODY><HTML>'
  Filename := TPath.Combine(TPath.GetPublicPath, 'MyHTML.html');
  TFile.WriteAllText(Filename, lHTML);

{$IF DEFINED(ANDROID)} OpenHTMLFile(Filename); {$ENDIF}
end;
Hat jemand einen hinweis was ich falsch mache?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#2

AW: Einfachen String als Datei speichern und via Intent an eine APP übergeben

  Alt 15. Jan 2024, 17:26
Wie sieht denn TPath.GetPublicPath aus?

War da nicht der Programmname im Pfad mit enthalten, so ala
storage/emulated/0/android/data/com.embarcadero.testapp/

Kann sein, dass die andere App auf dieses Verzeichnis einfach keinen Zugriff hatt.

Versuche doch mal irgendwas von TPath.Shared.....
Oder alternativ den Download-Ordner benutzen.

PS: Es ist bei manchen Pfaden so, dass sie sich rechtemäßig unterschiedlich verhalten, wenn man sie intern hat, oder wenn es eine SD-Karte gibt und sie dann da drauf liegen.
$2B or not $2B

Geändert von himitsu (16. Jan 2024 um 09:44 Uhr)
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.960 Beiträge
 
Delphi 12 Athens
 
#3

AW: Einfachen String als Datei speichern und via Intent an eine APP übergeben

  Alt 16. Jan 2024, 08:19
Wenn man den Download Ordner benutzen will muss man das inzwischen über
"Scoped storage" umsetzen, sonst kann man da seit Android 11 oder so auch
nicht mehr rein schreiben.

Grüße
TurboMagic
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
299 Beiträge
 
#4

AW: Einfachen String als Datei speichern und via Intent an eine APP übergeben

  Alt 16. Jan 2024, 16:44
Wie sieht denn TPath.GetPublicPath aus?

War da nicht der Programmname im Pfad mit enthalten, so ala
storage/emulated/0/android/data/com.embarcadero.testapp/

Kann sein, dass die andere App auf dieses Verzeichnis einfach keinen Zugriff hatt.

Versuche doch mal irgendwas von TPath.Shared.....
Oder alternativ den Download-Ordner benutzen.

PS: Es ist bei manchen Pfaden so, dass sie sich rechtemäßig unterschiedlich verhalten, wenn man sie intern hat, oder wenn es eine SD-Karte gibt und sie dann da drauf liegen.
Also, ich komme endlich zum antworten.
Ich hab es schon mit allem möglichen versucht, SharedDocument, Downloads... geht alles nicht.

Wenn ich mir den Filename ausgeben lasse, dann bekomme ich: /storage/emulated/0/Download/MyHtml.html
Wenn ich mir die URI ausgeben lasse, dann bekomme ich: content://my.app.emba.com.fileprovider/external_public_files/Download/MyHtml.html
Wenn ich die Datei später mit z.B. TotalComander aufrufe, dann öffnet der mir: content://com.ghisler.files/storage/emulated/0/Download/MyHtml.html

Ich verstehs nicht irgendwas mach ich doch falsch
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#5

AW: Einfachen String als Datei speichern und via Intent an eine APP übergeben

  Alt 16. Jan 2024, 17:21
Vermutlich hat der TotalComander die Berechtigung, um auf "fremde" Dateien zugreifen zu dürfen
und deine App hat das halt nicht.

Wie TurboMagic schon anklingen ließ, wird es immer schwerer, bis fast unmöglich, um Dateien zwischen Anwendungen auszutauschen, bzw. Diese gemeinsam nutzen zu können.

* einmal könnte man versuchen z.B. via TCP/IP sich zwischen den Programmen zu unterhalten
* oder ein Intend-Objekt und es absenden -> die andere Anwendung braucht dann einen Filter darauf, um es empfangen zu können
* oder man schreibt die Datei in Google-Drive und lädt sie in der anderen Anwendung wieder runter
* ...
$2B or not $2B
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.960 Beiträge
 
Delphi 12 Athens
 
#6

AW: Einfachen String als Datei speichern und via Intent an eine APP übergeben

  Alt 16. Jan 2024, 18:20
Wie geschrieben: der nötige Suchbegriff ist "scoped storage".
Ich hatte das sogar mal in einer App für meinen Arbeitgeber umgesetzt, allerdings ist die inzwischen
aus anderen Gründen gestorben und wirklich lustig war das aus einem Grund nicht:
Die Android Entwickler sind kurzsichtig oder engstirnig!

Warum? Weil man für scoped storage so einen Datei Laden Intent vom ANdroid aufrufen muss,
was eigentlich ganz ok wäre, wenn man da die Dateifilter auch flexibel angeben könnte und
nicht nur die paar vordefinierten Mimetypes nutzen könnte, für die es keine Erweiterungsmöglichgkeit
zu geben scheint.

Hallo Android Entwickler: nicht alles ist eine Textdatei, ein Bild, Video oder Musik!

=> da blieb mir dann glaube ich nur das Equivalent zu *.*

Grüße
TurboMagic
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
299 Beiträge
 
#7

AW: Einfachen String als Datei speichern und via Intent an eine APP übergeben

  Alt 17. Jan 2024, 09:14
Moin ihr beiden,

schon mal Danke für eure Antworten. Ich glaube aber das Problem liegt in diesem speziellen Fall an einer anderen Stelle.

Wieso denke ich das?
Ich hab ja bereits beschrieben, wie sich die einzelnen URIs verhalten:
Zitat:
Wenn ich mir den Filename ausgeben lasse, dann bekomme ich: /storage/emulated/0/Download/MyHtml.html
Wenn ich mir die URI ausgeben lasse, dann bekomme ich: content://my.app.emba.com.fileprovider/external_public_files/Download/MyHtml.html
Wenn ich die Datei später mit z.B. TotalComander aufrufe, dann öffnet der mir: content://com.ghisler.files/storage/emulated/0/Download/MyHtml.html
Ich denke nicht das es an Zugriffsrechten liegt. Warum?:
Die Datei, wenn ich z.B. SharedDownload angebe, wir auch dort gespeichert. Ich kann dann mit allen Apps, die irgendwie auf das Dateisystem zugreifen dürfen die Datei sehen und auch öffnen. Das hat an der Stelle auch nichts mit dem TotalComander und Zugriffsrechten zu tun. Ich lasse mit mir reden, wenn es darum geht, die Datei anzuzeigen, OK. Also der TotalComander sieht die Datei nur wenn er auf das Verzeichnis Zugriffsrechte hat, gut, geschenkt.
Warum ist das an der Stelle irrelevant?:
Mir geht es nicht um den Zugriff auf die Datei die im SharedDownload liegt, sondern um das Intent, dass an die App übergeben wird um das File zu öffnen. Wenn ich das mit dem TotalComander mache, erhalte ich als URI in der app mit der ich öffnen möchte (was ja auch klappt):
Code:
content://com.ghisler.files/storage/emulated/0/Download/MyHtml.html
Öffne ich das selbe Dokument mit Google Files und Teile es mit einer anderen App erhalte ich:
Code:
content://com.google.android.apps.nbu.files.provider/2/1000000088
Irgendwie fühlt sich das an, als hätte ich irgend ein Problem mit der URI und nicht mit den Rechten.
Hab ich damit recht, oder lieg ich komplett daneben?

Gruß
PJM
  Mit Zitat antworten Zitat
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
1.944 Beiträge
 
Delphi 12 Athens
 
#8

AW: Einfachen String als Datei speichern und via Intent an eine APP übergeben

  Alt 17. Jan 2024, 11:42
Ich benutze das hier um Dateien (Logs der App) mit Gmail "mailto" zu teilen...
Es funktioniert irgendwie nur mit GMail...ich glaube es geht nicht nicht mit whatsapp...
Auf jedenfall
-Baue ich die Fileprovider URL anders zusammen
-Ich setze einen Mime type damit er nicht versucht es zu öffnen...bei dir wäre aber vielleicht 'text/html' angemessen.
-Ich setzte Read permissions
Vielleicht hilft es wenn du mit den 3 sachen bei dir im Projekt etwas spielst....
Ich habe das auch nur durch wildes ausprobieren und raten ans laufen bekommen.

Delphi-Quellcode:
Class procedure TFileProviderService.SendFileToChooser(file_name: string);
{$IFDEF ANDROID}
var
  content,id:String;
  theFile: JFile;
  Intent: JIntent;
  FileURI:JNet_URI;
  ParcelURI:JParcelable;
{$ENDIF}
begin
{$IFDEF ANDROID}

  if System.SysUtils.TOSVersion.Check(7) then
  Begin
    theFile := TJFile.JavaClass.init(StringToJString(file_name));
    FileURI := TAndroidHelper.JFileToJURI(theFile);
    ParcelURI := JParcelable(FileURI);

    Intent := TJIntent.Create;
    Intent.setAction(TJIntent.JavaClass.ACTION_SEND);
    Intent.setDataAndType(fileuri,StringtoJstring('application/*'));
    Intent.PutExtra(TJIntent.JavaClass.EXTRA_STREAM, ParcelURI);
    Intent.SetFlags(TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION);
    //depricated// SharedActivity.startActivity(TJIntent.JavaClass.createChooser(intent, StrToJCharSequence ('Share With')));
    TAndroidHelper.Activity.startActivity(TJIntent.JavaClass.createChooser(intent, StrToJCharSequence ('Share With')));
  End
  else
  Begin
    theFile := TJFile.JavaClass.init(StringToJString(file_name));

    id := JStringToString( TAndroidHelper.Context.getApplicationContext.getPackageName ) + '.fileprovider';
    content := 'content://' + id + '/root' + JStringToString( theFile.getCanonicalPath );

    FileURI := TJnet_Uri.JavaClass.parse(StringtoJString(content));
    ParcelURI := JParcelable(FileURI);

    Intent := TJIntent.Create;
    Intent.setAction(TJIntent.JavaClass.ACTION_SEND);
    Intent.addFlags(TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION);
    Intent.PutExtra(TJIntent.JavaClass.EXTRA_STREAM, ParcelURI);
    Intent.setDataAndType(fileuri,StringtoJstring('application/*'));
    //depricated// SharedActivity.startActivity(TJIntent.JavaClass.createChooser(intent, StrToJCharSequence ('Share With')));
    TAndroidHelper.Activity.startActivity(TJIntent.JavaClass.createChooser(intent, StrToJCharSequence ('Share With')));
  End;
{$ENDIF}
end;
Ist das nicht schön wie einfach und leicht nachvollziehbar es ist eine Datei zu teilen oder ein Dokument zu öffnen?
Andreas
Monads? Wtf are Monads?

Geändert von QuickAndDirty (17. Jan 2024 um 11:48 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:07 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz