美文网首页Android
Webview视频压缩上传

Webview视频压缩上传

作者: 霁逸lei | 来源:发表于2021-05-21 12:43 被阅读0次

    1.视频文件选择、上传

    package com.example.myapplication;
    
    import android.Manifest;
    import android.app.Activity;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.util.Log;
    import android.webkit.ValueCallback;
    import android.webkit.WebChromeClient;
    import android.webkit.WebSettings;
    import android.webkit.WebView;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    
    import permissions.dispatcher.NeedsPermission;
    import permissions.dispatcher.RuntimePermissions;
    
    @RuntimePermissions
    public class WebActivity extends Activity {
    
        private static final int REQUEST_CODE_FILE_CHOOSER = 0x01;
        private ValueCallback<Uri> mUploadCallBack;
        private ValueCallback<Uri[]> mUploadCallBackAboveL;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_webview);
            WebView mWebView = findViewById(R.id.mWebView);
        }
    
        private void initWebViewSetting(WebView mWebView){
            WebSettings webSettings = mWebView.getSettings();
            webSettings.setJavaScriptEnabled(true);
            webSettings.setUseWideViewPort(true); // 关键点
            webSettings.setAllowFileAccess(true); // 允许访问文件
            webSettings.setSupportZoom(true); // 支持缩放
            webSettings.setLoadWithOverviewMode(true);
            webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); // 不加载缓存内容
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
            }
            webSettings.setDomStorageEnabled(true);
            //传图片
    //        mWebView.loadUrl("http://m.54php.cn/demo/h5_upload");
            //传视频
            mWebView.loadUrl("file:///android_asset/video/index.html");
            mWebView.setWebChromeClient(new WebChromeClient() {
    
                // For Android < 3.0
                public void openFileChooser(ValueCallback<Uri> valueCallback) {
                    mUploadCallBack = valueCallback;
                    showFileChooser();
                }
    
                // For Android  >= 3.0
                public void openFileChooser(ValueCallback valueCallback, String acceptType) {
                    mUploadCallBack = valueCallback;
                    showFileChooser();
                }
    
                //For Android  >= 4.1
                public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
                    mUploadCallBack = valueCallback;
                    showFileChooser();
                }
    
                // For Android >= 5.0
                @Override
                public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                    mUploadCallBackAboveL = filePathCallback;
                    WebActivityPermissionsDispatcher.showFileChooserWithPermissionCheck(WebActivity.this);
                    return true;
                }
            });
        }
    
        /**
         * 打开选择文件/相机
         * intent.setType("image/*");  //选择图片
         * intent1.setType("file/*");//文件上传
         * intent.setType("audio/*"); //选择音频
         * intent.setType("video/*"); //选择视频 (mp4 3gp 是android支持的视频格式)
         * intent.setType("video/*;image/*");//同时选择视频和图片
         */
        @NeedsPermission({Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE})
        public void showFileChooser() {
            //打开系统的文件选择界面
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("*/*");
            startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_CODE_FILE_CHOOSER);
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == REQUEST_CODE_FILE_CHOOSER) {
                Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
                if (result != null) {
                    //直接选取文件返回
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        if (mUploadCallBackAboveL != null) {
                            mUploadCallBackAboveL.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
                            mUploadCallBackAboveL = null;
                            return;
                        }
                    } else if (mUploadCallBack != null) {
                        mUploadCallBack.onReceiveValue(result);
                        mUploadCallBack = null;
                        return;
                    }
                }
            }
            clearUploadMessage();
            return;
        }
    
        /**
         * webview没有选择文件也要传null,防止下次无法执行
         */
        private void clearUploadMessage() {
            if (mUploadCallBackAboveL != null) {
                mUploadCallBackAboveL.onReceiveValue(null);
                mUploadCallBackAboveL = null;
            }
            if (mUploadCallBack != null) {
                mUploadCallBack.onReceiveValue(null);
                mUploadCallBack = null;
            }
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            WebActivityPermissionsDispatcher.onRequestPermissionsResult(this,requestCode,grantResults);
        }
    }
    
    

    2.视频压缩处理

    压缩后会返回视频的path,根据path获取URI然后返回上传接口

    找到两个开源压缩库,实测可用,20s的视频压缩了80%多,就是压缩时间7~8s
    https://github.com/fishwjy/VideoCompressor
    https://github.com/Tourenathan-G5organisation/SiliCompressor
    
    build.gradle
    implementation 'com.iceteck.silicompressorr:silicompressor:2.2.4'
    implementation 'com.googlecode.mp4parser:isoparser:1.1.22'
    
    manifest xml声明,android7.0以下不需要
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.example.myapplication"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/filepaths" />
    </provider>
    
    res目录创建xml文件夹,创建filepaths.xml
    <?xml version="1.0" encoding="utf-8"?>
    <paths>
        <external-path name="hm_video" path="Movies/Silicompressor/videos" />
    </paths>
    
    
    package com.example.myapplication;
    
    import android.Manifest;
    import android.app.Activity;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.Environment;
    import android.util.Log;
    import android.webkit.ValueCallback;
    import android.webkit.WebChromeClient;
    import android.webkit.WebSettings;
    import android.webkit.WebView;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.core.content.FileProvider;
    
    import com.iceteck.silicompressorr.SiliCompressor;
    
    import java.io.File;
    import java.net.URISyntaxException;
    
    import permissions.dispatcher.NeedsPermission;
    import permissions.dispatcher.RuntimePermissions;
    
    @RuntimePermissions
    public class WebActivity extends Activity {
    
        private static final int REQUEST_CODE_FILE_CHOOSER = 0x01;
        private ValueCallback<Uri> mUploadCallBack;
        private ValueCallback<Uri[]> mUploadCallBackAboveL;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_webview);
            WebView mWebView = findViewById(R.id.mWebView);
        }
    
        private void initWebViewSetting(WebView mWebView){
            WebSettings webSettings = mWebView.getSettings();
            webSettings.setJavaScriptEnabled(true);
            webSettings.setUseWideViewPort(true); // 关键点
            webSettings.setAllowFileAccess(true); // 允许访问文件
            webSettings.setSupportZoom(true); // 支持缩放
            webSettings.setLoadWithOverviewMode(true);
            webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); // 不加载缓存内容
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
            }
            webSettings.setDomStorageEnabled(true);
            //传图片
    //        mWebView.loadUrl("http://m.54php.cn/demo/h5_upload");
            //传视频
            mWebView.loadUrl("file:///android_asset/video/index.html");
            mWebView.setWebChromeClient(new WebChromeClient() {
    
                // For Android < 3.0
                public void openFileChooser(ValueCallback<Uri> valueCallback) {
                    mUploadCallBack = valueCallback;
                    showFileChooser();
                }
    
                // For Android  >= 3.0
                public void openFileChooser(ValueCallback valueCallback, String acceptType) {
                    mUploadCallBack = valueCallback;
                    showFileChooser();
                }
    
                //For Android  >= 4.1
                public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
                    mUploadCallBack = valueCallback;
                    showFileChooser();
                }
    
                // For Android >= 5.0
                @Override
                public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                    mUploadCallBackAboveL = filePathCallback;
                    WebActivityPermissionsDispatcher.showFileChooserWithPermissionCheck(WebActivity.this);
                    return true;
                }
            });
        }
    
        boolean compressVideoFlag= false;
        
        /**
         * 打开选择文件/相机
         * intent.setType("image/*");  //选择图片
         * intent1.setType("file/*");//文件上传
         * intent.setType("audio/*"); //选择音频
         * intent.setType("video/*"); //选择视频 (mp4 3gp 是android支持的视频格式)
         * intent.setType("video/*;image/*");//同时选择视频和图片
         */
        @NeedsPermission({Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE})
        public void showFileChooser() {
            //打开系统的文件选择界面
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("*/*");
            startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_CODE_FILE_CHOOSER);
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == REQUEST_CODE_FILE_CHOOSER) {
                Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
                if (result != null) {
                    if (compressVideoFlag){
                        //压缩后返回对应URI
                        handleCompressVideo(result);
                        return;
                    }
                    //直接选取文件返回
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        if (mUploadCallBackAboveL != null) {
                            mUploadCallBackAboveL.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
                            mUploadCallBackAboveL = null;
                            return;
                        }
                    } else if (mUploadCallBack != null) {
                        mUploadCallBack.onReceiveValue(result);
                        mUploadCallBack = null;
                        return;
                    }
                }
            }
            clearUploadMessage();
            return;
        }
        
        private void handleCompressVideo(final Uri videoContentUri){
            final String authority = getPackageName();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    File f = getExternalFilesDir(Environment.DIRECTORY_MOVIES);
                    try {
                        //视频缓存
                        String filePath = SiliCompressor.with(WebActivity.this).compressVideo(
                                videoContentUri,
                                f.getPath());
                        Log.d("TestWebActivity", filePath);
                        //Android 7.0后URI获取 权限更改
                        File resultFile = new File(filePath);
                        Uri uri;
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
                            uri = FileProvider.getUriForFile(WebActivity.this, authority, resultFile);
                        }else {
                            uri = Uri.fromFile(resultFile);
                        }
                        mUploadCallBackAboveL.onReceiveValue(new Uri[]{uri});
                        mUploadCallBackAboveL = null;
                        resultFile.delete();
                        clearUploadMessage();
                    } catch (URISyntaxException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    
        /**
         * webview没有选择文件也要传null,防止下次无法执行
         */
        private void clearUploadMessage() {
            if (mUploadCallBackAboveL != null) {
                mUploadCallBackAboveL.onReceiveValue(null);
                mUploadCallBackAboveL = null;
            }
            if (mUploadCallBack != null) {
                mUploadCallBack.onReceiveValue(null);
                mUploadCallBack = null;
            }
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            WebActivityPermissionsDispatcher.onRequestPermissionsResult(this,requestCode,grantResults);
        }
    }
    
    

    故障点getUriForFile报错IllegalArgumentException
    xml中配置的路径需要跟文件存储路径对应上
    如 文件路径为/storage/emulated/0/Android/data/com.example.myapplication/files/Movies
    配置的路径root为/storage/emulated/0//Movies

    image.png image.png

    参考附录,感谢大佬们
    Android开发笔记(一百六十六)H5通过WebView录像上传,github查aqi00可以找到本地assert使用的相关H5代码
    Android webview 实现h5的input type="file"选择图片调用系统相册/相机并进行图片压缩功能

    相关文章

      网友评论

        本文标题:Webview视频压缩上传

        本文链接:https://www.haomeiwen.com/subject/ntfwjltx.html