Android安卓 + webview + vue 实现图片上传

前提:需要首先实现web端的网页上传图片(只要网页上传图片成功,后续集成和android部分的相关操作,就可以成功实现图片上传)

步骤:

  1. web端实现网页上传
  2. web嵌入安卓webview实现安卓手机拍照和选择图片上传

问题:

  1. 对安卓开发不太了解的web开发小伙伴,需要粗略的了解一下安卓开发的一些基本内容,这一步需要自己去适当的学习,如果这一步没有,那就不用往下看了
  2. 图片上传和拍照上传,需要的一些权限
  3. 高安卓版本的手机拍照上传,需要进行的额外操作

web端实现网页上传的代码这边就不赘述了,需要了解的,可以联系我vx: 18918813817

接下来就是安卓部分的相关代码

// 拍照 + 文件选择
private android.webkit.ValueCallback<Uri[]> mUploadCallbackAboveL;
private Uri imageUri;
private int REQUEST_CODE = 1234;

// 需要实现图片上传,需要重载onShowFileChooser方法
private WebChromeClient webChromeClient = new WebChromeClient() {
    @Override
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
        mUploadCallbackAboveL = filePathCallback;
        try {
            takePhoto();
        } catch (Exception e) {
            Log.e("JKT", e.toString());
        }
        return true;
    }
};

这里是重载了onShowFileChooser方法,低版本的android是重载另外一个方法(低版本好像是<=4.0,个人觉得版本太低,可能已经没有什么需求是要适应这种版本的手机了,如果你需要了解低版本,自行百度吧)

好,下面开始takePhoto这个函数的重点部分

/**
     * 调用相机
     */
    private void takePhoto() {
        // 指定拍照存储位置的方式调起相机
        String filePath = Environment.getExternalStorageDirectory() + File.separator
                + Environment.DIRECTORY_PICTURES + File.separator;
        String fileName = "IMG_" + DateFormat.format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".jpg";
        File fileUri =  new File(filePath + fileName);
        imageUri = Uri.fromFile(fileUri);
        // 这里针对高版本的android需要进行特殊的图片路径设置,重点1
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            imageUri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider", fileUri);
        }


        Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        captureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

        Intent Photo = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

        Intent chooserIntent = Intent.createChooser(Photo, "Image Chooser");
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});

        startActivityForResult(chooserIntent, REQUEST_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE) {
            if (resultCode == 0) {
                // 这里需要对相机,和读取文件权限做检查,没有权限需要授权,重点2
                this.checkCameraPermissions();
            }
            if (mUploadCallbackAboveL != null) {
                chooseAbove(resultCode, data);
            } else {
                Toast.makeText(this, "发生错误", Toast.LENGTH_SHORT).show();
            }
        }
    }

    /**
     * Android API >= 21(Android 5.0) 版本的回调处理
     * @param resultCode 选取文件或拍照的返回码
     * @param data 选取文件或拍照的返回结果
     */
    // 重点3: 获取android的activity回调(也就是文件的数据),对拍照上传和选择图片上传分开处理
    private void chooseAbove(int resultCode, Intent data) {
        Log.e("JKT", "返回调用方法--chooseAbove");

        if (RESULT_OK == resultCode) {
            updatePhotos();

            if (data != null) {
                // 这里是针对从文件中选图片的处理
                Uri[] results;
                Uri uriData = data.getData();
                if (uriData != null) {
                    results = new Uri[]{uriData};
                    for (Uri uri : results) {
                        Log.e("JKT", "系统返回URI:" + uri.toString());
                    }
                    mUploadCallbackAboveL.onReceiveValue(results);
                } else {
                    mUploadCallbackAboveL.onReceiveValue(null);
                }
            } else {
                Log.e("JKT", "自定义结果:" + imageUri.toString());
                mUploadCallbackAboveL.onReceiveValue(new Uri[]{imageUri});
            }
        } else {
            mUploadCallbackAboveL.onReceiveValue(null);
        }
        mUploadCallbackAboveL = null;
    }

    private void updatePhotos() {
        // 该广播即使多发(即选取照片成功时也发送)也没有关系,只是唤醒系统刷新媒体文件
        Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        intent.setData(imageUri);
        sendBroadcast(intent);
    }

    private void checkCameraPermissions () {
        List<String> permissiongList = new ArrayList<>();
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            permissiongList.add(Manifest.permission.CAMERA);
        }
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            permissiongList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }
        if (!permissiongList.isEmpty()) {
            String[] permissions = permissiongList.toArray(new String[permissiongList.size()]);
            ActivityCompat.requestPermissions(this, permissions, 1);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0){
                    for (int result : grantResults) {
                        if (result != PackageManager.PERMISSION_GRANTED) {
                            Toast.makeText(getApplicationContext(), "需用户同意使用相关权限,才能正常使用该功能", Toast.LENGTH_SHORT).show();
                            return;
                        }
                    }
                } else {
                    Toast.makeText(getApplicationContext(), "系统发生未知错误,即将退出", Toast.LENGTH_SHORT).show();
                    finish();
                }
                break;
            default:
                break;
        }
    }

到了这里,应该上传图片,和拍照上传图片的问题应该可以解决了,但是当你使用高版本android手机进行拍照上传的时候,发现没有上传成功

通过日志发现,未能获取到读取文件相关权限吧,这是因为android高版本的手机对文件读写进行了额外的操作吧(<!--在安卓7.0以上禁止在应用外部公开 file://URI-->),所以需要我们多一些设置

在AndroidManifest.xml中添加provider

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_path" />
        </provider>

在res目录下新建xml文件夹,新建文件file_path.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="external_files"
        path="." />
</paths>

OK,拍照上传和文件上传的具体实现就大概这么多吧,遇到了一些问题,主要是权限相关的,还有安卓高版本文件读写的问题

因为是一枚web开发人员,android开发经验不多,了解的也不够透彻,所以如果有问题,希望看友可以指出来,非常感谢!

互相学习,共同进步!

猜你喜欢

转载自blog.csdn.net/qq_14855277/article/details/114524577