Datei-Upload in WebView

169

Ich habe seit einigen Tagen Probleme, Dateien von WebView hochzuladen, und es gibt keine Fortschritte. Ich habe alle vorgeschlagenen Lösungen gegoogelt und implementiert, aber keine funktioniert, wie: hier vorgeschlagene Lösungen und so weiter.

Problem: Ich habe eine HTML-Seite mit dem folgenden Code zum Hochladen einer Datei. Es funktioniert gut in einem Desktop-Browser wie Firefox und einem integrierten Browser von Emulator / AVD. Wenn ich auf die Schaltfläche "Durchsuchen ..." klicke, die vom Element gerendert wird, öffnet der Browser ein Dialogfeld, in dem ich eine Datei zum Hochladen auswählen kann.

Wenn ich jedoch im Android 3.0-Emulator / AVD auf "Datei auswählen" klicke, passiert nichts, es wird kein Dateidialog geöffnet !!!

<form method="POST" enctype="multipart/form-data">
File to upload: <input type="file" name="uploadfile">&nbsp;&nbsp;
<input type="submit" value="Press to Upload..."> to upload the file!
</form>

Könnte jemand bitte frühestens eine mögliche Lösung vorschlagen.

user741148
quelle
Sie können diese WebviewUnterklasse verwenden, die das
Hochladen von
@ MarcoW. Ich habe AdvancedWebView ausprobiert, kann aber immer noch keine Dateien hochladen.
Jiashie
@jiashie Datei-Uploads funktionieren auf allen Android-Versionen mit Ausnahme von Android 4.4, wo es keine Chance gibt, dass es funktioniert. Vielleicht bist du auf dieser Version? Andernfalls können Sie überprüfen, AdvancedWebView.isFileUploadAvailable()ob Uploads unterstützt werden. Und Sie können Ihren Code teilen und um Hilfe bei den Problemen bitten: github.com/delight-im/Android-AdvancedWebView/issues
caw
@ Hiram Kann ich eine Datei über Iframe in einer Webansicht in meiner Android-App hochladen? Was brauche ich, um das zu tun?
Gaurav Parashar

Antworten:

162

Dies ist eine vollständige Lösung für alle Android-Versionen, ich hatte auch Schwierigkeiten damit.

public class MyWb extends Activity {
/** Called when the activity is first created. */

WebView web;
ProgressBar progressBar;

private ValueCallback<Uri> mUploadMessage;  
 private final static int FILECHOOSER_RESULTCODE=1;  

 @Override  
 protected void onActivityResult(int requestCode, int resultCode,  
                                    Intent intent) {  
  if(requestCode==FILECHOOSER_RESULTCODE)  
  {  
   if (null == mUploadMessage) return;  
            Uri result = intent == null || resultCode != RESULT_OK ? null  
                    : intent.getData();  
            mUploadMessage.onReceiveValue(result);  
            mUploadMessage = null;  
  }
  }  

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    web = (WebView) findViewById(R.id.webview01);
    progressBar = (ProgressBar) findViewById(R.id.progressBar1);

    web = new WebView(this);  
    web.getSettings().setJavaScriptEnabled(true);
    web.loadUrl("http://www.script-tutorials.com/demos/199/index.html");
    web.setWebViewClient(new myWebClient());
    web.setWebChromeClient(new WebChromeClient()  
    {  
           //The undocumented magic method override  
           //Eclipse will swear at you if you try to put @Override here  
        // For Android 3.0+
        public void openFileChooser(ValueCallback<Uri> uploadMsg) {  

            mUploadMessage = uploadMsg;  
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);  
            i.addCategory(Intent.CATEGORY_OPENABLE);  
            i.setType("image/*");  
            MyWb.this.startActivityForResult(Intent.createChooser(i,"File Chooser"), FILECHOOSER_RESULTCODE);  

           }

        // For Android 3.0+
           public void openFileChooser( ValueCallback uploadMsg, String acceptType ) {
           mUploadMessage = uploadMsg;
           Intent i = new Intent(Intent.ACTION_GET_CONTENT);
           i.addCategory(Intent.CATEGORY_OPENABLE);
           i.setType("*/*");
           MyWb.this.startActivityForResult(
           Intent.createChooser(i, "File Browser"),
           FILECHOOSER_RESULTCODE);
           }

        //For Android 4.1
           public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
               mUploadMessage = uploadMsg;  
               Intent i = new Intent(Intent.ACTION_GET_CONTENT);  
               i.addCategory(Intent.CATEGORY_OPENABLE);  
               i.setType("image/*");  
               MyWb.this.startActivityForResult( Intent.createChooser( i, "File Chooser" ), MyWb.FILECHOOSER_RESULTCODE );

           }

    });  


    setContentView(web);  


}

public class myWebClient extends WebViewClient
{
    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        // TODO Auto-generated method stub
        super.onPageStarted(view, url, favicon);
    }

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // TODO Auto-generated method stub

        view.loadUrl(url);
        return true;

    }

    @Override
    public void onPageFinished(WebView view, String url) {
        // TODO Auto-generated method stub
        super.onPageFinished(view, url);

        progressBar.setVisibility(View.GONE);
    }
}

//flipscreen not loading again
@Override
public void onConfigurationChanged(Configuration newConfig){        
    super.onConfigurationChanged(newConfig);
}

// To handle "Back" key press event for WebView to go back to previous screen.
/*@Override
public boolean onKeyDown(int keyCode, KeyEvent event) 
{
    if ((keyCode == KeyEvent.KEYCODE_BACK) && web.canGoBack()) {
        web.goBack();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}*/
}

Außerdem möchte ich hinzufügen, dass die "Upload-Seite" wie die in diesem Beispiel bei <4 Versionen nicht funktioniert, da sie über eine Bildvorschau verfügt. Wenn Sie möchten, dass sie funktioniert, verwenden Sie einen einfachen PHP-Upload ohne Vorschau.

Update :

Sie finden die Lösung für Lutscher Geräte hier und Dank für gauntface

Update 2 :

Komplettlösung für alle Android-Geräte bis oreo hier und dies ist eine fortgeschrittenere Version , Sie sollten es sich ansehen, vielleicht kann es helfen.

Hiram
quelle
Vielen Dank für meine Zeitersparnis!
Ramesh Akula
20
@ Hifarrer du bist ein Lebensretter. Das hat gut funktioniert. PLUS, für uns Noobs hilft COMPLETE-Code dabei, die Platzierung und ihre Funktionsweise zu verstehen, anstatt nur eine Reihe von Funktionen einzufügen, und dann wissen wir nicht, wo wir sie platzieren und verwenden sollen. Vielen Dank für Ihre ausführliche Antwort.
Panama Jack
Wie gehe ich mit dieser Methode nach der Verschleierung um? Ich verwende dieselbe Methode ohne Verschleierung, sie funktioniert einwandfrei, aber wenn meine App mit Verschleierung bereitgestellt wird, wird diese Methode niemals aufgerufen. Ich habe diese Methode bewahrt. Hat jemand dieses Problem gesehen?
Harshawardhan
1
Es funktioniert, aber warum wird der Wert nicht so aktualisiert, wie er sein sollte? Das ist mein Test mit dem Eclipse Android API17 Emulator.
Jeffrey Neo
1
Das progressBarscheint dort unbenutzt. Ich kann nur sehen, dass es sich versteckt, aber nicht, wo es aktiviert ist. Ich denke, Sie müssten onProgressChanged(...)die benutzerdefinierte WebChromeClientVariante dafür hinzufügen . (Und so etwas wie getWindow().setFeatureInt( Window.FEATURE_PROGRESS, Window.PROGRESS_VISIBILITY_ON);in onCreate.)
Gr.
106

Arbeitsmethode von HONEYCOMB (API 11) bis Oreo (API 27)
[Nicht auf Pie 9.0 getestet]

static WebView mWebView;
private ValueCallback<Uri> mUploadMessage;
public ValueCallback<Uri[]> uploadMessage;
public static final int REQUEST_SELECT_FILE = 100;
private final static int FILECHOOSER_RESULTCODE = 1;

Geändert onActivityResult()

@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    {
        if (requestCode == REQUEST_SELECT_FILE)
        {
            if (uploadMessage == null)
                return;
            uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
            uploadMessage = null;
        }
    }
    else if (requestCode == FILECHOOSER_RESULTCODE)
    {
        if (null == mUploadMessage)
            return;
    // Use MainActivity.RESULT_OK if you're implementing WebView inside Fragment
    // Use RESULT_OK only if you're implementing WebView inside an Activity
        Uri result = intent == null || resultCode != MainActivity.RESULT_OK ? null : intent.getData();
        mUploadMessage.onReceiveValue(result);
        mUploadMessage = null;
    }
    else
        Toast.makeText(getActivity().getApplicationContext(), "Failed to Upload Image", Toast.LENGTH_LONG).show();
}

Jetzt in onCreate()oder onCreateView()fügen Sie den folgenden Code

    WebSettings mWebSettings = mWebView.getSettings();
    mWebSettings.setJavaScriptEnabled(true);
    mWebSettings.setSupportZoom(false);
    mWebSettings.setAllowFileAccess(true);
    mWebSettings.setAllowFileAccess(true);
    mWebSettings.setAllowContentAccess(true);

mWebView.setWebChromeClient(new WebChromeClient()
{
    // For 3.0+ Devices (Start)
    // onActivityResult attached before constructor
    protected void openFileChooser(ValueCallback uploadMsg, String acceptType)
    {
        mUploadMessage = uploadMsg;
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("image/*");
        startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE);
    }


    // For Lollipop 5.0+ Devices
    public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
    {
        if (uploadMessage != null) {
            uploadMessage.onReceiveValue(null);
            uploadMessage = null;
        }

        uploadMessage = filePathCallback;

        Intent intent = fileChooserParams.createIntent();
        try
        {
            startActivityForResult(intent, REQUEST_SELECT_FILE);
        } catch (ActivityNotFoundException e)
        {
            uploadMessage = null;
            Toast.makeText(getActivity().getApplicationContext(), "Cannot Open File Chooser", Toast.LENGTH_LONG).show();
            return false;
        }
        return true;
    }

    //For Android 4.1 only
    protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)
    {
        mUploadMessage = uploadMsg;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("image/*");
        startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE);
    }

    protected void openFileChooser(ValueCallback<Uri> uploadMsg)
    {
        mUploadMessage = uploadMsg;
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("image/*");
        startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
    }
});
zackygaurav
quelle
Mein Problem wurde gelöst. Danke dir.
Htin Aung
1
Vielen Dank für Ihren vollständigen Code. Es funktioniert gut, außer Kitkat Os. Würdest du mir bitte eine Idee geben, wie ich auch in Kitkat unterstützen kann? Vielen Dank
AndyBoy
Perfekte Antwort !! Vielen Dank @zackygaurav
Swr7der
Perfekt arbeiten
Hitesh Sahu
1
@NightFury Sie müssen dies tun, wenn Sie versuchen, auf einen http- Link zuzugreifen . Verwenden Sie stattdessen https
zackygaurav
45

Dies ist die einzige Lösung, die ich gefunden habe und die funktioniert!

WebView webview;

private ValueCallback<Uri> mUploadMessage;
private final static int FILECHOOSER_RESULTCODE = 1;

@Override
protected void onActivityResult(int requestCode, int resultCode,
        Intent intent) {
    if (requestCode == FILECHOOSER_RESULTCODE) {
        if (null == mUploadMessage)
            return;
        Uri result = intent == null || resultCode != RESULT_OK ? null
                : intent.getData();
        mUploadMessage.onReceiveValue(result);
        mUploadMessage = null;

    }
}

// Next part 

class MyWebChromeClient extends WebChromeClient {
    // The undocumented magic method override
    // Eclipse will swear at you if you try to put @Override here
    public void openFileChooser(ValueCallback<Uri> uploadMsg) {

        mUploadMessage = uploadMsg;
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("image/*");
        Cv5appActivity.this.startActivityForResult(
                Intent.createChooser(i, "Image Browser"),
                FILECHOOSER_RESULTCODE);
    }
}
Jbane
quelle
3
Können Sie bitte klarstellen, wo ich diesen Code platzieren soll? und wie soll ich es benutzen?
CAMOBAP
27
Ab 4.4 (KitKat) ist openFileChooser nicht mehr verfügbar, daher funktionieren Ansätze, die es verwenden, nicht.
Steve N
4
@nadeemgc In meinem Fall steuere ich auch den Webserver, sodass ich Android 4.4+ mithilfe eines anderen URL-Schemas (auch bekannt als "meine-App: // einige / andere / Argumente") für den Upload-Link erkenne und diese URLs abfange in shouldOverrideUrlLoading (), und dann eine Auswahl anzeigen und den Upload in nativem Code für diesen Fall durchführen. Es ist nicht gerade eine leichte Problemumgehung.
Steve N
2
Kann ich ein Bild in Android 4.4.2 mit Webview hochladen?
BABU K
@SteveN, können Sie ein Snippet bereitstellen? Es wäre großartig !
Gp2mv3
28

In 5.0 Lollipop hat Google eine offizielle Methode hinzugefügt, WebChromeClient.onShowFileChooser . Sie bieten sogar die Möglichkeit, die Absicht der Dateiauswahl automatisch zu generieren, sodass die eingegebenen MIME-Typen verwendet werden.

public class MyWebChromeClient extends WebChromeClient {
        // reference to activity instance. May be unnecessary if your web chrome client is member class.
    private MyActivity activity;

    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
        // make sure there is no existing message
        if (myActivity.uploadMessage != null) {
            myActivity.uploadMessage.onReceiveValue(null);
            myActivity.uploadMessage = null;
        }

        myActivity.uploadMessage = filePathCallback;

        Intent intent = fileChooserParams.createIntent();
        try {
            myActivity.startActivityForResult(intent, MyActivity.REQUEST_SELECT_FILE);
        } catch (ActivityNotFoundException e) {
            myActivity.uploadMessage = null;
            Toast.makeText(myActivity, "Cannot open file chooser", Toast.LENGTH_LONG).show();
            return false;
        }

        return true;
    }
}


public class MyActivity extends ... {
    public static final int REQUEST_SELECT_FILE = 100;
    public ValueCallback<Uri[]> uploadMessage;

    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        if (requestCode == REQUEST_SELECT_FILE) {
                if (uploadMessage == null) return;
                uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
                uploadMessage = null;
            }
        }
    }
}

Für Android-Versionen vor KitKat funktionieren die in den anderen Antworten genannten privaten Methoden. Ich habe keine gute Problemumgehung für KitKat (4.4) gefunden.

weiyin
quelle
in meiner Situation uploadMessage.onReceiveValue()funktioniert und hat einen Abschluss)
Ninja
Das hat bei mir nicht funktioniert. Ich habe versucht, mit Ihrem Code eine neue Klasse mit dem Namen "MyWebChromeClient" zu erstellen, aber festgestellt, dass MyActivity eine Klasse ist, die ich nicht importieren konnte. Ich konnte meine eigene Klasse mit dem Namen "MyActivity" erstellen, wusste aber nicht, was ich setzen soll hinein.
Rikkitikkitumbo
19

Ich fand, dass ich 3 Schnittstellendefinitionen brauchte, um verschiedene Versionen von Android zu handhaben.

public void openFileChooser(ValueCallback < Uri > uploadMsg) {
  mUploadMessage = uploadMsg;
  Intent i = new Intent(Intent.ACTION_GET_CONTENT);
  i.addCategory(Intent.CATEGORY_OPENABLE);
  i.setType("image/*");
  FreeHealthTrack.this.startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILECHOOSER_RESULTCODE);
}

public void openFileChooser(ValueCallback < Uri > uploadMsg, String acceptType) {
  openFileChooser(uploadMsg);
}

public void openFileChooser(ValueCallback < Uri > uploadMsg, String acceptType, String capture) {
  openFileChooser(uploadMsg);
}
Yaakov
quelle
3
Danke, der letzte wird für Jelly Bean benötigt, der für mich nicht funktioniert hat.
Shalafi
3
Wie gehe ich mit dieser Methode nach der Verschleierung um? Ich verwende dieselbe Methode ohne Verschleierung, sie funktioniert einwandfrei, aber wenn meine App mit Verschleierung bereitgestellt wird, wird diese Methode niemals aufgerufen. Ich habe diese Methode bewahrt. Hat jemand dieses Problem gesehen?
Harshawardhan
2
Es wäre besser, es umgekehrt zu machen, dh den Code in den letzten Code mit der reichsten Signatur einzufügen und anhand seiner Parameter zu entscheiden, welche Art von Absicht gestartet werden soll. Lassen Sie dann die anderen beiden den letzten mit Standardwerten für diese Parameter aufrufen.
Matto
16

Diese Lösung funktioniert auch für Honeycomb und Ice Cream Sandwich. Anscheinend hat Google eine coole neue Funktion eingeführt (Attribut akzeptieren) und vergessen, aus Gründen der Abwärtskompatibilität eine Überlastung zu implementieren.

protected class CustomWebChromeClient extends WebChromeClient
{
    // For Android 3.0+
    public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) 
    {  
        context.mUploadMessage = uploadMsg;  
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);  
        i.addCategory(Intent.CATEGORY_OPENABLE);  
        i.setType("image/*");  
        context.startActivityForResult( Intent.createChooser( i, "File Chooser" ), MainActivity.FILECHOOSER_RESULTCODE );  
    }

    // For Android < 3.0
    public void openFileChooser( ValueCallback<Uri> uploadMsg ) 
    {
        openFileChooser( uploadMsg, "" );
    }
}
Michel Olivier
quelle
Können Sie bitte klarstellen, wo ich diese Klasse platzieren soll? und wie soll ich es benutzen? Danke
CAMOBAP
Platzieren Sie diese Klasse an einer beliebigen Stelle in Ihrer Aktivität und verwenden Sie diesen Code webview.setWebChromeClient (neuer CustomWebChromeClient ());
Vishal Pawar
5
Ab 4.4 (KitKat) ist openFileChooser nicht mehr verfügbar, daher funktionieren Ansätze, die es verwenden, nicht.
Steve N
16

Die vollständige Lösung von hifarrer ist für mich sehr hilfreich.

Ich bin jedoch auf viele andere Probleme gestoßen - Unterstützung anderer MIME-Typen, Auflisten von Aufnahmegeräten (Kamera, Video, Audiorecoder), sofortiges Öffnen des Aufnahmegeräts (Beispiel: <input accept = "image / *; capture">) ...

Also habe ich eine Lösung entwickelt, die genauso funktioniert wie die Standard-Webbrowser-App.

Ich habe android-4.4.3_r1 / src / com / android / browser / UploadHandler.java verwendet. (danke an Rupert Rawnsley)

package org.mospi.agatenativewebview;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.webkit.JsResult;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebSettings.PluginState;
import android.widget.Toast;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        WebView webView = (WebView) findViewById(R.id.webView1);

        initWebView(webView);
        webView.loadUrl("http://google.com"); // TODO input your url

    }

    private final static Object methodInvoke(Object obj, String method, Class<?>[] parameterTypes, Object[] args) {
        try {
            Method m = obj.getClass().getMethod(method, new Class[] { boolean.class });
            m.invoke(obj, args);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private void initWebView(WebView webView) {

        WebSettings settings = webView.getSettings();

        settings.setJavaScriptEnabled(true);
        settings.setAllowFileAccess(true);
        settings.setDomStorageEnabled(true);
        settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
        settings.setLoadWithOverviewMode(true);
        settings.setUseWideViewPort(true);
        settings.setSupportZoom(true);
        // settings.setPluginsEnabled(true);
        methodInvoke(settings, "setPluginsEnabled", new Class[] { boolean.class }, new Object[] { true });
        // settings.setPluginState(PluginState.ON);
        methodInvoke(settings, "setPluginState", new Class[] { PluginState.class }, new Object[] { PluginState.ON });
        // settings.setPluginsEnabled(true);
        methodInvoke(settings, "setPluginsEnabled", new Class[] { boolean.class }, new Object[] { true });
        // settings.setAllowUniversalAccessFromFileURLs(true);
        methodInvoke(settings, "setAllowUniversalAccessFromFileURLs", new Class[] { boolean.class }, new Object[] { true });
        // settings.setAllowFileAccessFromFileURLs(true);
        methodInvoke(settings, "setAllowFileAccessFromFileURLs", new Class[] { boolean.class }, new Object[] { true });

        webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
        webView.clearHistory();
        webView.clearFormData();
        webView.clearCache(true);

        webView.setWebChromeClient(new MyWebChromeClient());
        // webView.setDownloadListener(downloadListener);
    }

    UploadHandler mUploadHandler;

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {

        if (requestCode == Controller.FILE_SELECTED) {
            // Chose a file from the file picker.
            if (mUploadHandler != null) {
                mUploadHandler.onResult(resultCode, intent);
            }
        }

        super.onActivityResult(requestCode, resultCode, intent);
    }

    class MyWebChromeClient extends WebChromeClient {
        public MyWebChromeClient() {

        }

        private String getTitleFromUrl(String url) {
            String title = url;
            try {
                URL urlObj = new URL(url);
                String host = urlObj.getHost();
                if (host != null && !host.isEmpty()) {
                    return urlObj.getProtocol() + "://" + host;
                }
                if (url.startsWith("file:")) {
                    String fileName = urlObj.getFile();
                    if (fileName != null && !fileName.isEmpty()) {
                        return fileName;
                    }
                }
            } catch (Exception e) {
                // ignore
            }

            return title;
        }

        @Override
        public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
            String newTitle = getTitleFromUrl(url);

            new AlertDialog.Builder(MainActivity.this).setTitle(newTitle).setMessage(message).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    result.confirm();
                }
            }).setCancelable(false).create().show();
            return true;
            // return super.onJsAlert(view, url, message, result);
        }

        @Override
        public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {

            String newTitle = getTitleFromUrl(url);

            new AlertDialog.Builder(MainActivity.this).setTitle(newTitle).setMessage(message).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    result.confirm();
                }
            }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    result.cancel();
                }
            }).setCancelable(false).create().show();
            return true;

            // return super.onJsConfirm(view, url, message, result);
        }

        // Android 2.x
        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
            openFileChooser(uploadMsg, "");
        }

        // Android 3.0
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
            openFileChooser(uploadMsg, "", "filesystem");
        }

        // Android 4.1
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            mUploadHandler = new UploadHandler(new Controller());
            mUploadHandler.openFileChooser(uploadMsg, acceptType, capture);
        }

        // Android 4.4, 4.4.1, 4.4.2
        // openFileChooser function is not called on Android 4.4, 4.4.1, 4.4.2,
        // you may use your own java script interface or other hybrid framework.          

        // Android 5.0.1
        public boolean onShowFileChooser(
                WebView webView, ValueCallback<Uri[]> filePathCallback,
                FileChooserParams fileChooserParams) {

            String acceptTypes[] = fileChooserParams.getAcceptTypes();

            String acceptType = "";
            for (int i = 0; i < acceptTypes.length; ++ i) {
                if (acceptTypes[i] != null && acceptTypes[i].length() != 0)
                    acceptType += acceptTypes[i] + ";";
            }
            if (acceptType.length() == 0)
                acceptType = "*/*";

            final ValueCallback<Uri[]> finalFilePathCallback = filePathCallback;

            ValueCallback<Uri> vc = new ValueCallback<Uri>() {

                @Override
                public void onReceiveValue(Uri value) {

                    Uri[] result;
                    if (value != null)
                        result = new Uri[]{value};
                    else
                        result = null;

                    finalFilePathCallback.onReceiveValue(result);

                }
            };

            openFileChooser(vc, acceptType, "filesystem");


            return true;
       }
    };

    class Controller {
        final static int FILE_SELECTED = 4;

        Activity getActivity() {
            return MainActivity.this;
        }
    }

    // copied from android-4.4.3_r1/src/com/android/browser/UploadHandler.java
    //////////////////////////////////////////////////////////////////////

    /*
     * Copyright (C) 2010 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

    // package com.android.browser;
    //
    // import android.app.Activity;
    // import android.content.ActivityNotFoundException;
    // import android.content.Intent;
    // import android.net.Uri;
    // import android.os.Environment;
    // import android.provider.MediaStore;
    // import android.webkit.ValueCallback;
    // import android.widget.Toast;
    //
    // import java.io.File;
    // import java.util.Vector;
    //
    // /**
    // * Handle the file upload callbacks from WebView here
    // */
    // public class UploadHandler {

    class UploadHandler {
        /*
         * The Object used to inform the WebView of the file to upload.
         */
        private ValueCallback<Uri> mUploadMessage;
        private String mCameraFilePath;
        private boolean mHandled;
        private boolean mCaughtActivityNotFoundException;
        private Controller mController;
        public UploadHandler(Controller controller) {
            mController = controller;
        }
        String getFilePath() {
            return mCameraFilePath;
        }
        boolean handled() {
            return mHandled;
        }
        void onResult(int resultCode, Intent intent) {
            if (resultCode == Activity.RESULT_CANCELED && mCaughtActivityNotFoundException) {
                // Couldn't resolve an activity, we are going to try again so skip
                // this result.
                mCaughtActivityNotFoundException = false;
                return;
            }
            Uri result = intent == null || resultCode != Activity.RESULT_OK ? null
                    : intent.getData();
            // As we ask the camera to save the result of the user taking
            // a picture, the camera application does not return anything other
            // than RESULT_OK. So we need to check whether the file we expected
            // was written to disk in the in the case that we
            // did not get an intent returned but did get a RESULT_OK. If it was,
            // we assume that this result has came back from the camera.
            if (result == null && intent == null && resultCode == Activity.RESULT_OK) {
                File cameraFile = new File(mCameraFilePath);
                if (cameraFile.exists()) {
                    result = Uri.fromFile(cameraFile);
                    // Broadcast to the media scanner that we have a new photo
                    // so it will be added into the gallery for the user.
                    mController.getActivity().sendBroadcast(
                            new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
                }
            }
            mUploadMessage.onReceiveValue(result);
            mHandled = true;
            mCaughtActivityNotFoundException = false;
        }
        void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            final String imageMimeType = "image/*";
            final String videoMimeType = "video/*";
            final String audioMimeType = "audio/*";
            final String mediaSourceKey = "capture";
            final String mediaSourceValueCamera = "camera";
            final String mediaSourceValueFileSystem = "filesystem";
            final String mediaSourceValueCamcorder = "camcorder";
            final String mediaSourceValueMicrophone = "microphone";
            // According to the spec, media source can be 'filesystem' or 'camera' or 'camcorder'
            // or 'microphone' and the default value should be 'filesystem'.
            String mediaSource = mediaSourceValueFileSystem;
            if (mUploadMessage != null) {
                // Already a file picker operation in progress.
                return;
            }
            mUploadMessage = uploadMsg;
            // Parse the accept type.
            String params[] = acceptType.split(";");
            String mimeType = params[0];
            if (capture.length() > 0) {
                mediaSource = capture;
            }
            if (capture.equals(mediaSourceValueFileSystem)) {
                // To maintain backwards compatibility with the previous implementation
                // of the media capture API, if the value of the 'capture' attribute is
                // "filesystem", we should examine the accept-type for a MIME type that
                // may specify a different capture value.
                for (String p : params) {
                    String[] keyValue = p.split("=");
                    if (keyValue.length == 2) {
                        // Process key=value parameters.
                        if (mediaSourceKey.equals(keyValue[0])) {
                            mediaSource = keyValue[1];
                        }
                    }
                }
            }
            //Ensure it is not still set from a previous upload.
            mCameraFilePath = null;
            if (mimeType.equals(imageMimeType)) {
                if (mediaSource.equals(mediaSourceValueCamera)) {
                    // Specified 'image/*' and requested the camera, so go ahead and launch the
                    // camera directly.
                    startActivity(createCameraIntent());
                    return;
                } else {
                    // Specified just 'image/*', capture=filesystem, or an invalid capture parameter.
                    // In all these cases we show a traditional picker filetered on accept type
                    // so launch an intent for both the Camera and image/* OPENABLE.
                    Intent chooser = createChooserIntent(createCameraIntent());
                    chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(imageMimeType));
                    startActivity(chooser);
                    return;
                }
            } else if (mimeType.equals(videoMimeType)) {
                if (mediaSource.equals(mediaSourceValueCamcorder)) {
                    // Specified 'video/*' and requested the camcorder, so go ahead and launch the
                    // camcorder directly.
                    startActivity(createCamcorderIntent());
                    return;
               } else {
                    // Specified just 'video/*', capture=filesystem or an invalid capture parameter.
                    // In all these cases we show an intent for the traditional file picker, filtered
                    // on accept type so launch an intent for both camcorder and video/* OPENABLE.
                    Intent chooser = createChooserIntent(createCamcorderIntent());
                    chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(videoMimeType));
                    startActivity(chooser);
                    return;
                }
            } else if (mimeType.equals(audioMimeType)) {
                if (mediaSource.equals(mediaSourceValueMicrophone)) {
                    // Specified 'audio/*' and requested microphone, so go ahead and launch the sound
                    // recorder.
                    startActivity(createSoundRecorderIntent());
                    return;
                } else {
                    // Specified just 'audio/*',  capture=filesystem of an invalid capture parameter.
                    // In all these cases so go ahead and launch an intent for both the sound
                    // recorder and audio/* OPENABLE.
                    Intent chooser = createChooserIntent(createSoundRecorderIntent());
                    chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(audioMimeType));
                    startActivity(chooser);
                    return;
                }
            }
            // No special handling based on the accept type was necessary, so trigger the default
            // file upload chooser.
            startActivity(createDefaultOpenableIntent());
        }
        private void startActivity(Intent intent) {
            try {
                mController.getActivity().startActivityForResult(intent, Controller.FILE_SELECTED);
            } catch (ActivityNotFoundException e) {
                // No installed app was able to handle the intent that
                // we sent, so fallback to the default file upload control.
                try {
                    mCaughtActivityNotFoundException = true;
                    mController.getActivity().startActivityForResult(createDefaultOpenableIntent(),
                            Controller.FILE_SELECTED);
                } catch (ActivityNotFoundException e2) {
                    // Nothing can return us a file, so file upload is effectively disabled.
                    Toast.makeText(mController.getActivity(), R.string.uploads_disabled,
                            Toast.LENGTH_LONG).show();
                }
            }
        }
        private Intent createDefaultOpenableIntent() {
            // Create and return a chooser with the default OPENABLE
            // actions including the camera, camcorder and sound
            // recorder where available.
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            Intent chooser = createChooserIntent(createCameraIntent(), createCamcorderIntent(),
                    createSoundRecorderIntent());
            chooser.putExtra(Intent.EXTRA_INTENT, i);
            return chooser;
        }
        private Intent createChooserIntent(Intent... intents) {
            Intent chooser = new Intent(Intent.ACTION_CHOOSER);
            chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);
            chooser.putExtra(Intent.EXTRA_TITLE,
                    mController.getActivity().getResources()
                            .getString(R.string.choose_upload));
            return chooser;
        }
        private Intent createOpenableIntent(String type) {
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType(type);
            return i;
        }
        private Intent createCameraIntent() {
            Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            File externalDataDir = Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_DCIM);
            File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
                    File.separator + "browser-photos");
            cameraDataDir.mkdirs();
            mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
                    System.currentTimeMillis() + ".jpg";
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
            return cameraIntent;
        }
        private Intent createCamcorderIntent() {
            return new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        }
        private Intent createSoundRecorderIntent() {
            return new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
        }
    }
}

zusätzliche String-Resoruce von res / values ​​/ string.xml:

<string name="uploads_disabled">File uploads are disabled.</string>
<string name="choose_upload">Choose file for upload</string>

Wenn Sie proguard verwenden, benötigen Sie möglicherweise die folgende Option in proguard-project.txt:

-keepclassmembers class * extends android.webkit.WebChromeClient {
   public void openFileChooser(...);
}

UPDATE # 1 (2015.09.09)

Fügt Code für die Kompatibilität mit Android 5.0.1 hinzu.

Unbekannter Stapel
quelle
Kann es nicht zum Laufen bringen in 4.4.2. Haben Sie es auf Android 4.4.2
Ana Llera
2
@Anna openFileChooser-Funktion wird unter Android 4.4, 4.4.1, 4.4.2 nicht aufgerufen. Dieser Fehler wurde unter Android 4.4.3 behoben. ref.) http://code.google.com/p/android/issues/detail?id=62220, aber leider verwenden viele Leute 4.4.2. Ich denke, Sie können Ihre eigene Java-Skript-Oberfläche (siehe Antwort von DanelK) oder ein anderes Hybrid-Framework (Cordova, Phonegap, Achat ...) verwenden. In meinem Fall kann ich HTML-Dateien auf dem Server nicht ändern. Also habe ich das Agate WebView Java Script Plugin verwendet. AgateWebViewFileUpload_AndroidEclipse
UnknownStack
@UnknownStack Ich versuche auch, das Hochladen von Achat-Webview-Dateien zu implementieren. Anstelle von htm page möchte ich eine URL für die Webansicht festlegen. Wie mache ich das?
Tushar Narang
@tusharnarang Öffnen Sie die Datei "assets / moml / ui / webView.xml". Suchen Sie dann das Attribut AGATEWEBVIEW.src und ersetzen Sie den Wert "index.htm" durch Ihre URL. (Ref. github.com/applusform/WebViewFileUploadFix )
UnknownStack
@UnknownStack. Wenn ich die Zurück-Taste drücke, wird die Anwendung geschlossen. Wo kann dieser Code in Ihrem Code verwendet werden? )) {this.webView.goBack (); return true; } return super.onKeyDown (keyCode, event); }
Sunil y
11

Ich fand es notwendig public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture), in Android 4.1 zu definieren . Dann folgte ich Michel Oliviers Lösung.

Stalepretzel
quelle
Können Sie bitte klarstellen, wo ich diese Methode definieren soll? und wie soll ich es benutzen?
CAMOBAP
11

Das ist Arbeit für mich. Arbeiten Sie auch für Nougat und Marshmallow [ 2][3]

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();
    private final static int FCR = 1;
    WebView webView;
    private String mCM;
    private ValueCallback<Uri> mUM;
    private ValueCallback<Uri[]> mUMA;

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);

        if (Build.VERSION.SDK_INT >= 21) {
            Uri[] results = null;

            //Check if response is positive
            if (resultCode == Activity.RESULT_OK) {
                if (requestCode == FCR) {

                    if (null == mUMA) {
                        return;
                    }
                    if (intent == null) {
                        //Capture Photo if no image available
                        if (mCM != null) {
                            results = new Uri[]{Uri.parse(mCM)};
                        }
                    } else {
                        String dataString = intent.getDataString();
                        if (dataString != null) {
                            results = new Uri[]{Uri.parse(dataString)};
                        }
                    }
                }
            }
            mUMA.onReceiveValue(results);
            mUMA = null;
        } else {

            if (requestCode == FCR) {
                if (null == mUM) return;
                Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
                mUM.onReceiveValue(result);
                mUM = null;
            }
        }
    }

    @SuppressLint({"SetJavaScriptEnabled", "WrongViewCast"})
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (Build.VERSION.SDK_INT >= 23 && (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, 1);
        }

        webView = (WebView) findViewById(R.id.ifView);
        assert webView != null;

        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setAllowFileAccess(true);

        if (Build.VERSION.SDK_INT >= 21) {
            webSettings.setMixedContentMode(0);
            webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
        } else if (Build.VERSION.SDK_INT >= 19) {
            webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
        } else if (Build.VERSION.SDK_INT < 19) {
            webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        }

        webView.setWebViewClient(new Callback());
        webView.loadUrl("https://infeeds.com/");
        webView.setWebChromeClient(new WebChromeClient() {

            //For Android 3.0+
            public void openFileChooser(ValueCallback<Uri> uploadMsg) {

                mUM = uploadMsg;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("*/*");
                MainActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), FCR);
            }

            // For Android 3.0+, above method not supported in some android 3+ versions, in such case we use this
            public void openFileChooser(ValueCallback uploadMsg, String acceptType) {

                mUM = uploadMsg;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("*/*");
                MainActivity.this.startActivityForResult(
                        Intent.createChooser(i, "File Browser"),
                        FCR);
            }

            //For Android 4.1+
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {

                mUM = uploadMsg;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("*/*");
                MainActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), MainActivity.FCR);
            }

            //For Android 5.0+
            public boolean onShowFileChooser(
                    WebView webView, ValueCallback<Uri[]> filePathCallback,
                    WebChromeClient.FileChooserParams fileChooserParams) {

                if (mUMA != null) {
                    mUMA.onReceiveValue(null);
                }

                mUMA = filePathCallback;
                Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                if (takePictureIntent.resolveActivity(MainActivity.this.getPackageManager()) != null) {

                    File photoFile = null;

                    try {
                        photoFile = createImageFile();
                        takePictureIntent.putExtra("PhotoPath", mCM);
                    } catch (IOException ex) {
                        Log.e(TAG, "Image file creation failed", ex);
                    }
                    if (photoFile != null) {
                        mCM = "file:" + photoFile.getAbsolutePath();
                        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
                    } else {
                        takePictureIntent = null;
                    }
                }

                Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
                contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
                contentSelectionIntent.setType("*/*");
                Intent[] intentArray;

                if (takePictureIntent != null) {
                    intentArray = new Intent[]{takePictureIntent};
                } else {
                    intentArray = new Intent[0];
                }

                Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
                chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
                chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
                startActivityForResult(chooserIntent, FCR);

                return true;
            }
        });
    }

    // Create an image file
    private File createImageFile() throws IOException {

        @SuppressLint("SimpleDateFormat") String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "img_" + timeStamp + "_";
        File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        return File.createTempFile(imageFileName, ".jpg", storageDir);
    }

    @Override
    public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {

        if (event.getAction() == KeyEvent.ACTION_DOWN) {

            switch (keyCode) {
                case KeyEvent.KEYCODE_BACK:

                    if (webView.canGoBack()) {
                        webView.goBack();
                    } else {
                        finish();
                    }

                    return true;
            }
        }

        return super.onKeyDown(keyCode, event);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

    public class Callback extends WebViewClient {
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            Toast.makeText(getApplicationContext(), "Failed loading app!", Toast.LENGTH_SHORT).show();
        }
    }
}
ISURU
quelle
9

Ich habe es tatsächlich geschafft, die Dateiauswahl in Kitkat anzuzeigen, ein Bild auszuwählen und den Dateipfad im Aktivitätsergebnis abzurufen, aber das einzige, was ich nicht "reparieren" kann (diese Problemumgehung verursachen), ist, die eingegebene Datei zum Füllen zu bringen raus mit Dateidaten.

Weiß jemand, wie man von einer Aktivität aus auf das Eingabefeld zugreift? Am dieses Beispiel unter Verwendung von Kommentar . Ist nur dieses letzte Stück, der letzte Stein in der Wand, den ich nur an der richtigen Stelle platzieren muss (obwohl ich das Hochladen der Bilddatei direkt aus dem Code auslösen könnte.

UPDATE # 1

Ich bin kein Hardcore-Android-Entwickler, also zeige ich Code auf Newbie-Ebene. Ich erstelle eine neue Aktivität in bereits vorhandenen Aktivitäten

Manifestierter Teil

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application android:label="TestApp">
 <activity android:name=".BrowseActivity"></activity>
</application>

Ist meine BrowseActivity Klasse aus diesem Beispiel zu schaffen Antwort . Die WebChromeClient () -Instanz sieht im Wesentlichen gleich aus, mit Ausnahme des letzten Teils, wodurch der Picker-UI-Teil ausgelöst wird ...

private final static int FILECHOOSER_RESULTCODE=1;  
private final static int KITKAT_RESULTCODE = 2;

...

// The new WebChromeClient() looks pretty much the same, except one piece...

WebChromeClient chromeClient = new WebChromeClient(){  
    // For Android 3.0+
    public void openFileChooser(ValueCallback<Uri> uploadMsg) { /* Default code */ }  

    // For Android 3.0+
    public void openFileChooser( ValueCallback uploadMsg, String acceptType ) { /* Default code */ }  

    //For Android 4.1, also default but it'll be as example
    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
        mUploadMessage = uploadMsg;
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("*/*");
        BrowseActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), BrowseActivity.FILECHOOSER_RESULTCODE);

    }  

    // The new code
    public void showPicker( ValueCallback<Uri> uploadMsg ){  
        // Here is part of the issue, the uploadMsg is null since it is not triggered from Android
        mUploadMessage = uploadMsg; 
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("*/*");
        BrowseActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), BrowseActivity.KITKAT_RESULTCODE);
    }}

Und noch ein paar Sachen

web = new WebView(this);
// Notice this part, setting chromeClient as js interface is just lazy
web.getSettings().setJavaScriptEnabled(true);
web.addJavascriptInterface(chromeClient, "jsi" );
web.getSettings().setAllowFileAccess(true);
web.getSettings().setAllowContentAccess(true);
web.clearCache(true);
web.loadUrl( "http://as3breeze.com/upload.html" );
web.setWebViewClient(new myWebClient());
web.setWebChromeClient(chromeClient);


@Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) {  
  Log.d("Result", "("+requestCode+ ") - (" +resultCode  + ") - (" + intent + ") - " + mUploadMessage);  
    if (null == intent) return;  
    Uri result = null;  
    if(requestCode==FILECHOOSER_RESULTCODE)  
    {  
        Log.d("Result","Old android");  
        if (null == mUploadMessage) return;  
        result = intent == null || resultCode != RESULT_OK ? null  : intent.getData();  
        mUploadMessage.onReceiveValue(result);  
        mUploadMessage = null;  
    } else if (requestCode == KITKAT_RESULTCODE) {  
        Log.d("Result","Kitkat android");  
        result = intent.getData();  
        final int takeFlags = intent.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION  | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);  
        String path = getPath( this, result);  
        File selectedFile = new File(path); 
//I used you example with a bit of editing so thought i would share, here i added a method to upload the file to the webserver
File selectedFile = new File(path);  
            UploadFile(selectedFile);


        //mUploadMessage.onReceiveValue( Uri.parse(selectedFile.toString()) );  
        // Now we have the file but since mUploadMessage was null, it gets errors
    }  
}

 public void UploadFile(File selectedFile)
{
    Random rnd = new Random();
    String sName = "File" + rnd.nextInt(999999) + selectedFile.getAbsolutePath().substring(selectedFile.getAbsolutePath().lastIndexOf("."));
    UploadedFileName = sName;
    uploadFile = selectedFile;
    if (progressBar != null && progressBar.isShowing())
    {
        progressBar.dismiss();
    }
 // prepare for a progress bar dialog
    progressBar = new ProgressDialog(mContext);
    progressBar.setCancelable(true);
    progressBar.setMessage("Uploading File");
    progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);            
    progressBar.show();
    new Thread() {

        public void run() 
        {
            int serverResponseCode;
            String serverResponseMessage;
            HttpURLConnection connection = null;
            DataOutputStream outputStream = null;
            DataInputStream inputStream = null;
            String pathToOurFile = uploadFile.getAbsolutePath();
            String urlServer = "http://serveraddress/Scripts/UploadHandler.php?name" + UploadedFileName;
            String lineEnd = "\r\n";
            String twoHyphens = "--";
            String boundary =  "*****";

            int bytesRead, bytesAvailable, bufferSize;
            byte[] buffer;
            int maxBufferSize = 1*1024*1024;

            try
            {
                FileInputStream fileInputStream = new FileInputStream(uploadFile);

                URL url = new URL(urlServer);
                connection = (HttpURLConnection) url.openConnection();
                Log.i("File", urlServer);

                // Allow Inputs &amp; Outputs.
                connection.setDoInput(true);
                connection.setDoOutput(true);
                connection.setUseCaches(false);

                // Set HTTP method to POST.
                connection.setRequestMethod("POST");

                connection.setRequestProperty("Connection", "Keep-Alive");
                connection.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
                Log.i("File", "Open conn");

                outputStream = new DataOutputStream( connection.getOutputStream() );

                outputStream.writeBytes(twoHyphens + boundary + lineEnd);
                outputStream.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + pathToOurFile +"\"" + lineEnd);
                outputStream.writeBytes(lineEnd);
                Log.i("File", "write bytes");

                bytesAvailable = fileInputStream.available();
                bufferSize = Math.min(bytesAvailable, maxBufferSize);
                buffer = new byte[bufferSize];
                Log.i("File", "available: " + fileInputStream.available());

                // Read file
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                Log.i("file", "Bytes Read: " + bytesRead);
                while (bytesRead > 0)
                {
                    outputStream.write(buffer, 0, bufferSize);
                    bytesAvailable = fileInputStream.available();
                    bufferSize = Math.min(bytesAvailable, maxBufferSize);
                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                }

                outputStream.writeBytes(lineEnd);
                outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

                // Responses from the server (code and message)
                serverResponseCode = connection.getResponseCode();
                serverResponseMessage = connection.getResponseMessage();
                Log.i("file repsonse", serverResponseMessage);

//once the file is uploaded call a javascript function to verify the user wants to save the image
                progressBar.dismiss();
                runOnUiThread(new Runnable() 
                {

                    @Override
                    public void run() 
                    {
                        Log.i("start", "File name: " + UploadedFileName);
                        WebView myWebView = (WebView) findViewById(R.id.webview);
                        myWebView.loadUrl("javascript:CheckImage('" + UploadedFileName + "')");
                    }
                });


                fileInputStream.close();
                outputStream.flush();
                outputStream.close();
            }
            catch (Exception ex)
            {
                Log.i("exception", "Error: " + ex.toString());
            }               
        }
    }.start();

}}

Zum Schluss noch etwas Code, um den tatsächlichen Dateipfad zu erhalten, Code, der auf SO gefunden wurde, und ich habe auch eine Post-URL in Kommentaren hinzugefügt, damit der Autor Credits für seine Arbeit erhält.

/**
 * Get a file path from a Uri. This will get the the path for Storage Access
 * Framework Documents, as well as the _data field for the MediaStore and
 * other file-based ContentProviders.
 *
 * @param context The context.
 * @param uri The Uri to query.
 * @author paulburke
 * @source https://stackoverflow.com/a/20559175
 */
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getPath(final Context context, final Uri uri) {

    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            if ("primary".equalsIgnoreCase(type)) {
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }

            // TODO handle non-primary volumes
        }
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {

            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

            return getDataColumn(context, contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[] {
                    split[1]
            };

            return getDataColumn(context, contentUri, selection, selectionArgs);
        }
    }
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(uri.getScheme())) {
        return getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }

    return null;
}

/**
 * Get the value of the data column for this Uri. This is useful for
 * MediaStore Uris, and other file-based ContentProviders.
 *
 * @param context The context.
 * @param uri The Uri to query.
 * @param selection (Optional) Filter used in the query.
 * @param selectionArgs (Optional) Selection arguments used in the query.
 * @return The value of the _data column, which is typically a file path.
 * @source https://stackoverflow.com/a/20559175
 */
public static String getDataColumn(Context context, Uri uri, String selection,
                                   String[] selectionArgs) {

    Cursor cursor = null;
    final String column = "_data";
    final String[] projection = {
            column
    };

    try {
        cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                null);
        if (cursor != null && cursor.moveToFirst()) {
            final int column_index = cursor.getColumnIndexOrThrow(column);
            return cursor.getString(column_index);
        }
    } finally {
        if (cursor != null)
            cursor.close();
    }
    return null;
}


/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is ExternalStorageProvider.
 * @source https://stackoverflow.com/a/20559175
 */
public static boolean isExternalStorageDocument(Uri uri) {
    return "com.android.externalstorage.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is DownloadsProvider.
 * @source https://stackoverflow.com/a/20559175
 */
public static boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is MediaProvider.
 * @source https://stackoverflow.com/a/20559175
 */
public static boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
}  

Zuletzt muss die HTML-Seite diese neue Methode von showPicker auslösen (speziell unter A4.4).

<form id="form-upload" method="post" enctype="multipart/form-data">
    <input id="fileupload" name="fileupload" type="file" onclick="javascript:prepareForPicker();"/>
</form>
<script type="text/javascript">
function getAndroidVersion() {
    var ua = navigator.userAgent; 
    var match = ua.match(/Android\s([0-9\.]*)/);
    return match ? match[1] : false;
};
function prepareForPicker(){
    if(getAndroidVersion().indexOf("4.4") != -1){
        window.jsi.showPicker();
        return false;
    }
}

function CheckImage(name)
{
//Check to see if user wants to save I used some ajax to save the file if necesarry
}
</script>
Deko
quelle
Entschuldigen Sie die späte Antwort, haben Sie keine funktionierende Demo für diese. Dies war zu dieser Zeit eine einfache Forschung. Entschuldigung :(
Deko
6

2019: Dieser Code hat bei mir funktioniert (Getestet auf Androids 5 - 9).

package com.example.filechooser;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Bundle;
import android.webkit.SslErrorHandler;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;


public class MainActivity extends Activity {

    // variables para manejar la subida de archivos
    private final static int FILECHOOSER_RESULTCODE = 1;
    private ValueCallback<Uri[]> mUploadMessage;

    // variable para manejar el navegador empotrado
    WebView mainWebView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        // instanciamos el webview
        mainWebView = findViewById(R.id.main_web_view);

        // establecemos el cliente interno para que la navegacion no se salga de la aplicacion
        mainWebView.setWebViewClient(new MyWebViewClient());

        // establecemos el cliente chrome para seleccionar archivos
        mainWebView.setWebChromeClient(new MyWebChromeClient());

        // configuracion del webview
        mainWebView.getSettings().setJavaScriptEnabled(true);

        // cargamos la pagina
        mainWebView.loadUrl("https://example.com");
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {

        // manejo de seleccion de archivo
        if (requestCode == FILECHOOSER_RESULTCODE) {

            if (null == mUploadMessage || intent == null || resultCode != RESULT_OK) {
                return;
            }

            Uri[] result = null;
            String dataString = intent.getDataString();

            if (dataString != null) {
                result = new Uri[]{ Uri.parse(dataString) };
            }

            mUploadMessage.onReceiveValue(result);
            mUploadMessage = null;
        }
    }


    // ====================
    // Web clients classes
    // ====================

    /**
     * Clase para configurar el webview
     */
    private class MyWebViewClient extends WebViewClient {

        // permite la navegacion dentro del webview
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    }


    /**
     * Clase para configurar el chrome client para que nos permita seleccionar archivos
     */
    private class MyWebChromeClient extends WebChromeClient {

        // maneja la accion de seleccionar archivos
        @Override
        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {

            // asegurar que no existan callbacks
            if (mUploadMessage != null) {
                mUploadMessage.onReceiveValue(null);
            }

            mUploadMessage = filePathCallback;

            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*"); // set MIME type to filter

            MainActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), MainActivity.FILECHOOSER_RESULTCODE );

            return true;
        }
    }

}

Hoffnung kann dir helfen.

sebasdev
quelle
Für die onActivityResult-Methode heißt es, dass der Aufruf an super fehlt
sumitkanoje
@sumitkanoje Versuchen Sie, den Aufruf von super vor dem if-Block zu setzen: super.onActivityResult (requestCode, resultCode, intent);
sebasdev
5

Habe eine LÖSUNG gefunden, die für mich funktioniert! Fügen Sie der Datei eine weitere Regel hinzu proguard-android.txt:

-keepclassmembers class * extends android.webkit.WebChromeClient {
     public void openFileChooser(...);
}
ViliusK
quelle
Welche Android-Version verwenden Sie?
Punchlinern
4.4.4 CyanogemMode 11
ViliusK
4

Kotlin-Lösung für Android 8:

private var mUploadMessage: ValueCallback<Uri>? = null
private var uploadMessage: ValueCallback<Array<Uri>>? = null

Konstanten:

const val FILECHOOSER_RESULTCODE = 1
const val REQUEST_SELECT_FILE = 100

WebView-Setup:

webView.webChromeClient = object : WebChromeClient() {
        override fun onPermissionRequest(request: PermissionRequest?) {
            Log.d("MainActivity", "onPermissionRequest")
            requestPermission(request)
        }


        // For Android 3.0+
        fun openFileChooser(uploadMsg: ValueCallback<*>, acceptType: String) {
            mUploadMessage = uploadMsg as ValueCallback<Uri>
            val i = Intent(Intent.ACTION_GET_CONTENT)
            i.addCategory(Intent.CATEGORY_OPENABLE)
            i.type = "*/*"
            this@MainActivity.startActivityForResult(
                    Intent.createChooser(i, "File Browser"),
                    FILECHOOSER_RESULTCODE)
        }

        //For Android 4.1
        fun openFileChooser(uploadMsg: ValueCallback<Uri>, acceptType: String, capture: String) {
            mUploadMessage = uploadMsg
            val i = Intent(Intent.ACTION_GET_CONTENT)
            i.addCategory(Intent.CATEGORY_OPENABLE)
            i.type = "image/*"
            this@MainActivity.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE)

        }

        protected fun openFileChooser(uploadMsg: ValueCallback<Uri>) {
            mUploadMessage = uploadMsg
            val intent = Intent(Intent.ACTION_GET_CONTENT)
            intent.addCategory(Intent.CATEGORY_OPENABLE)
            intent.type = "*/*"
            startActivityForResult(Intent.createChooser(intent, "File Chooser"), FILECHOOSER_RESULTCODE)
        }

        override fun onShowFileChooser(webView: WebView?, filePathCallback: ValueCallback<Array<Uri>>?, fileChooserParams: FileChooserParams?): Boolean {
            uploadMessage?.onReceiveValue(null)
            uploadMessage = null

            uploadMessage = filePathCallback

            val intent = fileChooserParams!!.createIntent()
            try {
                startActivityForResult(intent, REQUEST_SELECT_FILE)
            } catch (e: ActivityNotFoundException) {
                uploadMessage = null
                Toast.makeText(applicationContext, "Cannot Open File Chooser", Toast.LENGTH_LONG).show()
                return false
            }

            return true
        }

    }

Und der Teil onAcrtivityResult:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        if (requestCode === REQUEST_SELECT_FILE) {
            if (uploadMessage == null)
                return
            print("result code = " + resultCode)
            var results: Array<Uri>? = WebChromeClient.FileChooserParams.parseResult(resultCode, data)
            uploadMessage?.onReceiveValue(results)
            uploadMessage = null
        }
    } else if (requestCode === FILECHOOSER_RESULTCODE) {
        if (null == mUploadMessage)
            return
        // Use MainActivity.RESULT_OK if you're implementing WebView inside Fragment
        // Use RESULT_OK only if you're implementing WebView inside an Activity
        val result = if (intent == null || resultCode !== RESULT_OK) null else intent.data
        mUploadMessage?.onReceiveValue(result)
        mUploadMessage = null
    } else
        Toast.makeText(applicationContext, "Failed to Upload Image", Toast.LENGTH_LONG).show()
}

Bitte beachten Sie, dass unsere Intent-Variable "Daten" heißt.

WorieN
quelle
1
Vielen Dank! Ich würde dir ein Bier holen
Rafael Ruiz Muñoz
2

Haben Sie diese Links besucht? http://groups.google.com/group/android-developers/browse_thread/thread/dcaf8b2fdd8a90c4/62d5e2ffef31ebdb

http://moazzam-khan.com/blog/?tag=android-upload-file

http://evgenyg.wordpress.com/2010/05/01/uploading-files-multipart-post-apache/

Kurzes Beispiel für das Hochladen von Dateien über Java lib Apache Commons

Ich denke, Sie werden Hilfe davon bekommen

Android
quelle
Vielen Dank für Ihre Vorschläge Pragna. Das eigentliche Problem ist, dass in der Webansicht nicht das Dialogfeld zum Hochladen von Dateien angezeigt wird, in dem ich eine Datei zum Hochladen auswählen kann . Also, zuerst muss ich eine Lösung , die mir ermöglicht , die Datei - Upload - Dialogfeld angezeigt werden , dann habe ich auf die Links verweisen können Sie vorgeschlagen haben.
user741148
thx 4 ur Vorschläge Pragna. Keine funktioniert ... tatsächlich habe ich beobachtet, dass das Überschreiben der openFileChooser-Methode (ValueCallback <Uri>) von WebChromeClient in Android 2.2 funktioniert, wobei das Klicken auf ein Feld <input type = "file"> in der Benutzeroberfläche die Dateiauswahl erleichtert Galerie funktioniert jedoch nicht in Android 3.0 ... there4, ich dachte daran, das Hochladen von Dateien in Webview mit Flash-Datei-Upload zu versuchen, aber im Android 3.0-Emulator ist Flash nicht standardmäßig installiert und zur Installation ist die Market App nicht verfügbar und so weiter Komplikationen ... abschließend scheint eine Lösung mit Gegebenheiten unmöglich !
user741148
1

In KitKat können Sie das Storage Access Framework verwenden.

Storage Access Framework / Schreiben einer Client-App

NDC035
quelle
"Vielleicht"? Können Sie mehr Kontext für Ihren Beitrag bereitstellen? Bitte lesen Sie Wie man antwortet .
Brasofilo
Gibt es Beispielcode für die Implementierung in Android 4.4.2 mithilfe von Webview?
BABU K
1

Webview - Einzelne und mehrere Dateien auswählen

Sie benötigen zwei Minuten, um diesen Code zu implementieren:

build.gradle

implementation 'com.github.angads25:filepicker:1.1.1'

Java-Code:

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.bivoiclient.utils.Constants;
import com.github.angads25.filepicker.controller.DialogSelectionListener;
import com.github.angads25.filepicker.model.DialogConfigs;
import com.github.angads25.filepicker.model.DialogProperties;
import com.github.angads25.filepicker.view.FilePickerDialog;

import java.io.File;

public class WebBrowserScreen extends Activity {

    private WebView webView;
    private ValueCallback<Uri[]> mUploadMessage;
    private FilePickerDialog dialog;
    private String LOG_TAG = "DREG";
    private Uri[] results;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_complain);

        webView = findViewById(R.id.webview);
        WebSettings webSettings = webView.getSettings();
        webSettings.setAppCacheEnabled(true);
        webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        webSettings.setJavaScriptEnabled(true);
        webSettings.setLoadWithOverviewMode(true);
        webSettings.setAllowFileAccess(true);
        webView.setWebViewClient(new PQClient());
        webView.setWebChromeClient(new PQChromeClient());
        if (Build.VERSION.SDK_INT >= 19) {
            webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
        } else {
            webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        }

        webView.loadUrl(Constants.COMPLAIN_URL);

    }

    private void openFileSelectionDialog() {

        if (null != dialog && dialog.isShowing()) {
            dialog.dismiss();
        }

        //Create a DialogProperties object.
        final DialogProperties properties = new DialogProperties();

        //Instantiate FilePickerDialog with Context and DialogProperties.
        dialog = new FilePickerDialog(WebBrowserScreen.this, properties);
        dialog.setTitle("Select a File");
        dialog.setPositiveBtnName("Select");
        dialog.setNegativeBtnName("Cancel");
        properties.selection_mode = DialogConfigs.MULTI_MODE; // for multiple files
//        properties.selection_mode = DialogConfigs.SINGLE_MODE; // for single file
        properties.selection_type = DialogConfigs.FILE_SELECT;

        //Method handle selected files.
        dialog.setDialogSelectionListener(new DialogSelectionListener() {
            @Override
            public void onSelectedFilePaths(String[] files) {
                results = new Uri[files.length];
                for (int i = 0; i < files.length; i++) {
                    String filePath = new File(files[i]).getAbsolutePath();
                    if (!filePath.startsWith("file://")) {
                        filePath = "file://" + filePath;
                    }
                    results[i] = Uri.parse(filePath);
                    Log.d(LOG_TAG, "file path: " + filePath);
                    Log.d(LOG_TAG, "file uri: " + String.valueOf(results[i]));
                }
                mUploadMessage.onReceiveValue(results);
                mUploadMessage = null;
            }
        });
        dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialogInterface) {
                if (null != mUploadMessage) {
                    if (null != results && results.length >= 1) {
                        mUploadMessage.onReceiveValue(results);
                    } else {
                        mUploadMessage.onReceiveValue(null);
                    }
                }
                mUploadMessage = null;
            }
        });
        dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialogInterface) {
                if (null != mUploadMessage) {
                    if (null != results && results.length >= 1) {
                        mUploadMessage.onReceiveValue(results);
                    } else {
                        mUploadMessage.onReceiveValue(null);
                    }
                }
                mUploadMessage = null;
            }
        });

        dialog.show();

    }

    public class PQChromeClient extends WebChromeClient {

        @Override
        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
            // Double check that we don't have any existing callbacks
            if (mUploadMessage != null) {
                mUploadMessage.onReceiveValue(null);
            }
            mUploadMessage = filePathCallback;

            openFileSelectionDialog();

            return true;
        }

    }

    //Add this method to show Dialog when the required permission has been granted to the app.
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
        switch (requestCode) {
            case FilePickerDialog.EXTERNAL_READ_PERMISSION_GRANT: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    if (dialog != null) {
                        openFileSelectionDialog();
                    }
                } else {
                    //Permission has not been granted. Notify the user.
                    Toast.makeText(WebBrowserScreen.this, "Permission is Required for getting list of files", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // Check if the key event was the Back button and if there's history
        if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
            webView.goBack();
            return true;
        }
        // If it wasn't the Back key or there's no web page history, bubble up to the default
        // system behavior (probably exit the activity)

        return super.onKeyDown(keyCode, event);
    }


    public class PQClient extends WebViewClient {
        ProgressBar progressDialog;

        public boolean shouldOverrideUrlLoading(WebView view, String url) {

            // If url contains mailto link then open Mail Intent
            if (url.contains("mailto:")) {

                // Could be cleverer and use a regex
                //Open links in new browser
                view.getContext().startActivity(
                        new Intent(Intent.ACTION_VIEW, Uri.parse(url)));

                // Here we can open new activity

                return true;

            } else {
                // Stay within this webview and load url
                view.loadUrl(url);
                return true;
            }
        }

        // Show loader on url load
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            // Then show progress  Dialog
            // in standard case YourActivity.this
            if (progressDialog == null) {
                progressDialog = findViewById(R.id.progressBar);
                progressDialog.setVisibility(View.VISIBLE);
            }
        }

        // Called when all page resources loaded
        public void onPageFinished(WebView view, String url) {
            webView.loadUrl("javascript:(function(){ " +
                    "document.getElementById('android-app').style.display='none';})()");

            try {
                // Close progressDialog
                progressDialog.setVisibility(View.GONE);
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
    }

}
Ahamadullah Saikat
quelle
Diese Zeile zeigt den Fehlerimport com.bivoiclient.utils.Constants.
Md. Ashikur Rahman
Entfernen Sie diesen Import und setzen Sie Ihre URL auf Folgendes: webView.loadUrl (" google.com" );
Ahamadullah Saikat
Hallo Ahamadullah Saikat, für solche Bemühungen funktioniert es wie gewohnt ... Funktioniert nicht standardmäßig. Wenn ein Benutzer standardmäßig Anhangsoptionen in der Webansicht öffnen möchte, wie kann er dies tun? Es ist eine Umgehung.
Tarit Ray
0

Ich bin neu in Andriod und habe auch damit zu kämpfen. Laut Google Referenzhandbuch WebView.

Standardmäßig bietet ein WebView keine browserähnlichen Widgets, aktiviert kein JavaScript und Webseitenfehler werden ignoriert. Wenn Sie nur HTML als Teil Ihrer Benutzeroberfläche anzeigen möchten, ist dies wahrscheinlich in Ordnung. Der Benutzer muss nicht über das Lesen hinaus mit der Webseite interagieren, und die Webseite muss nicht mit dem Benutzer interagieren. Wenn Sie tatsächlich einen vollständigen Webbrowser möchten, möchten Sie die Browser-Anwendung wahrscheinlich mit einer URL-Absicht aufrufen, anstatt sie mit einer WebView anzuzeigen.

Beispielcode, den ich in MainActvity.java ausgeführt habe.

 Uri uri = Uri.parse("https://www.example.com");
 Intent intent = new Intent(Intent.ACTION_VIEW, uri);
 startActivity(intent);

Ausgetrieben

package example.com.myapp;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.content.Intent;
import android.net.Uri;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Uri uri = Uri.parse("http://www.example.com/");
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        startActivity(intent);
        getSupportActionBar().hide();
    }}
JetSet
quelle
0

Ich habe fast einen Monat lang zu diesem Thema recherchiert. Alles ist fehlgeschlagen. Alle Codes, die auf mehreren Websites angezeigt werden, funktionieren nicht gut. Aber hier gibt es die beste Lösung

https://github.com/chiclaim/android-webview-upload-file

Schritte

1) Klicken Sie auf Klonen oder herunterladen

2) Holen Sie sich die Zip-Datei in Ihr lokales Verzeichnis

3) Entpacken Sie die Zip-Datei

4) Öffnen Sie Android Studio

5) Gehe zu Datei ----> Öffnen ---> Navigiere zu dem Verzeichnis, in das du den Inhalt entpackt hast.

6) Ändern Sie die erforderliche Web-URL in webView.loadUrl ("Ihre URL hre"). in MainActivity.java

7) Funktioniert gut mit Version Android Studio 3.4.2

user3424922
quelle