Beiträge von Tecwan

    Hallo allerseits,


    ich möchte von meiner App ein paar POST-Daten an einen Server schicken.
    Die Daten bestehen aus ein paar Parametern und einem ByteArray, das einen beliebigen Inhalt haben kann.
    Der Inhalt des ByteArrays ist beispielsweise eine Bitmap.
    Diese soll auf dem Server unter dem angegebenen Namen new_fn gespeichert werden.


    Ich bekomme das allerdings nicht hin.


    Was funktioniert:
    Aufbau einer Verbindung und Übertragung der POST-Parameter an den Server; diese werden korrekt empfangen, der Server quittiert den Empfang auch mit einem ResponseCode 200.


    Was nicht funktioniert:
    Der Server schreibt kein File; ich nehme an, es werden auch keine Daten empfangen; jedenfalls gibt im PHP-Code eine Abfrage beispielsweise von $_FILES['file']['type'] keine Ausgabe - es sollte mime=image/png sein.


    Der PHP-Code zum Speichern des Files lautet

    Code
    move_uploaded_file($_FILES['filename']['tmp_name'], 'uploadFolder/' . $_POST['fn'])

    Der zugehörige Java-Code wirft keine Fehler; SERVERURL stimmt, "magic" und "fn"(= String new_fn, der Filename) kommen beim Server an, mime ist korrekt, und ByteArrayOutputStream outStream sind ca. 100 kB (im Test eine Bitmap im PNG-Format).


    Falls jemanden interessiert, woher ich die Angaben zur Übertragung habe: https://www.w3.org/TR/html401/…ct/forms.html#h-17.13.4.2 (ganz unten).


    Ich vermute, dass die Übergabe aus dem outStream nicht funktioniert, weiß aber nicht, wie die Zeile stattdessen lauten muss.
    Jemand eine Idee?

    Teste mal


    File myFile = new File(uri.getPath());
    String myPath = myFile.getAbsolutePath();
    String myDateiName = myFile.getAbsoluteFile();

    Erzeugt man aus dem SAF-uri ein File und liest deren diverse path-Informationen aus (getAbsolutePath oder getAbsoluteFile, ebenso die canonical Variante), erhält man ebenfalls nur Verweise vom Typ "image:60".


    Das SAF weigert sich beharrlich, seine Rolle als Vermittler zwischen Provider und Client aufzugeben.
    Da haben die API-Konstrukteure zwar m.M.n.etwas zu kurz gedacht, aber so ist Android eben.



    Hier mit müssten alle Datein zur auswahl stehen


    Das funktioniert ebenfalls nicht, da der ContentResolver nur Dokumente liefern kann, für die die vorhandenen Apps "ihre" Mime-Typen angemeldet haben.
    Unbekannte Dokumente tauchen daher gar nicht erst auf.


    Damit wird das Ganze für mich aber unbrauchbar, da die Dokumente nicht zwangsläufig auch auf dem Gerät geöffnet werden müssen.



    Fazit:
    Für begrenzte Zwecke - Auswahl nur einzelner Dokument-Typen - ist das SAF ganz praktisch, aber für meinen Zweck zu beschränkt.
    Mein eigener File-Dialog nimmt langsam Gestalt an, auch wenn das neue constrait Layout neue Fallstricke bereit hält. Aber das ist ein anderes Thema.



    Vielen Dank nochmal.

    @jogimuc Danke für die Antwort.
    Die Eingabe mehrerer Mime-Types auf einmal kannte ich schon.



    Den Mime-Type über den ContentResolver zu erhalten, ist auf jeden Fall ein nützliches Mosaiksteinchen.
    Schade nur, dass man mit dem SAF nicht den ursprünglichen Filenamen erhält (sondern nur z.B. "image:60).
    In meinem Fall spielt das für Bilder zwar keine Rolle, da diese beim Upload ohnehin neu vergeben werden, aber beim Upload von Dokumenten mit ihren aussagekräftigen Filenamen sieht das anders aus.



    Ansonsten hier der Code zur Nutzung des SAF, der streng genommen ja kein Datei-Auswahldialog ist, sondern zu einem Dokument die App öffnen soll.


    Aufruf des Auswahldialogs (context ist der Context der Activity, FILE_OPEN_REQUEST_CODE eine beliebig gewählte int):

    Code
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("*/*");
    String[] mimetypes = {"image/*", "video/*", "audio/*", "text/*", "application/pdf"};
    intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
    startActivityForResult(intent,FILE_OPEN_REQUEST_CODE);


    und die Behandlung des Ergebnisses:


    Ich denke, ich werde dennoch einen eigenen File-Dialog schreiben,
    - da ich somit die Möglichkeit habe, potenziell ALLE Files zur Auswahl anbieten zu können (also nicht nur die mit mime-Types, die auf dem Android-Gerät bereits bekannt sind),
    - weil ich vor allem auch die Original-Filenamen erhalte,
    - und weil ich so natürlich auch noch das Design anpassen kann.



    Vielleicht kennt jemand jemand einen Weg, aus einem über das SAF erhaltenem Uri doch noch den Original-Namen zu erhalten und postet diesen hier?
    Ich könnte mir auch vorstellen, dass dem API eine entsprechende Methode in Zukunft hinzugefügt wird.

    Hallo,
    ich schreibe an einer kleinen Messager App (API 24+), bei der u.a. Fotos und Dokumente auf einen Server geladen werden.
    Die Fotos werden zuvor verkleinert.
    In der bisherigen Testphase habe ich einen file chooser verwendet, mit dem ich durch das Dateisystem browse und als Ergebnis ein File mit einem Pfad wie z.B. "/mnt/sdcard/picturexy.jpg" erhalten habe.
    Da die typische Auswahl eines (von vielen) Fotos nur anhand des Names ohne Vorschau unpraktisch ist, möchte ich den file chooser ersetzen.

    Daher lag der Rückgriff auf das Bordmittel Storage Access Framework (SAF) nahe.
    Ich lasse also das File nach Vorgabe verschiedener Mime-Typen per Intent.ACTION_OPEN_DOCUMENT auswählen und erhalte einen Uri zurück.
    Und da beginnen meine Probleme.


    Meine App erwartet die Übergabe eines Files
    file = new File(uri.getPath())
    aus dem die Extension
    String extension = MimeTypeMap.getFileExtensionFromUrl(file.getName())
    und der MimeType
    String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
    bestimmt werden.
    Je nach Extension wird das File dann skaliert (wenn es ein Image ist) oder gleich auf den Server hochgeladen.
    Spätestens beim Upload wird zudem der MediaType (erhalten aus dem dem Mime-Type) benötigt.


    Aber: Das SAF liefert nicht diese Art von uri, sondern einen Pfad wie "/document/image:60".
    Daraus erhalte ich mit meinen bisherigen Methoden aber nicht den Filetyp.


    Wie kann ich aus dem vom SAF gelieferten uri den "echten" Pfad erhalten?
    Oder: wie lese ich den mime-Typ aus?


    (Ist etwa ernsthaft vorgesehen, aus dem uri-"image" auf den mime-Typ "image/*" zu schließen? Da fehlt noch der Subtyp "*", also jpg, png, ...)




    Und dann gibt es am Horizont noch das Problem, ob das SAF alle vorhandenen Files auf dem Gerät tatsächlich findet.
    Um in den dortigen Tabellen indiziert zu werden, müssen die Files ja bekannt gemacht worden sein, was normalerweise die App übernimmt.
    Meine App löst das so:

    Code
    DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
    manager.addCompletedDownload(downloaded_file.getName(),"myApp",true,"image/png",downloaded_file.getPath(),downloaded_file.length(),true);

    Aber wie ist das, wenn der User beispielsweise per USB-Kabel sein "Schaut_her.pdf" in den Download-Ordner seines Geräts geladen hat.
    Findet SAF dieses File dann überhaupt? (Ja, "application/pdf" ist als mime-Type in der Auswahl zugelassen)



    Ist das SAF für einen solchen Einsatz (beliebige Files verschiedener Apps, nicht zwangsläufig mit einem Content/Media/?Provider vertreten, dazu "external storage") überhaupt sinnvoll, oder sollte ich bei meinem alten File Chooser bleiben und diesen um eine Analyse der mime-Typen erweitern (also z.B. Typ-Icons und Thumbnails bei Bildern anzeigen)?
    Wenn ich daran denke, wieviel Datenmüll auf manchen Smartphones herumfliegt ("wieso löschen? Ich habe eine 64-GB-Speicherkarte drin..."), sind das nicht gerade rosige Aussichten, was die zu erwartende Performance angeht.
    Kann aber auch sein, dass ich grundsätzlich falsch liege - das SAF beansprucht schließlich ausdrücklich, über die Gerätegrenzen, d.h. auf die Cloud ausgedehnt, gültig zu sein.