Loading AndroidManifest.xml +2 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ android:sharedUserId="android.uid.system"> <protected-broadcast android:name="android.intent.action.SHOW_MISSED_CALLS_NOTIFICATION" /> <protected-broadcast android:name="com.android.server.telecom.MESSAGE_SENT" /> <!-- Prevents the activity manager from delaying any activity-start requests by this package, including requests immediately after Loading res/values/strings.xml +4 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,10 @@ a text response. [CHAR LIMIT=40] --> <string name="respond_via_sms_confirmation_format">Message sent to <xliff:g id="phone_number">%s</xliff:g>.</string> <!-- "Respond via SMS": Error toast shown after failing to send a text response. [CHAR LIMIT=40] --> <string name="respond_via_sms_failure_format">Message failed to send to <xliff:g id="phone_number">%s</xliff:g>.</string> <!-- Title of settings screen that allows user to enable and disable phone-accounts. Each method for placing a call (SIM1, SIM2, SIP account, etc) has a phone-account. Phone-accounts that are created by third party apps can be disabled and enabled by user. Loading src/com/android/server/telecom/RespondViaSmsManager.java +49 −29 Original line number Diff line number Diff line Loading @@ -18,10 +18,14 @@ package com.android.server.telecom; // TODO: Needed for move to system service: import com.android.internal.R; import com.android.internal.os.SomeArgs; import com.android.internal.telephony.SmsApplication; import android.app.Activity; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Resources; import android.os.Handler; Loading @@ -45,29 +49,36 @@ import java.util.List; * Helper class to manage the "Respond via Message" feature for incoming calls. */ public class RespondViaSmsManager extends CallsManagerListenerBase { private static final int MSG_SHOW_SENT_TOAST = 2; private static final String ACTION_MESSAGE_SENT = "com.android.server.telecom.MESSAGE_SENT"; private final CallsManager mCallsManager; private final TelecomSystem.SyncRoot mLock; private static final class MessageSentReceiver extends BroadcastReceiver { private final String mContactName; private final int mNumMessageParts; private int mNumMessagesSent = 0; MessageSentReceiver(String contactName, int numMessageParts) { mContactName = contactName; mNumMessageParts = numMessageParts; } private final Handler mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SHOW_SENT_TOAST: { SomeArgs args = (SomeArgs) msg.obj; try { String toastMessage = (String) args.arg1; Context context = (Context) args.arg2; showMessageSentToast(toastMessage, context); } finally { args.recycle(); public void onReceive(Context context, Intent intent) { if (getResultCode() == Activity.RESULT_OK) { mNumMessagesSent++; if (mNumMessagesSent == mNumMessageParts) { showMessageResultToast(mContactName, context, true); context.unregisterReceiver(this); } break; } else { context.unregisterReceiver(this); showMessageResultToast(mContactName, context, false); Log.w(RespondViaSmsManager.class.getSimpleName(), "Message failed with error %s", getResultCode()); } } } }; private final CallsManager mCallsManager; private final TelecomSystem.SyncRoot mLock; public RespondViaSmsManager(CallsManager callsManager, TelecomSystem.SyncRoot lock) { mCallsManager = callsManager; Loading Loading @@ -144,13 +155,15 @@ public class RespondViaSmsManager extends CallsManagerListenerBase { } } private void showMessageSentToast(final String phoneNumber, final Context context) { private static void showMessageResultToast(final String phoneNumber, final Context context, boolean success) { // ...and show a brief confirmation to the user (since // otherwise it's hard to be sure that anything actually // happened.) final Resources res = context.getResources(); final String formatString = res.getString( R.string.respond_via_sms_confirmation_format); final String formatString = res.getString(success ? R.string.respond_via_sms_confirmation_format : R.string.respond_via_sms_failure_format); final String confirmationMsg = String.format(formatString, phoneNumber); int startingPosition = confirmationMsg.indexOf(phoneNumber); int endingPosition = startingPosition + phoneNumber.length(); Loading Loading @@ -192,13 +205,20 @@ public class RespondViaSmsManager extends CallsManagerListenerBase { SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId); try { smsManager.sendTextMessage(phoneNumber, null, textMessage, null /*sentIntent*/, null /*deliveryIntent*/); SomeArgs args = SomeArgs.obtain(); args.arg1 = !TextUtils.isEmpty(contactName) ? contactName : phoneNumber; args.arg2 = context; mHandler.obtainMessage(MSG_SHOW_SENT_TOAST, args).sendToTarget(); ArrayList<String> messageParts = smsManager.divideMessage(textMessage); ArrayList<PendingIntent> sentIntents = new ArrayList<>(messageParts.size()); for (int i = 0; i < messageParts.size(); i++) { Intent intent = new Intent(ACTION_MESSAGE_SENT); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, i, intent, PendingIntent.FLAG_ONE_SHOT); sentIntents.add(pendingIntent); } MessageSentReceiver receiver = new MessageSentReceiver( !TextUtils.isEmpty(contactName) ? contactName : phoneNumber, messageParts.size()); context.registerReceiver(receiver, new IntentFilter(ACTION_MESSAGE_SENT)); smsManager.sendMultipartTextMessage(phoneNumber, null, messageParts, sentIntents/*sentIntent*/, null /*deliveryIntent*/); } catch (IllegalArgumentException e) { Log.w(RespondViaSmsManager.this, "Couldn't send SMS message: " + e.getMessage()); Loading Loading
AndroidManifest.xml +2 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ android:sharedUserId="android.uid.system"> <protected-broadcast android:name="android.intent.action.SHOW_MISSED_CALLS_NOTIFICATION" /> <protected-broadcast android:name="com.android.server.telecom.MESSAGE_SENT" /> <!-- Prevents the activity manager from delaying any activity-start requests by this package, including requests immediately after Loading
res/values/strings.xml +4 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,10 @@ a text response. [CHAR LIMIT=40] --> <string name="respond_via_sms_confirmation_format">Message sent to <xliff:g id="phone_number">%s</xliff:g>.</string> <!-- "Respond via SMS": Error toast shown after failing to send a text response. [CHAR LIMIT=40] --> <string name="respond_via_sms_failure_format">Message failed to send to <xliff:g id="phone_number">%s</xliff:g>.</string> <!-- Title of settings screen that allows user to enable and disable phone-accounts. Each method for placing a call (SIM1, SIM2, SIP account, etc) has a phone-account. Phone-accounts that are created by third party apps can be disabled and enabled by user. Loading
src/com/android/server/telecom/RespondViaSmsManager.java +49 −29 Original line number Diff line number Diff line Loading @@ -18,10 +18,14 @@ package com.android.server.telecom; // TODO: Needed for move to system service: import com.android.internal.R; import com.android.internal.os.SomeArgs; import com.android.internal.telephony.SmsApplication; import android.app.Activity; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Resources; import android.os.Handler; Loading @@ -45,29 +49,36 @@ import java.util.List; * Helper class to manage the "Respond via Message" feature for incoming calls. */ public class RespondViaSmsManager extends CallsManagerListenerBase { private static final int MSG_SHOW_SENT_TOAST = 2; private static final String ACTION_MESSAGE_SENT = "com.android.server.telecom.MESSAGE_SENT"; private final CallsManager mCallsManager; private final TelecomSystem.SyncRoot mLock; private static final class MessageSentReceiver extends BroadcastReceiver { private final String mContactName; private final int mNumMessageParts; private int mNumMessagesSent = 0; MessageSentReceiver(String contactName, int numMessageParts) { mContactName = contactName; mNumMessageParts = numMessageParts; } private final Handler mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SHOW_SENT_TOAST: { SomeArgs args = (SomeArgs) msg.obj; try { String toastMessage = (String) args.arg1; Context context = (Context) args.arg2; showMessageSentToast(toastMessage, context); } finally { args.recycle(); public void onReceive(Context context, Intent intent) { if (getResultCode() == Activity.RESULT_OK) { mNumMessagesSent++; if (mNumMessagesSent == mNumMessageParts) { showMessageResultToast(mContactName, context, true); context.unregisterReceiver(this); } break; } else { context.unregisterReceiver(this); showMessageResultToast(mContactName, context, false); Log.w(RespondViaSmsManager.class.getSimpleName(), "Message failed with error %s", getResultCode()); } } } }; private final CallsManager mCallsManager; private final TelecomSystem.SyncRoot mLock; public RespondViaSmsManager(CallsManager callsManager, TelecomSystem.SyncRoot lock) { mCallsManager = callsManager; Loading Loading @@ -144,13 +155,15 @@ public class RespondViaSmsManager extends CallsManagerListenerBase { } } private void showMessageSentToast(final String phoneNumber, final Context context) { private static void showMessageResultToast(final String phoneNumber, final Context context, boolean success) { // ...and show a brief confirmation to the user (since // otherwise it's hard to be sure that anything actually // happened.) final Resources res = context.getResources(); final String formatString = res.getString( R.string.respond_via_sms_confirmation_format); final String formatString = res.getString(success ? R.string.respond_via_sms_confirmation_format : R.string.respond_via_sms_failure_format); final String confirmationMsg = String.format(formatString, phoneNumber); int startingPosition = confirmationMsg.indexOf(phoneNumber); int endingPosition = startingPosition + phoneNumber.length(); Loading Loading @@ -192,13 +205,20 @@ public class RespondViaSmsManager extends CallsManagerListenerBase { SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId); try { smsManager.sendTextMessage(phoneNumber, null, textMessage, null /*sentIntent*/, null /*deliveryIntent*/); SomeArgs args = SomeArgs.obtain(); args.arg1 = !TextUtils.isEmpty(contactName) ? contactName : phoneNumber; args.arg2 = context; mHandler.obtainMessage(MSG_SHOW_SENT_TOAST, args).sendToTarget(); ArrayList<String> messageParts = smsManager.divideMessage(textMessage); ArrayList<PendingIntent> sentIntents = new ArrayList<>(messageParts.size()); for (int i = 0; i < messageParts.size(); i++) { Intent intent = new Intent(ACTION_MESSAGE_SENT); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, i, intent, PendingIntent.FLAG_ONE_SHOT); sentIntents.add(pendingIntent); } MessageSentReceiver receiver = new MessageSentReceiver( !TextUtils.isEmpty(contactName) ? contactName : phoneNumber, messageParts.size()); context.registerReceiver(receiver, new IntentFilter(ACTION_MESSAGE_SENT)); smsManager.sendMultipartTextMessage(phoneNumber, null, messageParts, sentIntents/*sentIntent*/, null /*deliveryIntent*/); } catch (IllegalArgumentException e) { Log.w(RespondViaSmsManager.this, "Couldn't send SMS message: " + e.getMessage()); Loading