Adds package picker for sending text messages.
Bug: 10608694
Change-Id: I645f00135615d29b78e72b80584fea0410d7da8d
diff --git a/src/com/android/phone/CallCommandService.java b/src/com/android/phone/CallCommandService.java
index 371ca7b..04c26d0 100644
--- a/src/com/android/phone/CallCommandService.java
+++ b/src/com/android/phone/CallCommandService.java
@@ -80,14 +80,13 @@
CallResult result = mCallModeler.getCallWithId(callId);
if (result != null) {
final String number = result.getConnection().getAddress();
+
Log.v(TAG, "Hanging up");
PhoneUtils.hangupRingingCall(result.getConnection().getCall());
+
if (rejectWithMessage) {
- if (message != null) {
- mRejectWithTextMessageManager.rejectCallWithMessage(number, message);
- } else {
- mRejectWithTextMessageManager.rejectCallWithNewMessage(number);
- }
+ mRejectWithTextMessageManager.rejectCallWithMessage(
+ result.getConnection().getCall(), message);
}
}
} catch (Exception e) {
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index dc7d64b..db06c30 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -1034,16 +1034,12 @@
//
boolean isRinging = (state == PhoneConstants.State.RINGING);
boolean isDialing = (phone.getForegroundCall().getState() == Call.State.DIALING);
- boolean showingQuickResponseDialog = (mInCallScreen != null) &&
- mInCallScreen.isQuickResponseDialogShowing();
boolean showingDisconnectedConnection =
PhoneUtils.hasDisconnectedConnections(phone) && isShowingCallScreen;
- boolean keepScreenOn = isRinging || isDialing ||
- (showingDisconnectedConnection && !showingQuickResponseDialog);
+ boolean keepScreenOn = isRinging || isDialing || showingDisconnectedConnection;
if (DBG) Log.d(LOG_TAG, "updateWakeState: keepScreenOn = " + keepScreenOn
+ " (isRinging " + isRinging
+ ", isDialing " + isDialing
- + ", showingQuickResponse " + showingQuickResponseDialog
+ ", showingDisc " + showingDisconnectedConnection + ")");
// keepScreenOn == true means we'll hold a full wake lock:
requestWakeState(keepScreenOn ? WakeState.FULL : WakeState.SLEEP);
diff --git a/src/com/android/phone/RejectWithTextMessageManager.java b/src/com/android/phone/RejectWithTextMessageManager.java
index b03211a..fda8f78 100644
--- a/src/com/android/phone/RejectWithTextMessageManager.java
+++ b/src/com/android/phone/RejectWithTextMessageManager.java
@@ -73,7 +73,11 @@
/** SharedPreferences file name for our persistent settings. */
private static final String SHARED_PREFERENCES_NAME = "respond_via_sms_prefs";
- // Preference keys for the 4 "canned responses"; see RespondViaSmsManager$Settings.
+ private Intent mIntent;
+
+ private ArrayList<ComponentName> mComponentsWithPermission = new ArrayList<ComponentName>();
+
+ // Preference keys for the 4 "canned responses"; see RespondViaSmsManager$Settings.
// Since (for now at least) the number of messages is fixed at 4, and since
// SharedPreferences can't deal with arrays anyway, just store the messages
// as 4 separate strings.
@@ -82,20 +86,11 @@
private static final String KEY_CANNED_RESPONSE_PREF_2 = "canned_response_pref_2";
private static final String KEY_CANNED_RESPONSE_PREF_3 = "canned_response_pref_3";
private static final String KEY_CANNED_RESPONSE_PREF_4 = "canned_response_pref_4";
- private static final String KEY_PREFERRED_PACKAGE = "preferred_package_pref";
- private static final String KEY_INSTANT_TEXT_DEFAULT_COMPONENT = "instant_text_def_component";
+ /* package */ static final String KEY_INSTANT_TEXT_DEFAULT_COMPONENT =
+ "instant_text_def_component";
- /**
- * Brings up the standard SMS compose UI.
- */
- private void launchSmsCompose(String phoneNumber) {
- if (DBG) log("launchSmsCompose: number " + phoneNumber);
-
- final Intent intent = getInstantTextIntent(phoneNumber, null, getSmsService());
-
- if (DBG) log("- Launching SMS compose UI: " + intent);
- PhoneGlobals.getInstance().startService(intent);
- }
+ /* package */ static final String TAG_ALL_SMS_SERVICES = "com.android.phone.AvailablePackages";
+ /* package */ static final String TAG_SEND_SMS = "com.android.phone.MessageIntent";
/**
* Read the (customizable) canned responses from SharedPreferences,
@@ -130,28 +125,10 @@
return responses;
}
- /**
- * Sends a text message without any interaction from the user.
- */
- private void sendText(String phoneNumber, String message, ComponentName component) {
- if (DBG) log("sendText: number "
- + phoneNumber + ", message '" + message + "'");
-
- PhoneGlobals.getInstance().startService(getInstantTextIntent(phoneNumber, message,
- component));
- }
-
- private void sendTextAndExit(String phoneNumber, String message, ComponentName component,
- boolean setDefaultComponent) {
+ private void sendTextAndExit() {
// Send the selected message immediately with no user interaction.
- sendText(phoneNumber, message, component);
-
- if (setDefaultComponent) {
- final SharedPreferences prefs = PhoneGlobals.getInstance().getSharedPreferences(
- SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
- prefs.edit()
- .putString(KEY_INSTANT_TEXT_DEFAULT_COMPONENT, component.flattenToString())
- .apply();
+ if (mIntent.getComponent() != null) {
+ PhoneGlobals.getInstance().startService(mIntent);
}
// ...and show a brief confirmation to the user (since
@@ -231,11 +208,7 @@
return intent;
}
- public void rejectCallWithNewMessage(String number) {
- launchSmsCompose(number);
- }
-
- private ComponentName getSmsService() {
+ private boolean getSmsService() {
if (DBG) log("sendTextToDefaultActivity()...");
final PackageManager packageManager = PhoneGlobals.getInstance().getPackageManager();
@@ -257,7 +230,8 @@
if (serviceInfo != null &&
PERMISSION_SEND_RESPOND_VIA_MESSAGE.equals(serviceInfo.permission)) {
- return componentName;
+ mIntent.setComponent(componentName);
+ return true;
} else {
SharedPreferences.Editor editor = prefs.edit();
editor.remove(KEY_INSTANT_TEXT_DEFAULT_COMPONENT);
@@ -265,29 +239,38 @@
}
}
- final ArrayList<ComponentName> componentsWithPermission =
- getPackagesWithInstantTextPermission();
+ mComponentsWithPermission = getPackagesWithInstantTextPermission();
- final int size = componentsWithPermission.size();
+ final int size = mComponentsWithPermission.size();
if (size == 0) {
Log.e(TAG, "No appropriate package receiving the Intent. Don't send anything");
- return null;
+ return false;
} else if (size == 1) {
- return componentsWithPermission.get(0);
+ mIntent.setComponent(mComponentsWithPermission.get(0));
+ return true;
} else {
Log.v(TAG, "Choosing from one of the apps");
// TODO(klp): Add an app picker.
- return componentsWithPermission.get(0);
+ final Intent intent = new Intent(Intent.ACTION_VIEW, null);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+ Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
+ Intent.FLAG_ACTIVITY_NO_ANIMATION |
+ Intent.FLAG_ACTIVITY_NO_HISTORY |
+ Intent.FLAG_FROM_BACKGROUND);
+ intent.setClass(PhoneGlobals.getInstance(), TextMessagePackageChooser.class);
+ intent.putExtra(TAG_ALL_SMS_SERVICES, mComponentsWithPermission);
+ intent.putExtra(TAG_SEND_SMS, mIntent);
+ PhoneGlobals.getInstance().startActivity(intent);
+ return false;
+ // return componentsWithPermission.get(0);
}
}
-
- public void rejectCallWithMessage(final String number, String message) {
- final ComponentName componentName = getSmsService();
-
- if (componentName != null) {
- sendTextAndExit(number, message, componentName,
- false);
+ public void rejectCallWithMessage(Call call, String message) {
+ mComponentsWithPermission.clear();
+ mIntent = getInstantTextIntent(call.getLatestConnection().getAddress(), message, null);
+ if (getSmsService()) {
+ sendTextAndExit();
}
}
diff --git a/src/com/android/phone/TextMessagePackageChooser.java b/src/com/android/phone/TextMessagePackageChooser.java
new file mode 100644
index 0000000..ae638cb
--- /dev/null
+++ b/src/com/android/phone/TextMessagePackageChooser.java
@@ -0,0 +1,218 @@
+/*
+
+ * Copyright (C) 2013 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.phone;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.AlertDialog;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TextMessagePackageChooser extends Activity {
+ private static final String TAG = TextMessagePackageChooser.class.getSimpleName();
+
+ /** SharedPreferences file name for our persistent settings. */
+ private static final String SHARED_PREFERENCES_NAME = "respond_via_sms_prefs";
+
+ private int mIconSize = -1;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final ArrayList<ComponentName> components = getIntent().getParcelableArrayListExtra(
+ RejectWithTextMessageManager.TAG_ALL_SMS_SERVICES);
+ BaseAdapter adapter = new PackageSelectionAdapter(this, components);
+
+ PackageClickListener clickListener = new PackageClickListener(components);
+
+ final CharSequence title = getResources().getText(
+ com.android.internal.R.string.whichApplication);
+ LayoutInflater inflater =
+ (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ final View view = inflater.inflate(com.android.internal.R.layout.always_use_checkbox,
+ null);
+ final CheckBox alwaysUse = (CheckBox) view.findViewById(
+ com.android.internal.R.id.alwaysUse);
+ alwaysUse.setText(com.android.internal.R.string.alwaysUse);
+ alwaysUse.setOnCheckedChangeListener(clickListener);
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this)
+ .setTitle(title)
+ .setCancelable(true)
+ .setOnCancelListener(new RespondViaSmsCancelListener())
+ .setAdapter(adapter, clickListener)
+ .setView(view);
+
+ builder.create().show();
+ }
+
+ private class PackageSelectionAdapter extends BaseAdapter {
+ private final LayoutInflater mInflater;
+ private final List<ComponentName> mComponents;
+
+ public PackageSelectionAdapter(Context context, List<ComponentName> components) {
+ mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mComponents = components;
+ }
+
+ @Override
+ public int getCount() {
+ return mComponents.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mComponents.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = mInflater.inflate(
+ com.android.internal.R.layout.activity_chooser_view_list_item, parent,
+ false);
+ }
+
+ final ComponentName component = mComponents.get(position);
+ final String packageName = component.getPackageName();
+ final PackageManager packageManager = getPackageManager();
+
+ // Set the application label
+ final TextView text = (TextView) convertView.findViewById(
+ com.android.internal.R.id.title);
+
+ text.setText("");
+ try {
+ final ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, 0);
+ final CharSequence label = packageManager.getApplicationLabel(appInfo);
+ if (label != null) {
+ text.setText(label);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Failed to load app label because package was not found.");
+ }
+
+ // Set the application icon
+ final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
+ Drawable drawable = null;
+ try {
+ drawable = getPackageManager().getApplicationIcon(packageName);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Failed to load icon because it wasn't found.");
+ }
+ if (drawable == null) {
+ drawable = getPackageManager().getDefaultActivityIcon();
+ }
+ icon.setImageDrawable(drawable);
+ ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) icon.getLayoutParams();
+ lp.width = lp.height = getIconSize();
+
+ return convertView;
+ }
+
+ }
+
+ private class PackageClickListener implements DialogInterface.OnClickListener,
+ CompoundButton.OnCheckedChangeListener {
+ final private List<ComponentName> mComponents;
+ private boolean mMakeDefault = false;
+
+ public PackageClickListener(List<ComponentName> components) {
+ mComponents = components;
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ final ComponentName component = mComponents.get(which);
+
+ if (mMakeDefault) {
+ final SharedPreferences prefs = PhoneGlobals.getInstance().getSharedPreferences(
+ SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
+ prefs.edit().putString(
+ RejectWithTextMessageManager.KEY_INSTANT_TEXT_DEFAULT_COMPONENT,
+ component.flattenToString()).apply();
+ }
+
+ final Intent messageIntent = (Intent) getIntent().getParcelableExtra(
+ RejectWithTextMessageManager.TAG_SEND_SMS);
+ if (messageIntent != null) {
+ messageIntent.setComponent(component);
+ PhoneGlobals.getInstance().startService(messageIntent);
+ }
+ finish();
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ Log.i(TAG, "mMakeDefault : " + isChecked);
+ mMakeDefault = isChecked;
+ }
+ }
+
+ /**
+ * OnCancelListener for the "Respond via SMS" popup.
+ */
+ public class RespondViaSmsCancelListener implements DialogInterface.OnCancelListener {
+ public RespondViaSmsCancelListener() {
+ }
+
+ /**
+ * Handles the user canceling the popup, either by touching
+ * outside the popup or by pressing Back.
+ */
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ finish();
+ }
+ }
+
+ private int getIconSize() {
+ if (mIconSize < 0) {
+ final ActivityManager am =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ mIconSize = am.getLauncherLargeIconSize();
+ }
+
+ return mIconSize;
+ }
+}