Android,无法使用 WebView 上传图片

Android, can't upload images using WebView

几天来我一直在为我的问题寻找解决方案,但找不到合适的解决方案。所以我想在开始为 Android 开发本机应用程序之前再次在这里询问,因为我无法解决这个问题。

如标题所述,我正在尝试通过使用 webview 将图像上传到 html 内容,通常是选择图像,在页面上显示它并允许用户裁剪它。 我制作了整个应用程序并在 phone 的普通浏览器上对其进行了测试,所以我不知道这行不通。这就是为什么它真令人沮丧。

我在互联网上找到的那些解决方案对我的 Android 不起作用,而且我读到它不再可能了。

有谁知道这是否可能?如果我能获得更多关于此的信息(即使可能与否?),那将是一个很大的帮助。 感谢 Adavnce...

尝试添加这些权限。

<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Android 6.0 Marshmallow introduces a new model for handling permissions, which streamlines the process for users when they install and upgrade apps. Provided you're using version 8.1 or later of Google Play services, you can configure your app to target the Android 6.0 Marshmallow SDK and use the new permissions model.

If your app supports the new permissions model, the user does not have to grant any permissions when they install or upgrade the app. Instead, the app must request permissions when it needs them at runtime, and the system shows a dialog to the user asking for the permission.

To learn more, see the documentation for Android 6.0 Marshmallow and the changes you must make to your app for the new permissions model.

Google 已添加 WebChromeClient.onShowFileChooser。他们甚至提供了一种自动生成文件选择器意图的方法,以便它使用输入接受 mime 类型。

这样实现(来自an answer by weiyin):

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

    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;
            }
        }
    }
}

确保使用 API 21+ 编译应用程序。正如您在 gradle 中提到的那样,这将适用于所有平台。

这是API11到23

的工作方法
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;

现在修改或覆盖您的 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();
}

现在在onCreate方法中粘贴以下代码

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);
}
});

这里没有解决问题的答案。一些专家 android 人正在提供将图像上传构建到 android 代码中的解决方案。这不是这个问题的要求。我也有同样的问题困扰我的问题.. 我们要问的是加载到 webview 应用程序中的 HTML/PHP 页面不会触发图库或相机应用程序,因为它会在桌面 computer/laptop 中触发 'upload file from PC' 在 Mozilla 或 chrome.. 这就像 iframe 中的网页一样.. 但在 android 应用程序的网页视图中.. 我想我已经说清楚了.. 我们不是 android 程序员我们是网络开发人员。

<form method="post" action="" enctype="multipart/form-data" name="form1">
<!-- this following input is not working in webview -->
<input size="25" name="file" type="file">
<input name="submit" type="submit" value="submit">
</form> 

有点晚了,上面的答案很有帮助,但我发现 Google 本身对此有一个很棒的实现。

inputfilesample in chromium-webview-samples

存储库是存档的,但示例非常有用。