项目中一般用于头像更换、单图拍摄取图等
1.先获取权限
2.再利用Intent 打开系统相机
// 拍摄照片权限
<uses-permission android:name="android.permission.CAMERA"/>
先把所需要的的权限用数组装起来(需要其他权限还可以在里面添加)
private static String[] PERMISSIONS_STORAGE = {
"android.permission.CAMERA"};
public void verifyStoragePermissions(Activity activity) {
//然后通过其中的一个函数来申请
int checkSelfPermission = ActivityCompat.checkSelfPermission(activity, PERMISSIONS_STORAGE[0]);
if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
// 没有写的权限,去申请写的权限,会弹出对话框
ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
}
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 1);
需要打开防止内存泄露工具 StrictMode
private void initPhoto() {
// android 7.0系统解决拍照的问题
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();
}
上面最好写在onCreate()里面
1.打开相机的时候创建绝对路径
2.根据绝对路径获取URI,并把URI通过Intent存起来
3.最后根据startActivityForResult在onActivityResult中返回中获取原图file
/**
* 本地绝对路径添加文件夹的名字
*/
private final String IMAGE_FILE_LOCATION = "image";
/**
* 图片名字
*/
private String localFileName = "";
/**
* 图片file
*/
private File file;
/**
*打开相机
*/
private void openCream() {
localFileName = System.currentTimeMillis() + "" + ".jpg";
//先验证手机是否有sdcard
String status = Environment.getExternalStorageState();
if (status.equals(Environment.MEDIA_MOUNTED)) {
try {
File dir = new File(Environment.getExternalStorageDirectory() + "/" + IMAGE_FILE_LOCATION);
if (!dir.exists()) {
dir.mkdirs();
}
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File file = new File(dir,localFileName );
Uri uri = Uri.fromFile(file);
intent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, 1);
} catch (ActivityNotFoundException e) {
Toast.makeText(getActivity(), "没有找到储存目录", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(getActivity(), "没有储存卡", Toast.LENGTH_LONG).show();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == 1) {
file = new File(Environment.getExternalStorageDirectory()
+ "/" + IMAGE_FILE_LOCATION + "/" + localFileName);
/**
*获取到压缩图(大概为300k左右)URI保存到本地并显示在imgview中
*/
setBackground(saveBitmap(rotateBitmap(getImage(file.getPath()), readPictureDegree(file.getPath()))));
}
}
}
原理:重新定义好bitmap的高(Width)和宽(Hight)
/**
* 图片按比例大小压缩方法
*
* @param srcPath (根据路径获取图片并压缩)
* @return Bitmap
*/
public static Bitmap getImage(String srcPath) {
BitmapFactory.Options newOpts = new BitmapFactory.Options();
// 开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;
// 此时返回bm为空
Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
// 这里设置高度为720f
float hh = 720f;
// 这里设置宽度为1024f
float ww = 1024f;
// 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
// be=1表示不缩放
int be = 1;
// 如果宽度大的话根据宽度固定大小缩放
if (w > h && w > ww) {
be = (int) (newOpts.outWidth / ww);
// 如果高度高的话根据宽度固定大小缩放
} else if (w < h && h > hh) {
be = (int) (newOpts.outHeight / hh);
}
if (be <= 0) {
be = 1;
}
// 设置缩放比例
newOpts.inSampleSize = be;
// 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
// 压缩好比例大小后再进行质量压缩
return compressImage(bitmap);
}
1.获取图片的方向
2.根据获取到的图片方向进行矫正
/**
* 图片正常方向
*
* @param bitmap 图片bitmap
* @param degrees 矫正方向
* @return Bitmap
*/
public static Bitmap rotateBitmap(Bitmap bitmap, int degrees) {
if (degrees == 0 || null == bitmap) {
return bitmap;
}
Matrix matrix = new Matrix();
matrix.setRotate(degrees, bitmap.getWidth() >> 1, bitmap.getHeight() >> 1);
Bitmap bmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.recycle();
return bmp;
}
/**
* 图片旋转
*
* @param path 图片路径
* @return int
*/
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;
default:
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}
根据URI利用文件流写进去
/**
* 保存图片
*
* @param bm 资源(这里也可以再次进行压缩)
* @return uri
*/
private Uri saveBitmap(Bitmap bm) {
try {
FileOutputStream fos = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
return Uri.fromFile(file);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
这里显示在一个imgview中
/**
* 设置图片背景
*
* @param uri URi
*/
private void setBackground(Uri uri) {
InputStream inputStream;
Drawable drawable = null;
try {
Log.i("图片回调", " uri " + uri);
inputStream = getActivity().getContentResolver().openInputStream(uri);
drawable = Drawable.createFromStream(inputStream, "dataString");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (drawable != null) {
imgview.setBackground(drawable);
imgview.setVisibility(View.VISIBLE);
Log.d("图片回调", "set ok");
} else {
imgview.setVisibility(View.GONE);
Log.e("图片回调", "setBackground error");
}
}
根据获取到的file,利用RequestBody
MultipartBuilder builder = new MultipartBuilder().type(MultipartBuilder.FORM);
if (file.exists()) {
RequestBody imageBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
builder.addFormDataPart("file", file.getName(), imageBody);
}
RequestBody requestBody = builder.build();
multipart/form-data :这个要看后台是需要什么形式传,图片或许是 image/*