最近在做項目,項目裏面有拍照上傳的功能,無非就是吊起系統拍照功能,然後獲取所拍照的地址,然後上傳即可。但是當我無意間拿了一部三星手機裝了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();
}
}
}