APP里有一个上传头像,可以直接从相册选择图片上传,也可以使用照相机拍照上传。这个功能在大部分机器下都正常,然而在部分机器(例如三星)却失败,另外独立写了个测试例子检查这个问题。
package com.penngo.camera;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import java.io.File;
public class MainActivity extends Activity {
private final static String tag = "MainActivity-->";
ImageView imageView;
Button photo_btn;
Button camera_btn;
private static int createTime = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(tag, "onCreate=========" + (createTime++));
setContentView(R.layout.activity_main);
imageView = (ImageView)(this.findViewById(R.id.imageView));
photo_btn = (Button)this.findViewById(R.id.photo_btn);
photo_btn.setOnClickListener(new View.OnClickListener(){
public void onClick(View var){
Intent intent1 = new Intent(Intent.ACTION_PICK);
intent1.setDataAndType(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent1, 1);
}
});
camera_btn = (Button)this.findViewById(R.id.camera_btn);
camera_btn.setOnClickListener(new View.OnClickListener(){
public void onClick(View var1){
Log.e(tag, "OnClickListener==============MediaStore.ACTION_IMAGE_CAPTURE");
String path = getImagePath(MainActivity.this);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(new File(path, "/touxiang.jpg")));
startActivityForResult(intent, 2);
}
});
}
public static String getImagePath(Context context) {
String path = "";
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
path = context.getExternalCacheDir().getAbsolutePath() + "/images";
}
else{
path = context.getCacheDir().getAbsolutePath() + "/images";
}
File dir = new File(path);
if(dir.exists() == false){
dir.mkdirs();
}
return path;
}
/**
* 裁剪图片
*/
public void startPhotoZoom(Uri uri) {
Log.e(tag, "startPhotoZoom==============com.android.camera.action.CROP");
String path = getImagePath(MainActivity.this);
//Uri cutUri = Uri.fromFile(new File(IMAGE_PATH, "touxiang_cut.jpg"));
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
// 下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 144);
intent.putExtra("outputY", 144);
intent.putExtra("return-data", true);
intent.putExtra("noFaceDetection", true);
intent.putExtra("scale", true); // 黑边
intent.putExtra("scaleUpIfNeeded", true); // 黑边
//intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(path, "/touxiang_cut.jpg")));
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(intent, 3);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.e(tag, "onActivityResult============= requestCode=" + requestCode + " resultCode:" + resultCode + " data:" + data);
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case 1:
if (data != null)
startPhotoZoom(data.getData());
break;
case 2:
startPhotoZoom(Uri
.fromFile(new File(getImagePath(MainActivity.this), "touxiang.jpg")));
break;
case 3:
if (data != null) {
setPicToView(data);
}
break;
default:
break;
}
}
}
/**
* 保存裁剪之后的图片数据
*/
private void setPicToView(Intent picdata) {
Bundle extras = picdata.getExtras();
if (extras != null) {
final Bitmap image = extras.getParcelable("data");
imageView.setImageBitmap(image);
}
}
@Override
protected void onResume() {
super.onResume();
Log.e(tag, "onResume==============");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e(tag, "onDestroy==============");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.e(tag, "onSaveInstanceState==============");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.e(tag, "onRestoreInstanceState==============");
}
/**
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
**/
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<ImageView
android:layout_width="200dip"
android:layout_height="200dip"
android:id="@+id/imageView"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="相册"
android:id="@+id/photo_btn"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginLeft="34dp"
android:layout_marginStart="34dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="拍照"
android:id="@+id/camera_btn"
android:layout_alignBottom="@+id/photo_btn"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="34dp"
android:layout_marginEnd="34dp" />
</RelativeLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.penngo.camera" >
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
正常机子的locat输出如下
09-08 17:14:45.657 23452-23452/com.penngo.camera E/MainActivity-->﹕ onCreate=========1
09-08 17:14:45.691 23452-23452/com.penngo.camera E/MainActivity-->﹕ onResume==============
09-08 17:14:58.350 23452-23452/com.penngo.camera E/MainActivity-->﹕ OnClickListener==============MediaStore.ACTION_IMAGE_CAPTURE
09-08 17:14:59.744 23452-23452/com.penngo.camera E/MainActivity-->﹕ onSaveInstanceState==============
09-08 17:15:03.187 23452-23452/com.penngo.camera E/MainActivity-->﹕ onActivityResult============= requestCode=2 resultCode:-1 data:null
09-08 17:15:03.209 23452-23452/com.penngo.camera E/MainActivity-->﹕ startPhotoZoom==============com.android.camera.action.CROP
09-08 17:15:03.222 23452-23452/com.penngo.camera E/MainActivity-->﹕ onResume==============
09-08 17:15:04.212 23452-23452/com.penngo.camera E/MainActivity-->﹕ onSaveInstanceState==============
09-08 17:15:05.775 23452-23452/com.penngo.camera E/MainActivity-->﹕ onActivityResult============= requestCode=3 resultCode:-1 data:Intent { (has extras) }
09-08 17:15:05.777 23452-23452/com.penngo.camera E/MainActivity-->﹕ onResume==============
失败机子的logcat输出
09-08 17:16:24.391 11453-11453/com.penngo.camera E/MainActivity-->﹕ onCreate=========1
09-08 17:16:24.421 11453-11453/com.penngo.camera E/MainActivity-->﹕ onResume==============
09-08 17:18:59.491 11453-11453/com.penngo.camera E/MainActivity-->﹕ OnClickListener==============MediaStore.ACTION_IMAGE_CAPTURE
09-08 17:19:01.081 11453-11453/com.penngo.camera E/MainActivity-->﹕ onSaveInstanceState==============
09-08 17:19:07.441 11453-11453/com.penngo.camera E/MainActivity-->﹕ onDestroy==============
09-08 17:19:07.461 11453-11453/com.penngo.camera E/MainActivity-->﹕ onCreate=========2
09-08 17:19:07.471 11453-11453/com.penngo.camera E/MainActivity-->﹕ onRestoreInstanceState==============
09-08 17:19:07.471 11453-11453/com.penngo.camera E/MainActivity-->﹕ onActivityResult============= requestCode=2 resultCode:-1 data:null
09-08 17:19:07.471 11453-11453/com.penngo.camera E/MainActivity-->﹕ startPhotoZoom==============com.android.camera.action.CROP
09-08 17:19:07.491 11453-11453/com.penngo.camera E/MainActivity-->﹕ onResume==============
09-08 17:19:07.561 11453-11453/com.penngo.camera E/MainActivity-->﹕ onSaveInstanceState==============
09-08 17:19:10.381 11453-11453/com.penngo.camera E/MainActivity-->﹕ onDestroy==============
09-08 17:19:10.391 11453-11453/com.penngo.camera E/MainActivity-->﹕ onCreate=========3
09-08 17:19:10.401 11453-11453/com.penngo.camera E/MainActivity-->﹕ onRestoreInstanceState==============
09-08 17:19:10.401 11453-11453/com.penngo.camera E/MainActivity-->﹕ onActivityResult============= requestCode=3 resultCode:-1 data:Intent { (has extras) }
09-08 17:19:10.411 11453-11453/com.penngo.camera E/MainActivity-->﹕ onResume==============
失败机子在调用MediaStore.ACTION_IMAGE_CAPTURE拍照时,会导致一次MainActivity onDestroy;拍照完成后,又重新MainActivity onCreate,并执行MainActivity onActivityResult;
在调用com.android.camera.action.CROP时,也导致MainActivity触发同样的事件执行。
通过比较看出失败每次调用摄像头时,都会先触发所在activity onDestroy,调用摄像头结束后,又会触发所在activity重新onCreate,
再比较拍照正常机子和失败机子,发现失败机子在调用摄像头时,会触发一次屏幕旋转,导致activity onDestroy的执行。
两个解决方法:
方法1、在activity销毁前,保存当前activity的状态,重载onSaveInstanceState、onRestoreInstanceState方法,在销毁前保存activity的数据状态
方法2、由于访问的出现是由于部分机器在调用摄像头时自动横竖屏切换造成的,修改AndroidManifest.xml配置,加入android:configChanges="orientation|keyboard|keyboardHidden|screenSize"限制activity屏幕切换
<!-- android:configChanges="orientation|keyboard|keyboardHidden|screenSize" -->
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>