Android,无法使用 WebView 上传图片

Posted

技术标签:

【中文标题】Android,无法使用 WebView 上传图片【英文标题】:Android, can't upload images using WebView 【发布时间】:2016-07-24 10:17:49 【问题描述】:

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

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

我在互联网上找到的那些解决方案不适用于我的 Android,我读到这也不可能了。

有人知道这是否可能吗?如果我能获得更多关于这方面的信息,那将是一个很大的帮助(即使有可能与否?) 提前感谢...

【问题讨论】:

您是否遵循自 API 23 以来遵循的新权限模型? 什么意思? @Sibidharan 当您使用 WebView 选择文件时,您的应用必须获得系统的许可才能读取EXTERNAL_STORAGE。 API 23 的权限模型是 RunTime OnDemand 模型。在您使用 WebView 从图库中选择图片之前,您是否表明了这一点? 它不影响.... 仍然跳过并且没有任何反应。但是您如何看待高级 webview 插件? 感谢您的帮助 :) 您保存了我的 WebApp @Sibidharan 【参考方案1】:

尝试添加这些权限。

<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 引入了新的处理模型 权限,简化用户安装时的流程 和升级应用程序。前提是您使用的是 8.1 版或更高版本的 Google 播放服务,您可以将您的应用配置为面向 Android 6.0 Marshmallow SDK 并使用新的权限模型。

如果您的应用支持新的权限模型,则用户没有 在他们安装或升级应用程序时授予任何权限。 相反,应用程序必须在需要时请求权限 运行时,系统会向用户显示一个对话框,询问 权限。

要了解更多信息,请参阅Android 6.0 Marshmallow 的文档和 您必须为 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 中提到的那样,这将适用于所有平台。

【讨论】:

引用代码时,请注明作者姓名,并标注为引用。请参阅our helpcenter,了解如何正确参考他人的作品。 @MartijnPieters 当然,感谢您让我知道这一点。我将遵循相同的所有未来报价。 完美解决方案 :) 谢谢【参考方案2】:

这是从 API 11 到 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);

);

【讨论】:

【参考方案3】:

这里没有解决问题的答案.. 一些专家 android 人员正在提供将图像上传到 android 代码中的解决方案.. 这不是这个问题要问.. 我有同样的问题困扰着我.. 我们要问的是加载到 webview 应用程序中的 HTML/php 页面不会触发画廊或相机应用程序,因为它会在 Mozilla 或 chrome 的台式计算机/笔记本电脑上触发“从 PC 上传文件”。它就像 iframe 中的网络一样。 .但是在android应用程序的web视图中..我想我已经说清楚了..我们不是android程序员,我们是web开发人员。

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

【讨论】:

您找到解决方案了吗?我也有同样的问题,没找到解决办法 @PanjabWeb 我想你没有理解这里的担忧。问题不是网络代码,而是 android webview 的 webclient 类的问题,它不允许网页的 iFrame 打开 Android 设备的图库或硬件摄像头以从中单击或选择图像(Android 安全补丁)。因此,您的 android 开发人员需要集成代码以使其适用于您的项目/产品。【参考方案4】:

有点晚了,上面的答案很有帮助,但我发现谷歌自己的一个很棒的实现。

inputfilesample in chromium-webview-samples

存储库是存档,但示例的作用就像一个魅力。

【讨论】:

以上是关于Android,无法使用 WebView 上传图片的主要内容,如果未能解决你的问题,请参考以下文章

解决小程序webview中无法上传图片问题

Android webview上传图片(调起相册/相机上传)

Android网页WebView图片文件上传的问题

Android,无法使用WebView上传图像

android 使用WebView上传文件 混淆打包之后就无法调用openFileChooser这个方法了

H5调用本地相册/相机上传图片