LocalSource.java revision bed703ef28f013639db3cd7a6b8a6e94d61075da
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 */
16package com.android.dreams.phototable;
17
18import android.content.Context;
19import android.content.SharedPreferences;
20import android.database.Cursor;
21import android.provider.MediaStore;
22
23import java.io.FileInputStream;
24import java.io.InputStream;
25import java.util.Collection;
26import java.util.HashMap;
27import java.util.LinkedList;
28import java.util.Set;
29
30/**
31 * Loads images from the local store.
32 */
33public class LocalSource extends PhotoSource {
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
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
50    private Set<String> getFoundAlbums() {
51        if (mFoundAlbumIds == null) {
52            findAlbums();
53        }
54        return mFoundAlbumIds;
55    }
56
57    @Override
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
116    protected Collection<ImageData> findImages(int howMany) {
117        log(TAG, "finding images");
118        LinkedList<ImageData> foundImages = new LinkedList<ImageData>();
119
120        String[] projection = {MediaStore.Images.Media.DATA, MediaStore.Images.Media.ORIENTATION,
121                MediaStore.Images.Media.BUCKET_ID, MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
122        String selection = "";
123        for (String id : getFoundAlbums()) {
124            if (mSettings.isAlbumEnabled(id)) {
125                String[] parts = id.split(":");
126                if (parts.length > 1) {
127                    if (selection.length() > 0) {
128                        selection += " OR ";
129                    }
130                    selection += MediaStore.Images.Media.BUCKET_ID + " = '" + parts[1] + "'";
131                }
132            }
133        }
134        if (selection.isEmpty()) {
135            return foundImages;
136        }
137
138        Cursor cursor = mResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
139                projection, selection, null, null);
140        if (cursor != null) {
141            if (cursor.getCount() > howMany && mLastPosition == INVALID) {
142                mLastPosition = pickRandomStart(cursor.getCount(), howMany);
143            }
144            cursor.moveToPosition(mLastPosition);
145
146            int dataIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
147            int orientationIndex = cursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION);
148            int bucketIndex = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID);
149            int nameIndex = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
150
151            if (dataIndex < 0) {
152                log(TAG, "can't find the DATA column!");
153            } else {
154                while (foundImages.size() < howMany && cursor.moveToNext()) {
155                    ImageData data = new ImageData();
156                    data.url = cursor.getString(dataIndex);
157                    data.orientation = cursor.getInt(orientationIndex);
158                    foundImages.offer(data);
159                    mLastPosition = cursor.getPosition();
160                }
161                if (cursor.isAfterLast()) {
162                    mLastPosition = -1;
163                }
164                if (cursor.isBeforeFirst()) {
165                    mLastPosition = INVALID;
166                }
167            }
168
169            cursor.close();
170        }
171        log(TAG, "found " + foundImages.size() + " items.");
172        return foundImages;
173    }
174
175    @Override
176    protected InputStream getStream(ImageData data, int longSide) {
177        FileInputStream fis = null;
178        try {
179            log(TAG, "opening:" + data.url);
180            fis = new FileInputStream(data.url);
181        } catch (Exception ex) {
182            log(TAG, ex.toString());
183            fis = null;
184        }
185
186        return (InputStream) fis;
187    }
188}
189