diff options
author | Tyler Gunn <tgunn@google.com> | 2015-08-07 01:55:08 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2015-08-07 01:55:08 +0000 |
commit | 9e9768d17a8980f7f688ba7c6861e8a74d46eb50 (patch) | |
tree | 9de8a05c08f176d81d4d765200d57173b6cd560f | |
parent | 1fe0223b00a631806e8bbad8b09752ca7389ca5d (diff) | |
parent | c35d396656363774843c84bd138e9f23367a5567 (diff) | |
download | android_packages_apps_ContactsCommon-9e9768d17a8980f7f688ba7c6861e8a74d46eb50.tar.gz android_packages_apps_ContactsCommon-9e9768d17a8980f7f688ba7c6861e8a74d46eb50.tar.bz2 android_packages_apps_ContactsCommon-9e9768d17a8980f7f688ba7c6861e8a74d46eb50.zip |
am c35d3966: Add CallHistory activity to CallSubjectDialog, plus others.
* commit 'c35d396656363774843c84bd138e9f23367a5567':
Add CallHistory activity to CallSubjectDialog, plus others.
-rw-r--r-- | res/layout/call_subject_history.xml | 33 | ||||
-rw-r--r-- | res/layout/dialog_call_subject.xml | 2 | ||||
-rw-r--r-- | res/values/colors.xml | 3 | ||||
-rw-r--r-- | res/values/styles.xml | 12 | ||||
-rw-r--r-- | src/com/android/contacts/common/CallUtil.java | 25 | ||||
-rw-r--r-- | src/com/android/contacts/common/dialog/CallSubjectDialog.java | 195 | ||||
-rw-r--r-- | src/com/android/contacts/common/dialog/CallSubjectHistory.java | 106 |
7 files changed, 357 insertions, 19 deletions
diff --git a/res/layout/call_subject_history.xml b/res/layout/call_subject_history.xml new file mode 100644 index 00000000..5f6ef3a7 --- /dev/null +++ b/res/layout/call_subject_history.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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 + --> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/background" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@android:color/transparent" > + + <ListView + android:id="@+id/subject_list" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_alignParentBottom="true" + android:background="@color/call_subject_history_background" + android:divider="@null" + android:elevation="8dp" /> + +</RelativeLayout>
\ No newline at end of file diff --git a/res/layout/dialog_call_subject.xml b/res/layout/dialog_call_subject.xml index 3b7adddf..005f4402 100644 --- a/res/layout/dialog_call_subject.xml +++ b/res/layout/dialog_call_subject.xml @@ -19,7 +19,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" - android:layout_height="match_parent" > + android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" diff --git a/res/values/colors.xml b/res/values/colors.xml index 7c212680..0dc85b51 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -163,4 +163,7 @@ <!-- Text color for the SEND & CALL button on the call subject dialog. --> <color name="call_subject_button">#00c853</color> + + <!-- Background color for the call subject history view. --> + <color name="call_subject_history_background">#ffffff</color> </resources> diff --git a/res/values/styles.xml b/res/values/styles.xml index 94916b88..6ab07d3e 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -98,4 +98,16 @@ background and text color. See also android:style/Widget.Holo.TextView.ListSepar <item name="android:windowFullscreen">true</item> <item name="android:windowIsFloating">true</item> </style> + + <!-- Theme used for the call subjection history selection activity. --> + <style name="Theme.CallSubjectSelector" parent="android:Theme.Material.Light"> + <item name="android:windowIsTranslucent">true</item> + <item name="android:windowNoTitle">true</item> + <item name="android:windowBackground">@android:color/transparent</item> + <item name="android:backgroundDimEnabled">false</item> + <item name="android:windowTranslucentStatus">false</item> + <item name="android:windowTranslucentNavigation">false</item> + <item name="android:windowDrawsSystemBarBackgrounds">false</item> + <item name="android:windowContentOverlay">@null</item> + </style> </resources> diff --git a/src/com/android/contacts/common/CallUtil.java b/src/com/android/contacts/common/CallUtil.java index 4f945523..a5587cac 100644 --- a/src/com/android/contacts/common/CallUtil.java +++ b/src/com/android/contacts/common/CallUtil.java @@ -116,4 +116,29 @@ public class CallUtil { } return false; } + + /** + * Determines if one of the call capable phone accounts defined supports calling with a subject + * specified. + * + * @param context The context. + * @return {@code true} if one of the call capable phone accounts supports calling with a + * subject specified, {@code false} otherwise. + */ + public static boolean isCallWithSubjectSupported(Context context) { + TelecomManager telecommMgr = (TelecomManager) + context.getSystemService(Context.TELECOM_SERVICE); + if (telecommMgr == null) { + return false; + } + + List<PhoneAccountHandle> accountHandles = telecommMgr.getCallCapablePhoneAccounts(); + for (PhoneAccountHandle accountHandle : accountHandles) { + PhoneAccount account = telecommMgr.getPhoneAccount(accountHandle); + if (account != null && account.hasCapabilities(PhoneAccount.CAPABILITY_CALL_SUBJECT)) { + return true; + } + } + return false; + } } diff --git a/src/com/android/contacts/common/dialog/CallSubjectDialog.java b/src/com/android/contacts/common/dialog/CallSubjectDialog.java index fb13940a..622be601 100644 --- a/src/com/android/contacts/common/dialog/CallSubjectDialog.java +++ b/src/com/android/contacts/common/dialog/CallSubjectDialog.java @@ -23,17 +23,24 @@ import android.app.DialogFragment; import android.app.FragmentTransaction; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; +import android.preference.PreferenceManager; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.text.Editable; +import android.text.InputFilter; import android.text.TextUtils; import android.text.TextWatcher; import android.util.Log; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.QuickContactBadge; import android.widget.TextView; @@ -43,6 +50,9 @@ import com.android.contacts.common.ContactPhotoManager; import com.android.contacts.common.R; import com.android.contacts.common.util.UriUtils; +import java.util.ArrayList; +import java.util.List; + /** * Implements a dialog which prompts for a call subject for an outgoing call. */ @@ -50,19 +60,25 @@ public class CallSubjectDialog extends DialogFragment { private static final String TAG = "CallSubjectDialog"; private static final String FRAGMENT_TAG = "callSubject"; private static final int CALL_SUBJECT_LIMIT = 16; + private static final int CALL_SUBJECT_HISTORY_SIZE = 5; + + private static final int REQUEST_SUBJECT = 1001; + + public static final String PREF_KEY_SUBJECT_HISTORY_COUNT = "subject_history_count"; + public static final String PREF_KEY_SUBJECT_HISTORY_ITEM = "subject_history_item"; /** * Fragment argument bundle keys: */ - private static final String ARG_PHOTO_ID = "PHOTO_ID"; - private static final String ARG_PHOTO_URI = "PHOTO_URI"; - private static final String ARG_CONTACT_URI = "CONTACT_URI"; - private static final String ARG_NAME_OR_NUMBER = "NAME_OR_NUMBER"; - private static final String ARG_IS_BUSINESS = "IS_BUSINESS"; - private static final String ARG_NUMBER = "NUMBER"; - private static final String ARG_DISPLAY_NUMBER = "DISPLAY_NUMBER"; - private static final String ARG_NUMBER_LABEL = "NUMBER_LABEL"; - private static final String ARG_PHONE_ACCOUNT_HANDLE = "PHONE_ACCOUNT_HANDLE"; + public static final String ARG_PHOTO_ID = "PHOTO_ID"; + public static final String ARG_PHOTO_URI = "PHOTO_URI"; + public static final String ARG_CONTACT_URI = "CONTACT_URI"; + public static final String ARG_NAME_OR_NUMBER = "NAME_OR_NUMBER"; + public static final String ARG_IS_BUSINESS = "IS_BUSINESS"; + public static final String ARG_NUMBER = "NUMBER"; + public static final String ARG_DISPLAY_NUMBER = "DISPLAY_NUMBER"; + public static final String ARG_NUMBER_LABEL = "NUMBER_LABEL"; + public static final String ARG_PHONE_ACCOUNT_HANDLE = "PHONE_ACCOUNT_HANDLE"; private Context mContext; private QuickContactBadge mContactPhoto; @@ -75,6 +91,8 @@ public class CallSubjectDialog extends DialogFragment { private int mLimit = CALL_SUBJECT_LIMIT; private int mPhotoSize; + private SharedPreferences mPrefs; + private List<String> mSubjectHistory; private long mPhotoID; private Uri mPhotoUri; @@ -112,7 +130,10 @@ public class CallSubjectDialog extends DialogFragment { private final View.OnClickListener mHistoryOnClickListener = new View.OnClickListener() { @Override public void onClick(View v) { - // TODO: Implement this (future CL). + hideSoftKeyboard(mContext, mCallSubjectView); + Intent intent = new Intent(mContext, CallSubjectHistory.class); + setTargetFragment(CallSubjectDialog.this, REQUEST_SUBJECT); + startActivityForResult(intent, REQUEST_SUBJECT); } }; @@ -122,17 +143,41 @@ public class CallSubjectDialog extends DialogFragment { private final View.OnClickListener mSendAndCallOnClickListener = new View.OnClickListener() { @Override public void onClick(View v) { + hideSoftKeyboard(mContext, mCallSubjectView); + String subject = mCallSubjectView.getText().toString(); Intent intent = CallUtil.getCallWithSubjectIntent(mNumber, mPhoneAccountHandle, - mCallSubjectView.getText().toString()); + subject); final TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); tm.placeCall(intent.getData(), intent.getExtras()); + + mSubjectHistory.add(subject); + saveSubjectHistory(mSubjectHistory); getDialog().dismiss(); } }; /** + * Show the call subhect dialog given a phone number to dial (e.g. from the dialpad). + * + * @param activity The activity. + * @param number The number to dial. + */ + public static void start(Activity activity, String number) { + start(activity, + -1 /* photoId */, + null /* photoUri */, + null /* contactUri */, + number /* nameOrNumber */, + false /* isBusiness */, + number /* number */, + null /* displayNumber */, + null /* numberLabel */, + null /* phoneAccountHandle */); + } + + /** * Creates a call subject dialog. * * @param activity The current activity. @@ -149,8 +194,6 @@ public class CallSubjectDialog extends DialogFragment { public static void start(Activity activity, long photoId, Uri photoUri, Uri contactUri, String nameOrNumber, boolean isBusiness, String number, String displayNumber, String numberLabel, PhoneAccountHandle phoneAccountHandle) { - final FragmentTransaction ft = activity.getFragmentManager().beginTransaction(); - final CallSubjectDialog fragment = new CallSubjectDialog(); Bundle arguments = new Bundle(); arguments.putLong(ARG_PHOTO_ID, photoId); arguments.putParcelable(ARG_PHOTO_URI, photoUri); @@ -161,6 +204,19 @@ public class CallSubjectDialog extends DialogFragment { arguments.putString(ARG_DISPLAY_NUMBER, displayNumber); arguments.putString(ARG_NUMBER_LABEL, numberLabel); arguments.putParcelable(ARG_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); + start(activity, arguments); + } + + /** + * Shows the call subject dialog given a Bundle containing all the arguments required to + * display the dialog (e.g. from Quick Contacts). + * + * @param activity The activity. + * @param arguments The arguments bundle. + */ + public static void start(Activity activity, Bundle arguments) { + final FragmentTransaction ft = activity.getFragmentManager().beginTransaction(); + final CallSubjectDialog fragment = new CallSubjectDialog(); fragment.setArguments(arguments); fragment.show(ft, FRAGMENT_TAG); } @@ -176,9 +232,11 @@ public class CallSubjectDialog extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { mContext = getActivity(); + mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext); mPhotoSize = mContext.getResources().getDimensionPixelSize( R.dimen.call_subject_dialog_contact_photo_size); readArguments(); + mSubjectHistory = loadSubjectHistory(mPrefs); LayoutInflater inflater = getActivity().getLayoutInflater(); View view = inflater.inflate(R.layout.dialog_call_subject, null); @@ -188,21 +246,23 @@ public class CallSubjectDialog extends DialogFragment { mNumberView = (TextView) view.findViewById(R.id.number); mCallSubjectView = (EditText) view.findViewById(R.id.call_subject); mCallSubjectView.addTextChangedListener(mTextWatcher); + InputFilter[] filters = new InputFilter[1]; + filters[0] = new InputFilter.LengthFilter(mLimit); + mCallSubjectView.setFilters(filters); + mCharacterLimitView = (TextView) view.findViewById(R.id.character_limit); mHistoryButton = view.findViewById(R.id.history_button); mHistoryButton.setOnClickListener(mHistoryOnClickListener); + mHistoryButton.setVisibility(mSubjectHistory.isEmpty() ? View.GONE : View.VISIBLE); mSendAndCallButton = view.findViewById(R.id.send_and_call_button); mSendAndCallButton.setOnClickListener(mSendAndCallOnClickListener); + showSoftKeyboard(mContext, mCallSubjectView); updateContactInfo(); updateCharacterLimit(); AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity()); dialogBuilder.setView(view); - final AlertDialog dialog = dialogBuilder.create(); - - dialog.getWindow().setLayout(ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.FILL_PARENT); return dialogBuilder.create(); } @@ -210,7 +270,11 @@ public class CallSubjectDialog extends DialogFragment { * Populates the contact info fields based on the current contact information. */ private void updateContactInfo() { - setPhoto(mPhotoID, mPhotoUri, mContactUri, mNameOrNumber, mIsBusiness); + if (mContactUri != null) { + setPhoto(mPhotoID, mPhotoUri, mContactUri, mNameOrNumber, mIsBusiness); + } else { + mContactPhoto.setVisibility(View.GONE); + } mNameView.setText(mNameOrNumber); if (!TextUtils.isEmpty(mNumberLabel) && !TextUtils.isEmpty(mDisplayNumber)) { mNumberView.setVisibility(View.VISIBLE); @@ -229,6 +293,7 @@ public class CallSubjectDialog extends DialogFragment { Bundle arguments = getArguments(); if (arguments == null) { Log.e(TAG, "Arguments cannot be null."); + return; } mPhotoID = arguments.getLong(ARG_PHOTO_ID); mPhotoUri = arguments.getParcelable(ARG_PHOTO_URI); @@ -296,4 +361,98 @@ public class CallSubjectDialog extends DialogFragment { false /* darkTheme */, true /* isCircular */, request); } } + + /** + * Loads the subject history from shared preferences. + * + * @param prefs Shared preferences. + * @return List of subject history strings. + */ + public static List<String> loadSubjectHistory(SharedPreferences prefs) { + int historySize = prefs.getInt(PREF_KEY_SUBJECT_HISTORY_COUNT, 0); + List<String> subjects = new ArrayList(historySize); + + for (int ix = 0 ; ix < historySize; ix++) { + String historyItem = prefs.getString(PREF_KEY_SUBJECT_HISTORY_ITEM + ix, null); + if (!TextUtils.isEmpty(historyItem)) { + subjects.add(historyItem); + } + } + + return subjects; + } + + /** + * Saves the subject history list to shared prefs, removing older items so that there are only + * {@link #CALL_SUBJECT_HISTORY_SIZE} items at most. + * + * @param history The history. + */ + private void saveSubjectHistory(List<String> history) { + // Remove oldest subject(s). + while (history.size() > CALL_SUBJECT_HISTORY_SIZE) { + history.remove(0); + } + + SharedPreferences.Editor editor = mPrefs.edit(); + int historyCount = 0; + for (String subject : history) { + if (!TextUtils.isEmpty(subject)) { + editor.putString(PREF_KEY_SUBJECT_HISTORY_ITEM + historyCount, + subject); + historyCount++; + } + } + editor.putInt(PREF_KEY_SUBJECT_HISTORY_COUNT, historyCount); + editor.apply(); + } + + /** + * Handles results from the CallSubjectHistory activity. + * + * @param requestCode The integer request code originally supplied to + * startActivityForResult(), allowing you to identify who this + * result came from. + * @param resultCode The integer result code returned by the child activity + * through its setResult(). + * @param data An Intent, which can return result data to the caller + */ + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode != REQUEST_SUBJECT || data == null) { + return; + } + + if (resultCode != Activity.RESULT_OK) { + return; + } + + String chosenSubject = data.getStringExtra(CallSubjectHistory.EXTRA_CHOSEN_SUBJECT); + mCallSubjectView.setText(chosenSubject); + super.onActivityResult(requestCode, resultCode, data); + } + + /** + * Hide software keyboard for the given {@link View}. + */ + public void hideSoftKeyboard(Context context, View view) { + InputMethodManager imm = (InputMethodManager) context.getSystemService( + Context.INPUT_METHOD_SERVICE); + if (imm != null) { + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + } + + /** + * Show software keyboard for the given {@link View}. + */ + public void showSoftKeyboard(Context context, View view) { + view.requestFocus(); + InputMethodManager imm = (InputMethodManager) context.getSystemService( + Context.INPUT_METHOD_SERVICE); + if (imm != null) { + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, + InputMethodManager.HIDE_IMPLICIT_ONLY); + } + } } diff --git a/src/com/android/contacts/common/dialog/CallSubjectHistory.java b/src/com/android/contacts/common/dialog/CallSubjectHistory.java new file mode 100644 index 00000000..1e983e60 --- /dev/null +++ b/src/com/android/contacts/common/dialog/CallSubjectHistory.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2015 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.contacts.common.dialog; + +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewTreeObserver; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ListView; + +import com.android.contacts.common.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * List activity which displays the call subject history. Shows at the bottom of the screen, + * on top of existing content. + */ +public class CallSubjectHistory extends Activity { + public static final String EXTRA_CHOSEN_SUBJECT = + "com.android.contracts.common.dialog.extra.CHOSEN_SUBJECT"; + + private View mBackground; + private ListView mSubjectList; + private SharedPreferences mSharedPreferences; + private List<String> mSubjects; + + /** + * Click listener which handles user clicks outside of the list view. Dismisses the activity + * and returns a {@link Activity#RESULT_CANCELED} result code. + */ + private View.OnClickListener mBackgroundListner = new View.OnClickListener() { + @Override + public void onClick(View v) { + setResult(RESULT_CANCELED); + finish(); + } + }; + + /** + * Item click listener which handles user clicks on the items in the list view. Dismisses + * the activity, returning the subject to the caller and closing the activity with the + * {@link Activity#RESULT_OK} result code. + */ + private AdapterView.OnItemClickListener mItemClickListener = + new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3) { + returnSubject(mSubjects.get(position)); + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + mSubjects = CallSubjectDialog.loadSubjectHistory(mSharedPreferences); + + this.requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(R.layout.call_subject_history); + + mBackground = findViewById(R.id.background); + mBackground.setOnClickListener(mBackgroundListner); + + mSubjectList = (ListView) findViewById(R.id.subject_list); + mSubjectList.setOnItemClickListener(mItemClickListener); + + ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, + android.R.layout.simple_list_item_1, mSubjects); + mSubjectList.setAdapter(adapter); + } + + /** + * Closes the activity and returns the subject chosen by the user to the caller. + * + * @param chosenSubject The chosen subject. + */ + private void returnSubject(String chosenSubject) { + Intent intent = getIntent(); + intent.putExtra(EXTRA_CHOSEN_SUBJECT, chosenSubject); + setResult(RESULT_OK, intent); + finish(); + } +} |