|
1 /* |
|
2 * Copyright (C) 2013 Square, Inc. |
|
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.squareup.picasso; |
|
17 |
|
18 import android.annotation.TargetApi; |
|
19 import android.content.ContentResolver; |
|
20 import android.content.Context; |
|
21 import android.content.UriMatcher; |
|
22 import android.graphics.Bitmap; |
|
23 import android.graphics.BitmapFactory; |
|
24 import android.net.Uri; |
|
25 import android.provider.ContactsContract; |
|
26 |
|
27 import java.io.IOException; |
|
28 import java.io.InputStream; |
|
29 |
|
30 import static android.os.Build.VERSION.SDK_INT; |
|
31 import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH; |
|
32 import static android.provider.ContactsContract.Contacts.openContactPhotoInputStream; |
|
33 import static com.squareup.picasso.Picasso.LoadedFrom.DISK; |
|
34 |
|
35 class ContactsPhotoBitmapHunter extends BitmapHunter { |
|
36 /** A lookup uri (e.g. content://com.android.contacts/contacts/lookup/3570i61d948d30808e537) */ |
|
37 private static final int ID_LOOKUP = 1; |
|
38 /** A contact thumbnail uri (e.g. content://com.android.contacts/contacts/38/photo) */ |
|
39 private static final int ID_THUMBNAIL = 2; |
|
40 /** A contact uri (e.g. content://com.android.contacts/contacts/38) */ |
|
41 private static final int ID_CONTACT = 3; |
|
42 /** |
|
43 * A contact display photo (high resolution) uri |
|
44 * (e.g. content://com.android.contacts/display_photo/5) |
|
45 */ |
|
46 private static final int ID_DISPLAY_PHOTO = 4; |
|
47 |
|
48 private static final UriMatcher matcher; |
|
49 |
|
50 static { |
|
51 matcher = new UriMatcher(UriMatcher.NO_MATCH); |
|
52 matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", ID_LOOKUP); |
|
53 matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", ID_LOOKUP); |
|
54 matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", ID_THUMBNAIL); |
|
55 matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", ID_CONTACT); |
|
56 matcher.addURI(ContactsContract.AUTHORITY, "display_photo/#", ID_DISPLAY_PHOTO); |
|
57 } |
|
58 |
|
59 final Context context; |
|
60 |
|
61 ContactsPhotoBitmapHunter(Context context, Picasso picasso, Dispatcher dispatcher, Cache cache, |
|
62 Stats stats, Action action) { |
|
63 super(picasso, dispatcher, cache, stats, action); |
|
64 this.context = context; |
|
65 } |
|
66 |
|
67 @Override Bitmap decode(Request data) throws IOException { |
|
68 InputStream is = null; |
|
69 try { |
|
70 is = getInputStream(); |
|
71 return decodeStream(is, data); |
|
72 } finally { |
|
73 Utils.closeQuietly(is); |
|
74 } |
|
75 } |
|
76 |
|
77 @Override Picasso.LoadedFrom getLoadedFrom() { |
|
78 return DISK; |
|
79 } |
|
80 |
|
81 private InputStream getInputStream() throws IOException { |
|
82 ContentResolver contentResolver = context.getContentResolver(); |
|
83 Uri uri = getData().uri; |
|
84 switch (matcher.match(uri)) { |
|
85 case ID_LOOKUP: |
|
86 uri = ContactsContract.Contacts.lookupContact(contentResolver, uri); |
|
87 if (uri == null) { |
|
88 return null; |
|
89 } |
|
90 // Resolved the uri to a contact uri, intentionally fall through to process the resolved uri |
|
91 case ID_CONTACT: |
|
92 if (SDK_INT < ICE_CREAM_SANDWICH) { |
|
93 return openContactPhotoInputStream(contentResolver, uri); |
|
94 } else { |
|
95 return ContactPhotoStreamIcs.get(contentResolver, uri); |
|
96 } |
|
97 case ID_THUMBNAIL: |
|
98 case ID_DISPLAY_PHOTO: |
|
99 return contentResolver.openInputStream(uri); |
|
100 default: |
|
101 throw new IllegalStateException("Invalid uri: " + uri); |
|
102 } |
|
103 } |
|
104 |
|
105 private Bitmap decodeStream(InputStream stream, Request data) throws IOException { |
|
106 if (stream == null) { |
|
107 return null; |
|
108 } |
|
109 BitmapFactory.Options options = null; |
|
110 if (data.hasSize()) { |
|
111 options = new BitmapFactory.Options(); |
|
112 options.inJustDecodeBounds = true; |
|
113 InputStream is = getInputStream(); |
|
114 try { |
|
115 BitmapFactory.decodeStream(is, null, options); |
|
116 } finally { |
|
117 Utils.closeQuietly(is); |
|
118 } |
|
119 calculateInSampleSize(data.targetWidth, data.targetHeight, options); |
|
120 } |
|
121 return BitmapFactory.decodeStream(stream, null, options); |
|
122 } |
|
123 |
|
124 @TargetApi(ICE_CREAM_SANDWICH) |
|
125 private static class ContactPhotoStreamIcs { |
|
126 static InputStream get(ContentResolver contentResolver, Uri uri) { |
|
127 return openContactPhotoInputStream(contentResolver, uri, true); |
|
128 } |
|
129 } |
|
130 } |