效果图
1.在res文件里面创建一个xml文件,然后创建file_paths文件
2.文件里面改成自己的包名
3.在AndroidMainfest.xml文件添加如下代码,并修改成自己的包名
4.在需要的Activity页面添加引用
import static android.support.v4.content.PermissionChecker.PERMISSION_GRANTED;
5.加入以下代码使用即可
//打开相机的返回码
private static final int CAMERA_REQUEST_CODE = 1;
//选择图片的返回码
private static final int IMAGE_REQUEST_CODE = 2;
//剪切图片的返回码
public static final int CROP_REREQUEST_CODE = 3;
// private ImageView iv;
//相机
public static final int REQUEST_CODE_PERMISSION_CAMERA = 100;
public static final int REQUEST_CODE_PERMISSION_GALLERY = 101;
//照片图片名
private String photo_image;
//截图图片名
private String crop_image;
//拍摄的图片的真实路径
private String takePath;
//拍摄的图片的虚拟路径
private Uri imageUri;
private Uri cropUri;
// private File tempFile = new File(Environment.getExternalStorageDirectory().getPath() + "/photo.jpg");
/**
* 拍照
*
* @param view
*/
public void onClickTakePhoto(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkPermission(REQUEST_CODE_PERMISSION_CAMERA);
return;
}
openCamera();
}
private void openCamera() {
if (isSdCardExist()) {
Intent cameraIntent = new Intent(
"android.media.action.IMAGE_CAPTURE");
photo_image = new SimpleDateFormat("yyyy_MMdd_hhmmss").format(new Date()) + ".jpg";
imageUri = getImageUri(photo_image);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT
, imageUri);
//添加这一句表示对目标应用临时授权该Uri所代表的文件
cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
cameraIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
startActivityForResult(cameraIntent, CAMERA_REQUEST_CODE);
} else {
Toast.makeText(this, "SD卡不存在", Toast.LENGTH_SHORT).show();
}
}
/**
* 打开图库
* 不需要用FileProvider
*
* @param view
*/
public void onClickOpenGallery(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkPermission(REQUEST_CODE_PERMISSION_GALLERY);
return;
}
openGallery();
}
private void openGallery() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");//相片类型
startActivityForResult(intent, IMAGE_REQUEST_CODE);
}
/**
* @param path 原始图片的路径
*/
public void cropPhoto(String path) {
crop_image = new SimpleDateFormat("yyyy_MMdd_hhmmss").format(new Date()) + "_crop" +
".jpg";
File cropFile = createFile(crop_image);
File file = new File(path);
Intent intent = new Intent("com.android.camera.action.CROP");
//TODO:访问相册需要被限制,需要通过FileProvider创建一个content类型的Uri
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//添加这一句表示对目标应用临时授权该Uri所代表的文件
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//TODO:访问相册需要被限制,需要通过FileProvider创建一个content类型的Uri
imageUri = FileProvider.getUriForFile(getApplicationContext(),
BuildConfig.APPLICATION_ID + ".provider", file);
cropUri = Uri.fromFile(cropFile);
//TODO:cropUri 是裁剪以后的图片保存的地方。也就是我们要写入此Uri.故不需要用FileProvider
//cropUri = FileProvider.getUriForFile(getApplicationContext(),
// BuildConfig.APPLICATION_ID + ".provider", cropFile);
} else {
imageUri = Uri.fromFile(file);
cropUri = Uri.fromFile(cropFile);
}
intent.setDataAndType(imageUri, "image/*");
intent.putExtra("crop", "true");
// //设置宽高比例
// intent.putExtra("aspectX", 1);
// intent.putExtra("aspectY", 1);
//设置裁剪图片宽高
intent.putExtra("outputX", 400);
intent.putExtra("outputY", 400);
intent.putExtra("scale", true);
//裁剪成功以后保存的位置
intent.putExtra(MediaStore.EXTRA_OUTPUT, cropUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, CROP_REREQUEST_CODE);
}
/**
* 获得一个uri。该uri就是将要拍摄的照片的uri
*
* @return
*/
private Uri getImageUri(String name) {
if (isSdCardExist()) {
File file = createFile(name);
if (file != null) {
takePath = file.getAbsolutePath();
Log.e("zmm", "图片的路径---》" + takePath);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return FileProvider.getUriForFile(getApplicationContext(),
BuildConfig.APPLICATION_ID + ".provider", file);
} else {
return Uri.fromFile(file);
}
}
}
return Uri.EMPTY;
}
public File createFile(String name) {
if (isSdCardExist()) {
File[] dirs = ContextCompat.getExternalFilesDirs(this, null);
if (dirs != null && dirs.length > 0) {
File dir = dirs[0];
return new File(dir, name);
}
}
return null;
}
Uri shangchaunImg;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case CAMERA_REQUEST_CODE://拍照成功并且返回
Log.e("zmm", "选择的图片的虚拟地址是------------>" +takePath);
cropPhoto(takePath);
// cropPhoto(getMediaUriFromPath(this,takePath),false);
break;
case IMAGE_REQUEST_CODE://选择图片成功返回
if (data != null && data.getData() != null) {
imageUri = data.getData();
cropPhoto(imageUri,true);
}
break;
case CROP_REREQUEST_CODE:
Log.e("zmm", "裁剪以后的地址是------------>" + cropUri);
shangchaunImg = cropUri;
decodeImage(cropUri);
break;
}
}
}
// 图片裁剪
private void cropPhoto(Uri uri, boolean fromCapture) {
Intent intent = new Intent("com.android.camera.action.CROP"); //打开系统自带的裁剪图片的intent
intent.setDataAndType(uri, "image/*");
intent.putExtra("scale", true);
// // 设置裁剪区域的宽高比例
// intent.putExtra("aspectX", 1);
// intent.putExtra("aspectY", 1);
// 设置裁剪区域的宽度和高度
intent.putExtra("outputX", 400);
intent.putExtra("outputY", 400);
// 取消人脸识别
intent.putExtra("noFaceDetection", true);
// 图片输出格式
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
// 若为false则表示不返回数据
intent.putExtra("return-data", false);
// 指定裁剪完成以后的图片所保存的位置,pic info显示有延时
if (fromCapture) {
// 如果是使用拍照,那么原先的uri和最终目标的uri一致
cropUri = uri;
} else { // 从相册中选择,那么裁剪的图片保存在take_photo中
String time = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA).format(new Date());
String fileName = "photo_" + time;
File mCutFile = new File(Environment.getExternalStorageDirectory() + "/take_photo", fileName + ".jpeg");
if (!mCutFile.getParentFile().exists()) {
mCutFile.getParentFile().mkdirs();
}
cropUri = getUriForFile(this, mCutFile);
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, cropUri);
Toast.makeText(this, "剪裁图片", Toast.LENGTH_SHORT).show();
// 以广播方式刷新系统相册,以便能够在相册中找到刚刚所拍摄和裁剪的照片
Intent intentBc = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intentBc.setData(uri);
this.sendBroadcast(intentBc);
startActivityForResult(intent, CROP_REREQUEST_CODE); //设置裁剪参数显示图片至ImageVie
}
// 从file中获取uri
// 7.0及以上使用的uri是contentProvider content://com.rain.takephotodemo.FileProvider/images/photo_20180824173621.jpg
// 6.0使用的uri为file:///storage/emulated/0/take_photo/photo_20180824171132.jpg
private static Uri getUriForFile(Context context, File file) {
if (context == null || file == null) {
throw new NullPointerException();
}
Uri uri;
if (Build.VERSION.SDK_INT >= 24) {
uri = FileProvider.getUriForFile(context.getApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", file);
} else {
uri = Uri.fromFile(file);
}
return uri;
}
/**
* 根据uri拿到bitmap
*
* @param imageUri 这个Uri是
*/
private void decodeImage(Uri imageUri) {
try {
Bitmap bitmapFormUri = getBitmapFormUri(this, imageUri);
img_suolv.setImageBitmap(bitmapFormUri);
beginupload(imageUri);
} catch (IOException e) {
e.printStackTrace();
}
}
public static Bitmap getBitmapFormUri(Activity ac, Uri uri) throws FileNotFoundException, IOException {
InputStream input = ac.getContentResolver().openInputStream(uri);
BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
onlyBoundsOptions.inJustDecodeBounds = true;
onlyBoundsOptions.inDither = true;//optional
onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
input.close();
int originalWidth = onlyBoundsOptions.outWidth;
int originalHeight = onlyBoundsOptions.outHeight;
if ((originalWidth == -1) || (originalHeight == -1))
return null;
//图片分辨率以480x800为标准
float hh = 800f;//这里设置高度为800f
float ww = 480f;//这里设置宽度为480f
//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int be = 1;//be=1表示不缩放
if (originalWidth > originalHeight && originalWidth > ww) {//如果宽度大的话根据宽度固定大小缩放
be = (int) (originalWidth / ww);
} else if (originalWidth < originalHeight && originalHeight > hh) {//如果高度高的话根据宽度固定大小缩放
be = (int) (originalHeight / hh);
}
if (be <= 0)
be = 1;
//比例压缩
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = be;//设置缩放比例
bitmapOptions.inDither = true;//optional
bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
input = ac.getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
input.close();
return compressImage(bitmap);//再进行质量压缩
}
/**
* 质量压缩方法
*
* @param image
* @return
*/
public static Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
while (baos.toByteArray().length / 1024 > 100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset();//重置baos即清空baos
//第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差 ,第三个参数:保存压缩后的数据的流
image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
options -= 10;//每次都减少10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
return bitmap;
}
/**
* 检查权限
*
* @param requestCode
*/
private void checkPermission(int requestCode) {
boolean granted = PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(this,
Manifest.permission_group.CAMERA);
if (granted) {//有权限
if (requestCode == REQUEST_CODE_PERMISSION_CAMERA) {
openCamera();//打开相机
} else {
openGallery();//打开图库
}
return;
}
//没有权限的要去申请权限
//注意:如果是在Fragment中申请权限,不要使用ActivityCompat.requestPermissions,
// 直接使用Fragment的requestPermissions方法,否则会回调到Activity的onRequestPermissionsResult
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest
.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
requestCode);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length > 0) {
boolean flag = true;
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PERMISSION_GRANTED) {
flag = false;
break;
}
}
//权限通过以后。自动回调拍照
if (flag) {
if (requestCode == REQUEST_CODE_PERMISSION_CAMERA) {
openCamera();//打开相机
} else {
openGallery();//打开图库
}
} else {
Toast.makeText(this, "请开启权限", Toast.LENGTH_SHORT).show();
}
}
}
/**
* 检查SD卡是否存在
*/
public boolean isSdCardExist() {
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
6.使用拍照或者打开图库
onClickTakePhoto(view); //拍照
onClickOpenGallery(view);//图库
7.记得要加入使用的权限
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 请求访问使用照相设备 -->
<uses-permission android:name="android.permission.INTERNET" /> <!-- 网络权限 -->
<uses-permission android:name="android.permission.VIBRATE" /> <!-- 震动权限 -->
<uses-permission android:name="android.permission.CAMERA" /> <!-- 摄像头权限 -->
<uses-feature android:name="android.hardware.camera.autofocus" /> <!-- 自动聚焦权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 读取sd卡 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 写入拨打电话权限 -->
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />