blob: 1ee9e20fd1438941fb74a4d95cada0b29f8c4855 [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 {
100 cursor.close();
101 }
102 return null;
103 }
104
105 private static boolean contactExists(Context context, Uri contactUri) {
106 Cursor cursor = context.getContentResolver().query(contactUri, null, null, null, null);
107 try {
108 if (cursor != null && cursor.moveToFirst()) {
109 return true;
110 }
111 } finally {
112 cursor.close();
113 }
114 return false;
115 }
116
117 /** Returns the phone number of the contact. */
118 public static String getNumber(Context context, Uri contactUri) {
119 // TODO: Investigate if this can be done in 1 query instead of 2.
120 ContentResolver contentResolver = context.getContentResolver();
121 Cursor contactCursor = contentResolver.query(contactUri, null, null, null, null);
122 try {
123 if (contactCursor != null && contactCursor.moveToFirst()) {
124 String id = contactCursor.getString(
125 contactCursor.getColumnIndex(ContactsContract.Contacts._ID));
126 if (contactCursor.getInt(contactCursor.getColumnIndex(
127 ContactsContract.Contacts.HAS_PHONE_NUMBER)) != 0) {
128 Cursor phoneCursor = contentResolver.query(
129 ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
130 ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
131 new String[]{id}, null);
132 try {
133 if (phoneCursor != null && phoneCursor.moveToFirst()) {
134 return phoneCursor.getString(
135 phoneCursor.getColumnIndex(
136 ContactsContract.CommonDataKinds.Phone.NUMBER));
137 }
138 } finally {
139 phoneCursor.close();
140 }
141 }
142 }
143 } finally {
144 contactCursor.close();
145 }
146 return null;
147 }
148
mariagpuyol95dc0402016-02-17 11:12:46 -0800149 /** Returns the Bitmap corresponding to the contact's photo. */
150 public static Bitmap getContactPhoto(Context context, Uri contactUri) {
151 Uri photoUri = Uri.withAppendedPath(contactUri,
152 ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
153 Cursor cursor = context.getContentResolver().query(photoUri,
154 new String[]{ContactsContract.Contacts.Photo.PHOTO}, null, null, null);
155 if (cursor == null) {
156 return null;
157 }
158 try {
159 if (cursor.moveToFirst()) {
160 byte[] data = cursor.getBlob(0);
161 if (data != null) {
162 return BitmapFactory.decodeStream(new ByteArrayInputStream(data));
163 }
164 }
165 } finally {
166 cursor.close();
167 }
168 return null;
169 }
170
171
mariagpuyolaee23782016-02-16 13:29:49 -0800172 /** Returns whether the contact uri is not null and corresponds to an existing contact. */
173 private boolean isValidEmergencyContact(Uri contactUri) {
174 return contactUri != null && contactExists(mContext, contactUri);
175 }
176
177 private void setEmergencyContacts(Set<Uri> emergencyContacts) {
178 Set<String> emergencyContactStrings = new ArraySet<String>(emergencyContacts.size());
179 for (Uri contactUri : emergencyContacts) {
180 emergencyContactStrings.add(contactUri.toString());
181 }
182 mSharedPreferences.edit().putStringSet(mKey, emergencyContactStrings).commit();
183 }
184}