【问题标题】:Using a webview to browse the photo gallery使用 webview 浏览照片库
【发布时间】:2015-02-24 05:46:01
【问题描述】:
Min SDK API 15

你好,

我使用的 webview 上有一个按钮,可以浏览应用程序的照片库。

但是,当在 webview 中单击按钮时,什么也没有发生。

网址格式为:

https://www.xxxxxxxxxxx

我添加了以下权限:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" android:required="false" />

我有一个片段,它将在 onCreateView 方法(仅限 sn-p)中加载 webview,并启用 javascript。

if(!message.isEmpty()) {            
    WebView webView = (WebView)view.findViewById(R.id.webview);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
    webView.setWebViewClient(new WebViewClient());
    webView.loadUrl(message);
}

我创建了一个简单的 html 页面来测试:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Test Android Popup</title>
</head>
<body>
<label>Test Alert 1:</label>
<button type="button" onClick="alert('Test Alert Box1');">Click Me!</button>
<br>
<label>Test Browse file</label>
<input type="file" name="img">
</body>
</html>

所以 url 将被加载到 webview 中。 webview 显示一个按钮,用户将单击该按钮来浏览其画廊中的照片。

网页视图如下所示:

当我单击它们时,所有按钮都不起作用。

非常感谢您的任何建议,

此代码 sn-p 适用于

 webView.setWebChromeClient(new WebChromeClient() {
            /* Open File */
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                mImageFilePath = uploadMsg;

                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                intent.setType("image/*");

                startActivityForResult(intent, FILECHOOSER_RESULTCODE);
            }


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

                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                intent.setType("image/*");

                startActivityForResult(intent, FILECHOOSER_RESULTCODE);
            }

        });

【问题讨论】:

  • 你的消息字符串是什么?你那里有 https:// 吗?只有万维网。不起作用... Ups 抱歉误读问题
  • 我刚刚用 uri 的格式更新了我的答案。
  • 我想你已经更新了你的问题...
  • 您确定网址的格式不是https://www.xxxxxxxx.*
  • 链接是我们的客户网站,格式为https://www.address_to_client

标签: android webview


【解决方案1】:

创建此文件并将其放置在您的资产文件夹中:webdemo.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>title</title>
</head>
<body>
<h1>Web View Demo</h1>
<br>
    <input type="button" value="Say hello"
        onClick="showAndroidToast('Hello Android!')" />
    <br />
    File Uri: <label id="lbluri">no file uri</label>
    <br />
    File Path: <label id="lblpath">no file path</label>
    <br />
    <input type="button" value="Choose Photo" onClick="choosePhoto()" />
    <script type="text/javascript">
        function showAndroidToast(toast) {
            Android.showToast(toast);
        }
        function setFilePath(file) {
            document.getElementById('lblpath').innerHTML = file;
            Android.showToast(file);
        }
        function setFileUri(uri) {
            document.getElementById('lbluri').innerHTML = uri;
            Android.showToast(uri);
        }
        function choosePhoto() {
            var file = Android.choosePhoto();
            window.alert("file = " + file);
        }
    </script>
</body>
</html>

专注于此处编写的 javascript。

将您的活动写如下: WebViewDemo.java

public class WebViewDemo extends Activity
{

    private WebView webView;

    final int SELECT_PHOTO = 1;

    @SuppressLint("SetJavaScriptEnabled")
    public void onCreate(Bundle savedInstanceState)
    {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.show_web_view);

        webView = (WebView) findViewById(R.id.webView1);

        webView.getSettings().setJavaScriptEnabled(true);

        webView.getSettings().setLoadWithOverviewMode(true);

        // Other webview settings
        webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
        webView.setScrollbarFadingEnabled(false);
        webView.getSettings().setBuiltInZoomControls(true);
        webView.getSettings().setPluginState(PluginState.ON);
        webView.getSettings().setAllowFileAccess(true);
        webView.getSettings().setSupportZoom(true);
        webView.addJavascriptInterface(new MyJavascriptInterface(this), "Android");

        webView.loadUrl("file:///android_asset/webdemo.html");

    }

    class MyJavascriptInterface
    {

        Context mContext;

        /** Instantiate the interface and set the context */
        MyJavascriptInterface(Context c)
        {
            mContext = c;
        }

        /** Show a toast from the web page */
        @JavascriptInterface
        public void showToast(String toast)
        {
            Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
        }

        @JavascriptInterface
        public String choosePhoto()
        {
            // TODO Auto-generated method stub
            String file = "test";
            Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
            photoPickerIntent.setType("image/*");
            startActivityForResult(photoPickerIntent, SELECT_PHOTO);
            return file;
        }

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent)
    {
        switch (requestCode)
        {
        case SELECT_PHOTO:
            if (resultCode == RESULT_OK)
            {
                Uri selectedImage = intent.getData();
                webView.loadUrl("javascript:setFileUri('" + selectedImage.toString() + "')");
                String path = getRealPathFromURI(this, selectedImage);
                webView.loadUrl("javascript:setFilePath('" + path + "')");
            }
        }

    }

    public String getRealPathFromURI(Context context, Uri contentUri)
    {
        Cursor cursor = null;
        try
        {
            String[] proj = { MediaStore.Images.Media.DATA };
            cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        }
        finally
        {
            if (cursor != null)
            {
                cursor.close();
            }
        }
    }

}

使用这段代码 sn-p 看看它是否有效。

下面的截图取自 Android 4.4 Kitkat 设备。

我不知道这个解决方案是否对你有用。对您来说,这可能只是一种解决方法或突破。 我希望它的某些部分会有所帮助。

【讨论】:

  • 谢谢,阿姆鲁特。我会试试这个。但是,我注意到您正在使用 javascript 接口。没有那个有可能做到这一点吗?
  • 根据您的问题/要求,据我所知,如果不使用界面,则无法解决您的问题。
  • 此解决方案不适用于 Android 5(但它适用于 4.3.1)。有什么建议吗?
【解决方案2】:

不幸的是,正如用户 Slartibartfast 在您的问题的其中一个 cmets 中所说,输入类型“文件”在 4.4 设备上不起作用。谷歌代码上有一个issue,表明这是一种预期行为(状态:WorkingAsIntended)。

即使如此,您提供的代码也适用于 4.4.4(在 Nexus 7 平板电脑上测试)和

在 5.0 上,他们添加了一个记录在案的 method 来执行此操作。我正在使用以下代码:

mWebView.setWebChromeClient(new WebChromeClient() {
    // For Android < 3.0 - undocumented method
    @SuppressWarnings("unused")
    public void openFileChooser( ValueCallback<Uri> uploadMsg ) {
        openFileChooser( uploadMsg, "" );
    }

    // For Android 3.0+ - undocumented method
    public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) {                
        mUploadCallback = uploadMsg;
        openFileChooserActivity();
    }

    // For Android > 4.1 - undocumented method
    @SuppressWarnings("unused")
    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
        openFileChooser( uploadMsg, "" );
    }

    // For Android > 5.0
    public boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
        mUploadCallbackLollipop = filePathCallback;
        openFileChooserActivity();
        return true;
    }
});

注意 > 5.0 更改的回调参数:从 ValueCallback&lt;Uri&gt;ValueCallback&lt;Uri[]&gt;

因此,对于 >= 4.4 和

  • 使用 javascript 检查 android 操作系统版本并提供一个 &lt;input type="file"&gt; 它可以工作的地方。在 4.4 版本中,使用您自己的 url 架构创建一个 html 元素(如 Sushant 所说,例如 &lt;form action="image://choose"&gt;)。然后,您可以在shouldOverrideUrlLoading 中捕获它,并使用文件路径从 java 调用 javascript 函数,但您将无法访问文件的内容。对于小文件,您可以将 base64 中的文件内容作为参数传递给您的 javascript 函数,但对于较大的文件,您肯定会遇到 OutOfMemory 异常。
  • 您可以执行上述步骤,但在 java 中处理文件上传并仅提供 javascript 函数的路径。带有提交的按钮可以利用 Amrut Bidri 所说的触发您在 java 中上传。

因此,作为结论,我看到 4.4 和 4.4.4 之间的操作系统版本有两个选项:使用 javascript 上传文件(内存问题)或在 java 中上传文件并在应用程序和应用程序之间实现您自己的通信机制网页浏览。对于他们两个,您都需要能够访问您在 web 视图中加载的网页。

我使用的是javascript上传的方式,因为我们使用的是小文件,实现起来有点快:

public boolean shouldOverrideUrlLoading(WebView view, String url) {         
    ... else if (url.startsWith(UPLOAD_FILE_URL_PREFIX)) {
        openFileChooserActivity();
        return true;
    }

    return false;
}

在活动结果上,我为 4.4 版本做了这样的事情(javascript 函数 insertFileForUpload 处理文件上传):

private void invokeJavascriptWithFileContent(Uri fileUri) {
    String fileContentInBase64 = readAndConvertFileToBase64(fileUri);

    if (!fileContentInBase64.isEmpty()) {
        String fileMimeType = getMimeType(activity, fileUri);
        String fileName = getFileName(activity, fileUri);

        // invoke javascript
        String js = String.format("javascript:insertFileForUpload(\"%s\",\"%s\",\"%s\")", 
                fileName,
                fileMimeType,
                fileContentInBase64
                );
        mWebView.loadUrl(js);
    }
}

public static String getMimeType(Context context, Uri fileUri)    
{
    ContentResolver cR = context.getContentResolver();
    MimeTypeMap mime = MimeTypeMap.getSingleton();
    String type = mime.getExtensionFromMimeType(cR.getType(fileUri));

    return type;
}

另外,关于https://github.com/delight-im/Android-AdvancedWebView,文件上传似乎有效,但他们说:“文件上传是自动处理的(使用 AdvancedWebView.isFileUploadAvailable() 检查可用性)”和“isFileUploadAvailable”包含以下代码:

/**
 * Returns whether file uploads can be used on the current device (generally all platform versions except for 4.4)
 *
 * @return whether file uploads can be used
 */
public static boolean isFileUploadAvailable() {
    return isFileUploadAvailable(false);
}

/**
 * Returns whether file uploads can be used on the current device (generally all platform versions except for 4.4)
 *
 * On Android 4.4.3/4.4.4, file uploads may be possible but will come with a wrong MIME type
 *
 * @param needsCorrectMimeType whether a correct MIME type is required for file uploads or `application/octet-stream` is acceptable
 * @return whether file uploads can be used
 */
public static boolean isFileUploadAvailable(final boolean needsCorrectMimeType) {
    if (Build.VERSION.SDK_INT == 19) {
        final String platformVersion = (Build.VERSION.RELEASE == null) ? "" : Build.VERSION.RELEASE;

        return !needsCorrectMimeType && (platformVersion.startsWith("4.4.3") || platformVersion.startsWith("4.4.4"));
    }
    else {
        return true;
    }
}

所以你可能只是在普通的 webview 上遇到了同样的问题,但我没有测试过这个库,所以我真的不能说。

我可能已经创建了一个混乱的答案,但我希望你能找到一些有用的东西。

【讨论】:

  • 感谢您的回答。
【解决方案3】:

你可以这样实现它

    webView.setWebViewClient(new WebViewClient() {


        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (url.equals("alert://alert")) {
                Toast.makeText(this, "alert", Toast.LENGTH_LONG).show();
            } else if (url.equals("choose://image")) {
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                intent.setType("image/*");

                startActivityForResult(intent, FILECHOOSER_RESULTCODE);
            }
            return true;
        }
    });

你的html应该是这样的

<!doctype html>
<html>
    <head>
    <meta charset="utf-8">
    <title>Test Android Popup</title>
    </head>
    <body>
        <label>Test Alert 1:</label>
        <form action="alert://alert">
             <input type="submit" value="Click me!">
        </form>
        <br>
        <label>Test Browse file</label>
        <form action="image://choose">
            <input type="submit" value="Choose File">
        </form>
    </body>
</html>

【讨论】:

    【解决方案4】:

    通过此代码可以获取移动文件的路径,只是我无法在php中上传文件。以下是我正在使用的 php 代码:

    $arquivo = $_POST['lblpath'];
    
    $url = "file:///storage/external_SD/fotos/IMG10022.jpg"; //url da imagem que venha de um textField
    
    //PEGA INFORMAÇÕES DA IMAGEM
    $file_info = getimagesize($url);    
    
    
    //VERIFICA EXTENSÃO DA IMAGEM
    if ($file_info['mime'] == "image/jpeg")
    $img = imagecreatefromjpeg($url);
    else if ($file_info['mime'] == "image/gif")
    $img = imagecreatefromgif($url);
    else if ($file_info['mime'] == "image/png")
    $img = imagecreatefrompng($url);
    
    $altura = $file_info[1];
    
    //PASSA AS MEDIDAS PARA A IMAGEM
    $x   = imagesx($img);
    $y   = imagesy($img);
    $largura = ($altura * $x)/$y;
    
    
    //CRIA A IMAGEM
    $nova = imagecreatetruecolor($largura, $altura);
    imagealphablending( $nova, false );
    imagesavealpha( $nova, true );
    imagecopyresampled($nova, $img, 0, 0, 0, 0, $largura, $altura, $x, $y);
    
    
    //NOME DA IMAGEM
    $imgName = end(explode("/", $url));
    
    //LOCAL PARA SALVAR
    $pasta = "images/"; // defina sua path
    $local = $pasta . $imgName;
    
    
    //SALVA NOVA IMAGEM
    if ($file_info['mime'] == "image/jpeg")
    imagejpeg($nova, $local, 100);
    else if ($file_info['mime'] == "image/png")
    imagepng($nova, $local, 9);
    
    //DESTROI ELEMENTOS
    imagedestroy($img);
    imagedestroy($nova);
    

    【讨论】:

      猜你喜欢
      • 2015-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-25
      • 1970-01-01
      • 2012-06-13
      相关资源
      最近更新 更多