Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Cross-Platform-Entwicklung (https://www.delphipraxis.net/91-cross-platform-entwicklung/)
-   -   Fehler beim Android-FileProvider: Datei wird nicht geöffnet (https://www.delphipraxis.net/200744-fehler-beim-android-fileprovider-datei-wird-nicht-geoeffnet.html)

philipp.hofmann 21. Mai 2019 09:13

Fehler beim Android-FileProvider: Datei wird nicht geöffnet
 
Hi,

ich finde den Fehler nicht, warum ich meine pdf nicht unter Android mit der damit verbundenen Standard-App öffnen kann:

Mit meiner App liefere ich die Datei:
Android/data/com.icTrainer/files/docs/icTrainer.pdf
aus, welche ich auch problemlos über den Dateimanager öffnen kann. Ich möchte die Datei jetzt auch über die App in der damit verbundenen Standard-App öffnen.

Dazu definiere ich in Android\Release\icTrainer\AndroidManifest den FileProvider (ich dokumentiere die ausgelieferten xml-Files nicht die Templates):

Delphi-Quellcode:
    ...
   <provider android:name="android.support.v4.content.FileProvider"
           android:authorities="com.icTrainer.fileprovider"
           android:exported="false"
           android:grantUriPermissions="true">
           <meta-data
             android:name="android.support.FILE_PROVIDER_PATHS"
             android:resource="@xml/fileprovider" />
        </provider>
    </application>
Und diesen definiere ich in Android\Release\icTrainer\res\xml\fileprovider.xml
Delphi-Quellcode:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
  <files-path name="ictresources" path="docs/" />
</paths>
und nun rufe ich es folgendermaßen via Delphi auf:
Delphi-Quellcode:
    var
     fileuri: JNet_Uri;
     Intent: JIntent;
    begin
      fileuri := StrToJURI('content://com.icTrainer.fileprovider/ictresources/icTrainer.pdf');
      Intent := TJIntent.Create;
      Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
      Intent.setDataAndType(fileuri,StringToJString('application/pdf'));
      Intent.setFlags(TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION);
      TAndroidHelper.Activity.StartActivity(Intent);
    end;
Trotzdem zeigt mir z.B. Word den Fehler
"Datei kann nicht geöffnet werden. Versuchen Sie, die Datei auf dem Gerät zu speicheren und sie dann zu öffnen"
an und öffnet das pdf-File nicht.

Wo ist der Fehler? Ich sträubte mich die Datei zuerst in ein öffentliches Verzeichnis zu kopieren, weil dadurch unnötiger Datenmüll entsteht.

Grüße, Philipp

Rollo62 22. Mai 2019 10:35

AW: Fehler beim Android-FileProvider: Datei wird nicht geöffnet
 
Zitat:

Zitat von philipp.hofmann (Beitrag 1432678)

und nun rufe ich es folgendermaßen via Delphi auf:

Delphi-Quellcode:
    var
     fileuri: JNet_Uri;
     Intent: JIntent;
    begin
      //fileuri := StrToJURI('content://com.icTrainer.fileprovider/ictresources/icTrainer.pdf');
      // Versuch es mal statt StrToJURL mit FileToUrl
      // passt nicht 1:1, weil Du kein temp. File hast, aber so funktioniert das bei mir
      LImageFile := TJFile.JavaClass.createTempFile(
                                       StringToJString( 'attachment' + AIndex.ToString ),
                                       StringToJString('.png'),
                                       LOutputDir);
      fileuri := TAndroidHelper.JFileToJURI( LImageFile );


      Intent := TJIntent.Create;
      Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
      Intent.setDataAndType(fileuri,StringToJString('application/pdf'));

      // Und die Permissions setze ich dabei so, mit addFlags
      //Intent.setFlags(TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION);
      Intent.setFlags( TJIntent.JavaClass.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET ); //<-- versuch mal das
      Intent.addFlags( TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION );      // und mit addFlags
      TAndroidHelper.Activity.StartActivity(Intent);
    end;
So funktioniert das sharing bei mir, auch auf Android 9.

Es gab da Änderungeb ich glaube ab API26, schau man in JFileToJURI.

philipp.hofmann 22. Mai 2019 12:35

AW: Fehler beim Android-FileProvider: Datei wird nicht geöffnet
 
Welches Verzeichnis nutzt du für deinen Output? Da du scheinbar in Gänze ohne Fileprovider-Definition arbeitest (sieht zumindest mal danach aus), scheint mir v.a. dies der Punkt bei dir zu sein, der hilft.

Wenn ich es mit TAndroidHelper.JFileToJURI probiere, bekomme ich die Fehlermeldung "Failed to find configured root that contains". Da habe ich also auch noch irgendeinen generellen Fehler/ein generelles Problem.

Mittlerweile hat Erik einen Fehler in PDFium behoben, so dass ich dies wieder benutzen kann.

Rollo62 22. Mai 2019 13:15

AW: Fehler beim Android-FileProvider: Datei wird nicht geöffnet
 
Doch, ich muss die FileProvider Option aktiviert haben (Entitlements Secure File, ...)
Deshalb meinte ich hja das Du mal in den JFileToJURI schaust, da wird das je nach Version umgeschaltet.

Delphi-Quellcode:
  if TOSVersion.Check(7) then
  begin
    LAuthority := Context.getApplicationContext.getPackageName.concat(StringToJString('.fileprovider'));
    Result := TJFileProvider.JavaClass.getUriForFile(Context, LAuthority, AFile);
  end
  else
    Result := TJnet_uri.JavaClass.fromFile(AFile);
Ich habe das aus gefühlten 1000 Quellen zusammengesucht, wo ich des öfteren gefunden hatte
das die Uri-Erstellung kritisch ist.

Ich benutze ein temporäres Verzeichnis, aber damit müsste man auch anders die Uri erzeugen können.
Der provider_path sieht bei mir so aus, und ich meine gelesen zu haben der "." dot bedeutet Root-Zugriff.
Delphi-Quellcode:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="." />
</paths>
Ist denn icTrainer.pdf dein lokales File ?
Dann versuch es doch mal genauso mit dem temp. Verzeichnis.
Delphi-Quellcode:
  LImageFile := TJFile.JavaClass.createTempFile(
                                       StringToJString( 'icTrainer' ),
                                       StringToJString('.pdf'),
                                       LOutputDir);
      fileuri := TAndroidHelper.JFileToJURI( LImageFile );
Speicher vor dem Versenden mache ich hiermit
Delphi-Quellcode:
    AImage.SaveToFile( JStringToString( LImageFile.getAbsolutePath ) );

philipp.hofmann 22. Mai 2019 15:38

AW: Fehler beim Android-FileProvider: Datei wird nicht geöffnet
 
Jetzt habe ich es. Damit man TAndroidHelper.JFileToJURI erfolgreich aufrufen kann, ist auch noch das Setting von Entitlements Secure File relevant. Ich hatte nur die ganzen Einstellungen in den XML-Files vorgenommen und TAndroidHelper.JFileToJURI macht dann tatsächlich etwas anderes als meine vorherige Implementierung, wo das Entitlements keinen Unterschied gemacht hatte.
Super Danke.

philipp.hofmann 22. Mai 2019 15:44

AW: Fehler beim Android-FileProvider: Datei wird nicht geöffnet
 
Der Vollständigkeithalber der angepasste Code:

Delphi-Quellcode:
uses Androidapi.JNI.Support;
...
  var fileuri: JNet_Uri;
    TheFile: JFile;
    Intent: JIntent;
  begin
    theFile := TJFile.JavaClass.init(StringToJString(appPath+'docs'), StringToJString('icTrainer.pdf'));
    fileuri := TAndroidHelper.JFileToJURI(theFile);
    Intent := TJIntent.Create;
    Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
    Intent.setDataAndType(fileuri,StringToJString('application/pdf'));
    Intent.setFlags(TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION);
    TAndroidHelper.Activity.StartActivity(Intent);
  end;
und Project Options - Application - Entitlement-List - Secure File Sharing = true
und die Anpassungen im Manifest-Template und die Datei .\res\xml\fileprovider.xml.

Rollo62 22. Mai 2019 16:10

AW: Fehler beim Android-FileProvider: Datei wird nicht geöffnet
 
Das freut mich, wieder mal ein Rätselspiel gegen den PC gewonnen :-D

Wenn Du Tokyo und nicht 10.3.1 Rio benutzt dann muss man da wirklich Einiges selber machen.
Rio hat das erzeugen der FileProvider schon drin, man muss nur das Android_Manifest.template löschen,
damit es dann einmal neu erzeugt wird, same file_provider.xml.

Das Setzen des Secure File Sharing Flags bleibt natürlich.

QuickAndDirty 18. Dez 2020 15:49

AW: Fehler beim Android-FileProvider: Datei wird nicht geöffnet
 
Zitat:

Zitat von philipp.hofmann (Beitrag 1432877)
Der Vollständigkeithalber der angepasste Code:

Delphi-Quellcode:
    theFile := TJFile.JavaClass.init(StringToJString(appPath+'docs'), StringToJString('icTrainer.pdf'));

Hallo , mal so ne Frage
was steht in appPath
?

philipp.hofmann 18. Dez 2020 17:58

AW: Fehler beim Android-FileProvider: Datei wird nicht geöffnet
 
Für Android steht dort das folgende:
Delphi-Quellcode:
  {$IFDEF ANDROID}
    appPath:=TFileUtils.adjustDir(System.IOUtils.TPath.GetPublicPath());
  {$ELSE}
    appPath:=TFileUtils.adjustDir(ExtractFilePath(ParamStr(0)));
  {$ENDIF}


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:41 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