[Cordova] 改进InAppBrowser插件(WebView),让其<input type="file">支持选择文件
来源:互联网 发布:清华镜像python 编辑:程序博客网 时间:2024/05/07 05:03
原文链接:http://blog.csdn.net/lovelyelfpop/article/details/52815700
默认安卓的WebView显示的网页,其中的文件选择控件<input type="file">是不能选择文件的,点击弹不出文件或图片选择。
其实Google给WebView提供了接口,只要实现这些接口,就可以选择文件了。
搜索了很多,最终发现StackOverflow上的这个答案,是我找到最能满足需求的一个解决方案了。
http://stackoverflow.com/questions/5907369/file-upload-in-webview#24280517
1、支持几乎所有安卓版本,从安卓2.x~7.0
安卓4.4、4.4.1和4.4.2是无法支持的,因为当时Google说WebView上传文件不安全,就去掉了。所以这3个版本没有解决办法。不过现在基本没有这3个系统版本的设备了吧。
4.4.3和4.4.4是支持的
2、支持指定accept="",限制选择文件的类型
如果指定了accept="image/*",那么就会支持选择图片;如果不指定,那就可以选择任何文件。等等。
3、支持拍照上传
指定了accept="image/*",除了支持选择图片,还可以拍照
下面提供InAppBrowser插件的改进:
先上效果图(文件选择控件指定了accept="image/*")
下图是安卓4.4.4的效果
下图是安卓6.0的效果
下图是安卓7.0的效果
1、修改cordova-plugin-inappbrowser\src\Android\InAppChromeClient.java
增加成员变量
-
- private CordovaPlugin plugin;
- public UploadHandler mUploadHandler;
增加构造函数
-
- public InAppChromeClient(CordovaWebView webView, CordovaPlugin plugin) {
- super();
- this.webView = webView;
- this.plugin = plugin;
- }
增加成员函数和内部类
-
-
- public void openFileChooser(ValueCallback<Uri> uploadMsg) {
- openFileChooser(uploadMsg, "");
- }
-
-
- public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
- openFileChooser(uploadMsg, "", "filesystem");
- }
-
-
- public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
- mUploadHandler = new UploadHandler(new Controller());
- mUploadHandler.openFileChooser(uploadMsg, acceptType, capture);
- }
-
-
-
-
-
-
- @SuppressLint("NewApi")
- 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;
- }
-
- public class Controller {
- final static int FILE_SELECTED = 4;
-
- CordovaInterface getCordova(){ return plugin.cordova; }
- }
-
-
-
-
- /*
- * 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:
- *
- * 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.
- */
- class UploadHandler {
-
-
-
- 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) {
-
-
- mCaughtActivityNotFoundException = false;
- return;
- }
- Uri result = intent == null || resultCode != Activity.RESULT_OK ? null
- : intent.getData();
-
-
-
-
-
-
- if (result == null && intent == null && resultCode == Activity.RESULT_OK) {
- File cameraFile = new File(mCameraFilePath);
- if (cameraFile.exists()) {
- result = Uri.fromFile(cameraFile);
-
-
- mController.getCordova().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";
-
-
- String mediaSource = mediaSourceValueFileSystem;
- if (mUploadMessage != null) {
-
- return;
- }
- mUploadMessage = uploadMsg;
-
- String params[] = acceptType.split(";");
- String mimeType = params[0];
- if (capture.length() > 0) {
- mediaSource = capture;
- }
- if (capture.equals(mediaSourceValueFileSystem)) {
-
-
-
-
- for (String p : params) {
- String[] keyValue = p.split("=");
- if (keyValue.length == 2) {
-
- if (mediaSourceKey.equals(keyValue[0])) {
- mediaSource = keyValue[1];
- }
- }
- }
- }
-
- mCameraFilePath = null;
- if (mimeType.equals(imageMimeType)) {
- if (mediaSource.equals(mediaSourceValueCamera)) {
-
-
- startActivity(createCameraIntent());
- return;
- } else {
-
-
-
- Intent chooser = createChooserIntent(createCameraIntent());
- chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(imageMimeType));
- startActivity(chooser);
- return;
- }
- } else if (mimeType.equals(videoMimeType)) {
- if (mediaSource.equals(mediaSourceValueCamcorder)) {
-
-
- startActivity(createCamcorderIntent());
- return;
- } else {
-
-
-
- Intent chooser = createChooserIntent(createCamcorderIntent());
- chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(videoMimeType));
- startActivity(chooser);
- return;
- }
- } else if (mimeType.equals(audioMimeType)) {
- if (mediaSource.equals(mediaSourceValueMicrophone)) {
-
-
- startActivity(createSoundRecorderIntent());
- return;
- } else {
-
-
-
- Intent chooser = createChooserIntent(createSoundRecorderIntent());
- chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(audioMimeType));
- startActivity(chooser);
- return;
- }
- }
-
-
- startActivity(createDefaultOpenableIntent());
- }
- private void startActivity(Intent intent) {
- try {
- mController.getCordova().startActivityForResult(plugin, intent, Controller.FILE_SELECTED);
- } catch (ActivityNotFoundException e) {
-
-
- try {
- mCaughtActivityNotFoundException = true;
- mController.getCordova().startActivityForResult(plugin, createDefaultOpenableIntent(),
- Controller.FILE_SELECTED);
- } catch (ActivityNotFoundException e2) {
-
- Toast.makeText(mController.getCordova().getActivity(), "File uploads are disabled.",
- Toast.LENGTH_LONG).show();
- }
- }
- }
- private Intent createDefaultOpenableIntent() {
-
-
-
- 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,
- "Choose file for 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);
- }
- }
别忘了顶部Import
-
- import org.apache.cordova.CordovaPlugin;
- import org.apache.cordova.CordovaInterface;
- import android.annotation.SuppressLint;
- 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;
2、修改cordova-plugin-inappbrowser\src\android\InAppBrowser.java
增加成员变量
-
- private InAppChromeClient chromeClient;
修改showWebPage方法里
-
- inAppWebView = new WebView(cordova.getActivity());
- inAppWebView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
- inAppWebView.setId(Integer.valueOf(6));
-
-
- chromeClient = new InAppChromeClient(thatWebView, InAppBrowser.this);
- inAppWebView.setWebChromeClient(chromeClient);
- WebViewClient client = new InAppBrowserClient(thatWebView, edittext);
增加一个Override方法
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent intent) {
- if (requestCode == InAppChromeClient.Controller.FILE_SELECTED) {
-
- if (chromeClient != null && chromeClient.mUploadHandler != null) {
- chromeClient.mUploadHandler.onResult(resultCode, intent);
- }
- }
- super.onActivityResult(requestCode, resultCode, intent);
- }
至于iOS版本的,最新的InAppBrowser插件1.5.0+已经支持选择文件了(1.5.0以前的版本不行,有bug) 0 0