Android WebView 选择图片

本文介绍如何在Android应用中使用WebView加载网页并实现图片选择功能。通过设置WebView参数,启用JavaScript和文件访问,自定义WebChromeClient来处理图片选择事件,使用Intent启动文件选择器,最后解析返回的URI获取选中的图片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android WebView 选择图片

public static final int SELECT_IMAGE_REQUEST_CODE = 1000;
private WebView mWebView;
private ValueCallback<Uri[]> mValueCallback;

private void setWeb() {
    mWebView.loadUrl(url);
    WebSettings webSettings = mWebView.getSettings();
    webSettings.setTextZoom(100);
    webSettings.setUseWideViewPort(true);
    webSettings.setLoadWithOverviewMode(true);
    webSettings.setAppCacheEnabled(true);
    webSettings.setDatabaseEnabled(true);
    webSettings.setDomStorageEnabled(true);
    webSettings.setAllowFileAccess(true);
    webSettings.setJavaScriptEnabled(true);
    webSettings.setLoadsImagesAutomatically(true);
    webSettings.setAllowFileAccessFromFileURLs(true);
    mWebView.setHorizontalScrollBarEnabled(false);
    mWebView.setVerticalScrollBarEnabled(false);
    mWebView.setWebChromeClient(new MyWebChromeClient());
}

class MyWebChromeClient extends WebChromeClient {
    @Override
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> valueCallback, FileChooserParams fileChooserParams) {
        resetWebSelectImageCallBack();
        mValueCallback = valueCallback;
        selectImage();
        return true;
    }
}

private void selectImage() {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("image/*");
    startActivityForResult(Intent.createChooser(intent, "Image Chooser"), SELECT_IMAGE_REQUEST_CODE);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (SELECT_IMAGE_REQUEST_CODE == requestCode) {
        if (RESULT_OK != resultCode) {
            resetWebSelectImageCallBack();
            return;
        }
        if (null != mValueCallback) {
            Uri uri = data.getData();
            mValueCallback.onReceiveValue(new Uri[]{UriUtils.file2Uri(UriUtils.uri2File(uri))});
            mValueCallback = null;
        }
    }
}

private void resetWebSelectImageCallBack() {
    if (null != mValueCallback) {
        mValueCallback.onReceiveValue(null);
        mValueCallback = null;
    }
}

UriUtils

/**
    * File to uri.
    *
    * @param file The file.
    * @return uri
    */
public static Uri file2Uri(@NonNull final File file) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        String authority = Utils.getApp().getPackageName() + ".utilcode.provider";
        return FileProvider.getUriForFile(Utils.getApp(), authority, file);
    } else {
        return Uri.fromFile(file);
    }
}

/**
    * Uri to file.
    *
    * @param uri The uri.
    * @return file
    */
public static File uri2File(@NonNull final Uri uri) {
    Log.d("UriUtils", uri.toString());
    String authority = uri.getAuthority();
    String scheme = uri.getScheme();
    String path = uri.getPath();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
            && path != null) {
        String[] externals = new String[]{"/external", "/external_path"};
        for (String external : externals) {
            if (path.startsWith(external + "/")) {
                File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
                        + path.replace(external, ""));
                if (file.exists()) {
                    Log.d("UriUtils", uri.toString() + " -> " + external);
                    return file;
                }
            }
        }
    }
    if (ContentResolver.SCHEME_FILE.equals(scheme)) {
        if (path != null) return new File(path);
        Log.d("UriUtils", uri.toString() + " parse failed. -> 0");
        return null;
    }// end 0
    else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
            && DocumentsContract.isDocumentUri(Utils.getApp(), uri)) {
        if ("com.android.externalstorage.documents".equals(authority)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];
            if ("primary".equalsIgnoreCase(type)) {
                return new File(Environment.getExternalStorageDirectory() + "/" + split[1]);
            } else {
                // Below logic is how External Storage provider build URI for documents
                // http://stackoverflow.com/questions/28605278/android-5-sd-card-label
                StorageManager mStorageManager = (StorageManager) Utils.getApp().getSystemService(Context.STORAGE_SERVICE);
                try {
                    Class<?> storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
                    Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
                    Method getUuid = storageVolumeClazz.getMethod("getUuid");
                    Method getState = storageVolumeClazz.getMethod("getState");
                    Method getPath = storageVolumeClazz.getMethod("getPath");
                    Method isPrimary = storageVolumeClazz.getMethod("isPrimary");
                    Method isEmulated = storageVolumeClazz.getMethod("isEmulated");

                    Object result = getVolumeList.invoke(mStorageManager);

                    final int length = Array.getLength(result);
                    for (int i = 0; i < length; i++) {
                        Object storageVolumeElement = Array.get(result, i);
                        //String uuid = (String) getUuid.invoke(storageVolumeElement);

                        final boolean mounted = Environment.MEDIA_MOUNTED.equals(getState.invoke(storageVolumeElement))
                                || Environment.MEDIA_MOUNTED_READ_ONLY.equals(getState.invoke(storageVolumeElement));

                        //if the media is not mounted, we need not get the volume details
                        if (!mounted) continue;

                        //Primary storage is already handled.
                        if ((Boolean) isPrimary.invoke(storageVolumeElement)
                                && (Boolean) isEmulated.invoke(storageVolumeElement)) {
                            continue;
                        }

                        String uuid = (String) getUuid.invoke(storageVolumeElement);

                        if (uuid != null && uuid.equals(type)) {
                            return new File(getPath.invoke(storageVolumeElement) + "/" + split[1]);
                        }
                    }
                } catch (Exception ex) {
                    Log.d("UriUtils", uri.toString() + " parse failed. " + ex.toString() + " -> 1_0");
                }
            }
            Log.d("UriUtils", uri.toString() + " parse failed. -> 1_0");
            return null;
        }// end 1_0
        else if ("com.android.providers.downloads.documents".equals(authority)) {
            final String id = DocumentsContract.getDocumentId(uri);
            if (!TextUtils.isEmpty(id)) {
                try {
                    final Uri contentUri = ContentUris.withAppendedId(
                            Uri.parse("content://downloads/public_downloads"),
                            Long.valueOf(id)
                    );
                    return getFileFromUri(contentUri, "1_1");
                } catch (NumberFormatException e) {
                    if (id.startsWith("raw:")) {
                        return new File(id.substring(4));
                    }
                }
            }
            Log.d("UriUtils", uri.toString() + " parse failed. -> 1_1");
            return null;
        }// end 1_1
        else if ("com.android.providers.media.documents".equals(authority)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];
            Uri contentUri;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            } else {
                Log.d("UriUtils", uri.toString() + " parse failed. -> 1_2");
                return null;
            }
            final String selection = "_id=?";
            final String[] selectionArgs = new String[]{split[1]};
            return getFileFromUri(contentUri, selection, selectionArgs, "1_2");
        }// end 1_2
        else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            return getFileFromUri(uri, "1_3");
        }// end 1_3
        else {
            Log.d("UriUtils", uri.toString() + " parse failed. -> 1_4");
            return null;
        }// end 1_4
    }// end 1
    else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
        return getFileFromUri(uri, "2");
    }// end 2
    else {
        Log.d("UriUtils", uri.toString() + " parse failed. -> 3");
        return null;
    }// end 3
}

private static File getFileFromUri(final Uri uri, final String code) {
    return getFileFromUri(uri, null, null, code);
}

private static File getFileFromUri(final Uri uri,
                                    final String selection,
                                    final String[] selectionArgs,
                                    final String code) {
    final Cursor cursor = Utils.getApp().getContentResolver().query(
            uri, new String[]{"_data"}, selection, selectionArgs, null);
    if (cursor == null) {
        Log.d("UriUtils", uri.toString() + " parse failed(cursor is null). -> " + code);
        return null;
    }
    try {
        if (cursor.moveToFirst()) {
            final int columnIndex = cursor.getColumnIndex("_data");
            if (columnIndex > -1) {
                return new File(cursor.getString(columnIndex));
            } else {
                Log.d("UriUtils", uri.toString() + " parse failed(columnIndex: " + columnIndex + " is wrong). -> " + code);
                return null;
            }
        } else {
            Log.d("UriUtils", uri.toString() + " parse failed(moveToFirst return false). -> " + code);
            return null;
        }
    } catch (Exception e) {
        Log.d("UriUtils", uri.toString() + " parse failed. -> " + code);
        return null;
    } finally {
        cursor.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值