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