1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.camera.data; 18 19 import android.content.Context; 20 import android.view.View; 21 22 import com.android.camera.Storage; 23 import com.android.camera.debug.Log; 24 import com.android.camera.util.Size; 25 import com.bumptech.glide.Glide; 26 import com.bumptech.glide.load.Key; 27 import com.bumptech.glide.signature.MediaStoreSignature; 28 import com.google.common.base.Optional; 29 30 import java.io.File; 31 import java.text.DateFormat; 32 33 import javax.annotation.Nonnull; 34 35 /** 36 * A base class for all the local media files. The bitmap is loaded in 37 * background thread. Subclasses should implement their own background loading 38 * thread by sub-classing BitmapLoadTask and overriding doInBackground() to 39 * return a bitmap. 40 */ 41 public abstract class FilmstripItemBase<T extends FilmstripItemData> implements FilmstripItem { 42 /** The minimum id to use to query for all media at a given media store uri */ 43 public static final int QUERY_ALL_MEDIA_ID = -1; 44 45 protected final Context mContext; 46 protected final GlideFilmstripManager mGlideManager; 47 protected final T mData; 48 protected final Metadata mMetaData; 49 protected final FilmstripItemAttributes mAttributes; 50 protected final DateFormat mDateFormatter = DateFormat.getDateTimeInstance(); 51 52 protected Size mSuggestedSize; 53 FilmstripItemBase(Context context, GlideFilmstripManager glideManager, T data, FilmstripItemAttributes attributes)54 public FilmstripItemBase(Context context, GlideFilmstripManager glideManager, T data, 55 FilmstripItemAttributes attributes) { 56 mContext = context; 57 mGlideManager = glideManager; 58 mData = data; 59 mAttributes = attributes; 60 61 mMetaData = new Metadata(); 62 63 mSuggestedSize = GlideFilmstripManager.TINY_THUMB_SIZE; 64 } 65 66 @Override getData()67 public FilmstripItemData getData() { 68 return mData; 69 } 70 71 @Override delete()72 public boolean delete() { 73 File fileToDelete = new File(mData.getFilePath()); 74 boolean deletionSucceeded = fileToDelete.delete(); 75 deleteIfEmptyCameraSubDir(fileToDelete.getParentFile()); 76 return deletionSucceeded; 77 } 78 79 @Override setSuggestedSize(int widthPx, int heightPx)80 public void setSuggestedSize(int widthPx, int heightPx) { 81 if (widthPx > 0 && heightPx > 0) { 82 mSuggestedSize = new Size(widthPx, heightPx); 83 } else { 84 Log.w(TAG, "Suggested size was set to a zero area value!"); 85 } 86 } 87 88 @Override recycle(@onnull View view)89 public void recycle(@Nonnull View view) { 90 Glide.clear(view); 91 } 92 93 @Override getMediaDetails()94 public Optional<MediaDetails> getMediaDetails() { 95 MediaDetails mediaDetails = new MediaDetails(); 96 mediaDetails.addDetail(MediaDetails.INDEX_TITLE, mData.getTitle()); 97 mediaDetails.addDetail(MediaDetails.INDEX_WIDTH, getDimensions().getWidth()); 98 mediaDetails.addDetail(MediaDetails.INDEX_HEIGHT, getDimensions().getHeight()); 99 mediaDetails.addDetail(MediaDetails.INDEX_PATH, mData.getFilePath()); 100 mediaDetails.addDetail(MediaDetails.INDEX_DATETIME, 101 mDateFormatter.format(mData.getLastModifiedDate())); 102 long mSizeInBytes = mData.getSizeInBytes(); 103 if (mSizeInBytes > 0) { 104 mediaDetails.addDetail(MediaDetails.INDEX_SIZE, mSizeInBytes); 105 } 106 107 Location location = mData.getLocation(); 108 if (location != Location.UNKNOWN) { 109 mediaDetails.addDetail(MediaDetails.INDEX_LOCATION, location.getLocationString()); 110 } 111 return Optional.of(mediaDetails); 112 } 113 114 @Override getAttributes()115 public FilmstripItemAttributes getAttributes() { 116 return mAttributes; 117 } 118 119 @Override getMetadata()120 public Metadata getMetadata() { 121 return mMetaData; 122 } 123 124 @Override getDimensions()125 public Size getDimensions() { 126 return mData.getDimensions(); 127 } 128 129 @Override getOrientation()130 public int getOrientation() { 131 return mData.getOrientation(); 132 } 133 generateSignature(FilmstripItemData data)134 protected final Key generateSignature(FilmstripItemData data) { 135 // Per Glide docs, make default mime type be the empty String 136 String mimeType = (data.getMimeType() == null) ? "" : data.getMimeType(); 137 long modTimeSeconds = (data.getLastModifiedDate() == null) ? 0 : 138 data.getLastModifiedDate().getTime() / 1000; 139 return new MediaStoreSignature(mimeType, modTimeSeconds, data.getOrientation()); 140 } 141 deleteIfEmptyCameraSubDir(File directory)142 private void deleteIfEmptyCameraSubDir(File directory) { 143 // Make sure 'directory' refers to a valid existing empty directory. 144 if (!directory.exists() || !directory.isDirectory() || directory.list().length != 0) { 145 return; 146 } 147 148 // Check if this is a 'Camera' sub-directory. 149 String cameraPathStr = Storage.instance().DIRECTORY; 150 String fileParentPathStr = directory.getParentFile().getAbsolutePath(); 151 Log.d(TAG, "CameraPathStr: " + cameraPathStr + " fileParentPathStr: " + fileParentPathStr); 152 153 // Delete the directory if it's an empty sub-directory of the Camera 154 // directory. 155 if (fileParentPathStr.equals(cameraPathStr)) { 156 if(!directory.delete()) { 157 Log.d(TAG, "Failed to delete: " + directory); 158 } 159 } 160 } 161 } 162