三星手機拍照強制切換到橫屏及照片旋轉問題

最近在做項目,項目裏面有拍照上傳的功能,無非就是吊起系統拍照功能,然後獲取所拍照的地址,然後上傳即可。但是當我無意間拿了一部三星手機裝了App之後,當使用拍照功能的時候,拍完之後,界面並沒有出現所拍的照片,之後才知道是三星手機在拍照的時候會強制切換到橫屏,導致生命週期重走了,所以拍出來的照片所保存的地址也跟着沒有了,然後我在清單文件中配置了該Activity的android:configChanges="orientation|keyboardHidden",然而並沒有什麼卵用,幸好Activity提供了onSaveInstanceState方法,用於保存數據,重走onCreate的時候再拿出來即可解決以上的問題,代碼如下:

@Override
	protected 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");
			
			//設置數據到相應的控件上
		}
	}
	
	@Override
	protected 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 block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.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即清空baos
		image.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即清空baos
		image.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();
		}
		
	}
}



發佈了43 篇原創文章 · 獲贊 17 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章