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