1666ea1b28a76aeba74744148b15099254d918671Owen Lin/* 2666ea1b28a76aeba74744148b15099254d918671Owen Lin * Copyright (C) 2007 The Android Open Source Project 3666ea1b28a76aeba74744148b15099254d918671Owen Lin * 4666ea1b28a76aeba74744148b15099254d918671Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5666ea1b28a76aeba74744148b15099254d918671Owen Lin * you may not use this file except in compliance with the License. 6666ea1b28a76aeba74744148b15099254d918671Owen Lin * You may obtain a copy of the License at 7666ea1b28a76aeba74744148b15099254d918671Owen Lin * 8666ea1b28a76aeba74744148b15099254d918671Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9666ea1b28a76aeba74744148b15099254d918671Owen Lin * 10666ea1b28a76aeba74744148b15099254d918671Owen Lin * Unless required by applicable law or agreed to in writing, software 11666ea1b28a76aeba74744148b15099254d918671Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12666ea1b28a76aeba74744148b15099254d918671Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13666ea1b28a76aeba74744148b15099254d918671Owen Lin * See the License for the specific language governing permissions and 14666ea1b28a76aeba74744148b15099254d918671Owen Lin * limitations under the License. 15666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 16666ea1b28a76aeba74744148b15099254d918671Owen Lin 17666ea1b28a76aeba74744148b15099254d918671Owen Linpackage com.android.camera; 18666ea1b28a76aeba74744148b15099254d918671Owen Lin 19666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.BaseImageList; 20666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.DrmImageList; 21666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.IImage; 22666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.IImageList; 23666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.ImageList; 24666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.ImageListUber; 25666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.SingleImageList; 26666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.VideoList; 27666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.VideoObject; 28666ea1b28a76aeba74744148b15099254d918671Owen Lin 29666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.content.ContentResolver; 30666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.content.ContentValues; 31666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.database.Cursor; 32666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.graphics.Bitmap; 33666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.graphics.Bitmap.CompressFormat; 34666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.location.Location; 35666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.media.ExifInterface; 36666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.net.Uri; 37666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.os.Environment; 38666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.os.Parcel; 39666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.os.Parcelable; 40666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.provider.DrmStore; 41666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.provider.MediaStore; 42666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.provider.MediaStore.Images; 43666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.util.Log; 44666ea1b28a76aeba74744148b15099254d918671Owen Lin 45666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.io.File; 46666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.io.FileNotFoundException; 47666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.io.FileOutputStream; 48666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.io.IOException; 49666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.io.OutputStream; 50666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.util.ArrayList; 51666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.util.HashMap; 52666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.util.Iterator; 53666ea1b28a76aeba74744148b15099254d918671Owen Lin 54666ea1b28a76aeba74744148b15099254d918671Owen Lin/** 55666ea1b28a76aeba74744148b15099254d918671Owen Lin * ImageManager is used to retrieve and store images 56666ea1b28a76aeba74744148b15099254d918671Owen Lin * in the media content provider. 57666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 58666ea1b28a76aeba74744148b15099254d918671Owen Linpublic class ImageManager { 59666ea1b28a76aeba74744148b15099254d918671Owen Lin private static final String TAG = "ImageManager"; 60666ea1b28a76aeba74744148b15099254d918671Owen Lin 61666ea1b28a76aeba74744148b15099254d918671Owen Lin private static final Uri STORAGE_URI = Images.Media.EXTERNAL_CONTENT_URI; 62666ea1b28a76aeba74744148b15099254d918671Owen Lin private static final Uri THUMB_URI 63666ea1b28a76aeba74744148b15099254d918671Owen Lin = Images.Thumbnails.EXTERNAL_CONTENT_URI; 64666ea1b28a76aeba74744148b15099254d918671Owen Lin 65666ea1b28a76aeba74744148b15099254d918671Owen Lin private static final Uri VIDEO_STORAGE_URI = 66666ea1b28a76aeba74744148b15099254d918671Owen Lin Uri.parse("content://media/external/video/media"); 67666ea1b28a76aeba74744148b15099254d918671Owen Lin 68666ea1b28a76aeba74744148b15099254d918671Owen Lin // ImageListParam specifies all the parameters we need to create an image 69666ea1b28a76aeba74744148b15099254d918671Owen Lin // list (we also need a ContentResolver). 70666ea1b28a76aeba74744148b15099254d918671Owen Lin public static class ImageListParam implements Parcelable { 71666ea1b28a76aeba74744148b15099254d918671Owen Lin public DataLocation mLocation; 72666ea1b28a76aeba74744148b15099254d918671Owen Lin public int mInclusion; 73666ea1b28a76aeba74744148b15099254d918671Owen Lin public int mSort; 74666ea1b28a76aeba74744148b15099254d918671Owen Lin public String mBucketId; 75666ea1b28a76aeba74744148b15099254d918671Owen Lin 76666ea1b28a76aeba74744148b15099254d918671Owen Lin // This is only used if we are creating a single image list. 77666ea1b28a76aeba74744148b15099254d918671Owen Lin public Uri mSingleImageUri; 78666ea1b28a76aeba74744148b15099254d918671Owen Lin 79666ea1b28a76aeba74744148b15099254d918671Owen Lin // This is only used if we are creating an empty image list. 80666ea1b28a76aeba74744148b15099254d918671Owen Lin public boolean mIsEmptyImageList; 81666ea1b28a76aeba74744148b15099254d918671Owen Lin 82666ea1b28a76aeba74744148b15099254d918671Owen Lin public ImageListParam() {} 83666ea1b28a76aeba74744148b15099254d918671Owen Lin 84666ea1b28a76aeba74744148b15099254d918671Owen Lin public void writeToParcel(Parcel out, int flags) { 85666ea1b28a76aeba74744148b15099254d918671Owen Lin out.writeInt(mLocation.ordinal()); 86666ea1b28a76aeba74744148b15099254d918671Owen Lin out.writeInt(mInclusion); 87666ea1b28a76aeba74744148b15099254d918671Owen Lin out.writeInt(mSort); 88666ea1b28a76aeba74744148b15099254d918671Owen Lin out.writeString(mBucketId); 89666ea1b28a76aeba74744148b15099254d918671Owen Lin out.writeParcelable(mSingleImageUri, flags); 90666ea1b28a76aeba74744148b15099254d918671Owen Lin out.writeInt(mIsEmptyImageList ? 1 : 0); 91666ea1b28a76aeba74744148b15099254d918671Owen Lin } 92666ea1b28a76aeba74744148b15099254d918671Owen Lin 93666ea1b28a76aeba74744148b15099254d918671Owen Lin private ImageListParam(Parcel in) { 94666ea1b28a76aeba74744148b15099254d918671Owen Lin mLocation = DataLocation.values()[in.readInt()]; 95666ea1b28a76aeba74744148b15099254d918671Owen Lin mInclusion = in.readInt(); 96666ea1b28a76aeba74744148b15099254d918671Owen Lin mSort = in.readInt(); 97666ea1b28a76aeba74744148b15099254d918671Owen Lin mBucketId = in.readString(); 98666ea1b28a76aeba74744148b15099254d918671Owen Lin mSingleImageUri = in.readParcelable(null); 99666ea1b28a76aeba74744148b15099254d918671Owen Lin mIsEmptyImageList = (in.readInt() != 0); 100666ea1b28a76aeba74744148b15099254d918671Owen Lin } 101666ea1b28a76aeba74744148b15099254d918671Owen Lin 102666ea1b28a76aeba74744148b15099254d918671Owen Lin public String toString() { 103666ea1b28a76aeba74744148b15099254d918671Owen Lin return String.format("ImageListParam{loc=%s,inc=%d,sort=%d," + 104666ea1b28a76aeba74744148b15099254d918671Owen Lin "bucket=%s,empty=%b,single=%s}", mLocation, mInclusion, 105666ea1b28a76aeba74744148b15099254d918671Owen Lin mSort, mBucketId, mIsEmptyImageList, mSingleImageUri); 106666ea1b28a76aeba74744148b15099254d918671Owen Lin } 107666ea1b28a76aeba74744148b15099254d918671Owen Lin 108666ea1b28a76aeba74744148b15099254d918671Owen Lin public static final Parcelable.Creator CREATOR 109666ea1b28a76aeba74744148b15099254d918671Owen Lin = new Parcelable.Creator() { 110666ea1b28a76aeba74744148b15099254d918671Owen Lin public ImageListParam createFromParcel(Parcel in) { 111666ea1b28a76aeba74744148b15099254d918671Owen Lin return new ImageListParam(in); 112666ea1b28a76aeba74744148b15099254d918671Owen Lin } 113666ea1b28a76aeba74744148b15099254d918671Owen Lin 114666ea1b28a76aeba74744148b15099254d918671Owen Lin public ImageListParam[] newArray(int size) { 115666ea1b28a76aeba74744148b15099254d918671Owen Lin return new ImageListParam[size]; 116666ea1b28a76aeba74744148b15099254d918671Owen Lin } 117666ea1b28a76aeba74744148b15099254d918671Owen Lin }; 118666ea1b28a76aeba74744148b15099254d918671Owen Lin 119666ea1b28a76aeba74744148b15099254d918671Owen Lin public int describeContents() { 120666ea1b28a76aeba74744148b15099254d918671Owen Lin return 0; 121666ea1b28a76aeba74744148b15099254d918671Owen Lin } 122666ea1b28a76aeba74744148b15099254d918671Owen Lin } 123666ea1b28a76aeba74744148b15099254d918671Owen Lin 124666ea1b28a76aeba74744148b15099254d918671Owen Lin // Location 125666ea1b28a76aeba74744148b15099254d918671Owen Lin public static enum DataLocation { NONE, INTERNAL, EXTERNAL, ALL } 126666ea1b28a76aeba74744148b15099254d918671Owen Lin 127666ea1b28a76aeba74744148b15099254d918671Owen Lin // Inclusion 128666ea1b28a76aeba74744148b15099254d918671Owen Lin public static final int INCLUDE_IMAGES = (1 << 0); 129666ea1b28a76aeba74744148b15099254d918671Owen Lin public static final int INCLUDE_DRM_IMAGES = (1 << 1); 130666ea1b28a76aeba74744148b15099254d918671Owen Lin public static final int INCLUDE_VIDEOS = (1 << 2); 131666ea1b28a76aeba74744148b15099254d918671Owen Lin 132666ea1b28a76aeba74744148b15099254d918671Owen Lin // Sort 133666ea1b28a76aeba74744148b15099254d918671Owen Lin public static final int SORT_ASCENDING = 1; 134666ea1b28a76aeba74744148b15099254d918671Owen Lin public static final int SORT_DESCENDING = 2; 135666ea1b28a76aeba74744148b15099254d918671Owen Lin 136666ea1b28a76aeba74744148b15099254d918671Owen Lin public static final String CAMERA_IMAGE_BUCKET_NAME = 137666ea1b28a76aeba74744148b15099254d918671Owen Lin Environment.getExternalStorageDirectory().toString() 138666ea1b28a76aeba74744148b15099254d918671Owen Lin + "/DCIM/Camera"; 139666ea1b28a76aeba74744148b15099254d918671Owen Lin public static final String CAMERA_IMAGE_BUCKET_ID = 140666ea1b28a76aeba74744148b15099254d918671Owen Lin getBucketId(CAMERA_IMAGE_BUCKET_NAME); 141666ea1b28a76aeba74744148b15099254d918671Owen Lin 142666ea1b28a76aeba74744148b15099254d918671Owen Lin /** 143666ea1b28a76aeba74744148b15099254d918671Owen Lin * Matches code in MediaProvider.computeBucketValues. Should be a common 144666ea1b28a76aeba74744148b15099254d918671Owen Lin * function. 145666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 146666ea1b28a76aeba74744148b15099254d918671Owen Lin public static String getBucketId(String path) { 147666ea1b28a76aeba74744148b15099254d918671Owen Lin return String.valueOf(path.toLowerCase().hashCode()); 148666ea1b28a76aeba74744148b15099254d918671Owen Lin } 149666ea1b28a76aeba74744148b15099254d918671Owen Lin 150666ea1b28a76aeba74744148b15099254d918671Owen Lin /** 151666ea1b28a76aeba74744148b15099254d918671Owen Lin * OSX requires plugged-in USB storage to have path /DCIM/NNNAAAAA to be 152666ea1b28a76aeba74744148b15099254d918671Owen Lin * imported. This is a temporary fix for bug#1655552. 153666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 154666ea1b28a76aeba74744148b15099254d918671Owen Lin public static void ensureOSXCompatibleFolder() { 155666ea1b28a76aeba74744148b15099254d918671Owen Lin File nnnAAAAA = new File( 156666ea1b28a76aeba74744148b15099254d918671Owen Lin Environment.getExternalStorageDirectory().toString() 157666ea1b28a76aeba74744148b15099254d918671Owen Lin + "/DCIM/100ANDRO"); 158666ea1b28a76aeba74744148b15099254d918671Owen Lin if ((!nnnAAAAA.exists()) && (!nnnAAAAA.mkdir())) { 159666ea1b28a76aeba74744148b15099254d918671Owen Lin Log.e(TAG, "create NNNAAAAA file: " + nnnAAAAA.getPath() 160666ea1b28a76aeba74744148b15099254d918671Owen Lin + " failed"); 161666ea1b28a76aeba74744148b15099254d918671Owen Lin } 162666ea1b28a76aeba74744148b15099254d918671Owen Lin } 163666ea1b28a76aeba74744148b15099254d918671Owen Lin 164666ea1b28a76aeba74744148b15099254d918671Owen Lin /** 165666ea1b28a76aeba74744148b15099254d918671Owen Lin * @return true if the mimetype is an image mimetype. 166666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 167666ea1b28a76aeba74744148b15099254d918671Owen Lin public static boolean isImageMimeType(String mimeType) { 168666ea1b28a76aeba74744148b15099254d918671Owen Lin return mimeType.startsWith("image/"); 169666ea1b28a76aeba74744148b15099254d918671Owen Lin } 170666ea1b28a76aeba74744148b15099254d918671Owen Lin 171666ea1b28a76aeba74744148b15099254d918671Owen Lin /** 172666ea1b28a76aeba74744148b15099254d918671Owen Lin * @return true if the mimetype is a video mimetype. 173666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 174666ea1b28a76aeba74744148b15099254d918671Owen Lin /* This is commented out because isVideo is not calling this now. 175666ea1b28a76aeba74744148b15099254d918671Owen Lin public static boolean isVideoMimeType(String mimeType) { 176666ea1b28a76aeba74744148b15099254d918671Owen Lin return mimeType.startsWith("video/"); 177666ea1b28a76aeba74744148b15099254d918671Owen Lin } 178666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 179666ea1b28a76aeba74744148b15099254d918671Owen Lin 180666ea1b28a76aeba74744148b15099254d918671Owen Lin /** 181666ea1b28a76aeba74744148b15099254d918671Owen Lin * @return true if the image is an image. 182666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 183666ea1b28a76aeba74744148b15099254d918671Owen Lin public static boolean isImage(IImage image) { 184666ea1b28a76aeba74744148b15099254d918671Owen Lin return isImageMimeType(image.getMimeType()); 185666ea1b28a76aeba74744148b15099254d918671Owen Lin } 186666ea1b28a76aeba74744148b15099254d918671Owen Lin 187666ea1b28a76aeba74744148b15099254d918671Owen Lin /** 188666ea1b28a76aeba74744148b15099254d918671Owen Lin * @return true if the image is a video. 189666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 190666ea1b28a76aeba74744148b15099254d918671Owen Lin public static boolean isVideo(IImage image) { 191666ea1b28a76aeba74744148b15099254d918671Owen Lin // This is the right implementation, but we use instanceof for speed. 192666ea1b28a76aeba74744148b15099254d918671Owen Lin //return isVideoMimeType(image.getMimeType()); 193666ea1b28a76aeba74744148b15099254d918671Owen Lin return (image instanceof VideoObject); 194666ea1b28a76aeba74744148b15099254d918671Owen Lin } 195666ea1b28a76aeba74744148b15099254d918671Owen Lin 196666ea1b28a76aeba74744148b15099254d918671Owen Lin // 197666ea1b28a76aeba74744148b15099254d918671Owen Lin // Stores a bitmap or a jpeg byte array to a file (using the specified 198666ea1b28a76aeba74744148b15099254d918671Owen Lin // directory and filename). Also add an entry to the media store for 199666ea1b28a76aeba74744148b15099254d918671Owen Lin // this picture. The title, dateTaken, location are attributes for the 200666ea1b28a76aeba74744148b15099254d918671Owen Lin // picture. The degree is a one element array which returns the orientation 201666ea1b28a76aeba74744148b15099254d918671Owen Lin // of the picture. 202666ea1b28a76aeba74744148b15099254d918671Owen Lin // 203666ea1b28a76aeba74744148b15099254d918671Owen Lin public static Uri addImage(ContentResolver cr, String title, long dateTaken, 204666ea1b28a76aeba74744148b15099254d918671Owen Lin Location location, String directory, String filename, 205666ea1b28a76aeba74744148b15099254d918671Owen Lin Bitmap source, byte[] jpegData, int[] degree) { 206666ea1b28a76aeba74744148b15099254d918671Owen Lin // We should store image data earlier than insert it to ContentProvider, otherwise 207666ea1b28a76aeba74744148b15099254d918671Owen Lin // we may not be able to generate thumbnail in time. 208666ea1b28a76aeba74744148b15099254d918671Owen Lin OutputStream outputStream = null; 209666ea1b28a76aeba74744148b15099254d918671Owen Lin String filePath = directory + "/" + filename; 210666ea1b28a76aeba74744148b15099254d918671Owen Lin try { 211666ea1b28a76aeba74744148b15099254d918671Owen Lin File dir = new File(directory); 212666ea1b28a76aeba74744148b15099254d918671Owen Lin if (!dir.exists()) dir.mkdirs(); 213666ea1b28a76aeba74744148b15099254d918671Owen Lin File file = new File(directory, filename); 214666ea1b28a76aeba74744148b15099254d918671Owen Lin outputStream = new FileOutputStream(file); 215666ea1b28a76aeba74744148b15099254d918671Owen Lin if (source != null) { 216666ea1b28a76aeba74744148b15099254d918671Owen Lin source.compress(CompressFormat.JPEG, 75, outputStream); 217666ea1b28a76aeba74744148b15099254d918671Owen Lin degree[0] = 0; 218666ea1b28a76aeba74744148b15099254d918671Owen Lin } else { 219666ea1b28a76aeba74744148b15099254d918671Owen Lin outputStream.write(jpegData); 220666ea1b28a76aeba74744148b15099254d918671Owen Lin degree[0] = getExifOrientation(filePath); 221666ea1b28a76aeba74744148b15099254d918671Owen Lin } 222666ea1b28a76aeba74744148b15099254d918671Owen Lin } catch (FileNotFoundException ex) { 223666ea1b28a76aeba74744148b15099254d918671Owen Lin Log.w(TAG, ex); 224666ea1b28a76aeba74744148b15099254d918671Owen Lin return null; 225666ea1b28a76aeba74744148b15099254d918671Owen Lin } catch (IOException ex) { 226666ea1b28a76aeba74744148b15099254d918671Owen Lin Log.w(TAG, ex); 227666ea1b28a76aeba74744148b15099254d918671Owen Lin return null; 228666ea1b28a76aeba74744148b15099254d918671Owen Lin } finally { 229666ea1b28a76aeba74744148b15099254d918671Owen Lin Util.closeSilently(outputStream); 230666ea1b28a76aeba74744148b15099254d918671Owen Lin } 231666ea1b28a76aeba74744148b15099254d918671Owen Lin 232666ea1b28a76aeba74744148b15099254d918671Owen Lin ContentValues values = new ContentValues(7); 233666ea1b28a76aeba74744148b15099254d918671Owen Lin values.put(Images.Media.TITLE, title); 234666ea1b28a76aeba74744148b15099254d918671Owen Lin 235666ea1b28a76aeba74744148b15099254d918671Owen Lin // That filename is what will be handed to Gmail when a user shares a 236666ea1b28a76aeba74744148b15099254d918671Owen Lin // photo. Gmail gets the name of the picture attachment from the 237666ea1b28a76aeba74744148b15099254d918671Owen Lin // "DISPLAY_NAME" field. 238666ea1b28a76aeba74744148b15099254d918671Owen Lin values.put(Images.Media.DISPLAY_NAME, filename); 239666ea1b28a76aeba74744148b15099254d918671Owen Lin values.put(Images.Media.DATE_TAKEN, dateTaken); 240666ea1b28a76aeba74744148b15099254d918671Owen Lin values.put(Images.Media.MIME_TYPE, "image/jpeg"); 241666ea1b28a76aeba74744148b15099254d918671Owen Lin values.put(Images.Media.ORIENTATION, degree[0]); 242666ea1b28a76aeba74744148b15099254d918671Owen Lin values.put(Images.Media.DATA, filePath); 243666ea1b28a76aeba74744148b15099254d918671Owen Lin 244666ea1b28a76aeba74744148b15099254d918671Owen Lin if (location != null) { 245666ea1b28a76aeba74744148b15099254d918671Owen Lin values.put(Images.Media.LATITUDE, location.getLatitude()); 246666ea1b28a76aeba74744148b15099254d918671Owen Lin values.put(Images.Media.LONGITUDE, location.getLongitude()); 247666ea1b28a76aeba74744148b15099254d918671Owen Lin } 248666ea1b28a76aeba74744148b15099254d918671Owen Lin 249666ea1b28a76aeba74744148b15099254d918671Owen Lin return cr.insert(STORAGE_URI, values); 250666ea1b28a76aeba74744148b15099254d918671Owen Lin } 251666ea1b28a76aeba74744148b15099254d918671Owen Lin 252666ea1b28a76aeba74744148b15099254d918671Owen Lin public static int getExifOrientation(String filepath) { 253666ea1b28a76aeba74744148b15099254d918671Owen Lin int degree = 0; 254666ea1b28a76aeba74744148b15099254d918671Owen Lin ExifInterface exif = null; 255666ea1b28a76aeba74744148b15099254d918671Owen Lin try { 256666ea1b28a76aeba74744148b15099254d918671Owen Lin exif = new ExifInterface(filepath); 257666ea1b28a76aeba74744148b15099254d918671Owen Lin } catch (IOException ex) { 258666ea1b28a76aeba74744148b15099254d918671Owen Lin Log.e(TAG, "cannot read exif", ex); 259666ea1b28a76aeba74744148b15099254d918671Owen Lin } 260666ea1b28a76aeba74744148b15099254d918671Owen Lin if (exif != null) { 261666ea1b28a76aeba74744148b15099254d918671Owen Lin int orientation = exif.getAttributeInt( 262666ea1b28a76aeba74744148b15099254d918671Owen Lin ExifInterface.TAG_ORIENTATION, -1); 263666ea1b28a76aeba74744148b15099254d918671Owen Lin if (orientation != -1) { 264666ea1b28a76aeba74744148b15099254d918671Owen Lin // We only recognize a subset of orientation tag values. 265666ea1b28a76aeba74744148b15099254d918671Owen Lin switch(orientation) { 266666ea1b28a76aeba74744148b15099254d918671Owen Lin case ExifInterface.ORIENTATION_ROTATE_90: 267666ea1b28a76aeba74744148b15099254d918671Owen Lin degree = 90; 268666ea1b28a76aeba74744148b15099254d918671Owen Lin break; 269666ea1b28a76aeba74744148b15099254d918671Owen Lin case ExifInterface.ORIENTATION_ROTATE_180: 270666ea1b28a76aeba74744148b15099254d918671Owen Lin degree = 180; 271666ea1b28a76aeba74744148b15099254d918671Owen Lin break; 272666ea1b28a76aeba74744148b15099254d918671Owen Lin case ExifInterface.ORIENTATION_ROTATE_270: 273666ea1b28a76aeba74744148b15099254d918671Owen Lin degree = 270; 274666ea1b28a76aeba74744148b15099254d918671Owen Lin break; 275666ea1b28a76aeba74744148b15099254d918671Owen Lin } 276666ea1b28a76aeba74744148b15099254d918671Owen Lin 277666ea1b28a76aeba74744148b15099254d918671Owen Lin } 278666ea1b28a76aeba74744148b15099254d918671Owen Lin } 279666ea1b28a76aeba74744148b15099254d918671Owen Lin return degree; 280666ea1b28a76aeba74744148b15099254d918671Owen Lin } 281666ea1b28a76aeba74744148b15099254d918671Owen Lin 282666ea1b28a76aeba74744148b15099254d918671Owen Lin // This is the factory function to create an image list. 283666ea1b28a76aeba74744148b15099254d918671Owen Lin public static IImageList makeImageList(ContentResolver cr, 284666ea1b28a76aeba74744148b15099254d918671Owen Lin ImageListParam param) { 285666ea1b28a76aeba74744148b15099254d918671Owen Lin DataLocation location = param.mLocation; 286666ea1b28a76aeba74744148b15099254d918671Owen Lin int inclusion = param.mInclusion; 287666ea1b28a76aeba74744148b15099254d918671Owen Lin int sort = param.mSort; 288666ea1b28a76aeba74744148b15099254d918671Owen Lin String bucketId = param.mBucketId; 289666ea1b28a76aeba74744148b15099254d918671Owen Lin Uri singleImageUri = param.mSingleImageUri; 290666ea1b28a76aeba74744148b15099254d918671Owen Lin boolean isEmptyImageList = param.mIsEmptyImageList; 291666ea1b28a76aeba74744148b15099254d918671Owen Lin 292666ea1b28a76aeba74744148b15099254d918671Owen Lin if (isEmptyImageList || cr == null) { 293666ea1b28a76aeba74744148b15099254d918671Owen Lin return new EmptyImageList(); 294666ea1b28a76aeba74744148b15099254d918671Owen Lin } 295666ea1b28a76aeba74744148b15099254d918671Owen Lin 296666ea1b28a76aeba74744148b15099254d918671Owen Lin if (singleImageUri != null) { 297666ea1b28a76aeba74744148b15099254d918671Owen Lin return new SingleImageList(cr, singleImageUri); 298666ea1b28a76aeba74744148b15099254d918671Owen Lin } 299666ea1b28a76aeba74744148b15099254d918671Owen Lin 300666ea1b28a76aeba74744148b15099254d918671Owen Lin // false ==> don't require write access 301666ea1b28a76aeba74744148b15099254d918671Owen Lin boolean haveSdCard = hasStorage(false); 302666ea1b28a76aeba74744148b15099254d918671Owen Lin 303666ea1b28a76aeba74744148b15099254d918671Owen Lin // use this code to merge videos and stills into the same list 304666ea1b28a76aeba74744148b15099254d918671Owen Lin ArrayList<BaseImageList> l = new ArrayList<BaseImageList>(); 305666ea1b28a76aeba74744148b15099254d918671Owen Lin 306666ea1b28a76aeba74744148b15099254d918671Owen Lin if (haveSdCard && location != DataLocation.INTERNAL) { 307666ea1b28a76aeba74744148b15099254d918671Owen Lin if ((inclusion & INCLUDE_IMAGES) != 0) { 308b62254a185d04ecfe2ddc837b7e0e54f0273c478Owen Lin l.add(new ImageList(cr, STORAGE_URI, sort, bucketId)); 309666ea1b28a76aeba74744148b15099254d918671Owen Lin } 310666ea1b28a76aeba74744148b15099254d918671Owen Lin if ((inclusion & INCLUDE_VIDEOS) != 0) { 311666ea1b28a76aeba74744148b15099254d918671Owen Lin l.add(new VideoList(cr, VIDEO_STORAGE_URI, sort, bucketId)); 312666ea1b28a76aeba74744148b15099254d918671Owen Lin } 313666ea1b28a76aeba74744148b15099254d918671Owen Lin } 314666ea1b28a76aeba74744148b15099254d918671Owen Lin if (location == DataLocation.INTERNAL || location == DataLocation.ALL) { 315666ea1b28a76aeba74744148b15099254d918671Owen Lin if ((inclusion & INCLUDE_IMAGES) != 0) { 316666ea1b28a76aeba74744148b15099254d918671Owen Lin l.add(new ImageList(cr, 317b62254a185d04ecfe2ddc837b7e0e54f0273c478Owen Lin Images.Media.INTERNAL_CONTENT_URI, sort, bucketId)); 318666ea1b28a76aeba74744148b15099254d918671Owen Lin } 319666ea1b28a76aeba74744148b15099254d918671Owen Lin if ((inclusion & INCLUDE_DRM_IMAGES) != 0) { 320666ea1b28a76aeba74744148b15099254d918671Owen Lin l.add(new DrmImageList( 321666ea1b28a76aeba74744148b15099254d918671Owen Lin cr, DrmStore.Images.CONTENT_URI, sort, bucketId)); 322666ea1b28a76aeba74744148b15099254d918671Owen Lin } 323666ea1b28a76aeba74744148b15099254d918671Owen Lin } 324666ea1b28a76aeba74744148b15099254d918671Owen Lin 325666ea1b28a76aeba74744148b15099254d918671Owen Lin // Optimization: If some of the lists are empty, remove them. 326666ea1b28a76aeba74744148b15099254d918671Owen Lin // If there is only one remaining list, return it directly. 327666ea1b28a76aeba74744148b15099254d918671Owen Lin Iterator<BaseImageList> iter = l.iterator(); 328666ea1b28a76aeba74744148b15099254d918671Owen Lin while (iter.hasNext()) { 329666ea1b28a76aeba74744148b15099254d918671Owen Lin BaseImageList sublist = iter.next(); 330666ea1b28a76aeba74744148b15099254d918671Owen Lin if (sublist.isEmpty()) { 331666ea1b28a76aeba74744148b15099254d918671Owen Lin sublist.close(); 332666ea1b28a76aeba74744148b15099254d918671Owen Lin iter.remove(); 333666ea1b28a76aeba74744148b15099254d918671Owen Lin } 334666ea1b28a76aeba74744148b15099254d918671Owen Lin } 335666ea1b28a76aeba74744148b15099254d918671Owen Lin 336666ea1b28a76aeba74744148b15099254d918671Owen Lin if (l.size() == 1) { 337666ea1b28a76aeba74744148b15099254d918671Owen Lin BaseImageList list = l.get(0); 338666ea1b28a76aeba74744148b15099254d918671Owen Lin return list; 339666ea1b28a76aeba74744148b15099254d918671Owen Lin } 340666ea1b28a76aeba74744148b15099254d918671Owen Lin 341666ea1b28a76aeba74744148b15099254d918671Owen Lin ImageListUber uber = new ImageListUber( 342666ea1b28a76aeba74744148b15099254d918671Owen Lin l.toArray(new IImageList[l.size()]), sort); 343666ea1b28a76aeba74744148b15099254d918671Owen Lin return uber; 344666ea1b28a76aeba74744148b15099254d918671Owen Lin } 345666ea1b28a76aeba74744148b15099254d918671Owen Lin 346666ea1b28a76aeba74744148b15099254d918671Owen Lin // This is a convenience function to create an image list from a Uri. 347666ea1b28a76aeba74744148b15099254d918671Owen Lin public static IImageList makeImageList(ContentResolver cr, Uri uri, 348666ea1b28a76aeba74744148b15099254d918671Owen Lin int sort) { 349666ea1b28a76aeba74744148b15099254d918671Owen Lin String uriString = (uri != null) ? uri.toString() : ""; 350666ea1b28a76aeba74744148b15099254d918671Owen Lin 351666ea1b28a76aeba74744148b15099254d918671Owen Lin // TODO: we need to figure out whether we're viewing 352666ea1b28a76aeba74744148b15099254d918671Owen Lin // DRM images in a better way. Is there a constant 353666ea1b28a76aeba74744148b15099254d918671Owen Lin // for content://drm somewhere?? 354666ea1b28a76aeba74744148b15099254d918671Owen Lin 355666ea1b28a76aeba74744148b15099254d918671Owen Lin if (uriString.startsWith("content://drm")) { 356666ea1b28a76aeba74744148b15099254d918671Owen Lin return makeImageList(cr, DataLocation.ALL, INCLUDE_DRM_IMAGES, sort, 357666ea1b28a76aeba74744148b15099254d918671Owen Lin null); 358666ea1b28a76aeba74744148b15099254d918671Owen Lin } else if (uriString.startsWith("content://media/external/video")) { 359666ea1b28a76aeba74744148b15099254d918671Owen Lin return makeImageList(cr, DataLocation.EXTERNAL, INCLUDE_VIDEOS, 360666ea1b28a76aeba74744148b15099254d918671Owen Lin sort, null); 361666ea1b28a76aeba74744148b15099254d918671Owen Lin } else if (isSingleImageMode(uriString)) { 362666ea1b28a76aeba74744148b15099254d918671Owen Lin return makeSingleImageList(cr, uri); 363666ea1b28a76aeba74744148b15099254d918671Owen Lin } else { 364666ea1b28a76aeba74744148b15099254d918671Owen Lin String bucketId = uri.getQueryParameter("bucketId"); 365666ea1b28a76aeba74744148b15099254d918671Owen Lin return makeImageList(cr, DataLocation.ALL, INCLUDE_IMAGES, sort, 366666ea1b28a76aeba74744148b15099254d918671Owen Lin bucketId); 367666ea1b28a76aeba74744148b15099254d918671Owen Lin } 368666ea1b28a76aeba74744148b15099254d918671Owen Lin } 369666ea1b28a76aeba74744148b15099254d918671Owen Lin 370666ea1b28a76aeba74744148b15099254d918671Owen Lin static boolean isSingleImageMode(String uriString) { 371666ea1b28a76aeba74744148b15099254d918671Owen Lin return !uriString.startsWith( 372666ea1b28a76aeba74744148b15099254d918671Owen Lin MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString()) 373666ea1b28a76aeba74744148b15099254d918671Owen Lin && !uriString.startsWith( 374666ea1b28a76aeba74744148b15099254d918671Owen Lin MediaStore.Images.Media.INTERNAL_CONTENT_URI.toString()); 375666ea1b28a76aeba74744148b15099254d918671Owen Lin } 376666ea1b28a76aeba74744148b15099254d918671Owen Lin 377666ea1b28a76aeba74744148b15099254d918671Owen Lin private static class EmptyImageList implements IImageList { 378666ea1b28a76aeba74744148b15099254d918671Owen Lin public void close() { 379666ea1b28a76aeba74744148b15099254d918671Owen Lin } 380666ea1b28a76aeba74744148b15099254d918671Owen Lin 381666ea1b28a76aeba74744148b15099254d918671Owen Lin public HashMap<String, String> getBucketIds() { 382666ea1b28a76aeba74744148b15099254d918671Owen Lin return new HashMap<String, String>(); 383666ea1b28a76aeba74744148b15099254d918671Owen Lin } 384666ea1b28a76aeba74744148b15099254d918671Owen Lin 385666ea1b28a76aeba74744148b15099254d918671Owen Lin public int getCount() { 386666ea1b28a76aeba74744148b15099254d918671Owen Lin return 0; 387666ea1b28a76aeba74744148b15099254d918671Owen Lin } 388666ea1b28a76aeba74744148b15099254d918671Owen Lin 389666ea1b28a76aeba74744148b15099254d918671Owen Lin public boolean isEmpty() { 390666ea1b28a76aeba74744148b15099254d918671Owen Lin return true; 391666ea1b28a76aeba74744148b15099254d918671Owen Lin } 392666ea1b28a76aeba74744148b15099254d918671Owen Lin 393666ea1b28a76aeba74744148b15099254d918671Owen Lin public IImage getImageAt(int i) { 394666ea1b28a76aeba74744148b15099254d918671Owen Lin return null; 395666ea1b28a76aeba74744148b15099254d918671Owen Lin } 396666ea1b28a76aeba74744148b15099254d918671Owen Lin 397666ea1b28a76aeba74744148b15099254d918671Owen Lin public IImage getImageForUri(Uri uri) { 398666ea1b28a76aeba74744148b15099254d918671Owen Lin return null; 399666ea1b28a76aeba74744148b15099254d918671Owen Lin } 400666ea1b28a76aeba74744148b15099254d918671Owen Lin 401666ea1b28a76aeba74744148b15099254d918671Owen Lin public boolean removeImage(IImage image) { 402666ea1b28a76aeba74744148b15099254d918671Owen Lin return false; 403666ea1b28a76aeba74744148b15099254d918671Owen Lin } 404666ea1b28a76aeba74744148b15099254d918671Owen Lin 405666ea1b28a76aeba74744148b15099254d918671Owen Lin public boolean removeImageAt(int i) { 406666ea1b28a76aeba74744148b15099254d918671Owen Lin return false; 407666ea1b28a76aeba74744148b15099254d918671Owen Lin } 408666ea1b28a76aeba74744148b15099254d918671Owen Lin 409666ea1b28a76aeba74744148b15099254d918671Owen Lin public int getImageIndex(IImage image) { 410666ea1b28a76aeba74744148b15099254d918671Owen Lin throw new UnsupportedOperationException(); 411666ea1b28a76aeba74744148b15099254d918671Owen Lin } 412666ea1b28a76aeba74744148b15099254d918671Owen Lin } 413666ea1b28a76aeba74744148b15099254d918671Owen Lin 414666ea1b28a76aeba74744148b15099254d918671Owen Lin public static ImageListParam getImageListParam(DataLocation location, 415666ea1b28a76aeba74744148b15099254d918671Owen Lin int inclusion, int sort, String bucketId) { 416666ea1b28a76aeba74744148b15099254d918671Owen Lin ImageListParam param = new ImageListParam(); 417666ea1b28a76aeba74744148b15099254d918671Owen Lin param.mLocation = location; 418666ea1b28a76aeba74744148b15099254d918671Owen Lin param.mInclusion = inclusion; 419666ea1b28a76aeba74744148b15099254d918671Owen Lin param.mSort = sort; 420666ea1b28a76aeba74744148b15099254d918671Owen Lin param.mBucketId = bucketId; 421666ea1b28a76aeba74744148b15099254d918671Owen Lin return param; 422666ea1b28a76aeba74744148b15099254d918671Owen Lin } 423666ea1b28a76aeba74744148b15099254d918671Owen Lin 424666ea1b28a76aeba74744148b15099254d918671Owen Lin public static ImageListParam getSingleImageListParam(Uri uri) { 425666ea1b28a76aeba74744148b15099254d918671Owen Lin ImageListParam param = new ImageListParam(); 426666ea1b28a76aeba74744148b15099254d918671Owen Lin param.mSingleImageUri = uri; 427666ea1b28a76aeba74744148b15099254d918671Owen Lin return param; 428666ea1b28a76aeba74744148b15099254d918671Owen Lin } 429666ea1b28a76aeba74744148b15099254d918671Owen Lin 430666ea1b28a76aeba74744148b15099254d918671Owen Lin public static ImageListParam getEmptyImageListParam() { 431666ea1b28a76aeba74744148b15099254d918671Owen Lin ImageListParam param = new ImageListParam(); 432666ea1b28a76aeba74744148b15099254d918671Owen Lin param.mIsEmptyImageList = true; 433666ea1b28a76aeba74744148b15099254d918671Owen Lin return param; 434666ea1b28a76aeba74744148b15099254d918671Owen Lin } 435666ea1b28a76aeba74744148b15099254d918671Owen Lin 436666ea1b28a76aeba74744148b15099254d918671Owen Lin public static IImageList makeImageList(ContentResolver cr, 437666ea1b28a76aeba74744148b15099254d918671Owen Lin DataLocation location, int inclusion, int sort, String bucketId) { 438666ea1b28a76aeba74744148b15099254d918671Owen Lin ImageListParam param = getImageListParam(location, inclusion, sort, 439666ea1b28a76aeba74744148b15099254d918671Owen Lin bucketId); 440666ea1b28a76aeba74744148b15099254d918671Owen Lin return makeImageList(cr, param); 441666ea1b28a76aeba74744148b15099254d918671Owen Lin } 442666ea1b28a76aeba74744148b15099254d918671Owen Lin 443666ea1b28a76aeba74744148b15099254d918671Owen Lin public static IImageList makeEmptyImageList() { 444666ea1b28a76aeba74744148b15099254d918671Owen Lin return makeImageList(null, getEmptyImageListParam()); 445666ea1b28a76aeba74744148b15099254d918671Owen Lin } 446666ea1b28a76aeba74744148b15099254d918671Owen Lin 447666ea1b28a76aeba74744148b15099254d918671Owen Lin public static IImageList makeSingleImageList(ContentResolver cr, Uri uri) { 448666ea1b28a76aeba74744148b15099254d918671Owen Lin return makeImageList(cr, getSingleImageListParam(uri)); 449666ea1b28a76aeba74744148b15099254d918671Owen Lin } 450666ea1b28a76aeba74744148b15099254d918671Owen Lin 451666ea1b28a76aeba74744148b15099254d918671Owen Lin private static boolean checkFsWritable() { 452666ea1b28a76aeba74744148b15099254d918671Owen Lin // Create a temporary file to see whether a volume is really writeable. 453666ea1b28a76aeba74744148b15099254d918671Owen Lin // It's important not to put it in the root directory which may have a 454666ea1b28a76aeba74744148b15099254d918671Owen Lin // limit on the number of files. 455666ea1b28a76aeba74744148b15099254d918671Owen Lin String directoryName = 456666ea1b28a76aeba74744148b15099254d918671Owen Lin Environment.getExternalStorageDirectory().toString() + "/DCIM"; 457666ea1b28a76aeba74744148b15099254d918671Owen Lin File directory = new File(directoryName); 458666ea1b28a76aeba74744148b15099254d918671Owen Lin if (!directory.isDirectory()) { 459666ea1b28a76aeba74744148b15099254d918671Owen Lin if (!directory.mkdirs()) { 460666ea1b28a76aeba74744148b15099254d918671Owen Lin return false; 461666ea1b28a76aeba74744148b15099254d918671Owen Lin } 462666ea1b28a76aeba74744148b15099254d918671Owen Lin } 463666ea1b28a76aeba74744148b15099254d918671Owen Lin File f = new File(directoryName, ".probe"); 464666ea1b28a76aeba74744148b15099254d918671Owen Lin try { 465666ea1b28a76aeba74744148b15099254d918671Owen Lin // Remove stale file if any 466666ea1b28a76aeba74744148b15099254d918671Owen Lin if (f.exists()) { 467666ea1b28a76aeba74744148b15099254d918671Owen Lin f.delete(); 468666ea1b28a76aeba74744148b15099254d918671Owen Lin } 469666ea1b28a76aeba74744148b15099254d918671Owen Lin if (!f.createNewFile()) { 470666ea1b28a76aeba74744148b15099254d918671Owen Lin return false; 471666ea1b28a76aeba74744148b15099254d918671Owen Lin } 472666ea1b28a76aeba74744148b15099254d918671Owen Lin f.delete(); 473666ea1b28a76aeba74744148b15099254d918671Owen Lin return true; 474666ea1b28a76aeba74744148b15099254d918671Owen Lin } catch (IOException ex) { 475666ea1b28a76aeba74744148b15099254d918671Owen Lin return false; 476666ea1b28a76aeba74744148b15099254d918671Owen Lin } 477666ea1b28a76aeba74744148b15099254d918671Owen Lin } 478666ea1b28a76aeba74744148b15099254d918671Owen Lin 479666ea1b28a76aeba74744148b15099254d918671Owen Lin public static boolean hasStorage() { 480666ea1b28a76aeba74744148b15099254d918671Owen Lin return hasStorage(true); 481666ea1b28a76aeba74744148b15099254d918671Owen Lin } 482666ea1b28a76aeba74744148b15099254d918671Owen Lin 483666ea1b28a76aeba74744148b15099254d918671Owen Lin public static boolean hasStorage(boolean requireWriteAccess) { 484666ea1b28a76aeba74744148b15099254d918671Owen Lin String state = Environment.getExternalStorageState(); 485666ea1b28a76aeba74744148b15099254d918671Owen Lin 486666ea1b28a76aeba74744148b15099254d918671Owen Lin if (Environment.MEDIA_MOUNTED.equals(state)) { 487666ea1b28a76aeba74744148b15099254d918671Owen Lin if (requireWriteAccess) { 488666ea1b28a76aeba74744148b15099254d918671Owen Lin boolean writable = checkFsWritable(); 489666ea1b28a76aeba74744148b15099254d918671Owen Lin return writable; 490666ea1b28a76aeba74744148b15099254d918671Owen Lin } else { 491666ea1b28a76aeba74744148b15099254d918671Owen Lin return true; 492666ea1b28a76aeba74744148b15099254d918671Owen Lin } 493666ea1b28a76aeba74744148b15099254d918671Owen Lin } else if (!requireWriteAccess 494666ea1b28a76aeba74744148b15099254d918671Owen Lin && Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { 495666ea1b28a76aeba74744148b15099254d918671Owen Lin return true; 496666ea1b28a76aeba74744148b15099254d918671Owen Lin } 497666ea1b28a76aeba74744148b15099254d918671Owen Lin return false; 498666ea1b28a76aeba74744148b15099254d918671Owen Lin } 499666ea1b28a76aeba74744148b15099254d918671Owen Lin 500666ea1b28a76aeba74744148b15099254d918671Owen Lin private static Cursor query(ContentResolver resolver, Uri uri, 501666ea1b28a76aeba74744148b15099254d918671Owen Lin String[] projection, String selection, String[] selectionArgs, 502666ea1b28a76aeba74744148b15099254d918671Owen Lin String sortOrder) { 503666ea1b28a76aeba74744148b15099254d918671Owen Lin try { 504666ea1b28a76aeba74744148b15099254d918671Owen Lin if (resolver == null) { 505666ea1b28a76aeba74744148b15099254d918671Owen Lin return null; 506666ea1b28a76aeba74744148b15099254d918671Owen Lin } 507666ea1b28a76aeba74744148b15099254d918671Owen Lin return resolver.query( 508666ea1b28a76aeba74744148b15099254d918671Owen Lin uri, projection, selection, selectionArgs, sortOrder); 509666ea1b28a76aeba74744148b15099254d918671Owen Lin } catch (UnsupportedOperationException ex) { 510666ea1b28a76aeba74744148b15099254d918671Owen Lin return null; 511666ea1b28a76aeba74744148b15099254d918671Owen Lin } 512666ea1b28a76aeba74744148b15099254d918671Owen Lin 513666ea1b28a76aeba74744148b15099254d918671Owen Lin } 514666ea1b28a76aeba74744148b15099254d918671Owen Lin 515666ea1b28a76aeba74744148b15099254d918671Owen Lin public static boolean isMediaScannerScanning(ContentResolver cr) { 516666ea1b28a76aeba74744148b15099254d918671Owen Lin boolean result = false; 517666ea1b28a76aeba74744148b15099254d918671Owen Lin Cursor cursor = query(cr, MediaStore.getMediaScannerUri(), 518666ea1b28a76aeba74744148b15099254d918671Owen Lin new String [] {MediaStore.MEDIA_SCANNER_VOLUME}, 519666ea1b28a76aeba74744148b15099254d918671Owen Lin null, null, null); 520666ea1b28a76aeba74744148b15099254d918671Owen Lin if (cursor != null) { 521666ea1b28a76aeba74744148b15099254d918671Owen Lin if (cursor.getCount() == 1) { 522666ea1b28a76aeba74744148b15099254d918671Owen Lin cursor.moveToFirst(); 523666ea1b28a76aeba74744148b15099254d918671Owen Lin result = "external".equals(cursor.getString(0)); 524666ea1b28a76aeba74744148b15099254d918671Owen Lin } 525666ea1b28a76aeba74744148b15099254d918671Owen Lin cursor.close(); 526666ea1b28a76aeba74744148b15099254d918671Owen Lin } 527666ea1b28a76aeba74744148b15099254d918671Owen Lin 528666ea1b28a76aeba74744148b15099254d918671Owen Lin return result; 529666ea1b28a76aeba74744148b15099254d918671Owen Lin } 530666ea1b28a76aeba74744148b15099254d918671Owen Lin} 531