OSDN Git Service

Updates to 3D gallery source.
[android-x86/packages-apps-Gallery2.git] / src / com / cooliris / media / PicasaDataSource.java
1 package com.cooliris.media;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5
6 import android.accounts.Account;
7 import android.content.ContentProviderClient;
8 import android.content.ContentResolver;
9 import android.content.Context;
10 import android.database.ContentObserver;
11 import android.database.Cursor;
12 import android.net.Uri;
13 import android.os.Handler;
14 import android.os.RemoteException;
15 import android.util.Log;
16
17 import com.cooliris.picasa.AlbumEntry;
18 import com.cooliris.picasa.Entry;
19 import com.cooliris.picasa.EntrySchema;
20 import com.cooliris.picasa.PicasaApi;
21 import com.cooliris.picasa.PicasaContentProvider;
22 import com.cooliris.picasa.PicasaService;
23
24 public final class PicasaDataSource implements DataSource {
25     private static final String TAG = "PicasaDataSource";
26     public static final DiskCache sThumbnailCache = new DiskCache("picasa-thumbs");
27     private static final String DEFAULT_BUCKET_SORT_ORDER = AlbumEntry.Columns.USER + ", " + AlbumEntry.Columns.DATE_PUBLISHED
28             + " DESC";
29
30     private ContentProviderClient mProviderClient;
31     private final Context mContext;
32     private ContentObserver mAlbumObserver;
33     private HashMap<String, Boolean> mAccountEnabled = new HashMap<String, Boolean>();
34
35     public PicasaDataSource(Context context) {
36         mContext = context;
37     }
38
39     public void loadMediaSets(final MediaFeed feed) {
40         if (mProviderClient == null) {
41             mProviderClient = mContext.getContentResolver().acquireContentProviderClient(PicasaContentProvider.AUTHORITY);
42         }
43         // Force permission dialog to be displayed if necessary. TODO: remove this after signed by Google.
44         PicasaApi.getAccounts(mContext);
45
46         // Ensure that users are up to date. TODO: also listen for accounts changed broadcast.
47         PicasaService.requestSync(mContext, PicasaService.TYPE_USERS_ALBUMS, 0);
48         Handler handler = ((Gallery) mContext).getHandler();
49         ContentObserver albumObserver = new ContentObserver(handler) {
50             public void onChange(boolean selfChange) {
51                 loadMediaSetsIntoFeed(feed, true);
52             }
53         };
54         mAlbumObserver = albumObserver;
55         loadMediaSetsIntoFeed(feed, true);
56
57         // Start listening.
58         ContentResolver cr = mContext.getContentResolver();
59         cr.registerContentObserver(PicasaContentProvider.ALBUMS_URI, false, mAlbumObserver);
60         cr.registerContentObserver(PicasaContentProvider.PHOTOS_URI, false, mAlbumObserver);
61     }
62
63     public void shutdown() {
64         if (mAlbumObserver != null) {
65             ContentResolver cr = mContext.getContentResolver();
66             cr.unregisterContentObserver(mAlbumObserver);
67         }
68     }
69
70     public void loadItemsForSet(final MediaFeed feed, final MediaSet parentSet, int rangeStart, int rangeEnd) {
71         if (parentSet == null) {
72             return;
73         } else {
74             // Return a list of items within an album.
75             addItemsToFeed(feed, parentSet, rangeStart, rangeEnd);
76         }
77     }
78
79     protected void loadMediaSetsIntoFeed(final MediaFeed feed, boolean sync) {
80         Account[] accounts = PicasaApi.getAccounts(mContext);
81         int numAccounts = accounts.length;
82         for (int i = 0; i < numAccounts; ++i) {
83             Account account = accounts[i];
84             boolean isEnabled = ContentResolver.getSyncAutomatically(account, PicasaContentProvider.AUTHORITY);
85             String username = account.name;
86             if (username.contains("@gmail.") || username.contains("@googlemail.")) {
87                 // Strip the domain from GMail accounts for canonicalization. TODO: is there an official way?
88                 username = username.substring(0, username.indexOf('@'));
89             }
90             mAccountEnabled.put(username, new Boolean(isEnabled));
91         }
92         ContentProviderClient client = mProviderClient;
93         if (client == null)
94             return;
95         try {
96             EntrySchema albumSchema = AlbumEntry.SCHEMA;
97             Cursor cursor = client.query(PicasaContentProvider.ALBUMS_URI, albumSchema.getProjection(), null, null,
98                     DEFAULT_BUCKET_SORT_ORDER);
99             AlbumEntry album = new AlbumEntry();
100             MediaSet mediaSet;
101             if (cursor.moveToFirst()) {
102                 int numAlbums = cursor.getCount();
103                 ArrayList<MediaSet> picasaSets = new ArrayList<MediaSet>(numAlbums);
104                 do {
105                     albumSchema.cursorToObject(cursor, album);
106                     Boolean accountEnabledObj = mAccountEnabled.get(album.user);
107                     boolean accountEnabled = (accountEnabledObj == null) ? false : accountEnabledObj.booleanValue();
108                     if (accountEnabled) {
109                         mediaSet = feed.getMediaSet(album.id);
110                         if (mediaSet == null) {
111                             mediaSet = feed.addMediaSet(album.id, this);
112                             mediaSet.mName = album.title;
113                             mediaSet.mEditUri = album.editUri;
114                             mediaSet.generateTitle(true);
115                         } else {
116                             mediaSet.setNumExpectedItems(album.numPhotos);
117                         }
118                         mediaSet.mPicasaAlbumId = album.id;
119                         mediaSet.mSyncPending = album.photosDirty;
120                         picasaSets.add(mediaSet);
121                     }
122                 } while (cursor.moveToNext());
123             }
124             cursor.close();
125         } catch (RemoteException e) {
126             Log.e(TAG, "Error occurred loading albums");
127         }
128     }
129
130     private void addItemsToFeed(MediaFeed feed, MediaSet set, int start, int end) {
131         ContentProviderClient client = mProviderClient;
132         Cursor cursor = null;
133         try {
134             // Query photos in the album.
135             EntrySchema photosSchema = PhotoProjection.SCHEMA;
136             String whereInAlbum = "album_id = " + Long.toString(set.mId);
137             cursor = client.query(PicasaContentProvider.PHOTOS_URI, photosSchema.getProjection(), whereInAlbum, null, null);
138             PhotoProjection photo = new PhotoProjection();
139             int count = cursor.getCount();
140             if (count < end) {
141                 end = count;
142             }
143             set.setNumExpectedItems(count);
144             set.generateTitle(true);
145             // Move to the next unread item.
146             int newIndex = start + 1;
147             if (newIndex > count || !cursor.move(newIndex)) {
148                 end = 0;
149                 cursor.close();
150                 set.updateNumExpectedItems();
151                 set.generateTitle(true);
152                 return;
153             }
154             if (set.mNumItemsLoaded == 0) {
155                 photosSchema.cursorToObject(cursor, photo);
156                 set.mMinTimestamp = photo.dateTaken;
157                 cursor.moveToLast();
158                 photosSchema.cursorToObject(cursor, photo);
159                 set.mMinTimestamp = photo.dateTaken;
160                 cursor.moveToFirst();
161             }
162             for (int i = 0; i < end; ++i) {
163                 photosSchema.cursorToObject(cursor, photo);
164                 MediaItem item = new MediaItem();
165                 item.mId = photo.id;
166                 item.mEditUri = photo.editUri;
167                 item.mMimeType = photo.contentType;
168                 item.mDateTakenInMs = photo.dateTaken;
169                 item.mLatitude = photo.latitude;
170                 item.mLongitude = photo.longitude;
171                 item.mThumbnailUri = photo.thumbnailUrl;
172                 item.mScreennailUri = photo.screennailUrl;
173                 item.mContentUri = photo.contentUrl;
174                 item.mCaption = photo.title;
175                 item.mWeblink = photo.htmlPageUrl;
176                 item.mDescription = photo.summary;
177                 item.mFilePath = item.mContentUri;
178                 feed.addItemToMediaSet(item, set);
179                 if (!cursor.moveToNext()) {
180                     break;
181                 }
182             }
183         } catch (Exception e) {
184             Log.e(TAG, "Error occurred loading photos for album " + set.mId);
185         } finally {
186             if (cursor != null) {
187                 cursor.close();
188             }
189         }
190     }
191
192     public void prime(final MediaItem item) {
193     }
194
195     public boolean performOperation(final int operation, final ArrayList<MediaBucket> mediaBuckets, final Object data) {
196         try {
197             if (operation == MediaFeed.OPERATION_DELETE) {
198                 ContentProviderClient client = mProviderClient;
199                 for (int i = 0, numBuckets = mediaBuckets.size(); i != numBuckets; ++i) {
200                     MediaBucket bucket = mediaBuckets.get(i);
201                     ArrayList<MediaItem> items = bucket.mediaItems;
202                     if (items == null) {
203                         // Delete an album.
204                         String albumUri = PicasaContentProvider.ALBUMS_URI + "/" + bucket.mediaSet.mId;
205                         client.delete(Uri.parse(albumUri), null, null);
206                     } else {
207                         // Delete a set of photos.
208                         for (int j = 0, numItems = items.size(); j != numItems; ++j) {
209                             MediaItem item = items.get(j);
210                             if (item != null) {
211                                 String itemUri = PicasaContentProvider.PHOTOS_URI + "/" + item.mId;
212                                 client.delete(Uri.parse(itemUri), null, null);
213                             }
214                         }
215                     }
216                 }
217             }
218             return true;
219         } catch (RemoteException e) {
220             return false;
221         }
222     }
223
224     public DiskCache getThumbnailCache() {
225         return sThumbnailCache;
226     }
227
228     /**
229      * The projection of PhotoEntry needed by the data source.
230      */
231     private static final class PhotoProjection extends Entry {
232         public static final EntrySchema SCHEMA = new EntrySchema(PhotoProjection.class);
233         @Column("edit_uri")
234         public String editUri;
235         @Column("title")
236         public String title;
237         @Column("summary")
238         public String summary;
239         @Column("date_taken")
240         public long dateTaken;
241         @Column("latitude")
242         public double latitude;
243         @Column("longitude")
244         public double longitude;
245         @Column("thumbnail_url")
246         public String thumbnailUrl;
247         @Column("screennail_url")
248         public String screennailUrl;
249         @Column("content_url")
250         public String contentUrl;
251         @Column("content_type")
252         public String contentType;
253         @Column("html_page_url")
254         public String htmlPageUrl;
255     }
256 }