1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.camera; 18 19 import android.content.ContentResolver; 20 import android.content.ContentValues; 21 import android.location.Location; 22 import android.net.Uri; 23 import android.os.Environment; 24 import android.os.StatFs; 25 import android.provider.MediaStore.Images; 26 import android.provider.MediaStore.Images.ImageColumns; 27 import android.util.Log; 28 29 import java.io.File; 30 import java.io.FileOutputStream; 31 32 public class Storage { 33 private static final String TAG = "CameraStorage"; 34 35 public static final String DCIM = 36 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString(); 37 38 public static final String DIRECTORY = DCIM + "/Camera"; 39 40 // Match the code in MediaProvider.computeBucketValues(). 41 public static final String BUCKET_ID = 42 String.valueOf(DIRECTORY.toLowerCase().hashCode()); 43 44 public static final long UNAVAILABLE = -1L; 45 public static final long PREPARING = -2L; 46 public static final long UNKNOWN_SIZE = -3L; 47 public static final long LOW_STORAGE_THRESHOLD= 50000000; 48 public static final long PICTURE_SIZE = 1500000; 49 50 private static final int BUFSIZE = 4096; 51 addImage(ContentResolver resolver, String title, long date, Location location, int orientation, byte[] jpeg, int width, int height)52 public static Uri addImage(ContentResolver resolver, String title, long date, 53 Location location, int orientation, byte[] jpeg, int width, int height) { 54 // Save the image. 55 String path = generateFilepath(title); 56 FileOutputStream out = null; 57 try { 58 out = new FileOutputStream(path); 59 out.write(jpeg); 60 } catch (Exception e) { 61 Log.e(TAG, "Failed to write image", e); 62 return null; 63 } finally { 64 try { 65 out.close(); 66 } catch (Exception e) { 67 } 68 } 69 70 // Insert into MediaStore. 71 ContentValues values = new ContentValues(9); 72 values.put(ImageColumns.TITLE, title); 73 values.put(ImageColumns.DISPLAY_NAME, title + ".jpg"); 74 values.put(ImageColumns.DATE_TAKEN, date); 75 values.put(ImageColumns.MIME_TYPE, "image/jpeg"); 76 values.put(ImageColumns.ORIENTATION, orientation); 77 values.put(ImageColumns.DATA, path); 78 values.put(ImageColumns.SIZE, jpeg.length); 79 values.put(ImageColumns.WIDTH, width); 80 values.put(ImageColumns.HEIGHT, height); 81 82 if (location != null) { 83 values.put(ImageColumns.LATITUDE, location.getLatitude()); 84 values.put(ImageColumns.LONGITUDE, location.getLongitude()); 85 } 86 87 Uri uri = null; 88 try { 89 uri = resolver.insert(Images.Media.EXTERNAL_CONTENT_URI, values); 90 } catch (Throwable th) { 91 // This can happen when the external volume is already mounted, but 92 // MediaScanner has not notify MediaProvider to add that volume. 93 // The picture is still safe and MediaScanner will find it and 94 // insert it into MediaProvider. The only problem is that the user 95 // cannot click the thumbnail to review the picture. 96 Log.e(TAG, "Failed to write MediaStore" + th); 97 } 98 return uri; 99 } 100 generateFilepath(String title)101 public static String generateFilepath(String title) { 102 return DIRECTORY + '/' + title + ".jpg"; 103 } 104 getAvailableSpace()105 public static long getAvailableSpace() { 106 String state = Environment.getExternalStorageState(); 107 Log.d(TAG, "External storage state=" + state); 108 if (Environment.MEDIA_CHECKING.equals(state)) { 109 return PREPARING; 110 } 111 if (!Environment.MEDIA_MOUNTED.equals(state)) { 112 return UNAVAILABLE; 113 } 114 115 File dir = new File(DIRECTORY); 116 dir.mkdirs(); 117 if (!dir.isDirectory() || !dir.canWrite()) { 118 return UNAVAILABLE; 119 } 120 121 try { 122 StatFs stat = new StatFs(DIRECTORY); 123 return stat.getAvailableBlocks() * (long) stat.getBlockSize(); 124 } catch (Exception e) { 125 Log.i(TAG, "Fail to access external storage", e); 126 } 127 return UNKNOWN_SIZE; 128 } 129 130 /** 131 * OSX requires plugged-in USB storage to have path /DCIM/NNNAAAAA to be 132 * imported. This is a temporary fix for bug#1655552. 133 */ ensureOSXCompatible()134 public static void ensureOSXCompatible() { 135 File nnnAAAAA = new File(DCIM, "100ANDRO"); 136 if (!(nnnAAAAA.exists() || nnnAAAAA.mkdirs())) { 137 Log.e(TAG, "Failed to create " + nnnAAAAA.getPath()); 138 } 139 } 140 } 141