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);
}
}
image.png image.png故障点getUriForFile报错IllegalArgumentException
xml中配置的路径需要跟文件存储路径对应上
如 文件路径为/storage/emulated/0/Android/data/com.example.myapplication/files/Movies
配置的路径root为/storage/emulated/0//Movies
参考附录,感谢大佬们
Android开发笔记(一百六十六)H5通过WebView录像上传,github查aqi00可以找到本地assert使用的相关H5代码
Android webview 实现h5的input type="file"选择图片调用系统相册/相机并进行图片压缩功能
网友评论