blob: bb606647acfc5ee933f87940882339e0756d50b7 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.emergency;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.provider.ContactsContract;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import java.util.Set;
/**
* Fragment that displays health information and emergency contacts.
* Takes in boolean readOnly to determine whether or not to allow information to be edited.
*/
public class EmergencyInfoFragment extends PreferenceFragment
implements ContactPreference.DeleteContactListener {
/** Result code for contact picker */
private static final int CONTACT_PICKER_RESULT = 1001;
/** Request code for runtime contacts permission */
private static final int PERMISSION_REQUEST = 1002;
/** Key for description preference */
private static final String DESCRIPTION_KEY = "description";
/** Key for emergency contacts preference */
private static final String EMERGENCY_CONTACTS_KEY = "emergency_contacts";
/** Key to look up whether or not the fragment should be read only from the bundle */
private static final String READ_ONLY_KEY = "read_only";
/** Key for date of birth preference */
private static final String DATE_OF_BIRTH_KEY = "date_of_birth";
/** Keys for all editable preferences- used to set up bindings */
private static final String[] PREFERENCE_KEYS = {"name", "address", DATE_OF_BIRTH_KEY,
"blood_type", "allergies", "medications", "medical_conditions", "organ_donor"};
/** Whether or not this fragment should be read only */
private boolean mReadOnly;
/** SharedPreferences- initialized in onCreate */
private SharedPreferences mSharedPreferences = null;
/** Emergency contact manager that handles adding an removing emergency contacts. */
private EmergencyContactManager mEmergencyContactManager;
/** Reference to the preferenceScreen controlled by this fragment */
private PreferenceScreen mPreferenceScreen;
/**
* Creates a new EmergencyInfoFragment that can be used to edit user info if {@code readOnly}
* is false. Otherwise, it provides a non-editable view of the emergency info.
*/
public static EmergencyInfoFragment createEmergencyInfoFragment(boolean readOnly) {
Bundle emergencyInfoArgs = new Bundle();
emergencyInfoArgs.putBoolean(READ_ONLY_KEY, readOnly);
EmergencyInfoFragment emergencyInfoFragment = new EmergencyInfoFragment();
emergencyInfoFragment.setArguments(emergencyInfoArgs);
return emergencyInfoFragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.emergency_info_layout, container, false);
FloatingActionButton editInfoButton =
(FloatingActionButton) view.findViewById(R.id.fab);
// The button is the entry point from ViewInfoActivity to EditInfoActivity.
if (!mReadOnly) {
editInfoButton.setVisibility(View.GONE);
} else {
editInfoButton.setVisibility(View.VISIBLE);
editInfoButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(getActivity(), EditInfoActivity.class);
startActivity(intent);
}
});
}
return view;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.emergency_info);
mReadOnly = getArguments().getBoolean(READ_ONLY_KEY);
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
mEmergencyContactManager = new EmergencyContactManager(getContext(), mSharedPreferences,
EMERGENCY_CONTACTS_KEY);
mPreferenceScreen = getPreferenceScreen();
for (String preferenceKey : PREFERENCE_KEYS) {
Preference preference = findPreference(preferenceKey);
if (!preferenceKey.equals(DATE_OF_BIRTH_KEY)) {
bindPreferenceSummaryToValue(preference);
}
if (mReadOnly) {
preference.setEnabled(false);
preference.setShouldDisableView(false);
preference.setSelectable(false);
}
}
populateEmergencyContacts();
if (mReadOnly) {
Preference description = findPreference(DESCRIPTION_KEY);
mPreferenceScreen.removePreference(description);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CONTACT_PICKER_RESULT && resultCode == Activity.RESULT_OK) {
Uri uri = data.getData();
mEmergencyContactManager.addContact(uri);
MetricsLogger.action(getContext(), MetricsEvent.ACTION_ADD_EMERGENCY_CONTACT);
populateEmergencyContacts();
// TODO: If there are multiple phone numbers, ask the user to pick one.
if (EmergencyContactManager.getNumber(getContext(), uri) == null) {
// TODO: show warning dialog: no phone number
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[],
int[] grantResults) {
if (requestCode == PERMISSION_REQUEST) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
populateEmergencyContacts();
} else {
mPreferenceScreen.removePreference(findPreference(EMERGENCY_CONTACTS_KEY));
}
}
}
@Override
public void onContactDelete(Uri contactUri) {
mEmergencyContactManager.removeContact(contactUri);
MetricsLogger.action(getContext(), MetricsEvent.ACTION_DELETE_EMERGENCY_CONTACT);
populateEmergencyContacts();
}
private static final Preference.OnPreferenceChangeListener
sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
MetricsLogger.action(preference.getContext(),
MetricsEvent.ACTION_EDIT_EMERGENCY_INFO_FIELD, preference.getKey());
if (preference instanceof ListPreference) {
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
if (index >= 0) {
preference.setSummary(listPreference.getEntries()[index]);
}
} else {
if (!stringValue.isEmpty()) {
preference.setSummary(stringValue);
} else {
preference.setSummary(preference.getContext()
.getResources().getString(R.string.default_summary_none));
}
}
return true;
}
};
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* @see #sBindPreferenceSummaryToValueListener
*/
private void bindPreferenceSummaryToValue(Preference preference) {
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
mSharedPreferences.getString(preference.getKey(), ""));
}
private void populateEmergencyContacts() {
PreferenceCategory emergencyContactsCategory =
(PreferenceCategory) findPreference(EMERGENCY_CONTACTS_KEY);
// TODO: Use a list adapter instead of removing all each time.
emergencyContactsCategory.removeAll();
Set<Uri> emergencyContacts = mEmergencyContactManager.getEmergencyContacts();
if (!emergencyContacts.isEmpty()) {
// Get permission if necessary, else populate emergency contacts list
boolean hasContactsPermission = ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED;
boolean hasCallPermission = ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED;
if (!hasContactsPermission || !hasCallPermission) {
requestPermissions(new String[]{
Manifest.permission.READ_CONTACTS,
Manifest.permission.CALL_PHONE}, PERMISSION_REQUEST);
} else {
for (Uri contactUri : emergencyContacts) {
final ContactPreference contactPreference =
new ContactPreference(getContext(),
contactUri,
EmergencyContactManager.getName(getContext(), contactUri),
this);
contactPreference.setOnPreferenceClickListener(
createContactPreferenceClickListener(contactPreference));
emergencyContactsCategory.addPreference(contactPreference);
}
}
}
if (!mReadOnly) {
// If in edit mode, add a button to create a new emergency contact.
emergencyContactsCategory.addPreference(createAddEmergencyContactPreference());
} else if (emergencyContactsCategory.getPreferenceCount() == 0) {
// If in view mode and there are no contacts, remove the section entirely.
mPreferenceScreen.removePreference(emergencyContactsCategory);
}
}
private Preference.OnPreferenceClickListener createContactPreferenceClickListener(
final ContactPreference contactPreference) {
return new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
if (mReadOnly) {
contactPreference.callContact();
} else {
contactPreference.displayContact();
}
return true;
}
};
}
/** Generates an add contact button */
private Preference createAddEmergencyContactPreference() {
Preference addEmergencyContact = new Preference(getContext());
addEmergencyContact.setTitle(getString(R.string.add_emergency_contact));
addEmergencyContact.setIcon(getResources().getDrawable(R.drawable.ic_menu_add_dark));
addEmergencyContact.setOnPreferenceClickListener(new Preference
.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Intent contactPickerIntent = new Intent(Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(contactPickerIntent, CONTACT_PICKER_RESULT);
return true;
}
});
return addEmergencyContact;
}
}