1 package com.android.testingcamera; 2 3 import java.io.File; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 7 import android.graphics.Bitmap; 8 import android.graphics.BitmapFactory; 9 import android.media.ExifInterface; 10 import android.media.MediaScannerConnection.OnScanCompletedListener; 11 import android.net.Uri; 12 import android.os.AsyncTask; 13 import android.os.Bundle; 14 import android.app.DialogFragment; 15 import android.content.Intent; 16 import android.text.method.ScrollingMovementMethod; 17 import android.view.LayoutInflater; 18 import android.view.View; 19 import android.view.View.OnClickListener; 20 import android.view.ViewGroup; 21 import android.widget.Button; 22 import android.widget.ImageView; 23 import android.widget.TextView; 24 25 public class SnapshotDialogFragment extends DialogFragment 26 implements OnScanCompletedListener{ 27 28 private ImageView mInfoImage; 29 private TextView mInfoText; 30 private Button mOkButton; 31 private Button mSaveButton; 32 private Button mSaveAndViewButton; 33 34 private byte[] mJpegImage; 35 private boolean mSaved = false; 36 private boolean mViewWhenReady = false; 37 private Uri mSavedUri = null; 38 39 public SnapshotDialogFragment() { 40 // Empty constructor required for DialogFragment 41 } 42 43 @Override 44 public View onCreateView(LayoutInflater inflater, ViewGroup container, 45 Bundle savedInstanceState) { 46 View view = inflater.inflate(R.layout.fragment_snapshot, container); 47 48 mOkButton = (Button) view.findViewById(R.id.snapshot_ok); 49 mOkButton.setOnClickListener(mOkButtonListener); 50 51 mSaveButton = (Button) view.findViewById(R.id.snapshot_save); 52 mSaveButton.setOnClickListener(mSaveButtonListener); 53 54 mSaveAndViewButton = (Button) view.findViewById(R.id.snapshot_view); 55 mSaveAndViewButton.setOnClickListener(mSaveAndViewButtonListener); 56 57 mInfoImage = (ImageView) view.findViewById(R.id.snapshot_image); 58 mInfoText= (TextView) view.findViewById(R.id.snapshot_text); 59 mInfoText.setMovementMethod(new ScrollingMovementMethod()); 60 61 if (mJpegImage != null) { 62 new AsyncTask<byte[], Integer, Bitmap>() { 63 @Override 64 protected Bitmap doInBackground(byte[]... params) { 65 byte[] jpegImage = params[0]; 66 BitmapFactory.Options opts = new BitmapFactory.Options(); 67 opts.inJustDecodeBounds = true; 68 BitmapFactory.decodeByteArray(jpegImage, 0, 69 jpegImage.length, opts); 70 // Keep image at less than 1 MP. 71 if (opts.outWidth > 1024 || opts.outHeight > 1024) { 72 int scaleFactorX = opts.outWidth / 1024 + 1; 73 int scaleFactorY = opts.outHeight / 1024 + 1; 74 int scaleFactor = scaleFactorX > scaleFactorY ? 75 scaleFactorX : scaleFactorY; 76 opts.inSampleSize = scaleFactor; 77 } 78 opts.inJustDecodeBounds = false; 79 Bitmap img = BitmapFactory.decodeByteArray(jpegImage, 0, 80 jpegImage.length, opts); 81 return img; 82 } 83 84 protected void onPostExecute(Bitmap img) { 85 mInfoImage.setImageBitmap(img); 86 } 87 }.execute(mJpegImage); 88 } 89 90 getDialog().setTitle("Snapshot result"); 91 return view; 92 } 93 94 public OnClickListener mOkButtonListener = new OnClickListener() { 95 public void onClick(View v) { 96 dismiss(); 97 } 98 }; 99 100 public OnClickListener mSaveButtonListener = new OnClickListener() { 101 public void onClick(View v) { 102 saveFile(); 103 } 104 }; 105 106 public OnClickListener mSaveAndViewButtonListener = new OnClickListener() { 107 public void onClick(View v) { 108 saveFile(); 109 viewFile(); 110 } 111 }; 112 113 public void updateImage(byte[] image) { 114 mJpegImage = image; 115 } 116 117 private String getAttrib(ExifInterface exif, String tag) { 118 String attribute = exif.getAttribute(tag); 119 return (attribute == null) ? "???" : attribute; 120 } 121 122 private void saveFile() { 123 if (!mSaved) { 124 TestingCamera parent = (TestingCamera) getActivity(); 125 parent.log("Saving image"); 126 127 File targetFile = parent.getOutputMediaFile(TestingCamera.MEDIA_TYPE_IMAGE); 128 if (targetFile == null) { 129 parent.logE("Unable to create file name"); 130 return; 131 } 132 parent.logIndent(1); 133 parent.log("File name: " + targetFile.toString()); 134 try { 135 FileOutputStream out = new FileOutputStream(targetFile); 136 out.write(mJpegImage); 137 out.close(); 138 mSaved = true; 139 parent.notifyMediaScannerOfFile(targetFile, this); 140 updateExif(targetFile); 141 } catch (IOException e) { 142 parent.logE("Unable to save file: " + e.getMessage()); 143 } 144 parent.logIndent(-1); 145 } 146 } 147 148 private void updateExif(File targetFile) { 149 ((TestingCamera) getActivity()).log("Extracting EXIF"); 150 try { 151 ExifInterface exif = new ExifInterface(targetFile.toString()); 152 153 String aperture = getAttrib(exif, ExifInterface.TAG_APERTURE); 154 155 String dateTime = getAttrib(exif, ExifInterface.TAG_DATETIME); 156 String exposureTime = getAttrib(exif, ExifInterface.TAG_EXPOSURE_TIME); 157 int flash = exif.getAttributeInt(ExifInterface.TAG_FLASH, 0); 158 double focalLength = exif.getAttributeDouble(ExifInterface.TAG_FOCAL_LENGTH, 0); 159 160 double gpsAltitude = exif.getAltitude(Double.NaN); 161 String gpsDatestamp = getAttrib(exif, ExifInterface.TAG_GPS_DATESTAMP); 162 float[] gpsCoords = new float[2]; 163 if (!exif.getLatLong(gpsCoords)) { 164 gpsCoords[0] = Float.NaN; 165 gpsCoords[1] = Float.NaN; 166 } 167 String gpsProcessingMethod = getAttrib(exif, ExifInterface.TAG_GPS_PROCESSING_METHOD); 168 String gpsTimestamp = getAttrib(exif, ExifInterface.TAG_GPS_TIMESTAMP); 169 170 int width = exif.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, 0); 171 int height = exif.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, 0); 172 String iso = getAttrib(exif, ExifInterface.TAG_ISO); 173 String make = getAttrib(exif, ExifInterface.TAG_MAKE); 174 String model = getAttrib(exif, ExifInterface.TAG_MODEL); 175 int orientationVal = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1); 176 int whiteBalance = exif.getAttributeInt(ExifInterface.TAG_WHITE_BALANCE, 0); 177 178 final String[] orientationStrings= new String[] { 179 "UNDEFINED", 180 "NORMAL", 181 "FLIP_HORIZONTAL", 182 "ROTATE_180", 183 "FLIP_VERTICAL", 184 "TRANSPOSE", 185 "ROTATE_90", 186 "TRANSVERSE", 187 "ROTATE_270" 188 }; 189 if (orientationVal >= orientationStrings.length) { 190 orientationVal = 0; 191 } 192 String orientation = orientationStrings[orientationVal]; 193 194 StringBuilder exifInfo = new StringBuilder(); 195 exifInfo.append("EXIF information for "). 196 append(targetFile.toString()).append("\n\n"); 197 exifInfo.append("Size: "). 198 append(width).append(" x ").append(height).append("\n"); 199 exifInfo.append("Make: "). 200 append(make).append("\n"); 201 exifInfo.append("Model: "). 202 append(model).append("\n"); 203 exifInfo.append("Orientation: "). 204 append(orientation).append("\n"); 205 exifInfo.append("Aperture: "). 206 append(aperture).append("\n"); 207 exifInfo.append("Focal length: "). 208 append(focalLength).append("\n"); 209 exifInfo.append("Exposure time: "). 210 append(exposureTime).append("\n"); 211 exifInfo.append("ISO: "). 212 append(iso).append("\n"); 213 exifInfo.append("Flash: "). 214 append(flash).append("\n"); 215 exifInfo.append("White balance: "). 216 append(whiteBalance).append("\n"); 217 exifInfo.append("Date/Time: "). 218 append(dateTime).append("\n"); 219 exifInfo.append("GPS altitude: "). 220 append(gpsAltitude).append("\n"); 221 exifInfo.append("GPS latitude: "). 222 append(gpsCoords[0]).append("\n"); 223 exifInfo.append("GPS longitude: "). 224 append(gpsCoords[1]).append("\n"); 225 exifInfo.append("GPS datestamp: "). 226 append(gpsDatestamp).append("\n"); 227 exifInfo.append("GPS timestamp: "). 228 append(gpsTimestamp).append("\n"); 229 exifInfo.append("GPS processing method: "). 230 append(gpsProcessingMethod).append("\n"); 231 mInfoText.setText(exifInfo.toString()); 232 233 } catch (IOException e) { 234 ((TestingCamera) getActivity()).logE("Unable to extract EXIF: " + e.getMessage()); 235 } 236 } 237 238 private synchronized void viewFile() { 239 if (!mSaved) return; 240 if (mSavedUri != null) { 241 ((TestingCamera) getActivity()).log("Viewing file"); 242 mViewWhenReady = false; 243 getActivity().startActivity(new Intent(Intent.ACTION_VIEW, mSavedUri)); 244 } else { 245 mViewWhenReady = true; 246 } 247 } 248 249 public synchronized void onScanCompleted(String path, Uri uri) { 250 mSavedUri = uri; 251 if (mViewWhenReady) viewFile(); 252 } 253 } 254