Android调用照相机展示高清图片及展示图片时图片倾斜问题

  • 一、概述
  • 二、配置权限
  • 三、封装CameraUtil工具类
    • 1、Android调用照相机
    • 2、调用系统相册
    • 3、拍摄完毕或在相册选取好照片后处理图片
  • 四、MainActivity如何调用
  • 五、Layout布局文件
  • 查看源码

一、概述

由于需要做一个调用Android原生照相机并展示出清楚的图片的demo,在网上查找了很多资料,没有找到一个我希望的完整文章。包括:调用照相机、调用手机图片、照相机拍出的图片展示清楚的图片、部分手机(如:小米、华为等)在展示图片时图片是倾斜的如何调正的问题。这里做一个总结,之后自己再遇到这样的问题也可以快速查看。

二、配置权限

首先需要在AndroidManifest.xml 文件添加需要的权限

 <uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_CONTACTS" />

由于Android 6.0以上的手机需要动态获取权限所以以上权限需要在代码中做判断API level 23以上版本需要在代码中动态获取

 if(currentapiVersion>23){if (HasPermission(mActivity,Manifest.permission.WRITE_EXTERNAL_STORAGE) && HasPermission(mActivity,Manifest.permission.READ_EXTERNAL_STORAGE)) {//具体操作}else{ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 2);}}
   /**检查有没有sd卡写入权限*/private boolean HasPermission(Context context,String permission){//Manifest.permission.WRITE_EXTERNAL_STORAGEint result= ContextCompat.checkSelfPermission(context,permission);return result ==PackageManager.PERMISSION_GRANTED;}

同时要在application中配置

<providerandroid:name="android.support.v4.content.FileProvider"android:authorities="${applicationId}.provider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" /></provider>

三、封装CameraUtil工具类

1、Android调用照相机

调用照相机时,设置照片存储路径,自定义照片名称(这里是根据时间命名),判断手机当前版本号,如果在API level 23以上则判断是否获取权限,如果没有则动态获取权限,如果已经获取权限了,则打开照相机。

 /**打开照相机*/public void OpenCamera(){Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//设置自定义存储路径mFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/systemCemer";File outFilePath = new File(mFilePath);//判断是否有该文件夹,没有则创建文件夹if (!outFilePath.exists()) {outFilePath.mkdirs();}//设置自定义照片的名字String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());mFilePath = mFilePath + "/" + fileName + ".jpg";File outFile = new File(mFilePath);//获取手机当前版本号int currentapiVersion = Build.VERSION.SDK_INT;if (currentapiVersion >23) {//currentapiVersion >23//判断是否有照相机权限if (HasPermission(mActivity,Manifest.permission.CAMERA)) {//判断是否有读取和写入的权限if (HasPermission(mActivity,Manifest.permission.WRITE_EXTERNAL_STORAGE) && HasPermission(mActivity,Manifest.permission.READ_EXTERNAL_STORAGE)) {Uri uri = Uri.fromFile(outFile);intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);//打开照相机mActivity.startActivityForResult(intent, REQUEST_CODE_TAKE_PICTURE);} else {//无储存权限ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 0);}} else {//无相机权限ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.CAMERA}, 1);}}else{imageUri = Uri.fromFile(outFile);intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//打开照相机mActivity.startActivityForResult(intent, REQUEST_CODE_TAKE_PICTURE);}}
    /** 检查有没有sd卡写入权限*/private boolean HasPermission(Context context,String permission){//Manifest.permission.WRITE_EXTERNAL_STORAGEint result= ContextCompat.checkSelfPermission(context,permission);return result ==PackageManager.PERMISSION_GRANTED;}

2、调用系统相册

打开系统相册,同样在调用系统相册前先判读是否获取权限。

/**打开相册前的权限判断各种*/public void OpenPhotoStrat(){int currentapiVersion = Build.VERSION.SDK_INT;if(currentapiVersion>23){if (HasPermission(mActivity,Manifest.permission.WRITE_EXTERNAL_STORAGE) && HasPermission(mActivity,Manifest.permission.READ_EXTERNAL_STORAGE)) {OpenPhoto();}else{ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 2);}}else{OpenPhoto();}}
 /**打开相册*/private void OpenPhoto(){Intent intent = new Intent("android.intent.action.GET_CONTENT");intent.setType("image/*");// 打开相册mActivity.startActivityForResult(intent, CHOOSE_PHOTO);}

3、拍摄完毕或在相册选取好照片后处理图片

因为这里写的是一个工具类,所以需要创建一个回调接口

    public interface ReturnBitmap {void returnBitmap(Bitmap bitmap);}

这里是根据Activity里面的回调方法onActivityResult,在工具类里面进行处理之后再返回给Activity处理好的Bitmap图片。其中有相册里获取图片(case CHOOSE_PHOTO:)和从照相机里获取的图片(case REQUEST_CODE_TAKE_PICTURE:)。

    //在CameraUtil里处理返回的结果public void onActivityResult(int requestCode, int resultCode, Intent data,ReturnBitmap returnBitmaps) {returnBitmap = returnBitmaps;switch (requestCode) {case CHOOSE_PHOTO:if (resultCode == mActivity.RESULT_OK) {handleImage(data);}break;//-----获取高清图片case REQUEST_CODE_TAKE_PICTURE:if (BuildConfig.DEBUG) Log.d("SystemCemerActivity", mFilePath);final Bitmap bitmap = loadingImageBitmap(mFilePath);if (bitmap!=null) {//picture.setImageBitmap(bitmap);returnBitmap.returnBitmap(bitmap);}break;default:break;}}

下面部分是相册返回的处理代码

    // 只在Android4.4及以上版本使用@TargetApi(19)private void handleImage(Intent data) {String imagePath = null;Uri uri = data.getData();if (DocumentsContract.isDocumentUri(mActivity, uri)) {// 通过document id来处理String docId = DocumentsContract.getDocumentId(uri);if ("com.android.providers.media.documents".equals(uri.getAuthority())) {// 解析出数字idString 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".equals(uri.getScheme())) {// 如果不是document类型的Uri,则使用普通方式处理imagePath = getImagePath(uri, null);}// 根据图片路径显示图片displayImage(imagePath);}
    /**** 如果不是document类型的Uri,则使用普通方式处理* @param uri* @param selection* @return*/private String getImagePath(Uri uri, String selection) {String path = null;// 通过Uri和selection来获取真实图片路径Cursor cursor = mActivity.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;}
    /**** 根据图片路径显示图片* @param imagePath*/private void displayImage(String imagePath) {if (imagePath != null) {Bitmap bitmap = BitmapFactory.decodeFile(imagePath);//旋转图片bitmap = rotateBitmapByDegree(bitmap,getBitmapDegree(imagePath));//picture.setImageBitmap(bitmap);returnBitmap.returnBitmap(bitmap);}else {Toast.makeText(mActivity, "failed to get image", Toast.LENGTH_SHORT).show();}}

下面的是照相机返回图片处理代码

    //整理高清图片public Bitmap loadingImageBitmap(String imagePath) {/*** 获取图片位置的宽与高*/final int width = mActivity.getWindowManager().getDefaultDisplay().getWidth();final int height = mActivity.getWindowManager().getDefaultDisplay().getHeight();/*** 通过设置optios来只加载大图的尺寸*/BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;Bitmap bitmap = null;try {bitmap = BitmapFactory.decodeFile(imagePath, options);/*** 计算手机宽高与显示大图的宽高,然后确定缩放有比例*/int widthRaio = (int) Math.ceil(options.outWidth/(float)width);int heightRaio = (int) Math.ceil(options.outHeight/(float)height);if (widthRaio>1&&heightRaio>1){if (widthRaio>heightRaio){options.inSampleSize = widthRaio;}else {options.inSampleSize = heightRaio;}}/*** 设置加载缩放后的图片*/options.inJustDecodeBounds = false;bitmap = BitmapFactory.decodeFile(imagePath, options);//旋转图片bitmap = rotateBitmapByDegree(bitmap,getBitmapDegree(imagePath));} catch (Exception e) {e.printStackTrace();}return bitmap;}

下面照片和照相机公用代码,主要作用是处理图片倾斜问题(如:小米、华为等会遇到这样的问题)。

    /*** 读取图片的旋转的角度** @param path 图片绝对路径* @return 图片的旋转角度*/public static int getBitmapDegree(String path) {int degree = 0;try {// 从指定路径下读取图片,并获取其EXIF信息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;}} catch (IOException e) {e.printStackTrace();}return degree;}
    /*** 将图片按照某个角度进行旋转** @param bm 需要旋转的图片* @param degree 旋转角度* @return 旋转后的图片*/public static Bitmap rotateBitmapByDegree(Bitmap bm,int degree) {Bitmap returnBm = null;//根据旋转角度,生成旋转矩阵Matrix matrix = new Matrix();matrix.postRotate(degree);try {//将原始图片按照旋转矩阵进行旋转,并得到新的图片returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);} catch (OutOfMemoryError e) {}if (returnBm == null) {returnBm = bm;}if (bm != returnBm) {bm.recycle();}return returnBm;}
}

这样一个CameraUtil工具类就封装完成了。

四、MainActivity如何调用

下面是调用CameraUtil工具类的方法,其中6.0以上需要配置
//6.0以上配置
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();
这些方法否则显示不出来图片

package com.wzp.mycamera;import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.annotation.RequiresApi;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;public class MainActivity extends Activity {private Button takePhoto;private ImageView picture;private Button chooseFromAlbum;private CameraUtil cameraUtil;@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);//6.0以上配置StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();StrictMode.setVmPolicy(builder.build());builder.detectFileUriExposure();takePhoto = (Button) findViewById(R.id.take_photo);picture = (ImageView) findViewById(R.id.picture);chooseFromAlbum = (Button) findViewById(R.id.choose_from_album);//-----创建CameraUtil实例cameraUtil = new CameraUtil(this);takePhoto.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//-----从CameraUtil中调用相机cameraUtil.OpenCamera();}});chooseFromAlbum.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//-----从CameraUtil中调用相机cameraUtil.OpenPhotoStrat();}});}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {cameraUtil.onActivityResult(requestCode, resultCode, data, new CameraUtil.ReturnBitmap() {@Overridepublic void returnBitmap(Bitmap bitmap) {picture.setImageBitmap(bitmap);}});}}

五、Layout布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><Buttonandroid:id="@+id/take_photo"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="启动相机" /><Buttonandroid:id="@+id/choose_from_album"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="从相册中选择图片" /><ImageViewandroid:id="@+id/picture"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center_horizontal"android:layout_margin="10dp"/>
</LinearLayout>

以上就是关于Android照相机调用的全部内容

查看源码

链接: 源码连接.

Android调用照相机展示高清图片及展示图片时图片倾斜问题相关推荐

  1. Android调用相机拍照高清原图(兼容7.0)

    在安卓更新7.0的版本后,要调用相机拍照获取原图则需要先把拍摄后的内容保存到目录,然后再借助provider调出来显示,相比以前可以说十分繁琐,但为了摆脱马赛克画质的困扰,为了更好的用户体验,还是硬着 ...

  2. 浅谈android中加载高清大图及图片压缩方式(二)

    这一讲就是本系列的第二篇,一起来聊下关于android中加载高清大图的问题,我们都知道如果我们直接加载原图的话,一个是非常慢,需要等待一定时间,如果没有在一定的时间内给用户响应的话,将会极大影响用户的 ...

  3. Android调用照相机拍照

    之前写在别的网站上写博客.后来没有坚持下来,以至于账号密码都忘了,好啦说正事 Android调用照相机拍照 这个在现在的应用中很常见,首先如果拍照是应用的必要功能,那么应该令它在Google Play ...

  4. Android应用开发揭秘[高清PDF版+源码]

    编辑推荐 本书内容全面,不仅详细讲解了Android框架.Android组件等基础知识,而且还深入阐述了传感器.语音识别.桌面组件开发等高级知识,最重要的是还全面介绍了如何利用原生的C/C++(NDK ...

  5. 【iOS-cocos2d-X 游戏开发之十六】Cocos2dx编译后的Android自动使用(-hd)高清图设置自适应屏幕...

    本篇主要介绍Cocos2dx项目开发过程中或者说项目务必遇到的一些知识点(ps.貌似Himi博客写的都是务必的 :tx:  Himi认为写别人没写的才更容易吸引人不是-) OK,不多说废话,第一个介绍 ...

  6. dvb-c usb android,安卓智能DVB-C高清数字机顶盒

    主要特征 DV6508-C采用高性能数字电视芯片方案,双核业务处理实现机制.内置蓝牙.WIFI.MIC模块:双USB2.0 接口,支持多种USB扩展应用,完全符合DVB-C标准,支持高清MPEG-2. ...

  7. 地牢猎手2 Android,地牢猎手2高清版 Dungeon Hunter 2 HD

    包名:com.gameloft.android.TBFV.GloftD2HP.ML小编评语: 相对于一代有了不小的提升,从数据包变成500m就可以看出这次会有更多的东西,赶快试试吧. Gameloft ...

  8. android系统电视缺点,高清智能电视安卓系统优势与不足解析

    今年,高清智能电视开始成为平板电视市场的一大焦点,其凭借丰富的应用软件打下了大片的"江山",作为高清智能电视,其高清晰度画面是必然的追求,而应用的丰富度是其最大的买点,其中最为关键 ...

  9. android调用照相机拍照获取照片并做简单剪裁

    1.调用系统的照相机程序 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(int ...

最新文章

  1. 出入口控制系统工程设计规范_[问答]连载77-控制系统之间如何时钟同步?
  2. android点击事件注册方式,Android界面控件(3)— 注册同一个点击事件的监听器...
  3. leetcode中求subset、全排列等问题的回溯算法总结
  4. sigmoid函数_机器学习面试常考知识之激活函数
  5. 使用WebDeployment Project改善VS2005发布网站问题
  6. mysql分组查询和子查询语句_6.MySQL分组聚合查询,子查询
  7. 关于DOM操作的几个类型
  8. springboot使用AOP打印日志信息
  9. 【java笔记】System类
  10. PhoneGap+Xcode6环境配置
  11. VC2005用不惯呀....
  12. if else 的或(||)
  13. 常见B端产品经理面试问题及答案(一)
  14. 20145322何志威 《Java程序设计》课程总结
  15. P1125 [NOIP2008 提高组] 笨小猴
  16. 摄像头取流转发 嵌入式系统_如何在不转发的情况下嵌入某人的Twitter视频
  17. 入门:链表的基本操作
  18. 愚见——工大之软件工程
  19. Visual Studio Code的下载和安装
  20. 西门子S71200自建数据类型统计设备OEE的方法

热门文章

  1. [二分][并查集] Jzoj P5904 刺客信条(AC)
  2. 解决word打空格不能出现下划线
  3. 7-33 有理数加法(分数 15)
  4. TMS320F2837xD和TMS320F2837xS的区别
  5. 虚拟机安装与配置(安装cent0S)
  6. OSI的七层模型,网线,网卡,集线器,交换机,路由器分别工作在七层模型中的哪一层?
  7. 应用自定义对象生成表格
  8. 跑步的好处, 跑步千万要注意这些事项!
  9. L-2 珍珠项链(PTA)
  10. 【教程】手把手教你如何利用工具(IE9的F12)去分析模拟登陆网站(百度首页)的内部逻辑过程