Java tutorial
/**************************************************************************************** * Copyright (c) 2013 Bibek Shrestha <bibekshrestha@gmail.com> * * Copyright (c) 2013 Zaur Molotnikov <qutorial@gmail.com> * * Copyright (c) 2013 Nicolas Raoul <nicolas.raoul@gmail.com> * * Copyright (c) 2013 Flavio Lerda <flerda@gmail.com> * * * * This program is free software; you can redistribute it and/or modify it under * * the terms of the GNU General Public License as published by the Free Software * * Foundation; either version 3 of the License, or (at your option) any later * * version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT ANY * * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * * PARTICULAR PURPOSE. See the GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see <http://www.gnu.org/licenses/>. * ****************************************************************************************/ package com.ichi2.anki.multimediacard.fields; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.provider.MediaStore; import android.provider.MediaStore.MediaColumns; import android.support.v4.content.FileProvider; import android.util.DisplayMetrics; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import com.ichi2.anki.R; import com.ichi2.compat.CompatHelper; import com.ichi2.utils.BitmapUtil; import com.ichi2.utils.ExifUtil; 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 java.util.Locale; import timber.log.Timber; public class BasicImageFieldController extends FieldControllerBase implements IFieldController { protected static final int ACTIVITY_SELECT_IMAGE = 1; protected static final int ACTIVITY_TAKE_PICTURE = 2; protected static final int IMAGE_PREVIEW_MAX_WIDTH = 100; private static final int IMAGE_SAVE_MAX_WIDTH = 1920; protected Button mBtnGallery; protected Button mBtnCamera; protected ImageView mImagePreview; protected String mTempCameraImagePath; private DisplayMetrics mMetrics = null; private int getMaxImageSize() { DisplayMetrics metrics = getDisplayMetrics(); int height = metrics.heightPixels; int width = metrics.widthPixels; return (int) Math.min(height * 0.4, width * 0.6); } @Override public void createUI(Context context, LinearLayout layout) { mImagePreview = new ImageView(mActivity); DisplayMetrics metrics = getDisplayMetrics(); int height = metrics.heightPixels; int width = metrics.widthPixels; LinearLayout.LayoutParams p = new LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT); setPreviewImage(mField.getImagePath(), getMaxImageSize()); mImagePreview.setScaleType(ImageView.ScaleType.CENTER_INSIDE); mImagePreview.setAdjustViewBounds(true); mImagePreview.setMaxHeight((int) Math.round(height * 0.4)); mImagePreview.setMaxWidth((int) Math.round(width * 0.6)); mBtnGallery = new Button(mActivity); mBtnGallery.setText(gtxt(R.string.multimedia_editor_image_field_editing_galery)); mBtnGallery.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); mActivity.startActivityForResult(i, ACTIVITY_SELECT_IMAGE); } }); mBtnCamera = new Button(mActivity); mBtnCamera.setText(gtxt(R.string.multimedia_editor_image_field_editing_photo)); mBtnCamera.setOnClickListener(new View.OnClickListener() { @SuppressLint("NewApi") @Override public void onClick(View v) { Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); File image; File storageDir; String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US).format(new Date()); try { storageDir = mActivity.getCacheDir(); image = File.createTempFile("img_" + timeStamp, ".jpg", storageDir); mTempCameraImagePath = image.getPath(); Uri uriSavedImage = FileProvider.getUriForFile(mActivity, mActivity.getApplicationContext().getPackageName() + ".apkgfileprovider", image); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage); mActivity.startActivityForResult(cameraIntent, ACTIVITY_TAKE_PICTURE); } catch (IOException e) { e.printStackTrace(); } } }); // Chromebooks do not support camera capture yet. if (CompatHelper.isChromebook()) { mBtnCamera.setVisibility(View.INVISIBLE); } layout.addView(mImagePreview, android.view.ViewGroup.LayoutParams.FILL_PARENT, p); layout.addView(mBtnGallery, android.view.ViewGroup.LayoutParams.FILL_PARENT); layout.addView(mBtnCamera, android.view.ViewGroup.LayoutParams.FILL_PARENT); } private String gtxt(int id) { return mActivity.getText(id).toString(); } protected DisplayMetrics getDisplayMetrics() { if (mMetrics == null) { mMetrics = new DisplayMetrics(); mActivity.getWindowManager().getDefaultDisplay().getMetrics(mMetrics); } return mMetrics; } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_CANCELED) { // Do Nothing. } else if (requestCode == ACTIVITY_SELECT_IMAGE) { Uri selectedImage = data.getData(); // Timber.d(selectedImage.toString()); String[] filePathColumn = { MediaColumns.DATA }; Cursor cursor = mActivity.getContentResolver().query(selectedImage, filePathColumn, null, null, null); cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(filePathColumn[0]); String filePath = cursor.getString(columnIndex); cursor.close(); mField.setImagePath(filePath); } else if (requestCode == ACTIVITY_TAKE_PICTURE) { String imagePath = rotateAndCompress(mTempCameraImagePath); mField.setImagePath(imagePath); mField.setHasTemporaryMedia(true); } setPreviewImage(mField.getImagePath(), getMaxImageSize()); } @Override public void onFocusLost() { } @Override public void onDone() { // } private String rotateAndCompress(String inPath) { // Set the rotation of the camera image and save as png File f = new File(inPath); // use same filename but with png extension for output file String outPath = inPath.substring(0, inPath.lastIndexOf(".")) + ".png"; // Load into a bitmap with max size of 1920 pixels and rotate if necessary Bitmap b = BitmapUtil.decodeFile(f, IMAGE_SAVE_MAX_WIDTH); FileOutputStream out = null; try { out = new FileOutputStream(outPath); b = ExifUtil.rotateFromCamera(f, b); b.compress(Bitmap.CompressFormat.PNG, 90, out); f.delete(); return outPath; } catch (FileNotFoundException e) { Timber.e("Error in BasicImageFieldController.rotateAndCompress() : " + e.getMessage()); return inPath; } finally { try { if (out != null) { out.close(); } } catch (IOException e) { e.printStackTrace(); } } } protected void setPreviewImage(String imagePath, int maxsize) { if (imagePath != null && !imagePath.equals("")) { // Caused bug on API <= 7 // mImagePreview.setImageURI(Uri.fromFile(new File(imagePath))); // fix but crashes with out of memory // mImagePreview.setImageURI(Uri.parse(new File(imagePath).toString())); // fix for both File f = new File(imagePath); Bitmap b = BitmapUtil.decodeFile(f, maxsize); int currentapiVersion = android.os.Build.VERSION.SDK_INT; if (currentapiVersion >= android.os.Build.VERSION_CODES.ECLAIR) { b = ExifUtil.rotateFromCamera(f, b); } mImagePreview.setImageBitmap(b); } } @Override public void onDestroy() { ImageView imageView = mImagePreview; BitmapUtil.freeImageView(imageView); } }