Android Intent-Filter für eine bestimmte Dateierweiterung?

Ich möchte in der Lage sein, eine Datei mit einer bestimmten Erweiterung aus dem Netz herunterzuladen, und habe es an meine Anwendung übergeben, um damit umzugehen, aber ich war nicht in der Lage, den Absichtsfilter herauszufinden. Der Dateityp ist nicht in den MIME-Typen enthalten, und ich habe versucht, zu verwenden

 

aber ich konnte das nicht zur Arbeit bringen.

Hier ist, wie ich meine Aktivität in meiner AndroidManifest.xml definiert habe, um dies zum Laufen zu bringen.

            

Das scheme der file zeigt an, dass dies passieren sollte, wenn eine lokale Datei geöffnet wird (anstatt Protokoll wie HTTP).

mimeType kann auf \*/\* , um zu jedem Mime-Typ zu passen.

pathPattern geben Sie an, welche Erweiterung pathPattern soll (in diesem Beispiel .kdb ). Das .* am Anfang entspricht einer beliebigen Zeichenfolge. Diese Strings benötigen doppeltes Escaping, also \\\\. entspricht einer literalen Periode. Dann enden Sie mit Ihrer Dateierweiterung. Ein Nachteil bei pathPattern ist, dass .* Kein gieriges Match ist, wie man es erwarten würde, wenn dies ein regulärer Ausdruck wäre. Dieses Muster kann nicht mit Pfaden übereinstimmen, die a enthalten . vor der .kdb . Eine ausführlichere Diskussion dieses Problems und eine Problemumgehung finden Sie hier

Schließlich werden gemäß der Android-Dokumentation sowohl host als auch scheme Attribute benötigt, damit das pathPattern Attribut funktioniert, also setze das auf den Platzhalter, um alles pathPattern .

Wenn Sie nun eine .kdb Datei in einer App wie Linda File Manager auswählen, wird meine App als Option .kdb . Ich sollte beachten, dass dies allein nicht erlaubt, diesen Dateityp in einem Browser herunterzuladen, da dies nur mit dem Dateischema registriert wird. Eine App wie Linda File Manager auf Ihrem Telefon zu haben, macht sich selbst generisch und erlaubt es Ihnen, jeden Dateityp herunterzuladen.

Ich muss zugeben, dass die einfache Aufgabe, Anhänge von E-Mails und Dateien aus dem Dateisystem auf Android zu öffnen, eine der verrückteren Erfahrungen war. Es ist einfach, zu viele Dateien oder zu wenige zu handhaben. Aber es richtig zu machen ist schwer. Die meisten auf stackoverflow geposteten Lösungen funktionierten für mich nicht korrekt.

Meine Anforderungen waren:

  • Mit meiner App können Sie Anhänge verwalten, die von meiner App geteilt werden
  • Habe in meiner App Dateien im Dateispeicher verwaltet, die von meiner App generiert wurden und eine bestimmte Erweiterung haben

Der beste Weg, um diese Aufgabe auszuführen, ist wahrscheinlich, einen benutzerdefinierten MIME-Typ für Ihre Anhänge anzugeben. Und Sie werden wahrscheinlich auch eine benutzerdefinierte Dateierweiterung haben. Nehmen wir an, unsere App heißt “Coole App” und wir generieren Dateianhänge mit “.cool” am Ende.

Das ist das nächste, das ich zu meinem Ziel gebracht habe und es funktioniert … zufriedenstellend.

                     

Anmerkungen:

  • Das pathPattern scheint für Anhänge mehr oder weniger ignoriert zu werden (wenn man android:scheme="content" ). Wenn jemand das Pfadmuster erhält, um nur auf bestimmte Muster zu reagieren, wäre ich begeistert, wie das geht.
  • Die Google Mail-App hat es abgelehnt, meine App in der Auswahl aufzulisten, wenn ich das Attribut android:host="*" hinzugefügt habe.
  • Es funktioniert wahrscheinlich immer noch, wenn diese intent-filter zusammengeführt werden, aber ich habe dies nicht verifiziert.
  • Um Anfragen eines Browsers beim Herunterladen einer Datei zu bearbeiten, kann das android:scheme="http" verwendet werden. Beachten Sie, dass bestimmte Browser den android:mimeType also experimentieren Sie mit android:mimeType="*/*" und überprüfen Sie den Debugger, was tatsächlich passiert ist und dann die Filterung zu straffen, nicht die lästige App, die alles behandelt .
  • Bestimmte File Explorer werden auch die MIME-Typen für Ihre Dateien durcheinander bringen. Der obige intent-filter wurde mit der Samsung App “My Files” auf einem Galaxy S3 getestet. Der FX Explorer weigert sich immer noch, die Datei richtig zu öffnen, und ich habe auch bemerkt, dass das App-Icon nicht für die Dateien verwendet wird. Auch wenn jemand das zur Arbeit bringt, bitte unten kommentieren.

Ich hoffe, dass Sie das nützlich finden und dass Sie keine Tage verschwenden müssen, um alle möglichen Kombinationen durchzugehen. Es gibt Raum für Verbesserungen, Kommentare sind willkommen.

Es gibt viele Fehlinformationen zu diesem Thema, nicht zuletzt aus der eigenen Dokumentation von Google. Das Beste, und angesichts der seltsamen Logik, möglicherweise die einzige echte Dokumentation ist der Quellcode.

Die Intent-Filterimplementierung weist eine Logik auf, die sich fast jeder Beschreibung entzieht. Der Parser-Code ist das andere relevante Teil des Puzzles.

Die folgenden Filter kommen einem vernünftigen Verhalten ziemlich nahe. Die Pfadmuster gelten für “Datei” -Schema-Absichten.

Die Übereinstimmung der globalen Mime-Typ-Muster stimmt mit allen Typen überein, solange die Dateierweiterung übereinstimmt. Dies ist nicht perfekt, aber es ist die einzige Möglichkeit, das Verhalten von Dateimanagern wie ES File Explorer anzupassen, und es ist auf Intents beschränkt, bei denen die URI / Dateierweiterung übereinstimmt.

Ich habe hier keine anderen Schemata wie “http” eingefügt, aber sie werden wahrscheinlich bei all diesen Filtern gut funktionieren.

Das ungerade Schema ist “Inhalt”, für das die Erweiterung dem Filter nicht zur Verfügung steht. Aber solange der Provider Ihren MIME-Typ angibt (zB wird Gmail den MIME-Typ für den Anhang ungehindert weitergeben), passt der Filter.

Bitte beachten Sie:

  1. Seien Sie sich bewusst, dass sich nichts in den Filtern konsistent verhält, es ist ein Labyrinth von Spezialfällen und behandelt die Verletzung des Prinzips der geringsten Überraschung als Designziel. Keiner der Mustervergleichsalgorithmen folgt derselben Syntax oder demselben Verhalten. Das Fehlen eines Feldes ist manchmal ein Platzhalter und manchmal nicht. Attribute innerhalb eines Datenelements müssen manchmal zusammengehen und manchmal die Gruppierung ignorieren. Es hätte wirklich besser gemacht werden können.
  2. Das Schema AND und der Host müssen angegeben werden, damit die Pfadregeln übereinstimmen (im Gegensatz zu Googles API-Leitfaden derzeit).
  3. Zumindest ES File Explorer generiert Absichten mit einem MIME-Typ von “”, der sehr unterschiedlich zu null gefiltert wird, ist nicht explizit abzugleichen und kann nur mit dem riskanten “* / *” Filter verglichen werden.
  4. Der Filter “* / *” stimmt NICHT mit Intents mit einem Null-MIME-Typ überein – das erfordert einen separaten Filter für diesen speziellen Fall ohne MIME-Typ.
  5. Dem Schema “Inhalt” kann nur der MIME-Typ zugeordnet werden, da der ursprüngliche Dateiname in der Absicht nicht verfügbar ist (zumindest bei Gmail).
  6. Die Gruppierung von Attributen in separaten “Daten” -Elementen ist (fast) irrelevant für die Interpretation, mit der speziellen Ausnahme von Host und Port – die zusammenpassen. Alles andere hat keine spezifische Assoziation innerhalb eines “Daten” -Elements oder zwischen “Daten” -Elementen.

In diesem Sinne, hier ein Beispiel mit Kommentaren:

                                           

Brians Antwort oben hat mich 90% des Weges dorthin gebracht. Um es fertig zu stellen, habe ich für Pantomime Typ verwendet

 android:mimeType="*/*" 

Ich vermute, dass frühere Plakate versucht haben, die gleichen Details zu veröffentlichen, aber die deutliche Kotierung des Sterns als Sternstrich, Stackoverflow zeigt es als nur einen Schrägstrich.

android:mimeType android:path , versuchen Sie android:mimeType , mit einem Wert des MIME-Typs dieses bestimmten Stücks Inhalt. Auch, android:path akzeptiert keine Platzhalter – verwenden Sie android:pathPattern dafür.

Brians Antwort ist sehr nahe, aber hier ist eine saubere und errorsfreie Möglichkeit, Ihre App aufzurufen, wenn Sie versuchen, eine Datei mit Ihrer eigenen benutzerdefinierten Erweiterung zu öffnen (keine Notwendigkeit für Schema oder Host):

        

Auf Android 4 wurden die Regeln strenger als früher. Benutzen:

   

Ich habe mich schon ziemlich lange mit einer benutzerdefinierten Dateierweiterung herumgeschlagen. Nach langem Suchen fand ich diese Webseite, auf der das Poster entdeckte, dass Androids patternMatcher-class (die für den pathPattern-Abgleich in Intent-Filtern verwendet wird) unerwartetes Verhalten hat, wenn dein Pfad das erste Zeichen deines Matchmusters an anderer Stelle im Pfad enthält (Wenn Sie beispielsweise versuchen, “* .xyz” zu finden, stoppt die patternMatcher-class, wenn sich früher ein “x” in Ihrem Pfad befindet). Hier ist, was er für eine Workaround gefunden hat, und arbeitete für mich, obwohl es ein bisschen wie ein Hack ist:

PatternMatcher wird für pathPattern bei IntentFilter verwendet, aber PatternMatcher’s Algorithmus ist mir ziemlich fremd. Hier ist Algorithmus von Android PatternMatcher.

Wenn das ‘. *’ Muster in der Mitte der Zeichenfolge steht, stoppt PatternMatcher die Schleife an diesem Punkt. (Siehe PatternMatcher.java des Android-Frameworks.)

Ex. string: “Dies ist ein Anhang” -Muster: “. att. “. Android PatternMatcher geben Schleife ein, um zu passen ‘. ‘Muster bis zum nächsten Zeichen des Musters (in diesem Beispiel’ a ‘) So,’. ‘Matching Loop stoppt bei Index 8 -‘ a ‘zwischen’ is ‘und’ my ‘. Daher gibt das Ergebnis dieser Übereinstimmung ‘falsch’ zurück.

Ziemlich merkwürdig, nicht wahr? Um dies zu umgehen – eigentlich die Möglichkeit zu reduzieren – sollte Entwickler nervige dumme Pfadmuster verwenden.

Ex. Ziel: Übereinstimmender URL-Pfad, der ‘Nachricht’ enthält.

  ...      ...  

Dies wird insbesondere beim Abgleich mit benutzerdefinierten Dateierweiterungen ausgegeben.

Keiner der oben genannten Vorgänge funktioniert ordnungsgemäß für VIEW- oder SEND-Aktionen, wenn das Suffix nicht mit einem MIME-Typ in der systemweiten MIME-database von Android registriert ist. Die einzigen Einstellungen, die ich für das angegebene Suffix gefunden habe, sind android:mimeType="*/*" , aber dann wird die Aktion für ALLE Dateien android:mimeType="*/*" . Klar NICHT was du willst!

Ich kann keine passende Lösung finden, ohne Mime und Suffix der Android-Mime-database hinzuzufügen, bisher habe ich keinen Weg gefunden, das zu tun. Wenn jemand weiß, wäre ein pointers grandios.

Ich habe versucht, dies für die Ewigkeit zu funktionieren und habe alle vorgeschlagenen Lösungen ausprobiert und kann Android immer noch nicht dazu bringen, bestimmte Dateierweiterungen zu erkennen. Ich habe einen Intent-Filter mit einem "*/*" Mimetyp, der scheinbar das Einzige ist, was funktioniert und Dateibrowser meine App jetzt als eine Option zum Öffnen von Dateien auflisten, aber meine App wird jetzt als eine Option zum Öffnen von ANY angezeigt KIND der Datei, obwohl ich bestimmte Dateierweiterungen mit dem pathPattern-Tag angegeben habe. Das geht so weit, dass selbst wenn ich versuche, einen Kontakt in meiner Kontaktliste anzuzeigen / zu bearbeiten, Android mich fragt, ob ich meine App verwenden möchte, um den Kontakt zu sehen, und das ist nur eine von vielen Situationen, in denen dies sehr SEHR nervig ist.

Irgendwann fand ich diesen Google Groups Post mit einer ähnlichen Frage, auf die ein eigentlicher Android Framework Engineer geantwortet hat. Sie erklärt, dass Android einfach nichts über Dateierweiterungen, nur MIME-Typen ( https://groups.google.com/forum/#!topic/android-developers/a7qsSl3vQq0 ) weiß.

Aus dem, was ich gesehen, versucht und gelesen habe, kann Android einfach nicht zwischen Dateierweiterungen unterscheiden und das pathPattern-Tag ist im Grunde eine gigantische Verschwendung von Zeit und Energie. Wenn Sie das Glück haben, nur Dateien eines bestimmten Mime-Typs (zB Text, Video oder Audio) zu benötigen, können Sie einen Intent-Filter mit einem Mime-Type verwenden. Wenn Sie eine bestimmte Dateierweiterung oder einen MIME-Typ benötigen, den Android nicht kennt, haben Sie kein Glück.

Wenn ich falsch liege, sag mir bitte, bis jetzt habe ich jeden Beitrag gelesen und jede vorgeschlagene Lösung ausprobiert, die ich finden konnte, aber keine hat funktioniert.

Ich könnte noch eine oder zwei Seiten darüber schreiben, wie häufig diese Art von Dingen in Android zu sein scheint und wie vermasselt die Entwicklererfahrung ist, aber ich werde dir meine wütenden Schimpfwörter ersparen;). Hoffe, ich habe jemandem etwas Ärger erspart.

Wenn Sie möchten, dass die Dateien direkt aus Google Mail, Dropbox oder einem der anderen Android-Datei-Tools geöffnet werden, verwenden Sie den folgenden Code (löschen Sie ‘android: host = “*”‘, wodurch die Datei für Google Mail nicht erreichbar ist):

            

Der Datenfilter muss gemäß Android Version 4.x in einer statement geschrieben sein

Verwenden Sie den folgenden Filter zum Öffnen von Browser, Gmail & Dateibrowser (getestet). HINWEIS: Bitte führen Sie keine zwei Filter zusammen, damit der Browser Ihre App ignoriert (getestet).