将拍照和相册选图封装成Demo,图片压缩用的是Android 开源压缩框架——Luban。先上效果动图:
效果图
一言以蔽之,拍照和相册选图这个开发中常见的功能,版本之间的重要区别是:
6.0以下的版本:只要在AndroidManifest中注明相机的使用权限,SDCard的读写2权限,就能在正常的写功能了
6.0:6.0以后Google不再允许开发者直接或许应用的权限,需要在用户知情的情况下授予权限,这便是运行时权限。相机,读,写3个权限除了要在AndroidManifest先声明,在写功能代码的时候还要做动态申请的操作。
7.0+: 众所周知Android四大组件之一内容提供器的作用,便是在不同的应用程序之间实现数据共享, Android 从 N 版本开始禁止通过 file://Uri 的方式在不同 App 之间共享文件,如此以来7.0版本以下直接获取图片文件路径的方法行不通了,所以我们写的应用,就需要通过内容提供器的方式,来获取系统文件管理器中目标文件的路径。
主要源码如下:
MainActivity:
package p.com.lubandemo.activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import java.io.File;
import p.com.lubandemo.R;
import p.com.lubandemo.rx.RxBus;
import p.com.lubandemo.rx.RxBusBaseMessage;
import p.com.lubandemo.rx.RxCode;
import p.com.lubandemo.util.STContext;
import p.com.lubandemo.view.FaceBlackPopWindow;
import rx.Subscription;
import rx.functions.Action1;
import top.zibin.luban.Luban;
import top.zibin.luban.OnCompressListener;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Handler uiHandler;
private Context context;
private FaceBlackPopWindow popupWindow;
private Button btn_popwindow;
MainActivity activity;
//动态写权限所用
public static boolean writeAccepted = false;
public static final int TAKE_PICTURE = 0;
public static final int PHOTO_REQUEST_GALLERY = 1; // 从相册中选择
public static Uri phototUri = null;
//7.0+ 拍照源路径所用
String loadUrl = "";
//所选相册图片的路径
String albumPath = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
uiHandler = new Handler();
activity = this;
btn_popwindow = findViewById(R.id.btn_popwindow);
context = MainActivity.this;
btn_popwindow.setOnClickListener(this);
Subscription subscription = RxBus.getDefault()
.toObservable(RxBusBaseMessage.class)
.subscribe(new Action1<RxBusBaseMessage>() {
@Override
public void call(RxBusBaseMessage message) {
if (message.getCode() == RxCode.FACE_BLACK_DISMISS) {
uiHandler.post(new Runnable() {
@Override
public void run() {
/**
更新UI
*/
dismissPop();
}
});
}
}
});
}
//6.0+运行时权限---写权限请求回掉函数(相机用)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 1:
writeAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
break;
}
}
private void dismissPop()
{
if(popupWindow!=null &&popupWindow.isShowing())
{
popupWindow.dismiss();
}
}
private void showFaceBlackPop()
{
popupWindow = new FaceBlackPopWindow(activity,activity.getWindow());
//弹出修改/次增加人脸黑名单弹出窗
//控件,为了popWindow一个基准``````````````
Button lin_face_warn = btn_popwindow;
popupWindow.showWindow(lin_face_warn);
}
// 压缩后图片文件存储位置
private String getPath() {
String path = STContext.getInst().imageFilePath;
File file = new File(path);
if (file.mkdirs()) {
return path;
}
return path;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) { // 如果返回码是可以用的
switch (requestCode) {
case TAKE_PICTURE:
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
//6.0以及以下的处理 luban 图片压缩的开源库
Luban.with(context)
.l