Android拍照和从相册获取图片(解决android7.0打开相机崩溃的问题),同时也解决了拍完照后图片方向不正的问题
2018-01-21 12:34
756 查看
本文转自:http://blog.csdn.net/wa172126691/article/details/78347852
在android7.0中相机操作需要动态申请权限,在点击打开相机按钮时要先判断权限,没有权限要申请,有权限再操作,同时在申请权限的回调方法中也要判断是否有权限,有权限的话再调用打开相机的方法
在android7.0中相机操作需要动态申请权限,在点击打开相机按钮时要先判断权限,没有权限要申请,有权限再操作,同时在申请权限的回调方法中也要判断是否有权限,有权限的话再调用打开相机的方法
package test.img.com.myimgtest.activity; import android.Manifest; import android.annotation.TargetApi; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.ContentUris; import android.content.ContentValues; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.media.ExifInterface; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.provider.DocumentsContract; 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.AppCompatActivity; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.Date; import test.img.com.myimgtest.R; import test.img.com.myimgtest.util.ImgPretreatment; public class ORCActivity888 extends AppCompatActivity { public static final int TAKE_PHOTO = 1;//启动相机标识 public static final int SELECT_PHOTO = 2;//启动相册标识 private ImageView imageView; private TextView textView; private File outputImagepath;//存储拍完照后的图片 private Bitmap orc_bitmap;//拍照和相册获取图片的Bitmap @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_orc); imageView = (ImageView) findViewById(R.id.shangchuan_img); textView = (TextView) findViewById(R.id.chazhi_tv); } /** * 打开相机 * * @param view */ public void xiangjiClick(View view) { //checkSelfPermission 检测有没有 权限 // PackageManager.PERMISSION_GRANTED 有权限 // PackageManager.PERMISSION_DENIED 拒绝权限 //一定要先判断权限,再打开相机,否则会报错 if(ActivityCompat.checkSelfPermission(this,Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){ //权限发生了改变 true // false,没有权限时 if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.CAMERA)){ new AlertDialog.Builder(this).setTitle("title") .setPositiveButton("ok", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 请求授权 ActivityCompat.requestPermissions(ORCActivity888.this,new String[]{Manifest.permission.CAMERA},1); } }).setNegativeButton("cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //不请求权限的操作 } }).create().show(); }else { ActivityCompat.requestPermissions(ORCActivity888.this,new String[]{Manifest.permission.CAMERA},1); } }else{ take_photo();//已经授权了就调用打开相机的方法 } } /** * 打开相册 */ public void xiangceClick(View view) { select_photo(); } /** * 拍照获取图片 **/ public void take_photo() { //获取系統版本 int currentapiVersion = Build.VERSION.SDK_INT; // 激活相机 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 判断存储卡是否可以用,可用进行存储 if (hasSdcard()) { SimpleDateFormat timeStampFormat = new SimpleDateFormat( "yyyy_MM_dd_HH_mm_ss"); String filename = timeStampFormat.format(new Date()); outputImagepath = new File(Environment.getExternalStorageDirectory(), filename + ".jpg"); if (currentapiVersion < 24) { // 从文件中创建uri Uri uri = Uri.fromFile(outputImagepath); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); } else { //兼容android7.0 使用共享文件的形式 ContentValues contentValues = new ContentValues(1); contentValues.put(MediaStore.Images.Media.DATA, outputImagepath.getAbsolutePath()); Uri uri = getApplication().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); } } // 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_CAREMA startActivityForResult(intent, TAKE_PHOTO); } /* * 判断sdcard是否被挂载 */ public static boolean hasSdcard() { return Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED); } /** * 从相册中获取图片 */ public void select_photo() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); } else { openAlbum(); } } /** * 打开相册的方法 */ private void openAlbum() { Intent intent = new Intent("android.intent.action.GET_CONTENT"); intent.setType("image/*"); startActivityForResult(intent, SELECT_PHOTO); } /** * 4.4以下系统处理图片的方法 */ private void handleImageBeforeKitKat(Intent data) { Uri uri = data.getData(); String imagePath = getImagePath(uri, null); displayImage(imagePath); } /** * 4.4及以上系统处理图片的方法 */ @TargetApi(Build.VERSION_CODES.KITKAT) private void handleImgeOnKitKat(Intent data) { String imagePath = null; Uri uri = data.getData(); Log.d("uri=intent.getData :", "" + uri); if (DocumentsContract.isDocumentUri(this, uri)) { String docId = DocumentsContract.getDocumentId(uri); //数据表里指定的行 Log.d("getDocumentId(uri) :", "" + docId); Log.d("uri.getAuthority() :", "" + uri.getAuthority()); if ("com.android.providers.media.documents".equals(uri.getAuthority())) { String id = docId.split(":")[1]; String selection = MediaStore.Images.Media._ID + "=" + id; imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection); } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) { Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId)); imagePath = getImagePath(contentUri, null); } } else if ("content".equalsIgnoreCase(uri.getScheme())) { imagePath = getImagePath(uri, null); } displayImage(imagePath); } /** * 通过uri和selection来获取真实的图片路径,从相册获取图片时要用 */ private String getImagePath(Uri uri, String selection) { String path = null; Cursor cursor = getContentResolver().query(uri, null, selection, null, null); if (cursor != null) { if (cursor.moveToFirst()) { path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); } cursor.close(); } return path; } /** * 拍完照和从相册获取玩图片都要执行的方法(根据图片路径显示图片) */ private void displayImage(String imagePath) { if (!TextUtils.isEmpty(imagePath)) { //orc_bitmap = BitmapFactory.decodeFile(imagePath);//获取图片 orc_bitmap = comp(BitmapFactory.decodeFile(imagePath)); //压缩图片 ImgUpdateDirection(imagePath);//显示图片,并且判断图片显示的方向,如果不正就放正 } else { Toast.makeText(this, "图片获取失败", Toast.LENGTH_LONG).show(); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { //打开相机后返回 case TAKE_PHOTO: if (resultCode == RESULT_OK) { /** * 这种方法是通过内存卡的路径进行读取图片,所以的到的图片是拍摄的原图 */ displayImage(outputImagepath.getAbsolutePath()); Log.i("tag", "拍照图片路径>>>>" + outputImagepath); } break; //打开相册后返回 case SELECT_PHOTO: if (resultCode == RESULT_OK) { //判断手机系统版本号 if (Build.VERSION.SDK_INT > 19) { //4.4及以上系统使用这个方法处理图片 handleImgeOnKitKat(data); } else { handleImageBeforeKitKat(data); } } break; default: break; } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case 1: //判断是否有权限 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { openAlbum();//打开相册 take_photo();//打开相机 } else { Toast.makeText(this, "你需要许可", Toast.LENGTH_LONG).show(); } break; default: break; } } @Override protected void onDestroy() { super.onDestroy(); if (orc_bitmap != null) { orc_bitmap.recycle(); } else { orc_bitmap = null; } } /** * 质量压缩方法 * * @param image * @return */ public static Bitmap compressImage(Bitmap image) { if (image != null) { 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 options -= 10;//每次都减少10 image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中 } ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中 Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片 return bitmap; } else { return null; } } //比例压缩 private Bitmap comp(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, baos); if (baos.toByteArray().length / 1024 > 1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出 baos.reset();//重置baos即清空baos image.compress(Bitmap.CompressFormat.JPEG, 50, baos);//这里压缩50%,把压缩后的数据存放到baos中 } ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray()); BitmapFactory.Options newOpts = new BitmapFactory.Options(); //开始读入图片,此时把options.inJustDecodeBounds 设回true了 newOpts.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts); newOpts.inJustDecodeBounds = false; int w = newOpts.outWidth; int h = newOpts.outHeight; //现在主流手机比较多是800*480分辨率,所以高和宽我们设置为 float hh = 800f;//这里设置高度为800f float ww = 480f;//这里设置宽度为480f //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 int be = 1;//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;//设置缩放比例 newOpts.inPreferredConfig = Bitmap.Config.RGB_565;//降低图片从ARGB888到RGB565 //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了 isBm = new ByteArrayInputStream(baos.toByteArray()); bitmap = BitmapFactory.decodeStream(isBm, null, newOpts); return bitmap;//压缩好比例大小后再进行质量压缩 } //改变拍完照后图片方向不正的问题 private void ImgUpdateDirection(String filepath) { int digree = 0;//图片旋转的角度 //根据图片的URI获取图片的绝对路径 Log.i("tag", ">>>>>>>>>>>>>开始"); //String filepath = ImgUriDoString.getRealFilePath(getApplicationContext(), uri); Log.i("tag", "》》》》》》》》》》》》》》》" + filepath); //根据图片的filepath获取到一个ExifInterface的对象 ExifInterface exif = null; try { exif = new ExifInterface(filepath); Log.i("tag", "exif》》》》》》》》》》》》》》》" + exif); if (exif != null) { // 读取图片中相机方向信息 int ori = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); // 计算旋转角度 switch (ori) { case ExifInterface.ORIENTATION_ROTATE_90: digree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: digree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: digree = 270; break; default: digree = 0; break; } } //如果图片不为0 if (digree != 0) { // 旋转图片 Matrix m = new Matrix(); m.postRotate(digree); orc_bitmap = Bitmap.createBitmap(orc_bitmap, 0, 0, orc_bitmap.getWidth(), orc_bitmap.getHeight(), m, true); } if (orc_bitmap != null) { imageView.setImageBitmap(orc_bitmap); } } catch (IOException e) { e.printStackTrace(); exif = null; } } }
相关文章推荐
- Android拍照和从相册获取图片(解决android7.0打开相机崩溃的问题),同时也解决了拍完照后图片方向不正的问题
- Android开发——相册拍照_03.解决相机拍照之后部分手机无法将图片保存到路径或部分手机点击相机确定无法返回问题
- android 调用系统相册选取照片或者打开相机拍照获取图片
- Android相机、相册获取图片,解决相机拍照图片被压缩模糊的情况
- android 调用系统相册选取照片或者打开相机拍照获取图片
- android 调用系统相册选取照片或者打开相机拍照获取图片,返回时回到手机桌面,然后才会跳转到当前activity
- android 调用系统相册选取照片或者打开相机拍照获取图片,返回时回到手机桌面,然后才会跳转到当前activity
- Android开发 调用系统相机相册图片功能,解决小米手机拍照或者图片横竖相反问题,及小米手机相册图片路径问题
- android 调用系统相册选取照片或者打开相机拍照获取图片,返回时为什么会回到home界面或者到前一个界面,然后才会跳转到当前activity
- Android基础--调用系统相机,打开相册,展示到界面,出现的一些问题Uri为空,data为null,图片错乱问题
- Android解决部分机型获取不到系统拍照图片,图库图片问题的解决
- Android打开相册vs拍照获取图片的原理实现
- Android部分手机拍照后获取的图片被旋转问题的解决方法
- Android拍照调用系统相册仿微信封装总结,治疗各种崩溃,图片横竖问题压缩等问题。
- 打开相机拍照和从本地相册获取图片以及图片的剪切
- 解决Android从相册中获取图片却无法裁剪的问题
- android打开相册选取图片或打开相机拍照并进行裁剪
- android 相机和相册获取相片剪裁报错问题解决,机型也解决
- 解决Android从相册中获取图片出错图片却无法裁剪问题的方法
- Android打开系统相机、相册,并进行裁剪图片的工具类CameraUtil,以及相册获取图片注意要点。