package com.miris.ui.activity;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.support.v7.widget.RecyclerView;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.Toast;
import android.widget.ViewSwitcher;
import com.miris.R;
import com.miris.ui.view.CameraPreview;
import com.miris.ui.view.RevealBackgroundView;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import butterknife.InjectView;
import butterknife.OnClick;
import static com.miris.Utils.isAndroid5;
/**
* Created by Miris on 09.02.15.
*/
public class TakePhotoActivity extends BaseActivity implements RevealBackgroundView.OnStateChangeListener, View.OnTouchListener{
public static final String ARG_REVEAL_START_LOCATION = "reveal_start_location";
private static final Interpolator ACCELERATE_INTERPOLATOR = new AccelerateInterpolator();
private static final Interpolator DECELERATE_INTERPOLATOR = new DecelerateInterpolator();
private static final int STATE_TAKE_PHOTO = 0;
private static final int STATE_SETUP_PHOTO = 1;
@InjectView(R.id.vRevealBackground)
RevealBackgroundView vRevealBackground;
@InjectView(R.id.vPhotoRoot)
View vTakePhotoRoot;
@InjectView(R.id.vShutter)
View vShutter;
@InjectView(R.id.ivTakenPhoto)
ImageView ivTakenPhoto;
@InjectView(R.id.vUpperPanel)
ViewSwitcher vUpperPanel;
@InjectView(R.id.vLowerPanel)
ViewSwitcher vLowerPanel;
@InjectView(R.id.camera_preview)
FrameLayout camera_preview;
@InjectView(R.id.rvFilters)
RecyclerView rvFilters;
@InjectView(R.id.btnTakePhoto)
Button btnTakePhoto;
@InjectView(R.id.btnVideoCam)
ImageButton btnVideoCam;
@InjectView(R.id.btnTakeGallery)
ImageButton btnTakeGallery;
@InjectView(R.id.btn_ic_close)
ImageButton btn_ic_close;
@InjectView(R.id.btnBack)
ImageButton btnBack;
@InjectView(R.id.touchListener)
RadioButton touchListener;
@InjectView(R.id.btn_ic_write)
ImageButton btn_ic_write;
private boolean pendingIntro;
private int currentState;
private File photoPath;
private Context mContext = this;
FrameLayout preview;
private Camera mCamera;
private CameraPreview mPreview;
public static String savedPath;
Bitmap clsBitmap;
Boolean viewVisible = false ;
private boolean cameraFront = false;
public static void startCameraFromLocation(int[] startingLocation, Activity startingActivity) {
Intent intent = new Intent(startingActivity, TakePhotoActivity.class);
intent.putExtra(ARG_REVEAL_START_LOCATION, startingLocation);
startingActivity.startActivity(intent);
}
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
touchListener.setChecked(false);
new ImageSaveTask().execute(data);
mCamera.startPreview();
}
};
private Camera.AutoFocusCallback mFocus = new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success) {
touchListener.setChecked(true);
} else
touchListener.setChecked(false);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_take_photo);
initLayout();
updateStatusBarColor();
updateState(STATE_TAKE_PHOTO);
setupRevealBackground(savedInstanceState);
vUpperPanel.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
vUpperPanel.getViewTreeObserver().removeOnPreDrawListener(this);
pendingIntro = true;
return true;
}
});
mContext = this;
touchListener.setChecked(false);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void updateStatusBarColor() {
if (isAndroid5()) {
getWindow().setStatusBarColor(0xff111111);
}
}
private void setupRevealBackground(Bundle savedInstanceState) {
vRevealBackground.setFillPaintColor(0xFF16181a);
vRevealBackground.setOnStateChangeListener(this);
if (savedInstanceState == null) {
final int[] startingLocation = getIntent().getIntArrayExtra(ARG_REVEAL_START_LOCATION);
vRevealBackground.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
vRevealBackground.getViewTreeObserver().removeOnPreDrawListener(this);
vRevealBackground.startFromLocation(startingLocation);
return true;
}
});
} else {
vRevealBackground.setToFinishedFrame();
}
}
@Override
protected void onResume() {
super.onResume();
if (!checkCameraHardware(mContext)) {
Toast.makeText(mContext, "no camera on this device!",Toast.LENGTH_SHORT).show();
finish();
}
if (mCamera == null) {
if (findFrontFacingCamera() < 0) {
Toast.makeText(this, "No front facing camera found.", Toast.LENGTH_LONG).show();
}
mCamera = Camera.open(findBackFacingCamera());
mPreview.refreshCamera(mCamera);
}
}
private int findFrontFacingCamera() {
int cameraId = -1;
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
cameraId = i;
cameraFront = true;
break;
}
}
return cameraId;
}
private int findBackFacingCamera() {
int cameraId = -1;
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
cameraId = i;
cameraFront = false;
break;
}
}
return cameraId;
}
private void initLayout() {
preview = (FrameLayout) findViewById(R.id.camera_preview);
mPreview = new CameraPreview(this, mCamera);
preview.addView(mPreview);
touchListener.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mCamera.autoFocus(mFocus);
break;
case MotionEvent.ACTION_UP:
mCamera.autoFocus(mFocus);
break;
case MotionEvent.ACTION_MOVE:
touchListener.setChecked(false);
}
return false;
}
});
}
@Override
protected void onPause() {
super.onPause();
releaseCamera();
}
@OnClick(R.id.btnTakePhoto)
public void onTakePhotoClick() {
mCamera.autoFocus(mFocus);
btnTakePhoto.setEnabled(false);
mCamera.takePicture(null, null, mPicture);
animateShutter();
}
@OnClick(R.id.btn_ic_write)
public void onBtnWriteClick() {
PublishActivity.openWithPhotoUri(this, null);
}
@OnClick(R.id.btnTakeGallery)
public void onbtnTakeGalleryClick() {
viewVisible = true;
Intent clsIntent = new Intent(Intent.ACTION_PICK);
clsIntent.setType(android.provider.MediaStore.Images.Media.CONTENT_TYPE);
clsIntent.setData(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(clsIntent, 100);
}
@OnClick(R.id.btnVideoCam)
public void onbtnVideoCamClick() {
int camerasNumber = Camera.getNumberOfCameras();
if (camerasNumber > 1) {
releaseCamera();
chooseCamera();
} else {
Toast toast = Toast.makeText(this, "Sorry, your phone has only one camera!", Toast.LENGTH_LONG);
toast.show();
}
}
protected void onActivityResult( int requestCode, int resultCode, Intent data ) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK) {
if(requestCode == 100) {
Uri uri = data.getData();
new loadImgDataTask().execute(uri);
} else if (requestCode == 200) {
// TODO: 2015-09-21
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
private void releaseCamera() {
// stop and release camera
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
public void chooseCamera() {
if (cameraFront) {
int cameraId = findBackFacingCamera();
if (cameraId >= 0) {
mCamera = Camera.open(cameraId);
mPreview.refreshCamera(mCamera);
}
} else {
int cameraId = findFrontFacingCamera();
if (cameraId >= 0) {
mCamera = Camera.open(cameraId);
mPreview.refreshCamera(mCamera);
}
}
}
class loadImgDataTask extends AsyncTask<Uri, Void, Void> {
@Override
protected Void doInBackground(Uri... uri) {
String urlPath = getImageNameToUri(uri[0]);
AssetFileDescriptor afd = null;
try {
afd = getContentResolver().openAssetFileDescriptor(uri[0], "r");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inJustDecodeBounds = true;
BitmapFactory.decodeFile(urlPath, opt);
if (opt.outHeight > 2000 || opt.outWidth > 2000) {
opt.inJustDecodeBounds = false;
opt.inSampleSize = 4;
clsBitmap = BitmapFactory.decodeFileDescriptor(afd.getFileDescriptor(), null, opt);
} else if (opt.outHeight > 1000 || opt.outWidth > 1000) {
opt.inJustDecodeBounds = false;
opt.inSampleSize = 2;
clsBitmap = BitmapFactory.decodeFileDescriptor(afd.getFileDescriptor(), null, opt);
} else {
try {
clsBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri[0]);
} catch (IOException e) {
e.printStackTrace();
}
}
File file = new File(urlPath);
ExifInterface exif = null;
try {
exif = new ExifInterface(urlPath);
} catch (IOException e) {
e.printStackTrace();
}
int exifOrientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int exifDegree = exifOrientationToDegrees(exifOrientation);
clsBitmap = rotate(clsBitmap, exifDegree);
photoPath = file;
return null ;
}
@Override
protected void onPostExecute(Void result) {
showTakenPicture(clsBitmap);
overridePendingTransition(0, 0);
viewVisible = true;
}
}
public int exifOrientationToDegrees(int exifOrientation) {
if(exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
return 90;
} else if(exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
return 180;
} else if(exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
return 270;
}
return 0;
}
public String getImageNameToUri(Uri data) {
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(data, proj, null, null, null);
String imgPath = null;
if (cursor != null && cursor.getCount() != 0){
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
imgPath = cursor.getString(column_index);
}
cursor.close();
return imgPath;
}
public Bitmap rotate(Bitmap bitmap, int degrees) {
if(degrees != 0 && bitmap != null) {
Matrix m = new Matrix();
m.setRotate(degrees, (float) bitmap.getWidth() / 2,
(float) bitmap.getHeight() / 2);
try {
Bitmap converted = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), m, true);
if(bitmap != converted) {
bitmap.recycle();
bitmap = converted;
}
} catch(OutOfMemoryError ex) {
}
}
return bitmap;
}
@OnClick(R.id.btn_ic_close)
public void onbtn_ic_closeClick() {
finish();
}
@OnClick(R.id.btnBack)
public void onbtnBackClick() {
viewVisible = false;
if (currentState == STATE_SETUP_PHOTO) {
btnTakePhoto.setEnabled(true);
vUpperPanel.showNext();
vLowerPanel.showNext();
updateState(STATE_TAKE_PHOTO);
} else {
super.onBackPressed();
}
}
@OnClick(R.id.btnAccept)
public void onAcceptClick() {
viewVisible = false;
PublishActivity.openWithPhotoUri(this, Uri.fromFile(photoPath));
}
private void animateShutter() {
vShutter.setVisibility(View.VISIBLE);
vShutter.setAlpha(0.f);
ObjectAnimator alphaInAnim = ObjectAnimator.ofFloat(vShutter, "alpha", 0f, 0.8f);
alphaInAnim.setDuration(100);
alphaInAnim.setStartDelay(100);
alphaInAnim.setInterpolator(ACCELERATE_INTERPOLATOR);
ObjectAnimator alphaOutAnim = ObjectAnimator.ofFloat(vShutter, "alpha", 0.8f, 0f);
alphaOutAnim.setDuration(200);
alphaOutAnim.setInterpolator(DECELERATE_INTERPOLATOR);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playSequentially(alphaInAnim, alphaOutAnim);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
vShutter.setVisibility(View.GONE);
}
});
animatorSet.start();
}
@Override
public void onStateChange(int state) {
if (RevealBackgroundView.STATE_FINISHED == state) {
vTakePhotoRoot.setVisibility(View.VISIBLE);
if (pendingIntro) {
startIntroAnimation();
}
} else {
vTakePhotoRoot.setVisibility(View.INVISIBLE);
}
}
private void startIntroAnimation() {
vUpperPanel.animate().translationY(0).setDuration(400).setInterpolator(DECELERATE_INTERPOLATOR);
vLowerPanel.animate().translationY(0).setDuration(400).setInterpolator(DECELERATE_INTERPOLATOR).start();
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
private void showTakenPicture(Bitmap bitmap) {
vUpperPanel.showNext();
vLowerPanel.showNext();
ivTakenPhoto.setImageBitmap(bitmap);
updateState(STATE_SETUP_PHOTO);
}
@Override
public void onBackPressed() {
viewVisible = false;
if (currentState == STATE_SETUP_PHOTO) {
btnTakePhoto.setEnabled(true);
vUpperPanel.showNext();
vLowerPanel.showNext();
updateState(STATE_TAKE_PHOTO);
} else {
super.onBackPressed();
}
}
private void updateState(int state) {
currentState = state;
if (currentState == STATE_TAKE_PHOTO) {
vUpperPanel.setInAnimation(this, R.anim.slide_in_from_right);
vLowerPanel.setInAnimation(this, R.anim.slide_in_from_right);
vUpperPanel.setOutAnimation(this, R.anim.slide_out_to_left);
vLowerPanel.setOutAnimation(this, R.anim.slide_out_to_left);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
ivTakenPhoto.setVisibility(View.GONE);
}
}, 400);
} else if (currentState == STATE_SETUP_PHOTO) {
vUpperPanel.setInAnimation(this, R.anim.slide_in_from_left);
vLowerPanel.setInAnimation(this, R.anim.slide_in_from_left);
vUpperPanel.setOutAnimation(this, R.anim.slide_out_to_right);
vLowerPanel.setOutAnimation(this, R.anim.slide_out_to_right);
ivTakenPhoto.setVisibility(View.VISIBLE);
}
}
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
return true;
} else {
Toast.makeText(mContext, "No camera found!", Toast.LENGTH_SHORT).show();
return false;
}
}
class ImageSaveTask extends AsyncTask<byte[], Void, Boolean> {
@Override
protected Boolean doInBackground(byte[]... data) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return false;
}
try {
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeByteArray(data[0], 0, data[0].length, options);
Matrix m = new Matrix();
m.setRotate(90, (float) bitmap.getWidth() / 2,
(float) bitmap.getHeight() / 2);
if (cameraFront) {
m.postScale(1, -1);
}
Bitmap converted = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), m, true);
try {
if(bitmap != converted) {
bitmap.recycle();
clsBitmap = converted;
}
} catch(OutOfMemoryError ex) {
}
ByteArrayOutputStream stream = new ByteArrayOutputStream();
clsBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byteArray = stream.toByteArray();
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(byteArray);
fos.close();
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(pictureFile);
mediaScanIntent.setData(contentUri);
mContext.sendBroadcast(mediaScanIntent);
photoPath = pictureFile;
} catch (IOException e) {
return false;
}
return true;
}
@Override
protected void onPostExecute(Boolean isDone) {
if (isDone) {
showTakenPicture(clsBitmap);
Toast.makeText(mContext, getString(R.string.save_toast), Toast.LENGTH_SHORT)
.show();
}
}
private File getOutputMediaFile() {
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"Miris");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
File mediaFile;
savedPath = mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg";
mediaFile = new File(savedPath);
return mediaFile;
}
}
@Override
public void onDestroy() {
if(mPreview != null){
mPreview = null;
}
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
super.onDestroy();
}
}