最近在做项目,项目里面有拍照上传的功能,无非就是吊起系统拍照功能,然后获取所拍照的地址,然后上传即可。但是当我无意间拿了一部三星手机装了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) savedInstanceState.getSerializable("mFiles");
mHomeWork = (List) 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) mHomeworkList);
savedInstanceState.putStringArrayList("mPicWork", (ArrayList) mPicWork);
savedInstanceState.putStringArrayList("mVoiceWork", (ArrayList) mVoiceWork);
savedInstanceState.putSerializable("mFiles",(Serializable) mFiles);
savedInstanceState.putSerializable("mHomeWork",(Serializable) mHomeWork);
}
当解决了强制横屏的问题,三星手机又来了一个旋转照片的毛病,拍出来的照片居然被旋转了90°或180°,感觉整个人不好了。百度了一下,下面就来整理一下,有关图片旋转问题,还有图片压缩问题。
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();
}
}
}