【问题标题】:Android webview, file input field filechooser doesn't show upAndroid webview,文件输入字段filechooser不显示
【发布时间】:2011-02-09 11:15:37
【问题描述】:

我应该在应用程序的 web 视图中显示网页。该页面包含一个 html 表单,其中一个字段是文件。所以它就像......

<input type="file" name="file">

如果我在浏览器中打开页面并按下选择文件按钮,文件选择器会弹出并且一切正常,但是当我在 web 视图中按下选择文件按钮时没有任何反应:/

任何想法如何使这项工作?

【问题讨论】:

  • 您使用的 Android 版本是什么?我相信在 FroYo (2.2) 之前,内置的 Android 浏览器不支持文件上传:code.google.com/p/android/issues/detail?id=2519(从 2.2 开始它应该可以工作,但在我运行 2.2 的 N1 上工作正常)。
  • @Charlie Collins 我正在 2.1、2.2、2.3 上尝试这个,如果它适用于其中任何一个都可以。即使在 2.1(Galaxy S) 上,它也可以在浏览器中正常工作,但我需要它才能在自定义应用程序的 WebView 中工作。您是说它在您的应用中使用 2.2 的 WebView 可以正常工作吗?
  • 我没有专门在 WebView 中尝试过,没有(我只是使用浏览器应用程序)。 Android 浏览器使用 WebViews:android.git.kernel.org/?p=platform/packages/apps/…
  • 另一件事,正如我所说的,我还没有尝试过,所以我只是在这里猜测,但也许您需要启用“文件访问”才能实现它?:developer.android.com/reference/android/webkit/… --我将快速编写一个测试并查看(这是一个有趣的问题;)。)
  • 不,在 WebView 中也不适合我。我知道很长一段时间 WebKit 手机不支持它(Android 也不支持,人们对此很生气,但不是 Android 的错),然后它被认为是一个“安全”问题,从 2.2 开始它变成了在常规浏览器中可用。我不确定为什么它在 WebView 中不起作用(我以前从未尝试过这样做)。

标签: android


【解决方案1】:

WebView 默认不打开文件选择器。但是,有可能使这项工作。 WebChromeClient 有隐藏方法openFileChooser,需要重写它才能弹出一个文件选择器,然后将结果返回给WebView。根据专家的说法,永远不要使用 Android SDK 的隐藏方法,所以这不是一个好的解决方案,可能不应该在企业应用程序中使用。然而,Android 的原生浏览器正是这样做的。在我的question 中提供了更多关于我如何覆盖此方法的信息。如果有人需要来源,请告诉我我会在某处发布。

【讨论】:

  • 嗨,我需要做同样的事情..你可以在某处发布示例代码吗??
  • @ghostCoder 嘿,我发布了它m0s-programming.blogspot.com/2011/02/… 如果您还有其他问题,请在这里提问 我不经常查看该博客。
  • @matteo 我不知道这是否是唯一的方法,但据我所知,它仍然是一种不会引起问题的有效方法。在较新版本的 android sdk 中,您只需覆盖 open 选择器方法的所有重载即可使其工作。
  • 是的,它仍然有效。完整的工作代码在这里:stackoverflow.com/questions/5907369/…(至少它在 2.3 和 4.1 和 4.2 中对我有用)。我发现代码 sn-ps 比这更简单,但它们都不起作用(也许它们只适用于某些特定的 Android 版本)......(注意:我注释掉了进度条的东西)
  • 您说不应该重写未记录的方法是对的。在 Android 4.4 中,使用 openFileChooser 的解决方案停止工作,请参阅此 bug 并以“WorkingAsIntended”的形式关闭。
【解决方案2】:

是否可以通过 webview 上传文件?

此功能在 1.3.0 及更高版本中可用。对于旧版本的应用程序,是的,但您需要添加一些额外的代码才能使其工作。将以下代码添加到您的 AndroidManifest.xml 文件中。将其置于其他使用权限元素下方:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

将此 java 类 MediaUtility.java 复制/粘贴到项目中。将其放入 com/robotemplates/webviewapp/utility 目录。

打开片段包中的 MainFragment.java。找到 renderView() 方法并替换“webView.setWebChromeClient(new WebChromeClient());”通过以下代码:

webView.setWebChromeClient(new WebChromeClient()
{
    public void openFileChooser(ValueCallback<Uri> filePathCallback)
    {
        mFilePathCallback4 = filePathCallback;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
    }

    public void openFileChooser(ValueCallback filePathCallback, String acceptType)
    {
        mFilePathCallback4 = filePathCallback;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
    }

    public void openFileChooser(ValueCallback<Uri> filePathCallback, String acceptType, String capture)
    {
        mFilePathCallback4 = filePathCallback;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
    }

    @Override
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
    {
        mFilePathCallback5 = filePathCallback;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
        return true;
    }
});

最后在 MainFragment 对象的某处添加以下代码(例如在“private boolean mLocal = false;”这一行下面):

private static final int REQUEST_FILE_PICKER = 1;
private ValueCallback<Uri> mFilePathCallback4;
private ValueCallback<Uri[]> mFilePathCallback5;

@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
    if(requestCode==REQUEST_FILE_PICKER)
    {
        if(mFilePathCallback4!=null)
        {
            Uri result = intent==null || resultCode!=Activity.RESULT_OK ? null : intent.getData();
            if(result!=null)
            {
                String path = MediaUtility.getPath(getActivity(), result);
                Uri uri = Uri.fromFile(new File(path));
                mFilePathCallback4.onReceiveValue(uri);
            }
            else
            {
                mFilePathCallback4.onReceiveValue(null);
            }
        }
        if(mFilePathCallback5!=null)
        {
            Uri result = intent==null || resultCode!=Activity.RESULT_OK ? null : intent.getData();
            if(result!=null)
            {
                String path = MediaUtility.getPath(getActivity(), result);
                Uri uri = Uri.fromFile(new File(path));
                mFilePathCallback5.onReceiveValue(new Uri[]{ uri });
            }
            else
            {
                mFilePathCallback5.onReceiveValue(null);
            }
        }

        mFilePathCallback4 = null;
        mFilePathCallback5 = null;
    }
}

不要忘记添加必要的导入:“import android.webkit.ValueCallback;”、“import com.robotemplates.webviewapp.utility.MediaUtility;”、“import java.io.File;”。如果仍有问题,请尝试在 Proguard 脚本中添加规则:https://code.google.com/p/android/issues/detail?id=62220#c120

【讨论】:

    猜你喜欢
    • 2017-07-12
    • 1970-01-01
    • 1970-01-01
    • 2012-03-11
    • 2019-12-16
    • 2020-01-30
    • 2011-10-06
    • 2011-08-31
    • 2016-01-08
    相关资源
    最近更新 更多