Android studio 简单的拍照功能,等比例高清晰度压缩图片
这个用第三方不太稳定 我推荐用系统相机就好
压缩用导入得第三方包 叫鲁班什么得,整体效果非常好,
不仅压缩率高,而且不会失真,比例也不用自己算了,用法有很多,可以自己琢磨一下
拍照得出来得图片目标在
内存根目录 名字叫tempCamera.jpg
我这里压缩直接替换了,你有需要得话可以保留原图。压缩图片路径在Luban()里面有备注
导包 压缩用到得 拍照用得系统相机 这个兼容性比较好
implementation 'top.zibin:Luban:1.1.8'
// 我这里动态判断权限用到的,你可以用其他的写法
implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.4@aar'
implementation 'io.reactivex.rxjava2:rxjava:2.0.7'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
--------我是分界线-------------------------------------
权限部分 放在清单里面
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<!--CAMER相机权限
下面是写出权限-->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
还有这个,兼容用的,没有这个拍照好像会报错
<!-- 7.0打开文件专用兼容权限 给一个私有文件权限 -->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.jph.takephoto.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
--------我是分界线-------------------------------------
file_paths.xml 内容 记得新建一个xml文件夹
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<external-path path="" name="camera_photos" />
</paths>
</resources>
--------我是分界线-------------------------------------
Activity 部分
/**
* 初始保存的图片 兼容性貌似更好 暂时不用 等待测试后结果 再决定是否使用这个
*/
public String CAMERA_TEMP = Environment.getExternalStorageDirectory().getPath() + File.separator + "tempCamera.jpg";
//拍照功能参数
private static final int TAKE_PHOTO = 1;
private static final int CHOOSE_PHOTO = 2;
private final static int CROP_IMAGE = 3;
private Uri imageUri;
// 动态获取权限后调用拍照
private void openCamera() {
RxPermissions rxPermissions = new RxPermissions(A_NdividualCenterActivity.this);
rxPermissions.request(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA, Manifest.permission.INTERNET)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Boolean>() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void accept(Boolean aBoolean) throws Exception {
if (aBoolean) {
//申请的权限全部允许
openCa();
} else {
//只要有一个权限被拒绝,就会执行
Toast.makeText(A_NdividualCenterActivity.this, "未授权权限,部分功能不能使用", Toast.LENGTH_SHORT).show();
}
}
});
}
/**
* 打开相机
*/
private void openCa() {
// 创建File对象,用于存储拍照后的图片
// 将图片命名为output_image.jpg,并将它存放在手机SD卡的应用关联缓存目录下
// getExternalCacheDir()可以得到这个目录
// File outputImage = new File(getExternalCacheDir(), "output_image.jpg");
File outputImage = new File(CAMERA_TEMP);
try {
if (outputImage.exists()) {
outputImage.delete();
}
outputImage.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
// 进行一个判断
// 如果运行设备的系统版本低于Android 7.0,就调用Uri的fromFile()方法将File对象转换成Uri对象
// 这个Uri对象标识着output_image.jpg这张图片的本地真实路径
// 否则,就调用FileProvider的getUriForFile()方法将File对象转换成一个封装过的Uri对象
// getUriForFile()方法接收 3个参数,第一个参数要求传入Context对象,第二个参数可以是任意唯一的字符串,第三个参数则是我们刚刚创建的File对象
// 之所以要进行这样一层转换,是因为从Android 7.0系统开始,直接使用本地真实路径的Uri被认为是不安全的,会抛出一个FileUriExposedException 异常
// 而FileProvider则是-种特殊的内容提供器,它使用了和内容提供器类似的机制来对数据进行保护,可以选择性地将封装过的Uri共享给外部,从而提高了应用的安全性
if (Build.VERSION.SDK_INT >= 24) {
CAMERA_TEMP = Environment.getExternalStorageDirectory().getPath() + File.separator + "tempCamera.jpg";//根目录下 上面也有声明 这里特别写一下 防止找不到
imageUri = FileProvider.getUriForFile(this, "com.jph.takephoto.fileprovider", new File(CAMERA_TEMP));//通过FileProvider创建一个content类型的Uri
} else {
imageUri = Uri.fromFile(outputImage);
}
//启用相机程序
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, TAKE_PHOTO);
}
//打开相册 这里没用到,不过很多人需要 这里写一下 没用到可以忽略
private void openAlbum() {
Intent intent_album = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent_album, CHOOSE_PHOTO);
}
/**
* 压缩
*/
private void Luban() {
Luban.with(this) //context
.load(CAMERA_TEMP) // 需要压缩的图片file
.ignoreBy(100) //压缩率 ,默认100,你觉得图片大 这个也可以改一下 图片会小一点
.setTargetDir(Environment.getExternalStorageDirectory().getPath() + File.separator) //压缩后文件目录
.filter(new CompressionPredicate() {
@Override
public boolean apply(String path) {
return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif"));
}
})
.setCompressListener(new OnCompressListener() {
@Override
public void onStart() {
// TODO 压缩开始前调用,可以在方法内启动 loading UI
}
@Override
public void onSuccess(File file) {
// TODO 压缩成功后调用,返回压缩后的图片文件
//如果希望替换原图可以执行这行
file.renameTo(new File(CAMERA_TEMP));
//将拍摄的照片显示出来
}
@Override
public void onError(Throwable e) {
// TODO 当压缩过程出现问题时调用
}
}).launch();
}
/**
* 拍完照后一般会跑这里 你可以在这里处理原图 我这里执行了压缩 并替换原图
这个放在外面别搞错了
* 接收图片处理
*
* @param requestCode [description]
* @param resultCode [description]
* @param data [description]
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case TAKE_PHOTO:
if (resultCode == RESULT_OK) {
Luban();//执行压缩
try {
Bitmap bitmap = null;
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
// iv_Camera.setImageBitmap(bitmap);//用一个ImageView展示图片
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
break;
default:
break;
}
}
--------我是分界线-------------------------------------


