1bd26069d391830856c57c2141cd2efbc8423d871Angus Kong/* 2bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * Copyright (C) 2013 The Android Open Source Project 3bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * 4bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * Licensed under the Apache License, Version 2.0 (the "License"); 5bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * you may not use this file except in compliance with the License. 6bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * You may obtain a copy of the License at 7bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * 8bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * http://www.apache.org/licenses/LICENSE-2.0 9bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * 10bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * Unless required by applicable law or agreed to in writing, software 11bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * distributed under the License is distributed on an "AS IS" BASIS, 12bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * See the License for the specific language governing permissions and 14bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * limitations under the License. 15bd26069d391830856c57c2141cd2efbc8423d871Angus Kong */ 16bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 17bd26069d391830856c57c2141cd2efbc8423d871Angus Kongpackage com.android.camera.data; 18bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 19b7639c641f2ed5d0c60546349c3aa9e90c026878Sascha Haeberlingimport android.app.Activity; 20bd26069d391830856c57c2141cd2efbc8423d871Angus Kongimport android.content.ContentResolver; 21bd26069d391830856c57c2141cd2efbc8423d871Angus Kongimport android.content.Context; 22bd26069d391830856c57c2141cd2efbc8423d871Angus Kongimport android.database.Cursor; 23bd26069d391830856c57c2141cd2efbc8423d871Angus Kongimport android.graphics.Bitmap; 24bd26069d391830856c57c2141cd2efbc8423d871Angus Kongimport android.graphics.BitmapFactory; 25de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Juddimport android.media.CamcorderProfile; 26bd26069d391830856c57c2141cd2efbc8423d871Angus Kongimport android.net.Uri; 278a2350a3d557465b53445685db0f9ac838cf90c5Angus Kongimport android.os.Bundle; 28bd26069d391830856c57c2141cd2efbc8423d871Angus Kongimport android.provider.MediaStore; 2943bf03f6e7f9a71b7553e7282b5799798997caf7Sam Juddimport android.view.LayoutInflater; 30bd26069d391830856c57c2141cd2efbc8423d871Angus Kongimport android.view.View; 31bd26069d391830856c57c2141cd2efbc8423d871Angus Kongimport android.widget.ImageView; 32af79e4288559ddbee4ba6ed3cb3d1d9657fc23eaAlan Newberger 33aeed91f3777d08a4160d68ddfc2626808a08b92dSam Juddimport com.android.camera.Storage; 342bca210e5fc8a77685775ffb403096167b017dceAngus Kongimport com.android.camera.debug.Log; 356f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberlingimport com.android.camera.util.CameraUtil; 36bd26069d391830856c57c2141cd2efbc8423d871Angus Kongimport com.android.camera2.R; 37af79e4288559ddbee4ba6ed3cb3d1d9657fc23eaAlan Newbergerimport com.bumptech.glide.BitmapRequestBuilder; 384021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Juddimport com.bumptech.glide.Glide; 39af79e4288559ddbee4ba6ed3cb3d1d9657fc23eaAlan Newbergerimport com.bumptech.glide.load.resource.bitmap.BitmapEncoder; 40bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 41bd26069d391830856c57c2141cd2efbc8423d871Angus Kongimport java.io.File; 426f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberlingimport java.text.DateFormat; 43aeed91f3777d08a4160d68ddfc2626808a08b92dSam Juddimport java.util.ArrayList; 44bd26069d391830856c57c2141cd2efbc8423d871Angus Kongimport java.util.Date; 45aeed91f3777d08a4160d68ddfc2626808a08b92dSam Juddimport java.util.List; 46e2fb9943fb2d5a51a651f138d88473bf7f62e0b9Sascha Haeberlingimport java.util.Locale; 47bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 48bd26069d391830856c57c2141cd2efbc8423d871Angus Kong/** 49bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * A base class for all the local media files. The bitmap is loaded in 50b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling * background thread. Subclasses should implement their own background loading 51b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling * thread by sub-classing BitmapLoadTask and overriding doInBackground() to 52b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling * return a bitmap. 53bd26069d391830856c57c2141cd2efbc8423d871Angus Kong */ 54bd26069d391830856c57c2141cd2efbc8423d871Angus Kongpublic abstract class LocalMediaData implements LocalData { 55aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd /** The minimum id to use to query for all media at a given media store uri */ 56aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd static final int QUERY_ALL_MEDIA_ID = -1; 57aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd private static final String CAMERA_PATH = Storage.DIRECTORY + "%"; 58aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd private static final String SELECT_BY_PATH = MediaStore.MediaColumns.DATA + " LIKE ?"; 59632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd private static final int MEDIASTORE_THUMB_WIDTH = 512; 60632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd private static final int MEDIASTORE_THUMB_HEIGHT = 384; 61aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd 623250987bd014d1c5463b8a39bbe988165ab1cc3fAngus Kong protected final long mContentId; 63a16e7b50f3148f581439509279f242092e254309ztenghui protected final String mTitle; 64a16e7b50f3148f581439509279f242092e254309ztenghui protected final String mMimeType; 65b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers protected final long mDateTakenInMilliSeconds; 66a16e7b50f3148f581439509279f242092e254309ztenghui protected final long mDateModifiedInSeconds; 67a16e7b50f3148f581439509279f242092e254309ztenghui protected final String mPath; 68bd26069d391830856c57c2141cd2efbc8423d871Angus Kong // width and height should be adjusted according to orientation. 69a16e7b50f3148f581439509279f242092e254309ztenghui protected final int mWidth; 70a16e7b50f3148f581439509279f242092e254309ztenghui protected final int mHeight; 71a16e7b50f3148f581439509279f242092e254309ztenghui protected final long mSizeInBytes; 72a16e7b50f3148f581439509279f242092e254309ztenghui protected final double mLatitude; 73a16e7b50f3148f581439509279f242092e254309ztenghui protected final double mLongitude; 748a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong protected final Bundle mMetaData; 75bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 7665ab02000f65a8677adf9fab5c296e0d3ef64cbcAlan Newberger private static final int JPEG_COMPRESS_QUALITY = 90; 7765ab02000f65a8677adf9fab5c296e0d3ef64cbcAlan Newberger private static final BitmapEncoder JPEG_ENCODER = 7865ab02000f65a8677adf9fab5c296e0d3ef64cbcAlan Newberger new BitmapEncoder(Bitmap.CompressFormat.JPEG, JPEG_COMPRESS_QUALITY); 7965ab02000f65a8677adf9fab5c296e0d3ef64cbcAlan Newberger 80c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong /** 81b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling * Used for thumbnail loading optimization. True if this data has a 82b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling * corresponding visible view. 83c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong */ 84bd26069d391830856c57c2141cd2efbc8423d871Angus Kong protected Boolean mUsing = false; 85bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 86280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling public LocalMediaData(long contentId, String title, String mimeType, 87b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers long dateTakenInMilliSeconds, long dateModifiedInSeconds, String path, 88a16e7b50f3148f581439509279f242092e254309ztenghui int width, int height, long sizeInBytes, double latitude, 89a16e7b50f3148f581439509279f242092e254309ztenghui double longitude) { 903250987bd014d1c5463b8a39bbe988165ab1cc3fAngus Kong mContentId = contentId; 9143bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd mTitle = title; 9243bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd mMimeType = mimeType; 93b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers mDateTakenInMilliSeconds = dateTakenInMilliSeconds; 94a16e7b50f3148f581439509279f242092e254309ztenghui mDateModifiedInSeconds = dateModifiedInSeconds; 9543bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd mPath = path; 96a16e7b50f3148f581439509279f242092e254309ztenghui mWidth = width; 97a16e7b50f3148f581439509279f242092e254309ztenghui mHeight = height; 98a16e7b50f3148f581439509279f242092e254309ztenghui mSizeInBytes = sizeInBytes; 99a16e7b50f3148f581439509279f242092e254309ztenghui mLatitude = latitude; 100a16e7b50f3148f581439509279f242092e254309ztenghui mLongitude = longitude; 1018a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong mMetaData = new Bundle(); 102a16e7b50f3148f581439509279f242092e254309ztenghui } 103a16e7b50f3148f581439509279f242092e254309ztenghui 104aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd private interface CursorToLocalData { 105aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd public LocalData build(Cursor cursor); 106aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd } 107aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd 108aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd private static List<LocalData> queryLocalMediaData(ContentResolver contentResolver, 109aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd Uri contentUri, String[] projection, long minimumId, String orderBy, 110aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd CursorToLocalData builder) { 111aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd String selection = SELECT_BY_PATH + " AND " + MediaStore.MediaColumns._ID + " > ?"; 112aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd String[] selectionArgs = new String[] { CAMERA_PATH, Long.toString(minimumId) }; 113aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd 114aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd Cursor cursor = contentResolver.query(contentUri, projection, 115aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd selection, selectionArgs, orderBy); 116aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd List<LocalData> result = new ArrayList<LocalData>(); 117aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd if (cursor != null) { 118aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd while (cursor.moveToNext()) { 119aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd LocalData data = builder.build(cursor); 120aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd if (data != null) { 121aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd result.add(data); 122aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd } else { 123aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd final int dataIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA); 1242bca210e5fc8a77685775ffb403096167b017dceAngus Kong Log.e(TAG, "Error loading data:" + cursor.getString(dataIndex)); 125aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd } 126aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd } 127de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd 128de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd cursor.close(); 129aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd } 130aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd return result; 131aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd } 132aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd 133bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 134bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public long getDateTaken() { 135b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers return mDateTakenInMilliSeconds; 136bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 137bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 138bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 139bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public long getDateModified() { 140a16e7b50f3148f581439509279f242092e254309ztenghui return mDateModifiedInSeconds; 141a16e7b50f3148f581439509279f242092e254309ztenghui } 142a16e7b50f3148f581439509279f242092e254309ztenghui 143a16e7b50f3148f581439509279f242092e254309ztenghui @Override 1443250987bd014d1c5463b8a39bbe988165ab1cc3fAngus Kong public long getContentId() { 1453250987bd014d1c5463b8a39bbe988165ab1cc3fAngus Kong return mContentId; 146bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 147bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 148bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 149bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public String getTitle() { 1504021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd return mTitle; 151bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 152bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 153bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 154bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public int getWidth() { 155a16e7b50f3148f581439509279f242092e254309ztenghui return mWidth; 156bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 157bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 158bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 159bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public int getHeight() { 160a16e7b50f3148f581439509279f242092e254309ztenghui return mHeight; 161bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 162bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 163bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 164c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong public int getRotation() { 16587fc5e1568f737e03327770cb3dee03c4b939c59Doris Liu return 0; 16687fc5e1568f737e03327770cb3dee03c4b939c59Doris Liu } 16787fc5e1568f737e03327770cb3dee03c4b939c59Doris Liu 16887fc5e1568f737e03327770cb3dee03c4b939c59Doris Liu @Override 169bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public String getPath() { 170a16e7b50f3148f581439509279f242092e254309ztenghui return mPath; 171a16e7b50f3148f581439509279f242092e254309ztenghui } 172a16e7b50f3148f581439509279f242092e254309ztenghui 173a16e7b50f3148f581439509279f242092e254309ztenghui @Override 174a16e7b50f3148f581439509279f242092e254309ztenghui public long getSizeInBytes() { 175a16e7b50f3148f581439509279f242092e254309ztenghui return mSizeInBytes; 176bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 177bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 178bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 179bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public boolean isUIActionSupported(int action) { 180bd26069d391830856c57c2141cd2efbc8423d871Angus Kong return false; 181bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 182bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 183bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 184bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public boolean isDataActionSupported(int action) { 185bd26069d391830856c57c2141cd2efbc8423d871Angus Kong return false; 186bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 187bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 188bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 1898a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong public boolean delete(Context context) { 190a16e7b50f3148f581439509279f242092e254309ztenghui File f = new File(mPath); 191bd26069d391830856c57c2141cd2efbc8423d871Angus Kong return f.delete(); 192bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 193bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 194bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 195bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public void onFullScreen(boolean fullScreen) { 196bd26069d391830856c57c2141cd2efbc8423d871Angus Kong // do nothing. 197bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 198bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 199bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 200bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public boolean canSwipeInFullScreen() { 201bd26069d391830856c57c2141cd2efbc8423d871Angus Kong return true; 202bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 203bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 2048a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong protected ImageView fillImageView(Context context, ImageView v, 205632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd int thumbWidth, int thumbHeight, int placeHolderResourceId, 20614ff6c8df2924ccad083591c0fc873322c6828c0Sascha Haeberling LocalDataAdapter adapter, boolean isInProgress) { 2074021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd Glide.with(context) 208632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .loadFromMediaStore(getUri(), mMimeType, mDateModifiedInSeconds, 0) 209632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .fitCenter() 210632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .placeholder(placeHolderResourceId) 211632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .into(v); 212bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 2131cfa3dd77d3828985d37beffbfad9388af054757Alan Newberger v.setContentDescription(context.getResources().getString( 2141cfa3dd77d3828985d37beffbfad9388af054757Alan Newberger R.string.media_date_content_description, 2151cfa3dd77d3828985d37beffbfad9388af054757Alan Newberger getReadableDate(mDateModifiedInSeconds))); 216a293597032795e3f245e9f0d5b20701375904e04Alan Newberger 217bd26069d391830856c57c2141cd2efbc8423d871Angus Kong return v; 218bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 219bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 220bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 221632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd public View getView(Context context, View recycled, int thumbWidth, int thumbHeight, 2224021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd int placeHolderResourceId, LocalDataAdapter adapter, boolean isInProgress) { 22343bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd final ImageView imageView; 22443bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd if (recycled != null) { 22543bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd imageView = (ImageView) recycled; 22643bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd } else { 227919bea1a10464f23aeb090a254ff36169d012e9aSpike Sprague imageView = (ImageView) LayoutInflater.from(context) 228919bea1a10464f23aeb090a254ff36169d012e9aSpike Sprague .inflate(R.layout.filmstrip_image, null); 229a93ba0dbd8e4000f3643567809a4a3fac554fd3cSpike Sprague imageView.setTag(R.id.mediadata_tag_viewtype, getItemViewType().ordinal()); 23043bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd } 23143bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd 232632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd return fillImageView(context, imageView, thumbWidth, thumbHeight, 2334021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd placeHolderResourceId, adapter, isInProgress); 234bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 235bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 236bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 237632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd public void loadFullImage(Context context, int thumbWidth, int thumbHeight, View view, 2384021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd LocalDataAdapter adapter) { 239caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers // Default is do nothing. 240caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers // Can be implemented by sub-classes. 241caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers } 242caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers 243caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers @Override 244bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public void prepare() { 245bd26069d391830856c57c2141cd2efbc8423d871Angus Kong synchronized (mUsing) { 246bd26069d391830856c57c2141cd2efbc8423d871Angus Kong mUsing = true; 247bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 248bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 249bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 250bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 2514021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd public void recycle(View view) { 252bd26069d391830856c57c2141cd2efbc8423d871Angus Kong synchronized (mUsing) { 253bd26069d391830856c57c2141cd2efbc8423d871Angus Kong mUsing = false; 254bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 255bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 256bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 257fae11a165e344a38811770c7d348eda214683edcSascha Haeberling @Override 258fae11a165e344a38811770c7d348eda214683edcSascha Haeberling public double[] getLatLong() { 259a16e7b50f3148f581439509279f242092e254309ztenghui if (mLatitude == 0 && mLongitude == 0) { 260fae11a165e344a38811770c7d348eda214683edcSascha Haeberling return null; 261fae11a165e344a38811770c7d348eda214683edcSascha Haeberling } 262fae11a165e344a38811770c7d348eda214683edcSascha Haeberling return new double[] { 263a16e7b50f3148f581439509279f242092e254309ztenghui mLatitude, mLongitude 264fae11a165e344a38811770c7d348eda214683edcSascha Haeberling }; 265fae11a165e344a38811770c7d348eda214683edcSascha Haeberling } 266fae11a165e344a38811770c7d348eda214683edcSascha Haeberling 267bd26069d391830856c57c2141cd2efbc8423d871Angus Kong protected boolean isUsing() { 268bd26069d391830856c57c2141cd2efbc8423d871Angus Kong synchronized (mUsing) { 269bd26069d391830856c57c2141cd2efbc8423d871Angus Kong return mUsing; 270bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 271bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 272bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 273bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 27488ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling public String getMimeType() { 275a16e7b50f3148f581439509279f242092e254309ztenghui return mMimeType; 27688ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling } 27788ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling 27888ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling @Override 279b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling public MediaDetails getMediaDetails(Context context) { 280b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaDetails mediaDetails = new MediaDetails(); 281a16e7b50f3148f581439509279f242092e254309ztenghui mediaDetails.addDetail(MediaDetails.INDEX_TITLE, mTitle); 282a16e7b50f3148f581439509279f242092e254309ztenghui mediaDetails.addDetail(MediaDetails.INDEX_WIDTH, mWidth); 283a16e7b50f3148f581439509279f242092e254309ztenghui mediaDetails.addDetail(MediaDetails.INDEX_HEIGHT, mHeight); 284a16e7b50f3148f581439509279f242092e254309ztenghui mediaDetails.addDetail(MediaDetails.INDEX_PATH, mPath); 285b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling mediaDetails.addDetail(MediaDetails.INDEX_DATETIME, 2861cfa3dd77d3828985d37beffbfad9388af054757Alan Newberger getReadableDate(mDateModifiedInSeconds)); 287a16e7b50f3148f581439509279f242092e254309ztenghui if (mSizeInBytes > 0) { 288a16e7b50f3148f581439509279f242092e254309ztenghui mediaDetails.addDetail(MediaDetails.INDEX_SIZE, mSizeInBytes); 289b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling } 290a16e7b50f3148f581439509279f242092e254309ztenghui if (mLatitude != 0 && mLongitude != 0) { 291a16e7b50f3148f581439509279f242092e254309ztenghui String locationString = String.format(Locale.getDefault(), "%f, %f", mLatitude, 292a16e7b50f3148f581439509279f242092e254309ztenghui mLongitude); 293e2fb9943fb2d5a51a651f138d88473bf7f62e0b9Sascha Haeberling mediaDetails.addDetail(MediaDetails.INDEX_LOCATION, locationString); 294b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling } 295b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling return mediaDetails; 296b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling } 297b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling 298ae5fa1499ab1d6d1d421228859d13ac45ad1d437Spike Sprague private static String getReadableDate(long dateInSeconds) { 2991cfa3dd77d3828985d37beffbfad9388af054757Alan Newberger DateFormat dateFormatter = DateFormat.getDateTimeInstance(); 3001cfa3dd77d3828985d37beffbfad9388af054757Alan Newberger return dateFormatter.format(new Date(dateInSeconds * 1000)); 3011cfa3dd77d3828985d37beffbfad9388af054757Alan Newberger } 3021cfa3dd77d3828985d37beffbfad9388af054757Alan Newberger 303b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling @Override 304c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong public abstract int getViewType(); 305bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 3068a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong @Override 3078a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong public Bundle getMetadata() { 3088a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong return mMetaData; 3098a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong } 3108a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong 31156102c6a83104cea1371114d77a57e1934f2c648Angus Kong @Override 31256102c6a83104cea1371114d77a57e1934f2c648Angus Kong public boolean isMetadataUpdated() { 313de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd return MetadataLoader.isMetadataCached(this); 31456102c6a83104cea1371114d77a57e1934f2c648Angus Kong } 31556102c6a83104cea1371114d77a57e1934f2c648Angus Kong 316a16e7b50f3148f581439509279f242092e254309ztenghui public static final class PhotoData extends LocalMediaData { 3172bca210e5fc8a77685775ffb403096167b017dceAngus Kong private static final Log.Tag TAG = new Log.Tag("PhotoData"); 318bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 319bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_ID = 0; 320bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_TITLE = 1; 321bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_MIME_TYPE = 2; 322bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_DATE_TAKEN = 3; 323bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_DATE_MODIFIED = 4; 324bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_DATA = 5; 325bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_ORIENTATION = 6; 326bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_WIDTH = 7; 327bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_HEIGHT = 8; 3286f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling public static final int COL_SIZE = 9; 329fae11a165e344a38811770c7d348eda214683edcSascha Haeberling public static final int COL_LATITUDE = 10; 330fae11a165e344a38811770c7d348eda214683edcSascha Haeberling public static final int COL_LONGITUDE = 11; 331bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 332caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers // GL max texture size: keep bitmaps below this value. 333caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers private static final int MAXIMUM_TEXTURE_SIZE = 2048; 334caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers 335bd26069d391830856c57c2141cd2efbc8423d871Angus Kong static final Uri CONTENT_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 336bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 337aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd private static final String QUERY_ORDER = MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC, " 338bd26069d391830856c57c2141cd2efbc8423d871Angus Kong + MediaStore.Images.ImageColumns._ID + " DESC"; 339bd26069d391830856c57c2141cd2efbc8423d871Angus Kong /** 340bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * These values should be kept in sync with column IDs (COL_*) above. 341bd26069d391830856c57c2141cd2efbc8423d871Angus Kong */ 342aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd private static final String[] QUERY_PROJECTION = { 343b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Images.ImageColumns._ID, // 0, int 344b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Images.ImageColumns.TITLE, // 1, string 345b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Images.ImageColumns.MIME_TYPE, // 2, string 346b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Images.ImageColumns.DATE_TAKEN, // 3, int 347b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Images.ImageColumns.DATE_MODIFIED, // 4, int 348b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Images.ImageColumns.DATA, // 5, string 349b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Images.ImageColumns.ORIENTATION, // 6, int, 0, 90, 180, 270 350b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Images.ImageColumns.WIDTH, // 7, int 351b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Images.ImageColumns.HEIGHT, // 8, int 352b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Images.ImageColumns.SIZE, // 9, long 353b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Images.ImageColumns.LATITUDE, // 10, double 354b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Images.ImageColumns.LONGITUDE // 11, double 355bd26069d391830856c57c2141cd2efbc8423d871Angus Kong }; 356bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 357e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong private static final int mSupportedUIActions = ACTION_DEMOTE | ACTION_PROMOTE | ACTION_ZOOM; 358bd26069d391830856c57c2141cd2efbc8423d871Angus Kong private static final int mSupportedDataActions = 359e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong DATA_ACTION_DELETE | DATA_ACTION_EDIT | DATA_ACTION_SHARE; 360bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 361bd26069d391830856c57c2141cd2efbc8423d871Angus Kong /** from MediaStore, can only be 0, 90, 180, 270 */ 362a16e7b50f3148f581439509279f242092e254309ztenghui private final int mOrientation; 3634021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd /** @see #getSignature() */ 3644021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd private final String mSignature; 365a16e7b50f3148f581439509279f242092e254309ztenghui 366571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong public static LocalData fromContentUri(ContentResolver cr, Uri contentUri) { 367571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong List<LocalData> newPhotos = query(cr, contentUri, QUERY_ALL_MEDIA_ID); 368571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong if (newPhotos.isEmpty()) { 369571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong return null; 370571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong } 371571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong return newPhotos.get(0); 372571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong } 373571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong 374a16e7b50f3148f581439509279f242092e254309ztenghui public PhotoData(long id, String title, String mimeType, 375b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers long dateTakenInMilliSeconds, long dateModifiedInSeconds, 376a16e7b50f3148f581439509279f242092e254309ztenghui String path, int orientation, int width, int height, 377a16e7b50f3148f581439509279f242092e254309ztenghui long sizeInBytes, double latitude, double longitude) { 378b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers super(id, title, mimeType, dateTakenInMilliSeconds, dateModifiedInSeconds, 379a16e7b50f3148f581439509279f242092e254309ztenghui path, width, height, sizeInBytes, latitude, longitude); 380a16e7b50f3148f581439509279f242092e254309ztenghui mOrientation = orientation; 3814021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd mSignature = mimeType + orientation + dateModifiedInSeconds; 382a16e7b50f3148f581439509279f242092e254309ztenghui } 383bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 384aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd static List<LocalData> query(ContentResolver cr, Uri uri, long lastId) { 385aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd return queryLocalMediaData(cr, uri, QUERY_PROJECTION, lastId, QUERY_ORDER, 386aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd new PhotoDataBuilder()); 387aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd } 388aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd 389aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd private static PhotoData buildFromCursor(Cursor c) { 390a16e7b50f3148f581439509279f242092e254309ztenghui long id = c.getLong(COL_ID); 391a16e7b50f3148f581439509279f242092e254309ztenghui String title = c.getString(COL_TITLE); 392a16e7b50f3148f581439509279f242092e254309ztenghui String mimeType = c.getString(COL_MIME_TYPE); 393b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers long dateTakenInMilliSeconds = c.getLong(COL_DATE_TAKEN); 394a16e7b50f3148f581439509279f242092e254309ztenghui long dateModifiedInSeconds = c.getLong(COL_DATE_MODIFIED); 395a16e7b50f3148f581439509279f242092e254309ztenghui String path = c.getString(COL_DATA); 396a16e7b50f3148f581439509279f242092e254309ztenghui int orientation = c.getInt(COL_ORIENTATION); 397a16e7b50f3148f581439509279f242092e254309ztenghui int width = c.getInt(COL_WIDTH); 398a16e7b50f3148f581439509279f242092e254309ztenghui int height = c.getInt(COL_HEIGHT); 399a16e7b50f3148f581439509279f242092e254309ztenghui if (width <= 0 || height <= 0) { 40062a622b22717b454d3de26bb3311536a27492b6eAngus Kong Log.w(TAG, "Zero dimension in ContentResolver for " 401a16e7b50f3148f581439509279f242092e254309ztenghui + path + ":" + width + "x" + height); 402bd26069d391830856c57c2141cd2efbc8423d871Angus Kong BitmapFactory.Options opts = new BitmapFactory.Options(); 403bd26069d391830856c57c2141cd2efbc8423d871Angus Kong opts.inJustDecodeBounds = true; 404a16e7b50f3148f581439509279f242092e254309ztenghui BitmapFactory.decodeFile(path, opts); 40562a622b22717b454d3de26bb3311536a27492b6eAngus Kong if (opts.outWidth > 0 && opts.outHeight > 0) { 406a16e7b50f3148f581439509279f242092e254309ztenghui width = opts.outWidth; 407a16e7b50f3148f581439509279f242092e254309ztenghui height = opts.outHeight; 408bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } else { 40962a622b22717b454d3de26bb3311536a27492b6eAngus Kong Log.w(TAG, "Dimension decode failed for " + path); 410a16e7b50f3148f581439509279f242092e254309ztenghui Bitmap b = BitmapFactory.decodeFile(path); 411bd26069d391830856c57c2141cd2efbc8423d871Angus Kong if (b == null) { 4123250987bd014d1c5463b8a39bbe988165ab1cc3fAngus Kong Log.w(TAG, "PhotoData skipped." 41362a622b22717b454d3de26bb3311536a27492b6eAngus Kong + " Decoding " + path + "failed."); 414bd26069d391830856c57c2141cd2efbc8423d871Angus Kong return null; 415bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 416a16e7b50f3148f581439509279f242092e254309ztenghui width = b.getWidth(); 417a16e7b50f3148f581439509279f242092e254309ztenghui height = b.getHeight(); 41862a622b22717b454d3de26bb3311536a27492b6eAngus Kong if (width == 0 || height == 0) { 41962a622b22717b454d3de26bb3311536a27492b6eAngus Kong Log.w(TAG, "PhotoData skipped. Bitmap size 0 for " + path); 42062a622b22717b454d3de26bb3311536a27492b6eAngus Kong return null; 42162a622b22717b454d3de26bb3311536a27492b6eAngus Kong } 422bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 423bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 42406578b59bf15c1ac35dbbffd979f40479b1cbda9ztenghui 425a16e7b50f3148f581439509279f242092e254309ztenghui long sizeInBytes = c.getLong(COL_SIZE); 426a16e7b50f3148f581439509279f242092e254309ztenghui double latitude = c.getDouble(COL_LATITUDE); 427a16e7b50f3148f581439509279f242092e254309ztenghui double longitude = c.getDouble(COL_LONGITUDE); 428b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers PhotoData result = new PhotoData(id, title, mimeType, dateTakenInMilliSeconds, 429a16e7b50f3148f581439509279f242092e254309ztenghui dateModifiedInSeconds, path, orientation, width, height, 430a16e7b50f3148f581439509279f242092e254309ztenghui sizeInBytes, latitude, longitude); 431a16e7b50f3148f581439509279f242092e254309ztenghui return result; 432a16e7b50f3148f581439509279f242092e254309ztenghui } 433a16e7b50f3148f581439509279f242092e254309ztenghui 43487fc5e1568f737e03327770cb3dee03c4b939c59Doris Liu @Override 435c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong public int getRotation() { 436a16e7b50f3148f581439509279f242092e254309ztenghui return mOrientation; 437bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 438bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 439bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 440bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public String toString() { 441a16e7b50f3148f581439509279f242092e254309ztenghui return "Photo:" + ",data=" + mPath + ",mimeType=" + mMimeType 442a16e7b50f3148f581439509279f242092e254309ztenghui + "," + mWidth + "x" + mHeight + ",orientation=" + mOrientation 443b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers + ",date=" + new Date(mDateTakenInMilliSeconds); 444bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 445bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 446bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 447c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong public int getViewType() { 448b21215a1a59812592380f31891becedbdec7468bAngus Kong return VIEW_TYPE_REMOVABLE; 449bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 450bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 451bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 452bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public boolean isUIActionSupported(int action) { 453bd26069d391830856c57c2141cd2efbc8423d871Angus Kong return ((action & mSupportedUIActions) == action); 454bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 455bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 456bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 457bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public boolean isDataActionSupported(int action) { 458bd26069d391830856c57c2141cd2efbc8423d871Angus Kong return ((action & mSupportedDataActions) == action); 459bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 460bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 461bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 4628a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong public boolean delete(Context context) { 4638a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong ContentResolver cr = context.getContentResolver(); 4643250987bd014d1c5463b8a39bbe988165ab1cc3fAngus Kong cr.delete(CONTENT_URI, MediaStore.Images.ImageColumns._ID + "=" + mContentId, null); 4658a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong return super.delete(context); 466bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 467bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 468bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 469571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong public Uri getUri() { 470bd26069d391830856c57c2141cd2efbc8423d871Angus Kong Uri baseUri = CONTENT_URI; 4713250987bd014d1c5463b8a39bbe988165ab1cc3fAngus Kong return baseUri.buildUpon().appendPath(String.valueOf(mContentId)).build(); 472bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 473bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 474bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 4756f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling public MediaDetails getMediaDetails(Context context) { 476b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaDetails mediaDetails = super.getMediaDetails(context); 477a16e7b50f3148f581439509279f242092e254309ztenghui MediaDetails.extractExifInfo(mediaDetails, mPath); 478bfd919aff7007f5dc26c74dfb97705c8e23e09b8Sascha Haeberling mediaDetails.addDetail(MediaDetails.INDEX_ORIENTATION, mOrientation); 4796f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling return mediaDetails; 4806f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling } 4816f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling 4826f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling @Override 483fae11a165e344a38811770c7d348eda214683edcSascha Haeberling public int getLocalDataType() { 484c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong return LOCAL_IMAGE; 485c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong } 486c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong 487c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong @Override 4888a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong public LocalData refresh(Context context) { 489aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd PhotoData newData = null; 490571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong Cursor c = context.getContentResolver().query(getUri(), QUERY_PROJECTION, null, 4918a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong null, null); 492aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd if (c != null) { 493aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd if (c.moveToFirst()) { 494aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd newData = buildFromCursor(c); 495aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd } 496aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd c.close(); 497bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 498aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd 499a16e7b50f3148f581439509279f242092e254309ztenghui return newData; 500bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 501bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 502bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 5034021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd public String getSignature() { 5044021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd return mSignature; 50543bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd } 50643bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd 50743bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd @Override 508632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd protected ImageView fillImageView(Context context, final ImageView v, final int thumbWidth, 509632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd final int thumbHeight, int placeHolderResourceId, LocalDataAdapter adapter, 5104021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd boolean isInProgress) { 511632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd loadImage(context, v, thumbWidth, thumbHeight, placeHolderResourceId, false); 512ae5fa1499ab1d6d1d421228859d13ac45ad1d437Spike Sprague 513159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague int stringId = R.string.photo_date_content_description; 514159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague if (PanoramaMetadataLoader.isPanorama(this) || 515159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague PanoramaMetadataLoader.isPanorama360(this)) { 516159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague stringId = R.string.panorama_date_content_description; 517159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague } else if (PanoramaMetadataLoader.isPanoramaAndUseViewer(this)) { 518159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague // assume it's a PhotoSphere 519159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague stringId = R.string.photosphere_date_content_description; 520159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague } else if (RgbzMetadataLoader.hasRGBZData(this)) { 521159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague stringId = R.string.refocus_date_content_description; 522159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague } 523159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague 524ae5fa1499ab1d6d1d421228859d13ac45ad1d437Spike Sprague v.setContentDescription(context.getResources().getString( 525159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague stringId, 526ae5fa1499ab1d6d1d421228859d13ac45ad1d437Spike Sprague getReadableDate(mDateModifiedInSeconds))); 527ae5fa1499ab1d6d1d421228859d13ac45ad1d437Spike Sprague 5284021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd return v; 5294021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd } 5304021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd 531632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd private void loadImage(Context context, ImageView imageView, int thumbWidth, 532632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd int thumbHeight, int placeHolderResourceId, boolean full) { 5334021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd 534acfad92c88807c99cf5165b201f24b9d76a8cdf4Sam Judd //TODO: Figure out why these can be <= 0. 535acfad92c88807c99cf5165b201f24b9d76a8cdf4Sam Judd if (thumbWidth <= 0 || thumbHeight <=0) { 536acfad92c88807c99cf5165b201f24b9d76a8cdf4Sam Judd return; 537acfad92c88807c99cf5165b201f24b9d76a8cdf4Sam Judd } 538acfad92c88807c99cf5165b201f24b9d76a8cdf4Sam Judd 539af79e4288559ddbee4ba6ed3cb3d1d9657fc23eaAlan Newberger BitmapRequestBuilder<Uri, Bitmap> request = Glide.with(context) 540632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .loadFromMediaStore(getUri(), mMimeType, mDateModifiedInSeconds, mOrientation) 541af79e4288559ddbee4ba6ed3cb3d1d9657fc23eaAlan Newberger .asBitmap() 542af79e4288559ddbee4ba6ed3cb3d1d9657fc23eaAlan Newberger .encoder(JPEG_ENCODER) 543632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .placeholder(placeHolderResourceId) 544632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .fitCenter(); 545632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd if (full) { 546632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd request.thumbnail(Glide.with(context) 547632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .loadFromMediaStore(getUri(), mMimeType, mDateModifiedInSeconds, 548632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd mOrientation) 549af79e4288559ddbee4ba6ed3cb3d1d9657fc23eaAlan Newberger .asBitmap() 550af79e4288559ddbee4ba6ed3cb3d1d9657fc23eaAlan Newberger .encoder(JPEG_ENCODER) 551632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .override(thumbWidth, thumbHeight) 552632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .fitCenter()) 553632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .override(Math.min(getWidth(), MAXIMUM_TEXTURE_SIZE), 554632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd Math.min(getHeight(), MAXIMUM_TEXTURE_SIZE)); 555632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd } else { 556632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd request.thumbnail(Glide.with(context) 557632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .loadFromMediaStore(getUri(), mMimeType, mDateModifiedInSeconds, 558632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd mOrientation) 559af79e4288559ddbee4ba6ed3cb3d1d9657fc23eaAlan Newberger .asBitmap() 560af79e4288559ddbee4ba6ed3cb3d1d9657fc23eaAlan Newberger .encoder(JPEG_ENCODER) 561632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .override(MEDIASTORE_THUMB_WIDTH, MEDIASTORE_THUMB_HEIGHT)) 562632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .override(thumbWidth, thumbHeight); 563632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd } 564632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd request.into(imageView); 565caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers } 5665850115399516c9186cc0a8231eb1b554f570441Sascha Haeberling 567caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers @Override 5684021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd public void recycle(View view) { 5694021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd super.recycle(view); 5704021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd if (view != null) { 571632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd Glide.clear(view); 5724021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd } 573bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 574bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 575aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd @Override 5764021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd public LocalDataViewType getItemViewType() { 5774021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd return LocalDataViewType.PHOTO; 578aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd } 579aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd 5804021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd @Override 581632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd public void loadFullImage(Context context, int thumbWidth, int thumbHeight, View v, 582632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd LocalDataAdapter adapter) 5834021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd { 584632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd loadImage(context, (ImageView) v, thumbWidth, thumbHeight, 0, true); 5854021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd } 586b7be228d192cb8f91079caaa2f77a884a40b1160ztenghui 5874021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd private static class PhotoDataBuilder implements CursorToLocalData { 5884021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd @Override 5894021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd public PhotoData build(Cursor cursor) { 5904021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd return LocalMediaData.PhotoData.buildFromCursor(cursor); 591bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 5924021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd } 593bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 594bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 595a16e7b50f3148f581439509279f242092e254309ztenghui public static final class VideoData extends LocalMediaData { 596bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_ID = 0; 597bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_TITLE = 1; 598bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_MIME_TYPE = 2; 599bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_DATE_TAKEN = 3; 600bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_DATE_MODIFIED = 4; 601bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_DATA = 5; 602bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_WIDTH = 6; 603bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public static final int COL_HEIGHT = 7; 60443bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd public static final int COL_SIZE = 8; 60543bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd public static final int COL_LATITUDE = 9; 60643bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd public static final int COL_LONGITUDE = 10; 60743bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd public static final int COL_DURATION = 11; 608bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 609bd26069d391830856c57c2141cd2efbc8423d871Angus Kong static final Uri CONTENT_URI = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; 610bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 611e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong private static final int mSupportedUIActions = ACTION_DEMOTE | ACTION_PROMOTE; 612bd26069d391830856c57c2141cd2efbc8423d871Angus Kong private static final int mSupportedDataActions = 613e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong DATA_ACTION_DELETE | DATA_ACTION_PLAY | DATA_ACTION_SHARE; 614bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 615aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd private static final String QUERY_ORDER = MediaStore.Video.VideoColumns.DATE_TAKEN 616aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd + " DESC, " + MediaStore.Video.VideoColumns._ID + " DESC"; 617bd26069d391830856c57c2141cd2efbc8423d871Angus Kong /** 618bd26069d391830856c57c2141cd2efbc8423d871Angus Kong * These values should be kept in sync with column IDs (COL_*) above. 619bd26069d391830856c57c2141cd2efbc8423d871Angus Kong */ 620aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd private static final String[] QUERY_PROJECTION = { 621b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Video.VideoColumns._ID, // 0, int 622b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Video.VideoColumns.TITLE, // 1, string 623b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Video.VideoColumns.MIME_TYPE, // 2, string 624b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Video.VideoColumns.DATE_TAKEN, // 3, int 625b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Video.VideoColumns.DATE_MODIFIED, // 4, int 626b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Video.VideoColumns.DATA, // 5, string 627b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Video.VideoColumns.WIDTH, // 6, int 628b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaStore.Video.VideoColumns.HEIGHT, // 7, int 62943bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd MediaStore.Video.VideoColumns.SIZE, // 8 long 63043bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd MediaStore.Video.VideoColumns.LATITUDE, // 9 double 63143bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd MediaStore.Video.VideoColumns.LONGITUDE, // 10 double 63243bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd MediaStore.Video.VideoColumns.DURATION // 11 long 633bd26069d391830856c57c2141cd2efbc8423d871Angus Kong }; 634bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 635b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling /** The duration in milliseconds. */ 636280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private final long mDurationInSeconds; 6374021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd private final String mSignature; 638a16e7b50f3148f581439509279f242092e254309ztenghui 639a16e7b50f3148f581439509279f242092e254309ztenghui public VideoData(long id, String title, String mimeType, 640b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers long dateTakenInMilliSeconds, long dateModifiedInSeconds, 641a16e7b50f3148f581439509279f242092e254309ztenghui String path, int width, int height, long sizeInBytes, 642a16e7b50f3148f581439509279f242092e254309ztenghui double latitude, double longitude, long durationInSeconds) { 643b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers super(id, title, mimeType, dateTakenInMilliSeconds, dateModifiedInSeconds, 644a16e7b50f3148f581439509279f242092e254309ztenghui path, width, height, sizeInBytes, latitude, longitude); 645a16e7b50f3148f581439509279f242092e254309ztenghui mDurationInSeconds = durationInSeconds; 6464021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd mSignature = mimeType + dateModifiedInSeconds; 647a16e7b50f3148f581439509279f242092e254309ztenghui } 648b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling 649571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong public static LocalData fromContentUri(ContentResolver cr, Uri contentUri) { 650571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong List<LocalData> newVideos = query(cr, contentUri, QUERY_ALL_MEDIA_ID); 651571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong if (newVideos.isEmpty()) { 652571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong return null; 653571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong } 654571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong return newVideos.get(0); 655571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong } 656571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong 657571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong static List<LocalData> query(ContentResolver cr, Uri uri, long lastId) { 658571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong return queryLocalMediaData(cr, uri, QUERY_PROJECTION, lastId, QUERY_ORDER, 659571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong new VideoDataBuilder()); 660aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd } 661aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd 662de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd /** 663de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd * We can't trust the media store and we can't afford the performance overhead of 664de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd * synchronously decoding the video header for every item when loading our data set 665de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd * from the media store, so we instead run the metadata loader in the background 666de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd * to decode the video header for each item and prefer whatever values it obtains. 667de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd */ 668de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd private int getBestWidth() { 669de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd int metadataWidth = VideoRotationMetadataLoader.getWidth(this); 670de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd if (metadataWidth > 0) { 671de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd return metadataWidth; 672de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd } else { 673de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd return mWidth; 674de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd } 675de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd } 676de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd 677de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd private int getBestHeight() { 678de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd int metadataHeight = VideoRotationMetadataLoader.getHeight(this); 679de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd if (metadataHeight > 0) { 680de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd return metadataHeight; 681de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd } else { 682de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd return mHeight; 683de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd } 684de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd } 685de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd 686de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd /** 687de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd * If the metadata loader has determined from the video header that we need to rotate the video 688de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd * 90 or 270 degrees, then we swap the width and height. 689de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd */ 690de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd @Override 691de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd public int getWidth() { 692de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd return VideoRotationMetadataLoader.isRotated(this) ? getBestHeight() : getBestWidth(); 693de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd } 694de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd 695de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd @Override 696de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd public int getHeight() { 697de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd return VideoRotationMetadataLoader.isRotated(this) ? getBestWidth() : getBestHeight(); 698de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd } 699de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd 700aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd private static VideoData buildFromCursor(Cursor c) { 701a16e7b50f3148f581439509279f242092e254309ztenghui long id = c.getLong(COL_ID); 702a16e7b50f3148f581439509279f242092e254309ztenghui String title = c.getString(COL_TITLE); 703a16e7b50f3148f581439509279f242092e254309ztenghui String mimeType = c.getString(COL_MIME_TYPE); 704b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers long dateTakenInMilliSeconds = c.getLong(COL_DATE_TAKEN); 705a16e7b50f3148f581439509279f242092e254309ztenghui long dateModifiedInSeconds = c.getLong(COL_DATE_MODIFIED); 706a16e7b50f3148f581439509279f242092e254309ztenghui String path = c.getString(COL_DATA); 707a16e7b50f3148f581439509279f242092e254309ztenghui int width = c.getInt(COL_WIDTH); 708a16e7b50f3148f581439509279f242092e254309ztenghui int height = c.getInt(COL_HEIGHT); 709a16e7b50f3148f581439509279f242092e254309ztenghui 710de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd // If the media store doesn't contain a width and a height, use the width and height 711de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd // of the default camera mode instead. When the metadata loader runs, it will set the 712de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd // correct values. 713a16e7b50f3148f581439509279f242092e254309ztenghui if (width == 0 || height == 0) { 714de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd Log.w(TAG, "failed to retrieve width and height from the media store, defaulting " + 715de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd " to camera profile"); 716de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH); 717de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd width = profile.videoFrameWidth; 718de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd height = profile.videoFrameHeight; 719bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 720b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling 721a16e7b50f3148f581439509279f242092e254309ztenghui long sizeInBytes = c.getLong(COL_SIZE); 722a16e7b50f3148f581439509279f242092e254309ztenghui double latitude = c.getDouble(COL_LATITUDE); 723a16e7b50f3148f581439509279f242092e254309ztenghui double longitude = c.getDouble(COL_LONGITUDE); 724a16e7b50f3148f581439509279f242092e254309ztenghui long durationInSeconds = c.getLong(COL_DURATION) / 1000; 725b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers VideoData d = new VideoData(id, title, mimeType, dateTakenInMilliSeconds, 726a16e7b50f3148f581439509279f242092e254309ztenghui dateModifiedInSeconds, path, width, height, sizeInBytes, 727a16e7b50f3148f581439509279f242092e254309ztenghui latitude, longitude, durationInSeconds); 728bd26069d391830856c57c2141cd2efbc8423d871Angus Kong return d; 729bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 730bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 731bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 732bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public String toString() { 733a16e7b50f3148f581439509279f242092e254309ztenghui return "Video:" + ",data=" + mPath + ",mimeType=" + mMimeType 734b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers + "," + mWidth + "x" + mHeight + ",date=" + new Date(mDateTakenInMilliSeconds); 735bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 736bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 737bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 738c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong public int getViewType() { 739b21215a1a59812592380f31891becedbdec7468bAngus Kong return VIEW_TYPE_REMOVABLE; 740bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 741bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 742bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 743bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public boolean isUIActionSupported(int action) { 744bd26069d391830856c57c2141cd2efbc8423d871Angus Kong return ((action & mSupportedUIActions) == action); 745bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 746bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 747bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 748bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public boolean isDataActionSupported(int action) { 749bd26069d391830856c57c2141cd2efbc8423d871Angus Kong return ((action & mSupportedDataActions) == action); 750bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 751bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 752bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 7538a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong public boolean delete(Context context) { 7548a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong ContentResolver cr = context.getContentResolver(); 7553250987bd014d1c5463b8a39bbe988165ab1cc3fAngus Kong cr.delete(CONTENT_URI, MediaStore.Video.VideoColumns._ID + "=" + mContentId, null); 7568a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong return super.delete(context); 757bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 758bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 759bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 760571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong public Uri getUri() { 761bd26069d391830856c57c2141cd2efbc8423d871Angus Kong Uri baseUri = CONTENT_URI; 7623250987bd014d1c5463b8a39bbe988165ab1cc3fAngus Kong return baseUri.buildUpon().appendPath(String.valueOf(mContentId)).build(); 763bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 764c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong 765c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong @Override 7666f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling public MediaDetails getMediaDetails(Context context) { 767b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling MediaDetails mediaDetails = super.getMediaDetails(context); 768a16e7b50f3148f581439509279f242092e254309ztenghui String duration = MediaDetails.formatDuration(context, mDurationInSeconds); 769b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling mediaDetails.addDetail(MediaDetails.INDEX_DURATION, duration); 770b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling return mediaDetails; 7716f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling } 7726f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling 7736f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling @Override 774fae11a165e344a38811770c7d348eda214683edcSascha Haeberling public int getLocalDataType() { 775c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong return LOCAL_VIDEO; 776c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong } 777bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 778bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 7798a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong public LocalData refresh(Context context) { 780571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong Cursor c = context.getContentResolver().query(getUri(), QUERY_PROJECTION, null, 7818a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong null, null); 782b0a5929b1dd0ddc2729e23ba95afdb43a1aecfd5Sascha Haeberling if (c == null || !c.moveToFirst()) { 783a16e7b50f3148f581439509279f242092e254309ztenghui return null; 784bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 785bd26069d391830856c57c2141cd2efbc8423d871Angus Kong VideoData newData = buildFromCursor(c); 786a16e7b50f3148f581439509279f242092e254309ztenghui return newData; 787bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 788bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 789bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 7904021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd public String getSignature() { 7914021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd return mSignature; 7924021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd } 7934021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd 7944021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd @Override 795632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd protected ImageView fillImageView(Context context, final ImageView v, final int thumbWidth, 796632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd final int thumbHeight, int placeHolderResourceId, LocalDataAdapter adapter, 7974021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd boolean isInProgress) { 798acfad92c88807c99cf5165b201f24b9d76a8cdf4Sam Judd 799acfad92c88807c99cf5165b201f24b9d76a8cdf4Sam Judd //TODO: Figure out why these can be <= 0. 800acfad92c88807c99cf5165b201f24b9d76a8cdf4Sam Judd if (thumbWidth <= 0 || thumbHeight <=0) { 801acfad92c88807c99cf5165b201f24b9d76a8cdf4Sam Judd return v; 802acfad92c88807c99cf5165b201f24b9d76a8cdf4Sam Judd } 803acfad92c88807c99cf5165b201f24b9d76a8cdf4Sam Judd 8044021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd Glide.with(context) 805632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .loadFromMediaStore(getUri(), mMimeType, mDateModifiedInSeconds, 0) 80665ab02000f65a8677adf9fab5c296e0d3ef64cbcAlan Newberger .asBitmap() 80765ab02000f65a8677adf9fab5c296e0d3ef64cbcAlan Newberger .encoder(JPEG_ENCODER) 808632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .thumbnail(Glide.with(context) 809632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .loadFromMediaStore(getUri(), mMimeType, mDateModifiedInSeconds, 0) 81065ab02000f65a8677adf9fab5c296e0d3ef64cbcAlan Newberger .asBitmap() 81165ab02000f65a8677adf9fab5c296e0d3ef64cbcAlan Newberger .encoder(JPEG_ENCODER) 812632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .override(MEDIASTORE_THUMB_WIDTH, MEDIASTORE_THUMB_HEIGHT)) 813632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .placeholder(placeHolderResourceId) 814632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .fitCenter() 815632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .override(thumbWidth, thumbHeight) 816632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd .into(v); 8174021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd 818159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague // Content descriptions applied to parent FrameView 819159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague // see getView 820ae5fa1499ab1d6d1d421228859d13ac45ad1d437Spike Sprague 8214021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd return v; 8224021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd } 8234021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd 8244021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd @Override 82543bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd public View getView(final Context context, View recycled, 826632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd int thumbWidth, int thumbHeight, int placeHolderResourceId, 82714ff6c8df2924ccad083591c0fc873322c6828c0Sascha Haeberling LocalDataAdapter adapter, boolean isInProgress) { 828bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 82943bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd final VideoViewHolder viewHolder; 83043bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd final View result; 83143bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd if (recycled != null) { 83243bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd result = recycled; 833bb3b39b13a7097a55e585e8d6197057500847708Spike Sprague viewHolder = (VideoViewHolder) recycled.getTag(R.id.mediadata_tag_target); 83443bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd } else { 83543bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd result = LayoutInflater.from(context).inflate(R.layout.filmstrip_video, null); 836a93ba0dbd8e4000f3643567809a4a3fac554fd3cSpike Sprague result.setTag(R.id.mediadata_tag_viewtype, getItemViewType().ordinal()); 83743bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd ImageView videoView = (ImageView) result.findViewById(R.id.video_view); 83843bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd ImageView playButton = (ImageView) result.findViewById(R.id.play_button); 83943bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd viewHolder = new VideoViewHolder(videoView, playButton); 840bb3b39b13a7097a55e585e8d6197057500847708Spike Sprague result.setTag(R.id.mediadata_tag_target, viewHolder); 84143bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd } 84243bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd 843632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd fillImageView(context, viewHolder.mVideoView, thumbWidth, thumbHeight, 8444021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd placeHolderResourceId, adapter, isInProgress); 845bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 846bd26069d391830856c57c2141cd2efbc8423d871Angus Kong // ImageView for the play icon. 84743bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd viewHolder.mPlayButton.setOnClickListener(new View.OnClickListener() { 848bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 849bd26069d391830856c57c2141cd2efbc8423d871Angus Kong public void onClick(View v) { 850280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling // TODO: refactor this into activities to avoid this class 851280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling // conversion. 852571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong CameraUtil.playVideo((Activity) context, getUri(), mTitle); 853bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 854bd26069d391830856c57c2141cd2efbc8423d871Angus Kong }); 855bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 856159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague result.setContentDescription(context.getResources().getString( 857159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague R.string.video_date_content_description, 858159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague getReadableDate(mDateModifiedInSeconds))); 859159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague 86043bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd return result; 86143bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd } 86243bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd 86343bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd @Override 8644021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd public void recycle(View view) { 8654021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd super.recycle(view); 866bb3b39b13a7097a55e585e8d6197057500847708Spike Sprague VideoViewHolder videoViewHolder = 867bb3b39b13a7097a55e585e8d6197057500847708Spike Sprague (VideoViewHolder) view.getTag(R.id.mediadata_tag_target); 868632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd Glide.clear(videoViewHolder.mVideoView); 869bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 870bd26069d391830856c57c2141cd2efbc8423d871Angus Kong 871bd26069d391830856c57c2141cd2efbc8423d871Angus Kong @Override 8724021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd public LocalDataViewType getItemViewType() { 8734021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd return LocalDataViewType.VIDEO; 874bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 875bd26069d391830856c57c2141cd2efbc8423d871Angus Kong } 876caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers 877aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd private static class VideoDataBuilder implements CursorToLocalData { 878aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd 879aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd @Override 880aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd public VideoData build(Cursor cursor) { 881aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd return LocalMediaData.VideoData.buildFromCursor(cursor); 882aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd } 883aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd } 884aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd 88543bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd private static class VideoViewHolder { 88643bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd private final ImageView mVideoView; 88743bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd private final ImageView mPlayButton; 88843bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd 88943bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd public VideoViewHolder(ImageView videoView, ImageView playButton) { 89043bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd mVideoView = videoView; 89143bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd mPlayButton = playButton; 89243bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd } 89343bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd } 894bd26069d391830856c57c2141cd2efbc8423d871Angus Kong} 895