Signed-off-by: hmz007 <hmz007@gmail.com> Change-Id: Ib87fdbe7a0be7dc961af3500fe9ea4589a127f9f
280 lines
11 KiB
Java
280 lines
11 KiB
Java
package com.android.testingcamera;
|
|
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
|
|
import android.Manifest;
|
|
import android.content.pm.PackageManager;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.BitmapFactory;
|
|
import android.media.ExifInterface;
|
|
import android.media.MediaScannerConnection.OnScanCompletedListener;
|
|
import android.net.Uri;
|
|
import android.os.AsyncTask;
|
|
import android.os.Bundle;
|
|
import android.app.DialogFragment;
|
|
import android.content.Intent;
|
|
import android.text.method.ScrollingMovementMethod;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.View.OnClickListener;
|
|
import android.view.ViewGroup;
|
|
import android.widget.Button;
|
|
import android.widget.ImageView;
|
|
import android.widget.TextView;
|
|
|
|
public class SnapshotDialogFragment extends DialogFragment
|
|
implements OnScanCompletedListener{
|
|
|
|
private ImageView mInfoImage;
|
|
private TextView mInfoText;
|
|
private Button mOkButton;
|
|
private Button mSaveButton;
|
|
private Button mSaveAndViewButton;
|
|
|
|
private byte[] mJpegImage;
|
|
private boolean mSaved = false;
|
|
private boolean mViewWhenReady = false;
|
|
private Uri mSavedUri = null;
|
|
|
|
public SnapshotDialogFragment() {
|
|
// Empty constructor required for DialogFragment
|
|
}
|
|
|
|
@Override
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
Bundle savedInstanceState) {
|
|
View view = inflater.inflate(R.layout.fragment_snapshot, container);
|
|
|
|
mOkButton = (Button) view.findViewById(R.id.snapshot_ok);
|
|
mOkButton.setOnClickListener(mOkButtonListener);
|
|
|
|
mSaveButton = (Button) view.findViewById(R.id.snapshot_save);
|
|
mSaveButton.setOnClickListener(mSaveButtonListener);
|
|
|
|
mSaveAndViewButton = (Button) view.findViewById(R.id.snapshot_view);
|
|
mSaveAndViewButton.setOnClickListener(mSaveAndViewButtonListener);
|
|
|
|
mInfoImage = (ImageView) view.findViewById(R.id.snapshot_image);
|
|
mInfoText= (TextView) view.findViewById(R.id.snapshot_text);
|
|
mInfoText.setMovementMethod(new ScrollingMovementMethod());
|
|
|
|
if (mJpegImage != null) {
|
|
new AsyncTask<byte[], Integer, Bitmap>() {
|
|
@Override
|
|
protected Bitmap doInBackground(byte[]... params) {
|
|
byte[] jpegImage = params[0];
|
|
BitmapFactory.Options opts = new BitmapFactory.Options();
|
|
opts.inJustDecodeBounds = true;
|
|
BitmapFactory.decodeByteArray(jpegImage, 0,
|
|
jpegImage.length, opts);
|
|
// Keep image at less than 1 MP.
|
|
if (opts.outWidth > 1024 || opts.outHeight > 1024) {
|
|
int scaleFactorX = opts.outWidth / 1024 + 1;
|
|
int scaleFactorY = opts.outHeight / 1024 + 1;
|
|
int scaleFactor = scaleFactorX > scaleFactorY ?
|
|
scaleFactorX : scaleFactorY;
|
|
opts.inSampleSize = scaleFactor;
|
|
}
|
|
opts.inJustDecodeBounds = false;
|
|
Bitmap img = BitmapFactory.decodeByteArray(jpegImage, 0,
|
|
jpegImage.length, opts);
|
|
return img;
|
|
}
|
|
|
|
@Override
|
|
protected void onPostExecute(Bitmap img) {
|
|
mInfoImage.setImageBitmap(img);
|
|
}
|
|
}.execute(mJpegImage);
|
|
}
|
|
|
|
getDialog().setTitle("Snapshot result");
|
|
return view;
|
|
}
|
|
|
|
public OnClickListener mOkButtonListener = new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
dismiss();
|
|
}
|
|
};
|
|
|
|
public OnClickListener mSaveButtonListener = new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
saveFile();
|
|
}
|
|
};
|
|
|
|
public OnClickListener mSaveAndViewButtonListener = new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
saveFile();
|
|
viewFile();
|
|
}
|
|
};
|
|
|
|
public void updateImage(byte[] image) {
|
|
mJpegImage = image;
|
|
}
|
|
|
|
public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
|
int[] grantResults) {
|
|
TestingCamera parent = (TestingCamera) getActivity();
|
|
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
|
parent.log("Storage write permission granted");
|
|
saveFile();
|
|
} else {
|
|
parent.log("Denied storage write permission; cannot save");
|
|
}
|
|
}
|
|
|
|
private String getAttrib(ExifInterface exif, String tag) {
|
|
String attribute = exif.getAttribute(tag);
|
|
return (attribute == null) ? "???" : attribute;
|
|
}
|
|
|
|
private void saveFile() {
|
|
if (!mSaved) {
|
|
TestingCamera parent = (TestingCamera) getActivity();
|
|
parent.log("Saving image");
|
|
|
|
if (parent.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
|
!= PackageManager.PERMISSION_GRANTED) {
|
|
parent.log("Requesting storage write permission");
|
|
parent.requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
|
parent.PERMISSIONS_REQUEST_SNAPSHOT);
|
|
return;
|
|
}
|
|
|
|
File targetFile = parent.getOutputMediaFile(TestingCamera.MEDIA_TYPE_IMAGE);
|
|
if (targetFile == null) {
|
|
parent.logE("Unable to create file name");
|
|
return;
|
|
}
|
|
parent.logIndent(1);
|
|
parent.log("File name: " + targetFile.toString());
|
|
try {
|
|
FileOutputStream out = new FileOutputStream(targetFile);
|
|
out.write(mJpegImage);
|
|
out.close();
|
|
mSaved = true;
|
|
parent.notifyMediaScannerOfFile(targetFile, this);
|
|
updateExif(targetFile);
|
|
} catch (IOException e) {
|
|
parent.logE("Unable to save file: " + e.getMessage());
|
|
}
|
|
parent.logIndent(-1);
|
|
}
|
|
}
|
|
|
|
private void updateExif(File targetFile) {
|
|
((TestingCamera) getActivity()).log("Extracting EXIF");
|
|
try {
|
|
ExifInterface exif = new ExifInterface(targetFile.toString());
|
|
|
|
String aperture = getAttrib(exif, ExifInterface.TAG_APERTURE);
|
|
|
|
String dateTime = getAttrib(exif, ExifInterface.TAG_DATETIME);
|
|
String exposureTime = getAttrib(exif, ExifInterface.TAG_EXPOSURE_TIME);
|
|
int flash = exif.getAttributeInt(ExifInterface.TAG_FLASH, 0);
|
|
double focalLength = exif.getAttributeDouble(ExifInterface.TAG_FOCAL_LENGTH, 0);
|
|
|
|
double gpsAltitude = exif.getAltitude(Double.NaN);
|
|
String gpsDatestamp = getAttrib(exif, ExifInterface.TAG_GPS_DATESTAMP);
|
|
float[] gpsCoords = new float[2];
|
|
if (!exif.getLatLong(gpsCoords)) {
|
|
gpsCoords[0] = Float.NaN;
|
|
gpsCoords[1] = Float.NaN;
|
|
}
|
|
String gpsProcessingMethod = getAttrib(exif, ExifInterface.TAG_GPS_PROCESSING_METHOD);
|
|
String gpsTimestamp = getAttrib(exif, ExifInterface.TAG_GPS_TIMESTAMP);
|
|
|
|
int width = exif.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, 0);
|
|
int height = exif.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, 0);
|
|
String iso = getAttrib(exif, ExifInterface.TAG_ISO);
|
|
String make = getAttrib(exif, ExifInterface.TAG_MAKE);
|
|
String model = getAttrib(exif, ExifInterface.TAG_MODEL);
|
|
int orientationVal = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
|
|
int whiteBalance = exif.getAttributeInt(ExifInterface.TAG_WHITE_BALANCE, 0);
|
|
|
|
final String[] orientationStrings= new String[] {
|
|
"UNDEFINED",
|
|
"NORMAL",
|
|
"FLIP_HORIZONTAL",
|
|
"ROTATE_180",
|
|
"FLIP_VERTICAL",
|
|
"TRANSPOSE",
|
|
"ROTATE_90",
|
|
"TRANSVERSE",
|
|
"ROTATE_270"
|
|
};
|
|
if (orientationVal >= orientationStrings.length) {
|
|
orientationVal = 0;
|
|
}
|
|
String orientation = orientationStrings[orientationVal];
|
|
|
|
StringBuilder exifInfo = new StringBuilder();
|
|
exifInfo.append("EXIF information for ").
|
|
append(targetFile.toString()).append("\n\n");
|
|
exifInfo.append("Size: ").
|
|
append(width).append(" x ").append(height).append("\n");
|
|
exifInfo.append("Make: ").
|
|
append(make).append("\n");
|
|
exifInfo.append("Model: ").
|
|
append(model).append("\n");
|
|
exifInfo.append("Orientation: ").
|
|
append(orientation).append("\n");
|
|
exifInfo.append("Aperture: ").
|
|
append(aperture).append("\n");
|
|
exifInfo.append("Focal length: ").
|
|
append(focalLength).append("\n");
|
|
exifInfo.append("Exposure time: ").
|
|
append(exposureTime).append("\n");
|
|
exifInfo.append("ISO: ").
|
|
append(iso).append("\n");
|
|
exifInfo.append("Flash: ").
|
|
append(flash).append("\n");
|
|
exifInfo.append("White balance: ").
|
|
append(whiteBalance).append("\n");
|
|
exifInfo.append("Date/Time: ").
|
|
append(dateTime).append("\n");
|
|
exifInfo.append("GPS altitude: ").
|
|
append(gpsAltitude).append("\n");
|
|
exifInfo.append("GPS latitude: ").
|
|
append(gpsCoords[0]).append("\n");
|
|
exifInfo.append("GPS longitude: ").
|
|
append(gpsCoords[1]).append("\n");
|
|
exifInfo.append("GPS datestamp: ").
|
|
append(gpsDatestamp).append("\n");
|
|
exifInfo.append("GPS timestamp: ").
|
|
append(gpsTimestamp).append("\n");
|
|
exifInfo.append("GPS processing method: ").
|
|
append(gpsProcessingMethod).append("\n");
|
|
mInfoText.setText(exifInfo.toString());
|
|
|
|
} catch (IOException e) {
|
|
((TestingCamera) getActivity()).logE("Unable to extract EXIF: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
private synchronized void viewFile() {
|
|
if (!mSaved) return;
|
|
if (mSavedUri != null) {
|
|
((TestingCamera) getActivity()).log("Viewing file");
|
|
mViewWhenReady = false;
|
|
getActivity().startActivity(new Intent(Intent.ACTION_VIEW, mSavedUri));
|
|
} else {
|
|
mViewWhenReady = true;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public synchronized void onScanCompleted(String path, Uri uri) {
|
|
mSavedUri = uri;
|
|
if (mViewWhenReady) viewFile();
|
|
}
|
|
}
|