安卓:
首先要用到FileProvider:
在AndroidManifest.xml中的application添加
<provider
android:authorities="com.gengcon.www.printdemo.MainActivity"
android:name="android.support.v4.content.FileProvider" //这里也可用android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/path"/>
</provider>
同时添加权限
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
在res->xml中添加path.xml文件
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<path>
<root-path name="root_path" path="."/>
</path>
<external-path
name="images"
path="Android/data/com.example.myapplication.MainActivity/test/"/>
</paths>
安卓拍照函数:
//拍照函数
@JavascriptInterface //可以通过js调取该函数
public void jsTakePhoto() {
Intent takepic=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takepic.resolveActivity(getPackageManager())!=null){
//这代表你的app可以允许相机
File photofile=null;
try{
photofile=cratephotofile();//去创建文件方法,获得图片路径创建的
showPIC=photofile;
if (photofile!=null) {
String pathtofile = photofile.getAbsolutePath();
Uri photouri= FileProvider.getUriForFile(MainActivity.this,"com.gengcon.www.printdemo.MainActivity",photofile);
//把这个图片和其他app分享,AUTHORITY是自己定义的,第三个必须是完整的图片路径
takepic.putExtra(MediaStore.EXTRA_OUTPUT,photouri);
//把share的Uri放进选好的路径
startActivityForResult(takepic,REQUEST_CAMERA);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
//创建相片文件
public File cratephotofile() throws IOException {//返回一个File类的文件
String name=new SimpleDateFormat("YYYYMMdd_HHmmss").format(new Date());
//年月日小时分秒
File stordir= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
//获得公共目录下的图片文件路径
File image=File.createTempFile(name,".jpg",stordir);
/**
* 获取图片的旋转角度,有些系统把拍照的图片旋转了,有的没有旋转
*/
return image;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// 扫描二维码/条码回传
if(requestCode ==REQUEST_CAMERA && resultCode == RESULT_OK){
//获取原图的旋转角度
int degree = ImageDispose.readPictureDegree(showPIC.getAbsolutePath());
System.out.println(degree+"========");
// 设置参数
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 只获取图片的大小信息,而不是将整张图片载入在内存中,避免内存溢出
BitmapFactory.decodeFile(showPIC.getPath(), options);
int height = options.outHeight;
int width= options.outWidth;
int inSampleSize =1; // 默认像素压缩比例
int minLen = Math.min(height, width); // 原图的最小边长
System.out.println(minLen+"=====milLen=======");
if(minLen > 2000) { // 如果原始图像的最小边长大于2000dp,则压缩为原图的1/2
inSampleSize =2;
}
options.inJustDecodeBounds = false; // 计算好压缩比例后,这次可以去加载原图了
options.inSampleSize = inSampleSize; // 设置为刚才计算的压缩比例
Bitmap bm = BitmapFactory.decodeFile(showPIC.getPath(), options); // 解码文件
//旋转原图回正方向
bm = ImageDispose.rotaingImageView(degree, bm);
//下面转换为base64 直接传给js
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG,80,bos);
try {
bos.flush();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
byte[] bb = bos.toByteArray();
String image = Base64.encodeToString(bb, Base64.NO_WRAP);
onReceiveImg(image);//调用js函数,将base64传过去
}
}
//该函数调用js中的onReceiveImg,将img的base64传过去
@SuppressLint("SetJavaScriptEnabled")
public void onReceiveImg(String img) {
mWebview.loadUrl("javascript:onReceiveImg('" + img + "')");
}
处理图片的工具类
public class ImageDispose {
/**
* 旋转图片
* @param angle
* @param bitmap
* @return Bitmap
*/
public static Bitmap rotaingImageView(int angle , Bitmap bitmap) {
//旋转图片 动作
Matrix matrix = new Matrix();;
matrix.postRotate(angle);
// 创建新的图片
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return resizedBitmap;
}
/**
* 读取图片属性:旋转的角度
* @param path 图片绝对路径
* @return degree旋转的角度
*/
public static int readPictureDegree(String path) {
int degree = 0;
try {
ExifInterface exifInterface = new ExifInterface(path);
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}
}
前端:
window.AndroidJSBridge.jsTakePhoto(); //调用安卓中的jsTakePhoto方法
给安卓调用的回调函数,可以取得img的base64
//安卓拍照返回base64
function onReceiveImg(img){
setHtml("data:image/jpg;base64,"+img); //前面加上url即可作为img的src显示
}
压缩并且通过formData上传:
const img = new Image()
img.src = mui("#waste_img")[0].src;
img.onload = function () {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.setAttribute('width', this.width)
canvas.setAttribute('height', this.height)
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
// 转成base64 文件
base64 = canvas.toDataURL('image/jpeg')
console.log(base64.length)
// 根据自己需求填写大小 我的目标是小于1兆
while (base64.length > 1024 * 1024 * 1) {
scale -= 0.1
base64 = canvas.toDataURL('image/jpeg', scale)
}
//这里对base64串进行操作,去掉url头,并转换为byte
const arr = base64.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bytes = atob(arr[1])
const bytesLength = bytes.length
const u8arr = new Uint8Array(bytesLength)
for (let i = 0; i < bytes.length; i++) {
u8arr[i] = bytes.charCodeAt(i)
}
const blob = new Blob([u8arr], { type: mime })
fd.append("photo",blob,Date.now() +'.jpg');
fd.append("wasteSource",vue.comeActive);
fd.append("wasteType",vue.categoryActive);
fd.append("wasteWeight",vue.weight);
fd.append("memo",vue.memo);
xhr.open('POST', app.BaseURL + 'appWeb/addWaste', true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
var res = JSON.parse(xhr.responseText)
console.log(res)
if(res.code==1){
mui.toat("添加成功")
}else{
mui.toast(res.message)
}
}
}
xhr.setRequestHeader('token',app.getToken())
xhr.send(fd);
}