web-dev-qa-db-de.com

Eingabe von HTML-Dateien in Android-Webansicht (Android 4.4, KitKat)

Ich habe den <input type="file"> auf dem Android-Webview verwendet. __ Ich habe es dank dieses Threads zum Laufen gebracht: Datei-Upload in WebView

Die akzeptierte Antwort (oder eine andere) funktioniert jedoch nicht mehr mit Android 4.4 KitKat Webview.

Weiß jemand, wie man das repariert? 

Es funktioniert auch nicht mit Ziel 18.

Ich habe mir Android 4.4-Quellcode angesehen und es scheint, dass sich der WebChromeClient nicht geändert hat, aber ich denke, dass setWebChromeClient auf dem KitKat-Webview nicht mehr funktioniert oder zumindest nicht die openFileChooser-Funktion.

42
jcesarmobile

Update 2: Es gibt ein einfacheres Plugin für Phonegap/Cordova

https://github.com/MaginSoft/MFileChooser

Update: Beispielprojekt mit dem Plugin Cesidio DiBenedetto

https://github.com/jcesarmobile/FileBrowserAndroidTest

Ich habe ein issue über das Android-Open-Source-Projekt geöffnet und die Antwort lautete:

Status: WorkingAsIntended

openFileChooser ist leider keine öffentliche API. Wir arbeiten an einer öffentlichen API in zukünftigen Versionen von Android.

Für diejenigen, die Phonegap/Cordova verwenden, wurde diese Problemumgehung auf dem Bug-Tracker veröffentlicht:

Cesidio DiBenedetto hat einen Kommentar abgegeben - 28/Mar/14 01:27

Hey alle, ich habe dieses Problem auch erlebt, also schrieb ich eine Cordova FileChooser Plugin zu einer "Bandhilfe" vorerst . Grundsätzlich ist in Android 4.4 (KitKat), wie in früheren Kommentaren erwähnt, Der Dateidialog wird nicht geöffnet. Das Onclick-Ereignis ist jedoch immer noch ausgelöst, so dass Sie das FileChooser-Plugin unter .__ aufrufen können. Öffnen Sie einen Dateidialog, und nach Auswahl können Sie eine Variable festlegen, die enthält den vollständigen Pfad zur Datei. An diesem Punkt können Sie die .__ verwenden. FileTransfer-Plugin, das Sie auf Ihren Server hochladen und in .__ einbinden können. Fortschrittsereignis, um den Fortschritt anzuzeigen. Dieses Plugin ist hauptsächlich konfiguriert für Android 4.4 würde ich daher empfehlen, die native Dateidialoge für frühere Android-Versionen. Möglicherweise gibt es Probleme mit dem plugin habe ich alle möglichen szenarien auf .__ nicht vollständig getestet. viele geräte, aber ich habe es auf einem Nexus 5 installiert und es hat gut funktioniert.

https://github.com/cdibened/filechooser

Ich habe es nicht getestet, weil ich eine eigene Problemumgehung entwickelt habe

Ein Kommentar aus einem Chromentwickler

Wir werden im nächsten größeren .__ eine öffentliche API zu WebViewClient hinzufügen. Freigabe für die Bearbeitung von Dateianforderungen.

Es scheint, als würden sie es jetzt als Fehler ansehen und werden es beheben

30
jcesarmobile

Ich habe es geschafft, das erwähnte Cesidio DiBenedettos Workaround in meiner App zu implementieren. Es funktioniert großartig, aber für jemanden, der noch nie PhoneGap/Cordove (wie ich) verwendet hat, könnte es ein bisschen schwierig sein. Hier ist ein kleines Howto, das ich während der Implementierung zusammengestellt habe.

Apache Cordova ist eine Plattform, mit der Sie mobile Apps für mehrere Plattformen nur mit Webtechnologien erstellen können. Die wichtigste Funktion ist, dass die native API in JavaScript exportiert wird und somit eine Möglichkeit zur Kommunikation zwischen der Website und der systemeigenen Anwendung besteht. Die typische PhoneGap/Cordova-App ist eine statische Website, die zusammen mit der Cordova-Schicht in einem APK gebündelt ist. Sie können jedoch Cordova verwenden, um eine Remote-Website anzuzeigen. Dies ist in unserem Fall der Fall.

Die Problemumgehung funktioniert folgendermaßen: Anstelle des Standards WebView verwenden wir CordovaWebView, um unsere Website anzuzeigen. Wenn der Benutzer auf "Durchsuchen" klickt, um eine Datei auszuwählen, wird dieser Klick mithilfe von Standard-JavaScript (jQuery ...) erfasst. Mit der Cordova-API aktivieren wir das Filechooser-Plug-In von Cesidio DiBenedetto auf der ursprünglichen Seite, die einen Nice-Dateibrowser öffnet. Wenn der Benutzer eine Datei auswählt, wird die Datei an die JavaScript-Seite zurückgesendet, von der aus wir sie auf unseren Webserver hochladen.

Wichtig zu wissen ist, dass Sie der Website Cordova-Support hinzufügen müssen. Okay, jetzt das eigentliche Howto ...

Zuerst müssen Sie Cordova zu Ihrer vorhandenen App hinzufügen. Ich folgte dieser Dokumentation . Einige Schritte waren mir unklar, also versuche ich mehr zu erklären:

  1. Laden und extrahieren Sie Cordova außerhalb Ihrer App und erstellen Sie cordova-3.4.0.jar wie beschrieben. Es wird wahrscheinlich zum ersten Mal fehlschlagen, da die Datei local.properties fehlt. In der Fehlerausgabe erfahren Sie, wie Sie es erstellen. Sie müssen es nur auf das SDK zeigen, das Sie zum Erstellen Ihrer Android-App verwenden. 

  2. Kopieren Sie die kompilierte JAR-Datei in Ihr App-Verzeichnis lib und fügen Sie das Jar als Bibliothek hinzu. Wenn Sie Android Studio wie mich verwenden, stellen Sie sicher, dass Sie compile fileTree(dir: 'libs', include: ['*.jar', '*.aar']) in dependencies in build.gradle haben. Klicken Sie dann einfach auf Sync-Projekt mit Gradle-Files und schon ist alles in Ordnung.

  3. Sie müssen die Datei /res/xml/main.xml nicht erstellen. Sie können den CordovaWebView auf dieselbe Weise behandeln wie den Standard-WebView, sodass Sie ihn direkt in Ihre Layoutdatei einfügen können. 

  4. Folgen Sie nun einfach den Schritten 5-7 in der Originaldokumentation, um Ihre Activity zusammenzustellen, in der die CordobaWebView ausgeführt wird. Es empfiehlt sich, den /framework/src/org/Apache/cordova/CordovaActivity.Java des heruntergeladenen Cordova-Pakets zu überprüfen. Sie können die meisten zur Implementierung erforderlichen Methoden einfach kopieren. Der 6. Schritt ist für unsere Zwecke sehr wichtig, da er das Filechooser-Plugin verwenden wird.

  5. Kopieren Sie keine HTML- und JavaScript-Dateien an einer beliebigen Stelle. Wir werden sie später Ihrer Website hinzufügen.

  6. Vergessen Sie nicht, die Datei config.xml zu kopieren (Sie müssen sie nicht ändern).

Um Ihre Website in die CordovaWebView zu laden, übergeben Sie einfach ihre URL an cwv.loadUrl() statt an Config.getStartUrl()

Zweitens müssen Sie das FileChooser-Plugin zu Ihrer App hinzufügen. Da wir nicht das Standard-Cordova-Setup verwenden, können wir nicht einfach cordova plugin add wie in der Readme-Anweisung angegeben drücken, sondern müssen es manuell hinzufügen.

  1. Laden Sie das Repository herunter und kopieren Sie die Quelldateien in Ihre App. Stellen Sie sicher, dass der Inhalt des Ordners res in den Ordner res der App geht. Sie können die JavaScript-Datei vorerst ignorieren.

  2. Fügen Sie Ihrer App READ_EXTERNAL_STORAGE-Berechtigung hinzu.

  3. Fügen Sie folgenden Code zu /res/xml/config.xml hinzu:

<feature name="FileChooser">
    <param name="Android-package" value="com.cesidiodibenedetto.filechooser.FileChooser" />
</feature>

Jetzt ist es an der Zeit, Cordova-Support zu Ihrer Website hinzuzufügen. Es ist einfacher als es sich anhört, Sie müssen lediglich cordova.js mit Ihrer Website verknüpfen. Es gibt jedoch zwei Dinge, die Sie kennen sollten.

Zunächst hat jede Plattform (Android, iOS, WP) eine eigene cordova.js. Stellen Sie daher sicher, dass Sie die Android-Version verwenden (Sie finden sie im Cordova-Paket, das Sie in /framework/assets/www heruntergeladen haben).

Zweitens: Wenn auf Ihre Website sowohl von CordovaWebView als auch von Standardbrowsern (Desktop oder Mobile) zugegriffen werden soll, ist es in der Regel sinnvoll, cordova.js nur zu laden, wenn die Seite in CordovaWebView angezeigt wird. Ich habe mehrere Möglichkeiten gefunden, CordovaWebView zu erkennen, aber der folgende funktionierte für mich. Hier ist der vollständige Code für Ihre Website:

function getAndroidVersion(ua) {
    var ua = ua || navigator.userAgent; 
    var match = ua.match(/Android\s([0-9\.]*)/);
    return match ? parseFloat(match[1]) : false;
};

if (window._cordovaNative && getAndroidVersion() >= 4.4) {
    // We have to use this ugly way to get cordova working
    document.write('<script src="/js/cordova.js" type="text/javascript"></script>');
}

Beachten Sie, dass wir auch die Android-Version überprüfen. Diese Problemumgehung ist nur für KitKat erforderlich.

An dieser Stelle sollten Sie das FileChooser -Plugin von Ihrer Website aus manuell aufrufen können.

var cordova = window.PhoneGap || window.Cordova || window.cordova;
cordova.exec(function(data) {}, function(data) {}, 'FileChooser', 'open', [{}]);

Dies sollte den Dateibrowser öffnen und Sie können eine Datei auswählen. Beachten Sie, dass dies nur möglich ist, nachdem das Ereignisgerät ausgelöst wurde. Um es zu testen, binden Sie diesen Code einfach mit jQuery an eine Schaltfläche.Der letzte Schritt ist, dies alles zusammenzustellen und das Upload-Formular zum Laufen zu bringen. Um dies zu erreichen, können Sie einfach den Anweisungen von Cesidio DiBenedetto folgen, die in der README beschrieben sind. Wenn der Benutzer die Datei in FileChooser auswählt, wird der Dateipfad auf die JavaScript-Seite zurückgegeben, von wo aus ein anderes Cordova-Plug-In, FileTransfer, verwendet wird, um den eigentlichen Upload durchzuführen. Das bedeutet, dass die Datei auf der nativen Seite hochgeladen wird, nicht in CordovaWebView (wenn ich sie richtig verstanden habe).

Ich hatte keine Lust, ein weiteres Cordova-Plugin zu meiner Anwendung hinzuzufügen, und ich war mir auch nicht sicher, wie es mit Cookies funktionieren würde (ich muss Cookies mit der Anfrage senden, da nur authentifizierte Benutzer Dateien hochladen dürfen), also entschied ich mich dafür es ist mein Weg Ich habe das FileChooser -Plugin so geändert, dass nicht der Pfad, sondern die gesamte Datei zurückgegeben wird. Wenn der Benutzer eine Datei auswählt, lese ich deren Inhalt, codiere sie mit base64, gebe sie als JSON an die Client-Seite weiter, wo ich sie decodiere, und sende sie mit JavaScript an den Server. Es funktioniert, aber es ist ein offensichtlicher Nachteil, da base64 ziemlich CPU-anspruchsvoll ist, so dass die App ein wenig einfrieren kann, wenn große Dateien hochgeladen werden. 

Um dies zu tun, fügen Sie diese Methode zunächst zu FileUtils hinzu: 

public static byte[] readFile(final Context context, final Uri uri) throws IOException { File file = FileUtils.getFile(context, uri); return org.Apache.commons.io.FileUtils.readFileToByteArray(file); }

// Get the URI of the selected file
final Uri uri = data.getData();
Log.i(TAG, "Uri = " + uri.toString());
JSONObject obj = new JSONObject();
try {
    obj.put("filepath", FileUtils.getPath(this.cordova.getActivity(), uri));
    obj.put("name", FileUtils.getFile(this.cordova.getActivity(), uri).getName());
    obj.put("type", FileUtils.getMimeType(this.cordova.getActivity(), uri));

    // attach the actual file content as base64 encoded string
    byte[] content = FileUtils.readFile(this.cordova.getActivity(), uri);
    String base64Content = Base64.encodeToString(content, Base64.DEFAULT);
    obj.put("content", base64Content);

    this.callbackContext.success(obj);
} catch (Exception e) {
    Log.e("FileChooser", "File select error", e);
    this.callbackContext.error(e.getMessage());
}

var cordova = window.PhoneGap || window.Cordova || window.cordova;
if (cordova) {
    $('form.fileupload input[type="file"]', context).on("click", function(e) {    
        cordova.exec(
            function(data) { 
                var url = $('form.fileupload', context).attr("action");

                // decode file from base64 (remove traling = first and whitespaces)
                var content = atob(data.content.replace(/\s/g, "").replace(/=+$/, ""));

                // convert string of bytes into actual byte array
                var byteNumbers = new Array(content.length);
                for (var i = 0; i < content.length; i++) {
                    byteNumbers[i] = content.charCodeAt(i);
                }
                var byteContent = new Uint8Array(byteNumbers);

                var formData = new FormData();
                var blob = new Blob([byteContent], {type: data.type}); 
                formData.append('file', blob, data.name);

                $.ajax({
                    url: url,
                    data: formData,
                    processData: false,
                    contentType: false,
                    type: 'POST',
                    success: function(data, statusText, xhr){
                        // do whatever you need
                    }
                });
            },
            function(data) { 
                console.log(data);
                alert("error");
            },
            'FileChooser', 'open', [{}]);
    });
}

Well, that's all. It took me several hours to get this working so I'm sharing my knowledge with a humble hope that it might help somebody.

21
tobik

Wenn noch jemand nach einer Lösung für die Dateieingabe mit einem Webview auf KitKat sucht.

openFileChooser wird nicht aufgerufen, wenn unter Android 4.4 geklickt wird
https://code.google.com/p/Android/issues/detail?id=62220

Eine chrombasierte Bibliothek namens Crosswalk kann verwendet werden, um dieses Problem zu lösen
https://crosswalk-project.org/documentation/downloads.html

Schritte
1. Importieren Sie das Android-Projekt xwalk_core_library, das Sie über den obigen Link heruntergeladen haben, als Bibliothek in Ihr Projekt
2. Fügen Sie in Ihrer Layout-XML Folgendes hinzu

       <org.xwalk.core.XWalkView
            Android:id="@+id/webpage_wv"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"          
        />

3. Führen Sie in der onCreate -Methode Ihrer Aktivität die folgenden Schritte aus

mXwalkView = (XWalkView) context.findViewById(R.id.webpage_wv);
mXwalkView.setUIClient(new UIClient(mXwalkView));
mXwalkView.load(navigateUrl, null); //navigate url is your page URL
  1. Fügen Sie die Aktivität Klassenvariablen hinzu 

    private ValueCallback mFilePathCallback; private XWalkView mXwalkView

  2. Der Dateieingabe-Dialog sollte jetzt angezeigt werden. Sie müssen jedoch Rückrufe bereitstellen, um die Datei abzurufen und an den Server zu senden.

  3. Sie müssten onActivityResult Ihrer Aktivität überschreiben

    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
      super.onActivityResult(requestCode, resultCode, intent);
    
    if (mXwalkView != null) {
    
        if (mFilePathCallback != null) {
            Uri result = intent == null || resultCode != Activity.RESULT_OK ? null
                    : intent.getData();
            if (result != null) {
                String path = MediaUtility.getPath(getActivity(), result);
                Uri uri = Uri.fromFile(new File(path));
                mFilePathCallback.onReceiveValue(uri);
            } else {
                mFilePathCallback.onReceiveValue(null);
            }
        }
    
        mFilePathCallback = null;
    }
    mXwalkView.onActivityResult(requestCode, resultCode, intent);
    
    }
    
  4. Die MediaUtility-Klasse finden Sie unter 
    Holen Sie sich einen echten Pfad von URI, Android KitKat neuen Speicherzugriffs-Frameworks
    Siehe Paul Burkes Antwort

  5. Erstellen Sie eine Unterklasse in Ihrer Aktivität, um das Datenobjekt für mFilePathCallback abzurufen

    class UIClient extends XWalkUIClient {
    public UIClient(XWalkView xwalkView) {
        super(xwalkView);
    }
    
    public void openFileChooser(XWalkView view,
            ValueCallback<Uri> uploadFile, String acceptType, String capture) {
        super.openFileChooser(view, uploadFile, acceptType, capture);
    
        mFilePathCallback = uploadFile;
        Log.d("fchooser", "Opened file chooser.");
    }
    

    }

  6. Du bist alles erledigt. Die Dateiupload sollte jetzt funktionieren ..__ Vergessen Sie nicht, die für Crosswalk erforderlichen Berechtigungen zu Ihrem Manifest hinzuzufügen.

    benutzungsberechtigung Android: name = "Android.permission.ACCESS_FINE_LOCATION"
    using-permission Android: name = "Android.permission.ACCESS_NETWORK_STATE"
    using-permission Android: name = "Android.permission.ACCESS_WIFI_STATE"
    using-permission Android: name = "Android.permission.CAMERA" 
    using-permission Android: name = "Android.permission.INTERNET"
    using-permission Android: name = "Android.permission.MODIFY_AUDIO_SETTINGS"
    using-permission Android: name = "Android.permission.RECORD_AUDIO"
    using-permission Android: name = "Android.permission.WAKE_LOCK"
    using-permission Android: name = "Android.permission.WRITE_EXTERNAL_STORAGE" 

8
agomes

Die Dateiauswahl in einem Webview funktioniert jetzt in der neuesten Android-Version 4.4.3. 

Versuchte es mit Nexus 5.

5

Ich habe meine eigene Lösung für dieses Problem erstellt, ohne Bibliotheken, Cordova-Plugins oder benutzerdefinierte WebViews zu verwenden, und sie funktioniert ordnungsgemäß in allen Android Versionen.

Diese Lösung beinhaltet die Verwendung von sehr einfachem Javascript, um zwischen Ihrer Website in WebView und der App Android) zu kommunizieren und die Dateiauswahl und den Upload direkt von Ihrer Android) - Anwendung aus durchzuführen , Entfernen aller Methoden openFileChooser (), showFileChooser () und onShowFileChooser () WebChromeClient.

Der erste Schritt besteht darin, eine JavaScript-Konsolenmeldung auszulösen von der Website, wenn der Benutzer auf eine Dateieingabe klickt, einen eindeutigen Code zu schreiben, der zum Hochladen der Datei mit einem eindeutigen Namen oder Pfad. Beispiel: Verketten der vollständigen Datumszeit mit einer großen Zufallszahl:

<input type="file" name="user_file" onclick="console.log('app.upload=20170405173025_456743538912');">

Dann kann Ihre App diese Nachrichten über die onConsoleMessage () -Methode von WebChromeClient lesen, diese Nachricht erkennen, den Code lesen und Dateiauswahl auslösen:

webview.setWebChromeClient(new WebChromeClient() {
    // Overriding this method you can read messages from JS console.
    public boolean onConsoleMessage(ConsoleMessage message){          
        String messageText = message.message();
        // Check if received message is a file upload and get the unique code
        if(messageText.length()>11 && messageText.substring(0,11).equals("app.upload=")) {
           String code = messageText.substring(11);
           triggerFileUploadSelection(code);
           return true;
        }
        return false;
    }
});

Zur Dateiauswahl können Sie einfach eine einfache Android ACTION_PICK-Absicht wie folgt verwenden:

public void triggerFileUploadSelection(String code){
    // For Android 6.0+ you must check for permissions in runtime to read from external storage
    checkOrRequestReadPermission();

    // Store code received from Javascript to use it later (code could also be added to the intent as an extra)
    fileUploadCode = code;

    // Build a simple intent to pick any file, you can replace "*/*" for "image/*" to upload only images if needed
    Intent filePickerIntent = new Intent(Intent.ACTION_PICK);
    filePickerIntent.setType("*/*");

    // FILE_UPLOAD_CODE is just any unique integer request code to identify the activity result when the user selects the file
    startActivityForResult( Intent.createChooser(filePickerIntent, getString(R.string.chooseFileToUpload) ), FILE_UPLOAD_CODE );
}

Nachdem der Benutzer eine Datei ausgewählt hat (oder nicht), können Sie die Datei Uri empfangen und sie in einen echten Dateipfad übersetzen mit:

@Override
public void onActivityResult (int requestCode, int resultCode, Intent data) {
    if(requestCode==FILE_UPLOAD_CODE) {
        if(data != null && resultCode == RESULT_OK){
            // user selected a file
            try{
                Uri selectedFileUri = data.getData();
                if(selectedFileUri!=null) {
                    // convert file URI to a real file path with an auxiliary function (below)
                    String filePath = getPath(selectedFileUri);
                    if(filePath!=null) {
                        // I got the file path, I can upload the file to the server (I pass webview as an argument to be able to update it when upload is completed)
                        uploadSelectedFile(getApplicationContext(), filePath, fileUploadCode, webview);
                    }else{
                        showToastFileUploadError();
                    }
                }else{
                    showToastFileUploadError();
                }
            }catch (Exception e){
                e.printStackTrace();
                showToastFileUploadError();
            }
        }else{
            // user didn't select anything
        }
    }
}

// I used this method for images, and it uses MediaStore.Images so you should probably 
// use another method to get the path from the Uri if you are working with any kind of file
public String getPath(Uri uri) {
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    if(cursor==null)return null;
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}

Die uploadSelectedFile-Methode erstellt einfach ein Objekt mit allen darin enthaltenen Informationen (filePath, fileUploadCode und WebView) und Löst eine AsyncTask aus, die die Datei hochlädt und aktualisiert die WebView, wenn sie fertig ist :

public static void uploadSelectedFile(Context c, String filePath, String code, WebView webView){
    // YOU CAN SHOW A SPINNER IN THE WEB VIEW EXECUTING ANY JAVASCRIPT YOU WANT LIKE THIS:
    webView.loadUrl("javascript: Element.show('my_upload_spinner');void 0"); 
    // void 0 avoids at the end avoids some browser redirection problems when executing javascript commands like this

    // CREATE A REQUEST OBJECT (you must also define this class with those three fields and a response field that we will use later):
    FileUploadRequest request = new FileUploadRequest(filePath, code, webView);

    // Trigger an async task to upload the file, and pass on the request object with all needed data
    FileUploadAsyncTask task = new FileUploadAsyncTask();
    task.execute(request);
}

Die AsyncTask empfängt das Anforderungsobjekt mit allen Informationen und verwendet MultipartUtility, um eine mehrteilige Anforderung zu erstellen und sie einfach an den Server zu senden. Sie können viele Java Multipart Utilities von vielen Orten bekommen, eines davon ist hier: http://www.codejava.net/Java-se/networking/upload-files -durch-Senden-einer-mehrteiligen-Anfrage-programmatisch

public class FileUploadAsyncTask extends AsyncTask<FileUploadRequest, Void, FileUploadRequest> {
    @Override
    protected FileUploadRequest doInBackground(FileUploadRequest... requests) {
        FileUploadRequest request = requests[0];

        try {
            // Generate a multipart request pointing to the URL where you will receive uploaded file
            MultipartUtility multipart = new MultipartUtility("http://www.example.com/file_upload.php", "UTF-8");
            // Add a field called file_code, to send the code to the server script
            multipart.addFormField("file_code", request.code);
            // Add the file to the request
            multipart.addFilePart("file_path", new File(request.filePath));

            // Send the request to the server and get the response and save it back in the request object
            request.response = multipart.finish(); // response from server.
        } catch (IOException e) {
            request.response = "FAILED";
            e.printStackTrace();
        }
        return request;
    }

Jetzt haben wir die Datei auf den Server hochgeladen und können unsere Website mithilfe von Javascript erneut über unsere onPostExecute-Methode in unserer AsyncTask aktualisieren. Das Wichtigste ist, den Dateicode in ein verstecktes Feld in Ihrem Formular zu setzen, damit Sie diesen Code erhalten, wenn der Benutzer das Formular sendet. Sie können auch eine Nachricht auf der Site anzeigen oder das hochgeladene Bild (wenn es sich um ein Bild handelt) ganz einfach anzeigen:

@Override
protected void onPostExecute(FileUploadRequest request) {
    super.onPostExecute(request);

    // check for a response telling everything if upload was successful or failed
    if(request.response.equals("OK")){
        // set uploaded file code field in a hidden field in your site form (ESSENTIAL TO ASSOCIATE THE UPLOADED FILE WHEN THE USER SENDS THE WEBSITE FORM)
        request.webView.loadUrl("javascript: document.getElementById('app_upload_code_hidden').value = '"+request.code+"';void 0");

        // Hide spinner (optional)
        //request.webView.loadUrl("javascript: Element.hide('my_upload_spinner');void 0");

        // show a message in the website, or the uploaded image in an image tag setting the src attribute 
        // to the URL of the image you just uploaded to your server. 
        // (you must implement your own fullUrl method in your FileUploadRequest class)
        // request.webView.loadUrl("javascript: document.getElementById('app_uploaded_image').src = '"+request.fullUrl()+"';void 0");
        // request.webView.loadUrl("javascript: Element.show('app_uploaded_image');void 0");
    }
}

Jetzt ist der Teil Android fertig, und Sie müssen Server-Seite arbeiten, um die Datei zu erhalten Sie laden über Android App AsyncTask und speichern Sie es, wo immer Sie brauchen.

Sie müssen auch Ihr Website-Formular bearbeiten, wenn der Benutzer es sendet und mit der Datei, die der Benutzer aus der App hochgeladen hat, alles tun, was Sie brauchen. Dazu erhalten Sie den Datei-Code in der Form (wir haben diesen in einem Feld in onPostExecute () ausgefüllt), und Sie müssen diesen Datei-Code verwenden, um die Datei zu finden, die die App hochgeladen hat = zu deinem Server. Um dies zu erreichen, können Sie die Datei in einem Pfad speichern, indem Sie diesen Code als Dateinamen verwenden, oder den Code und den Pfad, in den Sie die Datei hochgeladen haben, in einer Datenbank speichern.

Diese Lösung basiert nur auf Elementen, die verfügbar und mit allen Android Versionen kompatibel sind, daher sollte sie auf jedem Gerät funktionieren (und ich habe darüber keine Beschwerden mehr erhalten).

Wenn Sie mehrere Dateieingaben haben auf derselben Seite können Sie eine Feldnummer oder einen zusätzlichen Bezeichner senden zusammen mit dem eindeutigen Dateicode in der anfänglichen Javascript-Nachricht, Übergeben Sie diesen Bezeichner im gesamten App-Code und aktualisieren Sie damit die richtigen Elemente in onPostExecute ().

Ich habe den eigentlichen Code hier ein wenig geändert. Wenn also etwas fehlschlägt, handelt es sich wahrscheinlich um einen Tippfehler oder ein kleines Detail, wenn Sie einige Dinge umbenennen.

Es sind ziemlich viele Informationen zu verarbeiten. Wenn jemand eine Klärung benötigt oder Vorschläge oder Korrekturen hat, teilen Sie mir dies bitte mit.

1

Trotz der Tatsache, dass die KitKat-Version nicht mit dem webview type = Dateiformatfeld kompatibel ist, können wir die addJavascriptInterface-Methode von webview verwenden, um die Aufgabe zum Hochladen von Dateien auszuführen. Serverseite sollte die Android-Version beurteilen. Wenn sie niedriger als 4.4 ist, verwenden Sie WebViewChromeClient private Methoden. Wenn 4.4 oder höher, lassen Sie den Server die Android-Methode aufrufen, um miteinander zu kommunizieren (z. B. Dateiinhalt asynchron hochladen).

// code

webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new WebViewJavaScriptInterface(this), "app");


Hier ist ein Link, der helfen könnte ...

Aufruf-Android-Methoden-von-Javascript

1
tounaobun

Der neue Dateibrowser von KitKat wird in Chrome ebenso verrückt, wie WebView Chromium jetzt verwendet. Dies könnte ein verwandtes Problem sein. Ich habe festgestellt, dass das Hochladen von Dateien direkt von der Kamera aus funktioniert, nicht jedoch über den Ordner "Images". Wenn Sie stattdessen aus 'Galerie' hochladen, können Sie auf dieselben Dateien zugreifen. Gah.

Es scheint, als ob ein Fix fertig ist, aber auf Veröffentlichung wartet:

https://code.google.com/p/chromium/issues/detail?id=278640

0
Igor Zinken

wenn Sie einfach einen Webview-Wrapper in Ihre Website einfügen und ihn als App starten möchten, schauen Sie sich nicht mit dem Standard-Webview von Android um, auf die eine oder andere Weise ist es ein gewaltiger Kopfschmerz. Für mich haben zwei Dinge nicht funktioniert out 1. Eingabedatei 2. Stripe-Checkout-Integeration (die erweiterte JS-API verwendet)

Was ich getan habe, um aus der Dunkelheit zu kommen 

Sie haben gerade eine Beispiel-App mit Cordova erstellt. Es ist viel einfacher, dass wir denken.

  1. Installieren Sie Cordova von seiner offiziellen Seite und erstellen Sie eine Beispiel-App.
  2. Sie erhalten eine apk-Datei. ( Du hast es)
  3. Sie gehen aus der erstellten App in den Ordner www, öffnen die Datei index.js, suchen und ersetzen die Zeile durch OnDeviceReady: function () {window.open (' http://yourdomain.com/yourpage ') } Führen Sie die App erneut aus, um die Site zu öffnen

  4. Nun der Master-Schritt. Bisher verwendete Cordova nur einen moderaten Webview. Alles sollte sich eines Tages ändern. Fügen Sie das Crosswalk-Plugin zu Ihrer Cordova-App hinzu. Dadurch wird das langsame Webview durch eine brandneue, vollwertige Chromansicht ersetzt https://crosswalk-project.org/documentation/cordova.html

  5. führen Sie cordova clean und dann cordova build --release aus, um den alten Build zu bereinigen.

  6. Öffnen Sie die config.xml in dem von Cordva App angegebenen App-Verzeichnis und fügen Sie <allow-navigation href="http://yourdomain.com/*" /> hinzu.
  7. Führen Sie die App erneut aus. Zauber!.
0
Code Tree