blob: 69c91f630a154c8a6119b2d9ef75ac423202cf03 [file] [log] [blame]
mariagpuyolaee23782016-02-16 13:29:49 -08001/*
2 * Copyright (C) 2016 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.emergency;
17
18import android.content.ContentResolver;
19import android.content.Context;
20import android.content.SharedPreferences;
21import android.database.Cursor;
mariagpuyol95dc0402016-02-17 11:12:46 -080022import android.graphics.Bitmap;
23import android.graphics.BitmapFactory;
mariagpuyolaee23782016-02-16 13:29:49 -080024import android.net.Uri;
25import android.provider.ContactsContract;
26import android.util.ArraySet;
27
mariagpuyol95dc0402016-02-17 11:12:46 -080028import java.io.ByteArrayInputStream;
mariagpuyolaee23782016-02-16 13:29:49 -080029import java.util.Collections;
30import java.util.Set;
31
32/**
33 * Manages emergency contacts of the user.
34 */
35public class EmergencyContactManager {
36 private final SharedPreferences mSharedPreferences;
37 private final String mKey;
38 private final Context mContext;
39
40 /**
41 * Creates a new instance initialized with context and the shared preferences used to store the
42 * emergency contacts under the specified key.
43 */
44 public EmergencyContactManager(Context context, SharedPreferences sharedPreferences,
45 String key) {
46 mContext = context;
47 mSharedPreferences = sharedPreferences;
48 mKey = key;
49 }
50
51 /**
52 * Adds a new contact to the emergency contacts. */
53 public void addContact(Uri contactUri) {
54 // TODO: Consider refactoring this to use always setContacts() rather than
55 // addContact()/removeContact()
56 Set<Uri> emergencyContacts = getEmergencyContacts();
57 if (emergencyContacts.add(contactUri)) {
58 setEmergencyContacts(emergencyContacts);
59 }
60 }
61
62 /** Removes the specified contact from the list of emergency contacts. */
63 public void removeContact(Uri contactUri) {
64 // TODO: Consider refactoring this to use always setContacts() rather than
65 // addContact()/removeContact()
66 Set<Uri> emergencyContacts = getEmergencyContacts();
67 if (emergencyContacts.remove(contactUri)) {
68 setEmergencyContacts(emergencyContacts);
69 }
70 }
71
72 public Set<Uri> getEmergencyContacts() {
73 Set<String> emergencyContactStrings = mSharedPreferences.getStringSet(mKey,
74 Collections.<String>emptySet());
75 Set<Uri> emergencyContacts = new ArraySet<Uri>(emergencyContactStrings.size());
76 for (String emergencyContact : emergencyContactStrings) {
77 Uri contactUri = Uri.parse(emergencyContact);
78 if (isValidEmergencyContact(contactUri)) {
79 emergencyContacts.add(contactUri);
80 }
81 }
82 // If not all contacts were added, then we need to overwrite the emergency contacts stored
83 // in shared preferences. This deals with emergency contacts being deleted from contacts:
84 // currently we have no way to being notified when this happens.
85 if (emergencyContacts.size() != emergencyContactStrings.size()) {
86 setEmergencyContacts(emergencyContacts);
87 }
88 return emergencyContacts;
89 }
90
91 /** Returns the display name of the contact. */
92 public static String getName(Context context, Uri contactUri) {
93 Cursor cursor = context.getContentResolver().query(contactUri, null, null, null, null);
94 try {
95 if (cursor != null && cursor.moveToFirst()) {
96 return cursor.getString(cursor.getColumnIndex(
97 ContactsContract.Contacts.DISPLAY_NAME));
98 }
99 } finally {
mariagpuyol0504a442016-02-17 16:22:57 -0800100 if (cursor != null) {
101 cursor.close();
102 }
mariagpuyolaee23782016-02-16 13:29:49 -0800103 }
104 return null;
105 }
106
107 private static boolean contactExists(Context context, Uri contactUri) {
108 Cursor cursor = context.getContentResolver().query(contactUri, null, null, null, null);
109 try {
110 if (cursor != null && cursor.moveToFirst()) {
111 return true;
112 }
113 } finally {
mariagpuyol0504a442016-02-17 16:22:57 -0800114 if (cursor != null) {
115 cursor.close();
116 }
mariagpuyolaee23782016-02-16 13:29:49 -0800117 }
118 return false;
119 }
120
mariagpuyol0504a442016-02-17 16:22:57 -0800121
mariagpuyolaee23782016-02-16 13:29:49 -0800122 /** Returns the phone number of the contact. */
mariagpuyol0504a442016-02-17 16:22:57 -0800123 public static String[] getPhoneNumbers(Context context, Uri contactUri) {
124 // TODO: Investigate passing around CONTENT_LOOKUP_URI instead of content CONTENT_URI.
125 // The method to get the CONTENT_LOOKUP_URI when the user selects a contact is:
126 // ContactsContract.Contacts.getLookupUri(ContentResolver resolver, Uri contactUri)
127 // Then use ContactsContract.Contacts.lookupContact(ContentResolver resolver, Uri lookupUri)
128 // to get the CONTENT_URI
mariagpuyolaee23782016-02-16 13:29:49 -0800129 ContentResolver contentResolver = context.getContentResolver();
130 Cursor contactCursor = contentResolver.query(contactUri, null, null, null, null);
131 try {
132 if (contactCursor != null && contactCursor.moveToFirst()) {
mariagpuyolaee23782016-02-16 13:29:49 -0800133 if (contactCursor.getInt(contactCursor.getColumnIndex(
134 ContactsContract.Contacts.HAS_PHONE_NUMBER)) != 0) {
mariagpuyol0504a442016-02-17 16:22:57 -0800135 String id = contactCursor.getString(
136 contactCursor.getColumnIndex(ContactsContract.Contacts._ID));
mariagpuyolaee23782016-02-16 13:29:49 -0800137 Cursor phoneCursor = contentResolver.query(
mariagpuyol0504a442016-02-17 16:22:57 -0800138 ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
139 null,
140 ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + id,
141 null,
142 null);
mariagpuyolaee23782016-02-16 13:29:49 -0800143 try {
144 if (phoneCursor != null && phoneCursor.moveToFirst()) {
mariagpuyol0504a442016-02-17 16:22:57 -0800145 String[] phoneNumbers =
146 new String[phoneCursor.getCount()];
147 for (int i = 0; i < phoneCursor.getCount(); i++) {
148 String phoneNumber =
149 phoneCursor.getString(phoneCursor.getColumnIndex(
150 ContactsContract.CommonDataKinds.Phone.NUMBER));
151
152 phoneNumbers[i] = phoneNumber;
153 phoneCursor.moveToNext();
154 }
155 return phoneNumbers;
mariagpuyolaee23782016-02-16 13:29:49 -0800156 }
157 } finally {
mariagpuyol0504a442016-02-17 16:22:57 -0800158 if (phoneCursor != null) {
159 phoneCursor.close();
160 }
mariagpuyolaee23782016-02-16 13:29:49 -0800161 }
162 }
163 }
164 } finally {
mariagpuyol0504a442016-02-17 16:22:57 -0800165 if (contactCursor != null) {
166 contactCursor.close();
167 }
mariagpuyolaee23782016-02-16 13:29:49 -0800168 }
169 return null;
170 }
171
mariagpuyol95dc0402016-02-17 11:12:46 -0800172 /** Returns the Bitmap corresponding to the contact's photo. */
173 public static Bitmap getContactPhoto(Context context, Uri contactUri) {
174 Uri photoUri = Uri.withAppendedPath(contactUri,
175 ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
176 Cursor cursor = context.getContentResolver().query(photoUri,
177 new String[]{ContactsContract.Contacts.Photo.PHOTO}, null, null, null);
178 if (cursor == null) {
179 return null;
180 }
181 try {
182 if (cursor.moveToFirst()) {
183 byte[] data = cursor.getBlob(0);
184 if (data != null) {
185 return BitmapFactory.decodeStream(new ByteArrayInputStream(data));
186 }
187 }
188 } finally {
189 cursor.close();
190 }
191 return null;
192 }
193
194
mariagpuyolaee23782016-02-16 13:29:49 -0800195 /** Returns whether the contact uri is not null and corresponds to an existing contact. */
196 private boolean isValidEmergencyContact(Uri contactUri) {
197 return contactUri != null && contactExists(mContext, contactUri);
198 }
199
200 private void setEmergencyContacts(Set<Uri> emergencyContacts) {
201 Set<String> emergencyContactStrings = new ArraySet<String>(emergencyContacts.size());
202 for (Uri contactUri : emergencyContacts) {
203 emergencyContactStrings.add(contactUri.toString());
204 }
205 mSharedPreferences.edit().putStringSet(mKey, emergencyContactStrings).commit();
206 }
207}