/**
* Copyright (c) 2013-2014, Rinc Liu (http://rincliu.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.rincliu.library.activity;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.OnScanCompletedListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageView;
import com.rincliu.library.R;
import com.rincliu.library.util.RLSysUtil;
import com.rincliu.library.widget.RLOnClickListener;
import com.rincliu.library.widget.dialog.RLLoadingDialog;
public class RLCameraActivity extends RLActivity {
private Camera camera;
private byte[] mData;
private boolean isFlashEnabled = false;
private String flashMode = Parameters.FLASH_MODE_OFF;
private ImageView iv_flash, iv_yes, iv_no, iv_camera;
private RLLoadingDialog pd;
private int maxWidth, maxHeight;
private long maxSize;
private String outputFile;
@Override
@SuppressWarnings("deprecation")
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!RLSysUtil.isExternalStorageAvailable()) {
exit(false);
}
setContentView(R.layout.activity_camera);
String savePath = getIntent().getStringExtra("savePath");
DisplayMetrics dm = getResources().getDisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
maxWidth = getIntent().getIntExtra("maxWidth", dm.widthPixels);
maxHeight = getIntent().getIntExtra("maxHeight", dm.heightPixels);
maxSize = getIntent().getLongExtra("maxSize", 4 * dm.widthPixels * dm.heightPixels);
if (TextUtils.isEmpty(savePath)) {
savePath = Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_DCIM;
} else {
if (!new File(savePath).exists()) {
new File(savePath).mkdirs();
}
}
if (!savePath.endsWith(File.separator)) {
savePath += File.separator;
}
outputFile = savePath + System.currentTimeMillis() + ".jpg";
pd = new RLLoadingDialog(this);
iv_flash = (ImageView) findViewById(R.id.iv_flash);
iv_yes = (ImageView) findViewById(R.id.iv_yes);
iv_no = (ImageView) findViewById(R.id.iv_no);
iv_camera = (ImageView) findViewById(R.id.iv_camera);
SurfaceView surfaceView = (SurfaceView) this.findViewById(R.id.sv_camera);
if (getIntent().getBooleanExtra("isAutoFlash", false)) {
iv_flash.setVisibility(View.GONE);
flashMode = Parameters.FLASH_MODE_AUTO;
}
iv_flash.setOnClickListener(new RLOnClickListener() {
@Override
public void onClickX(View view) {
isFlashEnabled = !isFlashEnabled;
flashMode = isFlashEnabled ? Parameters.FLASH_MODE_ON : Parameters.FLASH_MODE_OFF;
Parameters params = camera.getParameters();
params.setFlashMode(flashMode);
camera.setParameters(params);
iv_flash.setImageDrawable(getResources().getDrawable(
isFlashEnabled ? R.drawable.btn_camera_flash_on : R.drawable.btn_camera_flash_off));
}
});
iv_yes.setOnClickListener(new RLOnClickListener() {
@Override
public void onClickX(View arg0) {
pd.show();
new Thread() {
@Override
public void run() {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
Bitmap srcBmp = BitmapFactory.decodeByteArray(mData, 0, mData.length, opts);
opts.inJustDecodeBounds = false;
int w = opts.outWidth;
int h = opts.outHeight;
int size = 0;
if (w > maxWidth || h > maxHeight) {
double scale = 1;
if (w > maxWidth) {
if (h > maxHeight) {
scale = w > h ? w / maxWidth : h / maxHeight;
} else {
scale = w / maxWidth;
}
} else {
scale = h / maxHeight;
}
double log = Math.log(scale) / Math.log(2);
double logCeil = Math.ceil(log);
size = (int) Math.pow(2, logCeil);
}
opts.inSampleSize = size;
srcBmp = BitmapFactory.decodeByteArray(mData, 0, mData.length, opts);
Bitmap dstBmp;
float degrees = 0f;
switch (getDisplayRotation()) {
case Surface.ROTATION_0:
degrees = 90f;
break;
case Surface.ROTATION_90:
degrees = 0f;
break;
case Surface.ROTATION_180:
degrees = 270f;
break;
case Surface.ROTATION_270:
degrees = 180f;
break;
}
Matrix matrix = new Matrix();
matrix.reset();
matrix.postRotate(degrees);
dstBmp = Bitmap.createBitmap(srcBmp, 0, 0, srcBmp.getWidth(), srcBmp.getHeight(), matrix, true);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quality = 100;
dstBmp.compress(CompressFormat.JPEG, quality, baos);
while (baos.toByteArray().length > maxSize) {
baos.reset();
dstBmp.compress(CompressFormat.JPEG, quality, baos);
quality -= 10;
}
try {
baos.writeTo(new FileOutputStream(outputFile));
} catch (Exception e) {
e.printStackTrace();
exit(false);
} finally {
try {
baos.flush();
baos.close();
} catch (IOException e) {
e.printStackTrace();
exit(false);
}
}
if (!dstBmp.isRecycled()) {
dstBmp.recycle();
}
if (!srcBmp.isRecycled()) {
srcBmp.recycle();
}
getIntent().putExtra("outputFile", outputFile);
String path = new File(outputFile).getParent();
String mime = "image/jpg";
MediaScannerConnection.scanFile(RLCameraActivity.this, new String[] {path}, new String[] {mime},
new OnScanCompletedListener() {
@Override
public void onScanCompleted(String arg0, Uri arg1) {
exit(true);
}
});
}
}.start();
}
});
iv_no.setOnClickListener(new RLOnClickListener() {
@Override
public void onClickX(View arg0) {
camera.startPreview();
iv_yes.setVisibility(View.GONE);
iv_no.setVisibility(View.GONE);
iv_camera.setVisibility(View.VISIBLE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
});
iv_camera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
camera.takePicture(null, null, new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
iv_yes.setVisibility(View.VISIBLE);
iv_no.setVisibility(View.VISIBLE);
iv_camera.setVisibility(View.GONE);
mData = data;
switch (getDisplayRotation())
{
case Surface.ROTATION_0:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
case Surface.ROTATION_90:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case Surface.ROTATION_180:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
break;
case Surface.ROTATION_270:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
break;
}
}
});
}
});
surfaceView.setFocusable(true);
surfaceView.setFocusableInTouchMode(true);
SurfaceHolder holder = surfaceView.getHolder();
if (android.os.Build.VERSION.SDK_INT < 11) {
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Camera.Parameters params = camera.getParameters();
params.setFlashMode(flashMode);
params.setPictureFormat(ImageFormat.JPEG);
switch (getDisplayRotation()) {
case Surface.ROTATION_0:
camera.setDisplayOrientation(90);
break;
case Surface.ROTATION_90:
camera.setDisplayOrientation(0);
break;
case Surface.ROTATION_180:
camera.setDisplayOrientation(270);
break;
case Surface.ROTATION_270:
camera.setDisplayOrientation(180);
break;
}
setBestPreviewSize(params);
camera.setParameters(params);
camera.startPreview();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (camera == null) {
camera = Camera.open();
}
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
camera.autoFocus(new AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success) {
Camera.Parameters params = camera.getParameters();
params.setFlashMode(flashMode);
params.setPictureFormat(ImageFormat.JPEG);
setBestPreviewSize(params);
camera.setParameters(params);
}
}
});
} catch (Exception e) {
camera.release();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
mData = null;
camera = null;
}
});
}
private void setBestPreviewSize(Camera.Parameters params)
{
int maxPreviewWidth = 0, maxPreviewHeight = 0;
for (Size size : params.getSupportedPreviewSizes())
{
if (size.width >= maxPreviewWidth || size.height >= maxPreviewHeight)
{
maxPreviewWidth = size.width;
maxPreviewHeight = size.height;
}
}
params.setPreviewSize(maxPreviewWidth, maxPreviewHeight);
}
private final Handler handler = new Handler();
private void exit(final boolean isSuccess) {
mData = null;
handler.post(new Runnable() {
@Override
public void run() {
if (pd.isShowing()) {
pd.dismiss();
}
setResult(isSuccess ? RESULT_OK : RESULT_CANCELED, getIntent());
finish();
overridePendingTransition(R.anim.reload, R.anim.reload);
}
});
}
@Override
public void onBackPressed() {
super.onBackPressed();
exit(false);
}
}