android 开发 实现一个进入相机拍照后裁剪图片或者进入相册选中裁剪图片的功能

时间:2022-01-16 00:31:23

实现思维路径:

以进入相机拍照的思维路线为例子:

1.进入app

2.判断之前是否保存头像,如果有就显示历史图像 (下面代码中在getOldAvatar();方法中执行这个逻辑)

3.点击更换图像的Button或者布局,启动对话框(下面代码中在dialogueBox();方法执行这个逻辑)

4.系统版本判断授权方式(静态还是动态授权),判断之前是否已经授权 (setPermissions(Permissions_CAMERA_KEY);这个方法执行授权逻辑)

5.如果是首次授权,就执行首次授权完成后马上运行的回调方法 onRequestPermissionsResult

5.判断完成不管是否是首次授权还是之前就是授权过了都要执行enterCamera();方法启动相机并且发送携带数据的请求

6.启动相机完成后,并且拍照完成退出相机,都要运行Intent返回数据请求回调方法onActivityResult。将传入的数据传入到cropPhoto(data.getData());方法里去执行图片剪裁。

7.在cropPhoto方法里将携带数据跳转到裁剪界面中裁剪图片,裁剪完成后又要回到onActivityResult回调方法里,执行裁剪完的数据回调工作。

8.在onActivityResult回调方法里,裁剪完的图片将运行setPicToView 方法保存图片。保存的图片将在下次启动activity时作为历史头像调用。

package com.example.lenovo.mydemoapp;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.Manifest; import com.example.lenovo.mydemoapp.myAppCompatActivity.MyAppCompatAcitivity;
import com.example.lenovo.mydemoapp.myLayout.TitleLayout; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List; public class PersonalDataModification extends AppCompatActivity{
private static final String TAG = "PDM";
private TitleLayout mTitleLayout;
private TextView mTitleText;
private LinearLayout mPersonalDataModification_Avatar,mDialog_CameraButton,mDialog_GalleryButton;
private ImageView mPersonalDataModification_imageView_Avatar;
//得到外部存储根目录路径
private String mAvatarPath = Environment.getExternalStorageDirectory() + "/myAvatar/";
private String mAvatarName = "Avatar.jpg";
private Bitmap mBitmap;
/*
进入相册,相机,照片裁剪的key组
*/
private static final int ENTER_GALLERY = 1;
private static final int ENTER_CAMERA = 2;
private static final int ENTER_CROP_PHOTO = 3;
//需要在进入相机拍照或者相册选择图像中做区分。所以写了一个KEY来处理不同的Button
private static final int Permissions_GALLERY_KEY = 1;
private static final int Permissions_CAMERA_KEY = 2;
//需要的权限 注意请不要将数组写成 private String mPermissions[] = {"Manifest.permission.WRITE_EXTERNAL_STORAGE"};
//这样加了引号的是错误的
private String mPermissions[] = {Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();
setContentView(R.layout.activity_personal_data_modification);
// 设置标题栏
setTitle();
//显示历史头像
getOldAvatar();
// 添加对话框
dialogueBox();
}
/*
对话框
*/
public void dialogueBox(){
mPersonalDataModification_Avatar = (LinearLayout)findViewById(R.id.PersonalDataModification_Avatar);
mPersonalDataModification_Avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//添加对话框
AlertDialog.Builder builder = new AlertDialog.Builder(PersonalDataModification.this);
//创建对话框 注意一定要这样写 在下面的dialog才能执行dismiss();方法
final AlertDialog dialog = builder.create();
View view = LayoutInflater.from(getBaseContext()).inflate(R.layout.dialog_layout,null,false);
//导入视图
dialog.setView(view);
mDialog_CameraButton = (LinearLayout)view.findViewById(R.id.PersonalDataModification_Dialog_CameraButton);
mDialog_GalleryButton = (LinearLayout)view.findViewById(R.id.PersonalDataModification_Dialog_GalleryButton);
//相机
mDialog_CameraButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//设置权限
setPermissions(Permissions_CAMERA_KEY);
//关闭对话框
dialog.dismiss();
}
});
//相册
mDialog_GalleryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setPermissions(Permissions_GALLERY_KEY);
dialog.dismiss();
}
});
//创建并且显示
dialog.show();
}
});
}
public void setPermissions(int mPermissions_KEY){
/*
要添加List原因是想判断数组里如果有个别已经授权的权限,就不需要再添加到List中。添加到List中的权限后续将转成数组去申请权限
*/
List<String> permissionsList = new ArrayList<>();
//判断系统版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for (int i = 0; i < mPermissions.length; i++) {
//判断一个权限是否已经允许授权,如果没有授权就会将单个未授权的权限添加到List里面
if (ContextCompat.checkSelfPermission(this.getApplicationContext(), mPermissions[i]) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(mPermissions[i]);
}
}
//判断List不是空的,如果有内容就运行获取权限
if (!permissionsList.isEmpty()) {
String [] permissions = permissionsList.toArray(new String[permissionsList.size()]);
for (int j=0;j<permissions.length;j++){
Log.e(TAG,permissions[j]);
}
Log.e(TAG,"需要授权的权限有:"+permissions.length+"条");
//执行授权的代码。此处执行后会弹窗授权
ActivityCompat.requestPermissions(this, permissions, mPermissions_KEY);
} else { //如果是空的说明全部权限都已经授权了,就不授权了,直接执行进入相机或者图库
switch (mPermissions_KEY) {
case Permissions_CAMERA_KEY:
enterCamera();
break;
case Permissions_GALLERY_KEY:
enterGallery();
break;
default:
break;
}
}
}else {
Toast.makeText(getBaseContext(), "6.0以下的版本无需授权", Toast.LENGTH_SHORT).show();
Log.e(TAG,"6.0以下的版本无需授权");
switch (mPermissions_KEY) {
case Permissions_CAMERA_KEY:
enterCamera();
break;
case Permissions_GALLERY_KEY:
enterGallery();
break;
default:
break;
}
}
}
/*
授权完成后马上会运行的回调方法,此处写入首次授权完成后,要运行的内容
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == Permissions_CAMERA_KEY) {
if (grantResults.length > 0) { //安全写法,如果小于0,肯定会出错了
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e(TAG, "全部权限都成功授权进入相机");
enterCamera();
} else {
finish();
Toast.makeText(getBaseContext(), "授权失败", Toast.LENGTH_SHORT).show();
Log.e(TAG, "相机授权失败");
}
}
}
} else if (requestCode == Permissions_GALLERY_KEY) {
if (requestCode == Permissions_GALLERY_KEY) {
if (grantResults.length > 0) {
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e(TAG, "全部权限都成功授权进入相册");
enterGallery();
} else {
finish();
Toast.makeText(getBaseContext(), "授权失败", Toast.LENGTH_SHORT).show();
Log.e(TAG, "相册授权失败");
}
}
}
}
}
}
/*
点击后进入相机
*/
public void enterCamera(){
//MediaStore 多媒体存储 ACTION行动 IMAGE 图片 CAPTURW捕获
Intent intentGallery = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
/* 多媒体存储,额外制造 从文件里获取路径(获取外部存储目录 图片名称head.jpg)
将图片设置名称并且保存到外部存储空间里
*/
intentGallery.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(new File(Environment.getExternalStorageDirectory(), mAvatarName)));
//跳转页面启动相册,携带数据请求码
startActivityForResult(intentGallery,ENTER_CAMERA);
}
/*
点击后进入相册
*/
public void enterGallery(){
Intent intentCamera = new Intent(Intent.ACTION_PICK,null);
//设置数据和类型 多媒体存储.图片.媒体.外部.内容.URI image/*图片格式
intentCamera.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,"image/*");
startActivityForResult(intentCamera, ENTER_GALLERY); }
/*
从Intent中返回请求数据的方法,活动退出后运行这个方法
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
/*
相册选中图片后的数据回调
*/
case ENTER_GALLERY:
if(resultCode == RESULT_OK){
cropPhoto(data.getData());
}
break;
/*
拍照完成后的数据回调
*/
case ENTER_CAMERA:
if (resultCode == RESULT_OK) {
File temp = new File(Environment.getExternalStorageDirectory() + "/"+mAvatarName);
cropPhoto(Uri.fromFile(temp));// 裁剪图片 cropPhoto 200行方法
}
break;
/*
裁剪完成后的数据回调
*/
case ENTER_CROP_PHOTO:
if (data.resolveActivity(getPackageManager())!=null) {//判断Intent是否为空
Bundle extras = data.getExtras();
mBitmap = extras.getParcelable("data");
if (mBitmap != null) {
setPicToView(mBitmap);// 保存在SD卡中
mPersonalDataModification_imageView_Avatar.setImageBitmap(mBitmap);// 用ImageButton显示出来
}
}
break;
default:
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
/*
调用系统的裁剪功能,进入裁剪页面
*/
public void cropPhoto(Uri uri){
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri,"image/*");
intent.putExtra("crop","ture");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 250);
intent.putExtra("outputY", 250);
intent.putExtra("return-data", true);
Log.e(TAG,"头像裁剪");
startActivityForResult(intent, ENTER_CROP_PHOTO);
}
/*
显示默认头像或者历史设置的头像
*/
public void getOldAvatar(){
mPersonalDataModification_imageView_Avatar = (ImageView)findViewById(R.id.PersonalDataModification_imageView_Avatar);
//从文件存储里得到图片
Bitmap bt = BitmapFactory.decodeFile(mAvatarPath+mAvatarName);
//判断不是空头像
if (bt != null){
Drawable drawable = new BitmapDrawable(getResources(),bt);
//重新设置头像图片 注意这里使用的是setImageDrawable,不是setImageResource
mPersonalDataModification_imageView_Avatar.setImageDrawable(drawable);
Log.e(TAG,"使用历史头像");
}else {
//如果没有旧的头像就使用系统默认的
mPersonalDataModification_imageView_Avatar.setImageResource(R.drawable.ic_woman_default);
Log.e(TAG,"使用默认头像");
}
}
/*
保存到sd卡是为了下一次进入apk的时候直接读取图片,
*/
private void setPicToView(Bitmap mBitmap) {
String sdStatus = Environment.getExternalStorageState();
if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { // 检测sd是否可用
return;
} try {
File dir = new File(mAvatarPath);
dir.mkdirs();// 创建文件夹
File file = new File(mAvatarPath, mAvatarName);
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream b = new FileOutputStream(file);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, b);// 把图片数据写入图片b
b.flush(); //刷新
b.close(); //关闭
}catch(IOException e){
e.printStackTrace();
}
/*
FileOutputStream b = null;
File file = new File(mAvatarPath);
file.mkdirs();// 创建文件夹
String fileName = mAvatarPath + mAvatarName;// 图片名字
try {
b = new FileOutputStream(fileName);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, b);// 把图片数据写入图片b
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
b.flush(); //刷新
b.close(); //关闭
} catch (IOException e) {
e.printStackTrace();
}
}
*/
}
}