• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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 package com.android.dreams.phototable;
17 
18 import android.content.Context;
19 import android.content.SharedPreferences;
20 import android.database.Cursor;
21 import android.provider.MediaStore;
22 
23 import java.io.FileInputStream;
24 import java.io.InputStream;
25 import java.util.Collection;
26 import java.util.HashMap;
27 import java.util.LinkedList;
28 import java.util.Set;
29 
30 /**
31  * Loads images from the local store.
32  */
33 public class LocalSource extends CursorPhotoSource {
34     private static final String TAG = "PhotoTable.LocalSource";
35 
36     private final String mUnknownAlbumName;
37     private final String mLocalSourceName;
38     private Set<String> mFoundAlbumIds;
39     private int mLastPosition;
40 
LocalSource(Context context, SharedPreferences settings)41     public LocalSource(Context context, SharedPreferences settings) {
42         super(context, settings);
43         mLocalSourceName = mResources.getString(R.string.local_source_name, "Photos on Device");
44         mUnknownAlbumName = mResources.getString(R.string.unknown_album_name, "Unknown");
45         mSourceName = TAG;
46         mLastPosition = INVALID;
47         fillQueue();
48     }
49 
getFoundAlbums()50     private Set<String> getFoundAlbums() {
51         if (mFoundAlbumIds == null) {
52             findAlbums();
53         }
54         return mFoundAlbumIds;
55     }
56 
57     @Override
findAlbums()58     public Collection<AlbumData> findAlbums() {
59         log(TAG, "finding albums");
60         HashMap<String, AlbumData> foundAlbums = new HashMap<String, AlbumData>();
61 
62         String[] projection = {MediaStore.Images.Media.DATA, MediaStore.Images.Media.BUCKET_ID,
63                 MediaStore.Images.Media.BUCKET_DISPLAY_NAME, MediaStore.Images.Media.DATE_TAKEN};
64         // This is a horrible hack that closes the where clause and injects a grouping clause.
65         Cursor cursor = mResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
66                 projection, null, null, null);
67         if (cursor != null) {
68             cursor.moveToPosition(-1);
69 
70             int dataIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
71             int bucketIndex = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID);
72             int nameIndex = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
73             int updatedIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN);
74 
75             if (bucketIndex < 0) {
76                 log(TAG, "can't find the ID column!");
77             } else {
78                 while (cursor.moveToNext()) {
79                     String id = TAG + ":" + cursor.getString(bucketIndex);
80                     AlbumData data = foundAlbums.get(id);
81                     if (foundAlbums.get(id) == null) {
82                         data = new AlbumData();
83                         data.id = id;
84                         data.account = mLocalSourceName;
85 
86                         if (dataIndex >= 0) {
87                             data.thumbnailUrl = cursor.getString(dataIndex);
88                         }
89 
90                         if (nameIndex >= 0) {
91                             data.title = cursor.getString(nameIndex);
92                         } else {
93                             data.title = mUnknownAlbumName;
94                         }
95 
96                         log(TAG, data.title + " found");
97                         foundAlbums.put(id, data);
98                     }
99                     if (updatedIndex >= 0) {
100                         long updated = cursor.getLong(updatedIndex);
101                         data.updated = (data.updated == 0 ?
102                                         updated :
103                                         Math.min(data.updated, updated));
104                     }
105                 }
106             }
107             cursor.close();
108 
109         }
110         log(TAG, "found " + foundAlbums.size() + " items.");
111         mFoundAlbumIds = foundAlbums.keySet();
112         return foundAlbums.values();
113     }
114 
115     @Override
openCursor(ImageData data)116     protected void openCursor(ImageData data) {
117         log(TAG, "opening single album");
118 
119         String[] projection = {MediaStore.Images.Media.DATA, MediaStore.Images.Media.ORIENTATION,
120                 MediaStore.Images.Media.BUCKET_ID, MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
121         String selection = MediaStore.Images.Media.BUCKET_ID + " = '" + data.albumId + "'";
122 
123         data.cursor = mResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
124                 projection, selection, null, null);
125     }
126 
127     @Override
findPosition(ImageData data)128     protected void findPosition(ImageData data) {
129         if (data.position == -1) {
130             if (data.cursor == null) {
131                 openCursor(data);
132             }
133             if (data.cursor != null) {
134                 int dataIndex = data.cursor.getColumnIndex(MediaStore.Images.Media.DATA);
135                 data.cursor.moveToPosition(-1);
136                 while (data.position == -1 && data.cursor.moveToNext()) {
137                     String url = data.cursor.getString(dataIndex);
138                     if (url != null && url.equals(data.url)) {
139                         data.position = data.cursor.getPosition();
140                     }
141                 }
142                 if (data.position == -1) {
143                     // oops!  The image isn't in this album. How did we get here?
144                     data.position = INVALID;
145                 }
146             }
147         }
148     }
149 
150     @Override
unpackImageData(Cursor cursor, ImageData data)151     protected ImageData unpackImageData(Cursor cursor, ImageData data) {
152         if (data == null) {
153             data = new ImageData();
154         }
155         int dataIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
156         int orientationIndex = cursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION);
157         int bucketIndex = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID);
158 
159         data.url = cursor.getString(dataIndex);
160         data.albumId = cursor.getString(bucketIndex);
161         data.position = UNINITIALIZED;
162         data.cursor = null;
163         data.orientation = cursor.getInt(orientationIndex);
164 
165         return data;
166     }
167 
168     @Override
findImages(int howMany)169     protected Collection<ImageData> findImages(int howMany) {
170         log(TAG, "finding images");
171         LinkedList<ImageData> foundImages = new LinkedList<ImageData>();
172 
173         String[] projection = {MediaStore.Images.Media.DATA, MediaStore.Images.Media.ORIENTATION,
174                 MediaStore.Images.Media.BUCKET_ID, MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
175         String selection = "";
176         for (String id : getFoundAlbums()) {
177             if (mSettings.isAlbumEnabled(id)) {
178                 String[] parts = id.split(":");
179                 if (parts.length > 1) {
180                     if (selection.length() > 0) {
181                         selection += " OR ";
182                     }
183                     selection += MediaStore.Images.Media.BUCKET_ID + " = '" + parts[1] + "'";
184                 }
185             }
186         }
187         if (selection.isEmpty()) {
188             return foundImages;
189         }
190 
191         Cursor cursor = mResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
192                 projection, selection, null, null);
193         if (cursor != null) {
194             int dataIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
195 
196             if (cursor.getCount() > howMany && mLastPosition == INVALID) {
197                 mLastPosition = pickRandomStart(cursor.getCount(), howMany);
198             }
199             cursor.moveToPosition(mLastPosition);
200 
201             if (dataIndex < 0) {
202                 log(TAG, "can't find the DATA column!");
203             } else {
204                 while (foundImages.size() < howMany && cursor.moveToNext()) {
205                     ImageData data = unpackImageData(cursor, null);
206                     foundImages.offer(data);
207                     mLastPosition = cursor.getPosition();
208                 }
209                 if (cursor.isAfterLast()) {
210                     mLastPosition = -1;
211                 }
212                 if (cursor.isBeforeFirst()) {
213                     mLastPosition = INVALID;
214                 }
215             }
216 
217             cursor.close();
218         }
219         log(TAG, "found " + foundImages.size() + " items.");
220         return foundImages;
221     }
222 
223     @Override
getStream(ImageData data, int longSide)224     protected InputStream getStream(ImageData data, int longSide) {
225         FileInputStream fis = null;
226         try {
227             log(TAG, "opening:" + data.url);
228             fis = new FileInputStream(data.url);
229         } catch (Exception ex) {
230             log(TAG, ex.toString());
231             fis = null;
232         }
233 
234         return (InputStream) fis;
235     }
236 }
237 
238