三星手机拍照强制切换到横屏及照片旋转问题

来源:互联网 发布:淘宝网的性用品有用吗 编辑:程序博客网 时间:2024/03/29 08:17

最近在做项目,项目里面有拍照上传的功能,无非就是吊起系统拍照功能,然后获取所拍照的地址,然后上传即可。但是当我无意间拿了一部三星手机装了App之后,当使用拍照功能的时候,拍完之后,界面并没有出现所拍的照片,之后才知道是三星手机在拍照的时候会强制切换到横屏,导致生命周期重走了,所以拍出来的照片所保存的地址也跟着没有了,然后我在清单文件中配置了该Activity的android:configChanges="orientation|keyboardHidden",然而并没有什么卵用,幸好Activity提供了onSaveInstanceState方法,用于保存数据,重走onCreate的时候再拿出来即可解决以上的问题,代码如下:

@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreateBM(savedInstanceState);if(savedInstanceState != null){//因为三星部分机型,拍照的时候他会强制切换到横屏,导致该类重走生命周期,所有的数据重置了,所以要保存之前的数据,在此重新获取//三星的camera强制切换到横屏  导致Activity重启生命周期 (但是部分机型  配置  android:configChanges  也不能阻止横竖屏切换);//重新获取重走生命周期之前的数据mFiles = (List<File>) savedInstanceState.getSerializable("mFiles");mHomeWork =  (List<HomeWork>) savedInstanceState.getSerializable("mHomeWork");mVoiceWork = savedInstanceState.getStringArrayList("mVoiceWork");mPicWork = savedInstanceState.getStringArrayList("mPicWork");mHomeworkList = savedInstanceState.getStringArrayList("mHomeworkList");//设置数据到相应的控件上}}@Overrideprotected void onSaveInstanceState(Bundle savedInstanceState) {//保存数据savedInstanceState.putStringArrayList("mHomeworkList", (ArrayList<String>) mHomeworkList);savedInstanceState.putStringArrayList("mPicWork", (ArrayList<String>) mPicWork);savedInstanceState.putStringArrayList("mVoiceWork", (ArrayList<String>) mVoiceWork);savedInstanceState.putSerializable("mFiles",(Serializable) mFiles);savedInstanceState.putSerializable("mHomeWork",(Serializable) mHomeWork);}
当解决了强制横屏的问题,三星手机又来了一个旋转照片的毛病,拍出来的照片居然被旋转了90°或180°,感觉整个人不好了。百度了一下,下面就来整理一下,有关图片旋转问题,还有图片压缩问题。
拍出来的照片,可以根据ExifInterface类来获取其旋转的角度。但是旋转的时候,是通过Bitmap来做的,所以就需要将本地图片在读取成Bitmap,但是过大的图片加载到内存肯定是要崩的,所以就需要对照片进行压缩,但是处理拍出来的照片的时候,切记一定要先获取其旋转的角度,再压缩,然后再旋转。如果先压缩,压缩后的照片就不是本来的那张原始照片的,并没有旋转,所以它获取出来的旋转角度是0°。以下是相关的代码

import java.io.File;import java.io.IOException;import android.graphics.Bitmap;import android.graphics.Matrix;import android.media.ExifInterface;/** * 获取图片角度和旋转图片 * @author chenj * */public class CaremaUtil {/** * 读取图片的旋转的角度 * * @param path *            图片绝对路径 * @return 图片的旋转角度 */public static int getBitmapDegree(File pathFile) {return getBitmapDegree(pathFile.getAbsolutePath());}/** * 读取图片的旋转的角度 * * @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;}}

import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import android.graphics.Bitmap;import android.graphics.BitmapFactory;/** * 读取和保存图片 * @author chenj * */public class BitmapUtil {/** * 读取图片 * @param filePath * @return */public static Bitmap getBitmapFromPath(String filePath){Bitmap decodeFile = BitmapFactory.decodeFile(filePath);return decodeFile;}/** * 读取图片 * @param file * @return */public static Bitmap getBitmapFromFile(File file){return getBitmapFromPath(file.getAbsolutePath());}/** * 保存Bitmap到本地 * @param bitmap * @param file */public static void saveBitmapToSD(Bitmap bitmap, File file){try {boolean delete = file.delete();FileOutputStream fos = new FileOutputStream(file);bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);//这里100表示不压缩,将不压缩的数据存放到baos中//回收图片,清理内存if(bitmap != null && !bitmap.isRecycled()){bitmap.recycle();bitmap = null;    System.gc();}fos.flush();fos.close();} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}                }}

import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.util.UUID;import com.bm.app.App;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.BitmapFactory.Options;import android.text.TextUtils;/** * 压缩图片 * @author chenj * */public class CompressUtil {//保存的路径private static String mSavePath = new File(App.getInstance().getExternalCacheDir(),"aaa/bbb/ccc").getAbsolutePath();/** * 压缩文件,源文件和压缩后的文件都存在,源文件并没有被删除 * @param pathFile * @return */public static File compress(File pathFile){//如果小于500KB就直接返回,不进行压缩if(pathFile.length() < 1024 * 500){ return pathFile;}File file = new File(mSavePath);if(!file.exists()){file.mkdirs();}String imageFileName = UUID.randomUUID().toString()+getFileSuffix(pathFile.getAbsolutePath());//定义一个file,为压缩后的图片File f = new File(mSavePath,imageFileName);try{//先将所选图片转化为流的形式,path所得到的图片路径 FileInputStream is = new  FileInputStream(pathFile); int size = 3; if(pathFile.length() < 1024 * 500){ size = 1; }else if(pathFile.length() > 1024 * 1024 * 5){ size = 5; }  Options options = new Options(); options.inSampleSize = size; //将图片缩小为原来的  1/size ,不然图片很大时会报内存溢出错误 Bitmap image = BitmapFactory.decodeStream(is,null,options); is.close();ByteArrayOutputStream baos = new ByteArrayOutputStream();                image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//这里100表示不压缩,将不压缩的数据存放到baos中int per = 100;                while (baos.toByteArray().length / 1024 > 500) { // 循环判断如果压缩后图片是否大于500kb,大于继续压缩baos.reset();// 重置baos即清空baosimage.compress(Bitmap.CompressFormat.JPEG, per, baos);// 将图片压缩为原来的(100-per)%,把压缩后的数据存放到baos中per -= 10;// 每次都减少10               }//回收图片,清理内存if(image != null && !image.isRecycled()){    image.recycle();    image = null;    System.gc();}ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中baos.close();FileOutputStream os;os = new FileOutputStream(f);//将输入流复制到输出流中copyStream(isBm, os);isBm.close();os.close();}catch(Exception e){e.printStackTrace();}return f;}/** * 压缩源文件,只保存压缩后的文件,源文件将被删除,压缩后的文件名和源文件一样 * @param pathFile * @return */public static File compressSourceFile(String path){return compressSourceFile(new File(path));}/** * 压缩源文件,只保存压缩后的文件,源文件将被删除,压缩后的文件名和源文件一样 * @param pathFile * @return */public static File compressSourceFile(File pathFile){try{//先将所选图片转化为流的形式,path所得到的图片路径 FileInputStream is = new  FileInputStream(pathFile); int size = 3; if(pathFile.length() < 1024 * 500){ size = 1; }else if(pathFile.length() > 1024 * 1024 * 5){ size = 5; }  Options options = new Options(); options.inSampleSize = size; //将图片缩小为原来的  1/size ,不然图片很大时会报内存溢出错误 Bitmap image = BitmapFactory.decodeStream(is,null,options); is.close();ByteArrayOutputStream baos = new ByteArrayOutputStream();                image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//这里100表示不压缩,将不压缩的数据存放到baos中int per = 100;                while (baos.toByteArray().length / 1024 > 500) { // 循环判断如果压缩后图片是否大于500kb,大于继续压缩baos.reset();// 重置baos即清空baosimage.compress(Bitmap.CompressFormat.JPEG, per, baos);// 将图片压缩为原来的(100-per)%,把压缩后的数据存放到baos中per -= 10;// 每次都减少10               }//回收图片,清理内存if(image != null && !image.isRecycled()){    image.recycle();    image = null;    System.gc();}pathFile.delete();//删除源文件ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中baos.close();FileOutputStream os;os = new FileOutputStream(pathFile);//将输入流复制到输出流中copyStream(isBm, os);isBm.close();os.close();}catch(Exception e){e.printStackTrace();}return pathFile;}/** * 获取文件的后缀名 * @param path * @return */public static String getFileSuffix(String path){if(path == null) return ".png";int lastIndexOf = path.lastIndexOf(".");if(lastIndexOf == -1) return ".png";return path.substring(lastIndexOf);}/** * 流复制 * @param is * @param os */public static void copyStream(InputStream is,OutputStream os){try{int index = -1;byte[] bys = new byte[1024 * 8];while((index = is.read(bys)) != -1){os.write(bys, 0, index);}}catch(Exception e){e.printStackTrace();}}}



0 0