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