Storage.java revision 215c38b391c506948ee6113283c90fedc7eeefba
1c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh/*
2c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh * Copyright (C) 2010 The Android Open Source Project
3c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh *
4c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License");
5c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh * you may not use this file except in compliance with the License.
6c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh * You may obtain a copy of the License at
7c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh *
8c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh *      http://www.apache.org/licenses/LICENSE-2.0
9c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh *
10c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh * Unless required by applicable law or agreed to in writing, software
11c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS,
12c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh * See the License for the specific language governing permissions and
14c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh * limitations under the License.
15c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh */
16c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh
17c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yehpackage com.android.camera;
18c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh
19215c38b391c506948ee6113283c90fedc7eeefbaOwen Linimport android.annotation.TargetApi;
20d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yehimport android.content.ContentResolver;
21d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yehimport android.content.ContentValues;
22d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yehimport android.location.Location;
23d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yehimport android.net.Uri;
24215c38b391c506948ee6113283c90fedc7eeefbaOwen Linimport android.os.Build;
25c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yehimport android.os.Environment;
26c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yehimport android.os.StatFs;
27d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yehimport android.provider.MediaStore.Images;
28d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yehimport android.provider.MediaStore.Images.ImageColumns;
29215c38b391c506948ee6113283c90fedc7eeefbaOwen Linimport android.provider.MediaStore.MediaColumns;
30c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yehimport android.util.Log;
31c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh
32215c38b391c506948ee6113283c90fedc7eeefbaOwen Linimport com.android.gallery3d.common.ApiHelper;
33215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin
34721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yehimport java.io.File;
35d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yehimport java.io.FileOutputStream;
36721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh
37bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenpublic class Storage {
38c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh    private static final String TAG = "CameraStorage";
39c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh
408ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li    public static final String DCIM =
41721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString();
42721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh
43721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh    public static final String DIRECTORY = DCIM + "/Camera";
44721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh
45d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh    // Match the code in MediaProvider.computeBucketValues().
46d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh    public static final String BUCKET_ID =
47d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh            String.valueOf(DIRECTORY.toLowerCase().hashCode());
48d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh
49c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh    public static final long UNAVAILABLE = -1L;
50c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh    public static final long PREPARING = -2L;
51c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh    public static final long UNKNOWN_SIZE = -3L;
52a5edbe951a507a066f7601204e633dbd2dff3224Chih-yu Huang    public static final long LOW_STORAGE_THRESHOLD= 50000000;
53c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh
54215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
55215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin    private static void setImageSize(ContentValues values, int width, int height) {
56215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin        // The two fields are available since ICS but got published in JB
57215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin        if (ApiHelper.HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT) {
58215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin            values.put(MediaColumns.WIDTH, width);
59215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin            values.put(MediaColumns.HEIGHT, height);
60215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin        }
61215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin    }
62215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin
63ea312297ff6132bbafed99b90a72e4858b888fa4Angus Kong    public static Uri addImage(ContentResolver resolver, String title, long date,
64ea312297ff6132bbafed99b90a72e4858b888fa4Angus Kong                Location location, int orientation, byte[] jpeg, int width, int height) {
65d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        // Save the image.
66e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen        String path = generateFilepath(title);
67d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        FileOutputStream out = null;
68d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        try {
69d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh            out = new FileOutputStream(path);
70d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh            out.write(jpeg);
71d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        } catch (Exception e) {
72d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh            Log.e(TAG, "Failed to write image", e);
73d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh            return null;
74d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        } finally {
75d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh            try {
76d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh                out.close();
77d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh            } catch (Exception e) {
78d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh            }
79d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        }
80d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh
810aaed976b603c56006213d196e6b0703285dafd5Chia-chi Yeh        // Insert into MediaStore.
82d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        ContentValues values = new ContentValues(9);
83d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        values.put(ImageColumns.TITLE, title);
84d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        values.put(ImageColumns.DISPLAY_NAME, title + ".jpg");
85d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        values.put(ImageColumns.DATE_TAKEN, date);
86d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        values.put(ImageColumns.MIME_TYPE, "image/jpeg");
87a3d2bab37e9c008e3b4c7e4ba93ba1fc40bd4b90Wu-cheng Li        // Clockwise rotation in degrees. 0, 90, 180, or 270.
88d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        values.put(ImageColumns.ORIENTATION, orientation);
89d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        values.put(ImageColumns.DATA, path);
90d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        values.put(ImageColumns.SIZE, jpeg.length);
91215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin
92215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin        setImageSize(values, width, height);
93d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh
94d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        if (location != null) {
95d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh            values.put(ImageColumns.LATITUDE, location.getLatitude());
96d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh            values.put(ImageColumns.LONGITUDE, location.getLongitude());
97d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        }
98d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh
9980efb2ecfb09db1ac0915b13a91165d06bfbee74Chih-Chung Chang        Uri uri = null;
10080efb2ecfb09db1ac0915b13a91165d06bfbee74Chih-Chung Chang        try {
10180efb2ecfb09db1ac0915b13a91165d06bfbee74Chih-Chung Chang            uri = resolver.insert(Images.Media.EXTERNAL_CONTENT_URI, values);
10280efb2ecfb09db1ac0915b13a91165d06bfbee74Chih-Chung Chang        } catch (Throwable th)  {
10380efb2ecfb09db1ac0915b13a91165d06bfbee74Chih-Chung Chang            // This can happen when the external volume is already mounted, but
10480efb2ecfb09db1ac0915b13a91165d06bfbee74Chih-Chung Chang            // MediaScanner has not notify MediaProvider to add that volume.
10580efb2ecfb09db1ac0915b13a91165d06bfbee74Chih-Chung Chang            // The picture is still safe and MediaScanner will find it and
10680efb2ecfb09db1ac0915b13a91165d06bfbee74Chih-Chung Chang            // insert it into MediaProvider. The only problem is that the user
10780efb2ecfb09db1ac0915b13a91165d06bfbee74Chih-Chung Chang            // cannot click the thumbnail to review the picture.
10880efb2ecfb09db1ac0915b13a91165d06bfbee74Chih-Chung Chang            Log.e(TAG, "Failed to write MediaStore" + th);
1090aaed976b603c56006213d196e6b0703285dafd5Chia-chi Yeh        }
1108ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li        return uri;
111d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh    }
112d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh
113cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang    // newImage() and updateImage() together do the same work as
1143839c28061f5513745b6f4f060586610089ce5bbChih-Chung Chang    // addImage. newImage() is the first step, and it inserts the DATE_TAKEN and
1153839c28061f5513745b6f4f060586610089ce5bbChih-Chung Chang    // DATA fields into the database.
1163839c28061f5513745b6f4f060586610089ce5bbChih-Chung Chang    //
1173839c28061f5513745b6f4f060586610089ce5bbChih-Chung Chang    // We also insert hint values for the WIDTH and HEIGHT fields to give
1183839c28061f5513745b6f4f060586610089ce5bbChih-Chung Chang    // correct aspect ratio before the real values are updated in updateImage().
1193839c28061f5513745b6f4f060586610089ce5bbChih-Chung Chang    public static Uri newImage(ContentResolver resolver, String title,
1203839c28061f5513745b6f4f060586610089ce5bbChih-Chung Chang            long date, int width, int height) {
121cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        String path = generateFilepath(title);
122cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang
123cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        // Insert into MediaStore.
1243839c28061f5513745b6f4f060586610089ce5bbChih-Chung Chang        ContentValues values = new ContentValues(4);
125cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        values.put(ImageColumns.DATE_TAKEN, date);
126cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        values.put(ImageColumns.DATA, path);
127215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin
128215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin        setImageSize(values, width, height);
129cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang
130cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        Uri uri = null;
131cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        try {
132cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            uri = resolver.insert(Images.Media.EXTERNAL_CONTENT_URI, values);
133cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        } catch (Throwable th)  {
134cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            // This can happen when the external volume is already mounted, but
135cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            // MediaScanner has not notify MediaProvider to add that volume.
136cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            // The picture is still safe and MediaScanner will find it and
137cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            // insert it into MediaProvider. The only problem is that the user
138cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            // cannot click the thumbnail to review the picture.
139cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            Log.e(TAG, "Failed to new image" + th);
140cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        }
141cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        return uri;
142cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang    }
143cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang
144cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang    // This is the second step. It completes the partial data added by
145cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang    // newImage. All columns other than DATE_TAKEN and DATA are inserted
146cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang    // here. This method also save the image data into the file.
147cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang    //
148cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang    // Returns true if the update is successful.
149cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang    public static boolean updateImage(ContentResolver resolver, Uri uri,
150cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            String title, Location location, int orientation, byte[] jpeg,
151cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            int width, int height) {
152cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        // Save the image.
153cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        String path = generateFilepath(title);
154e8c7f9b282971cfefbbed0229af2602558bd3905Chih-Chung Chang        String tmpPath = path + ".tmp";
155cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        FileOutputStream out = null;
156cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        try {
157e8c7f9b282971cfefbbed0229af2602558bd3905Chih-Chung Chang            // Write to a temporary file and rename it to the final name. This
158e8c7f9b282971cfefbbed0229af2602558bd3905Chih-Chung Chang            // avoids other apps reading incomplete data.
159e8c7f9b282971cfefbbed0229af2602558bd3905Chih-Chung Chang            out = new FileOutputStream(tmpPath);
160cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            out.write(jpeg);
161e8c7f9b282971cfefbbed0229af2602558bd3905Chih-Chung Chang            out.close();
162e8c7f9b282971cfefbbed0229af2602558bd3905Chih-Chung Chang            new File(tmpPath).renameTo(new File(path));
163cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        } catch (Exception e) {
164cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            Log.e(TAG, "Failed to write image", e);
165cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            return false;
166cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        } finally {
167cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            try {
168cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang                out.close();
169cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            } catch (Exception e) {
170cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            }
171cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        }
172cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang
173cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        // Insert into MediaStore.
174cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        ContentValues values = new ContentValues(9);
175cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        values.put(ImageColumns.TITLE, title);
176cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        values.put(ImageColumns.DISPLAY_NAME, title + ".jpg");
177cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        values.put(ImageColumns.MIME_TYPE, "image/jpeg");
178a3d2bab37e9c008e3b4c7e4ba93ba1fc40bd4b90Wu-cheng Li        // Clockwise rotation in degrees. 0, 90, 180, or 270.
179cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        values.put(ImageColumns.ORIENTATION, orientation);
180cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        values.put(ImageColumns.SIZE, jpeg.length);
181215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin
182215c38b391c506948ee6113283c90fedc7eeefbaOwen Lin        setImageSize(values, width, height);
183cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang
184cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        if (location != null) {
185cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            values.put(ImageColumns.LATITUDE, location.getLatitude());
186cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            values.put(ImageColumns.LONGITUDE, location.getLongitude());
187cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        }
188cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang
189cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        try {
190cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            resolver.update(uri, values, null, null);
191cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        } catch (Throwable th) {
192cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            Log.e(TAG, "Failed to update image" + th);
193cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            return false;
194cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        }
195cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang
196cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        return true;
197cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang    }
198cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang
199cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang    public static void deleteImage(ContentResolver resolver, Uri uri) {
200cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        try {
201cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            resolver.delete(uri, null, null);
202cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        } catch (Throwable th) {
203cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang            Log.e(TAG, "Failed to delete image: " + uri);
204cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang        }
205cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang    }
206cd511956fe9b800b1abcc02934857f3f766e6367Chih-Chung Chang
207e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen    public static String generateFilepath(String title) {
208e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen        return DIRECTORY + '/' + title + ".jpg";
209e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen    }
210e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen
211c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh    public static long getAvailableSpace() {
212721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh        String state = Environment.getExternalStorageState();
213595d33f1308089ea4e656e247548a71b218d9fa5Wu-cheng Li        Log.d(TAG, "External storage state=" + state);
214721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh        if (Environment.MEDIA_CHECKING.equals(state)) {
215721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh            return PREPARING;
216721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh        }
217721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh        if (!Environment.MEDIA_MOUNTED.equals(state)) {
218721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh            return UNAVAILABLE;
219721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh        }
220721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh
221721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh        File dir = new File(DIRECTORY);
222721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh        dir.mkdirs();
223721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh        if (!dir.isDirectory() || !dir.canWrite()) {
224721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh            return UNAVAILABLE;
225721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh        }
226721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh
227c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh        try {
228721d2d2a963799fad4bda9bb4b278c24fc469303Chia-chi Yeh            StatFs stat = new StatFs(DIRECTORY);
229c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh            return stat.getAvailableBlocks() * (long) stat.getBlockSize();
230c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh        } catch (Exception e) {
231c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh            Log.i(TAG, "Fail to access external storage", e);
232c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh        }
233c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh        return UNKNOWN_SIZE;
234c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh    }
235d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh
236d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh    /**
237d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh     * OSX requires plugged-in USB storage to have path /DCIM/NNNAAAAA to be
238d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh     * imported. This is a temporary fix for bug#1655552.
239d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh     */
240d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh    public static void ensureOSXCompatible() {
24107713606e48802a2516c34c9bb9df4fc7f77553fWu-cheng Li        File nnnAAAAA = new File(DCIM, "100ANDRO");
242d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        if (!(nnnAAAAA.exists() || nnnAAAAA.mkdirs())) {
243d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh            Log.e(TAG, "Failed to create " + nnnAAAAA.getPath());
244d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh        }
245d1ec4e36667086836cd243bee38aded5e1fd88b1Chia-chi Yeh    }
246c8a7fc07e3b905a723e753b0c9144de2b0343f1fChia-chi Yeh}
247