13651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala/* 23651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala * Copyright (C) 2016 The Android Open Source Project 33651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala * 43651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala * Licensed under the Apache License, Version 2.0 (the "License"); 53651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala * you may not use this file except in compliance with the License. 63651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala * You may obtain a copy of the License at 73651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala * 83651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala * http://www.apache.org/licenses/LICENSE-2.0 93651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala * 103651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala * Unless required by applicable law or agreed to in writing, software 113651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala * distributed under the License is distributed on an "AS IS" BASIS, 123651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala * See the License for the specific language governing permissions and 143651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala * limitations under the License. 153651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvala */ 163651aa3f8296eae150590b765fda1d87f49fb5b6Eino-Ville Talvalapackage com.android.devcamera; 17a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 18a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvalaimport android.content.ContentResolver; 19a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvalaimport android.content.ContentValues; 20a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvalaimport android.content.Context; 21a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvalaimport android.content.SharedPreferences; 22a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvalaimport android.os.SystemClock; 23a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvalaimport android.provider.MediaStore; 24a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvalaimport android.util.Log; 25a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 26a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvalaimport java.io.File; 27a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvalaimport java.io.FileOutputStream; 28a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvalaimport java.io.IOException; 29a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvalaimport java.io.OutputStream; 30a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 31a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala/** 32a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala * This class has methods required to save a JPEG to disk as well as update the 33a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala * MediaStore database. 34a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala */ 35a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 36a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 37a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvalapublic class MediaSaver { 38a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala private static final String TAG = "Snappy_MediaSaver"; 39a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala private static final String MY_PREFS_NAME = "SnappyPrefs"; 40a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 41a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala // MediaStore is slow/broken 42a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala private static final boolean UDPATE_MEDIA_STORE = true; 43a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 44a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 45a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala public static int getNextInt(Context context) { 46a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala SharedPreferences prefs = context.getSharedPreferences(MY_PREFS_NAME, Context.MODE_PRIVATE); 47a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala int i = prefs.getInt("counter", 1); 48a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala SharedPreferences.Editor editor = prefs.edit(); 49a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala editor.putInt("counter", i+1); 50a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala editor.commit(); 51a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala return i; 52a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala } 53a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 54a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala /** 55a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala * @param context Application context. 56a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala * @param jpegData JPEG byte stream. 57a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala */ 58a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala public static String saveJpeg(Context context, byte[] jpegData, ContentResolver resolver) { 59a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala String filename = ""; 60a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala try { 61a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala File file; 62a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala while (true) { 63a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala int i = getNextInt(context); 64a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala filename = String.format("/sdcard/DCIM/Camera/SNAP_%05d.JPG", i); 65a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala file = new File(filename); 66a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala if (file.createNewFile()) { 67a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala break; 68a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala } 69a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala } 70a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 71a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala long t0 = SystemClock.uptimeMillis(); 72a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala OutputStream os = new FileOutputStream(file); 73a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala os.write(jpegData); 74a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala os.flush(); 75a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala os.close(); 76a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala long t1 = SystemClock.uptimeMillis(); 77a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 78a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala // update MediaStore so photos apps can find photos right away. 79a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala if (UDPATE_MEDIA_STORE) { 80a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala // really slow for some reason: MediaStore.Images.Media.insertImage(resolver, file.getAbsolutePath(), file.getName(), file.getName()); 81a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala insertImage(resolver, file); 82a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala } 83a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala long t2 = SystemClock.uptimeMillis(); 84a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 85a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala Log.v(TAG, String.format("Wrote JPEG %d bytes as %s in %.3f seconds; mediastore update = %.3f secs", 86a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala jpegData.length, file, (t1 - t0) * 0.001, (t2 - t1) * 0.001) ); 87a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala } catch (IOException e) { 88a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala Log.e(TAG, "Error creating new file: ", e); 89a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala } 90a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala return filename; 91a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala } 92a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 93a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 94a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala // We use this instead of MediaStore.Images.Media.insertImage() because we want to add date metadata 95a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala public static void insertImage(ContentResolver cr, File file) { 96a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 97a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala ContentValues values = new ContentValues(); 98a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala values.put(MediaStore.Images.Media.TITLE, file.getName()); 99a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala values.put(MediaStore.Images.Media.DISPLAY_NAME, file.getName()); 100a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala values.put(MediaStore.Images.Media.DESCRIPTION, file.getName()); 101a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); 102a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath()); 103a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala // Add the date meta data to ensure the image is added at the front of the gallery 104a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis()); 105a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()); 106a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 107a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala try { 108a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); 109a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala } catch (Exception e) { 110a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala Log.w(TAG, "Error updating media store for " + file, e); 111a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala } 112a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala } 113a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala 114a8a96dfce795a6621cdf7b890442fa5ed1252a55Eino-Ville Talvala} 115