How to send sms with SmsManager with customised thread ID in Android?

后端 未结 1 1140
情深已故
情深已故 2021-01-27 10:57

I would like to create an SMS with a customised thread ID say \"10001\". How can I do that ? Reason is because I needed to implement a delete SMS function and the only way to de

相关标签:
1条回答
  • 2021-01-27 11:25

    The SmsObserver class is a ContentObserver that registers itself on the content://sms/ Uri and checks changes in the SMS table against the recipient's address and message body to retrieve the assigned thread ID for an outgoing SMS message. The class offers an interface that your sending class needs to implement in order to receive the thread ID when it's determined, as this will happen asynchronously.

    public class SmsObserver extends ContentObserver {
        private static final Handler handler = new Handler();
        private static final Uri uri = Uri.parse("content://sms/");
    
        private final Context context;
        private final ContentResolver resolver;
        private final String address;
        private final String body;
    
        public interface OnSmsSentListener {
            public void onSmsSent(int threadId);
        }
    
        public SmsObserver(Context context, String address, String body) {
            super(handler);
    
            if (context instanceof OnSmsSentListener) {
                this.context = context;
                this.resolver = context.getContentResolver();
                this.address = address;
                this.body = body;
            }
            else {
                throw new IllegalArgumentException(
                    "Context must implement OnSmsSentListener interface");
            }
        }
    
        public void start() {
            if (resolver != null) {
                resolver.registerContentObserver(uri, true, this);
            }
            else {
                throw new IllegalStateException(
                    "Current SmsObserver instance is invalid");
            }
        }
    
        @Override
        public void onChange(boolean selfChange, Uri uri) {
            Cursor cursor = null;
    
            try {
                cursor = resolver.query(uri, null, null, null, null);
    
                if (cursor != null && cursor.moveToFirst()) {
                    final int type = cursor.getInt(
                        cursor.getColumnIndex(Telephony.Sms.TYPE));
    
                    if(type == Telephony.Sms.Sent.MESSAGE_TYPE_SENT) {
                        final String address = cursor.getString(
                            cursor.getColumnIndex(Telephony.Sms.ADDRESS));
                        final String body = cursor.getString(
                            cursor.getColumnIndex(Telephony.Sms.BODY));
                        final int threadId = cursor.getInt(
                            cursor.getColumnIndex(Telephony.Sms.THREAD_ID));
    
                        if (PhoneNumberUtils.compare(address, this.address) &&
                            body.equals(this.body)) {
    
                            ((OnSmsSentListener) context).onSmsSent(threadId);
                            resolver.unregisterContentObserver(this);
                        }
                    }
                }
            }
            finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }
    }
    

    An instance of this needs to be started before the message is sent, and the thread ID will be passed into the sending class's interface method implementation. For example, if you're sending from an Activity upon clicking a Button:

    public class MainActivity extends Activity
        implements SmsObserver.OnSmsSentListener {
        ...
    
        public void onClick(View v) {
            String address = "+1 234 567 8900";
            String body = "HI Greg! ";
    
            new SmsObserver(this, address, body).start();
    
            SmsManager smsManager = SmsManager.getDefault();
            smsManager.sendTextMessage(address, null, body, null, null);
        }
    
        @Override
        public void onSmsSent(int threadId) {
            // Here's the thread ID.
        }
    }
    

    Please note that you will need the READ_SMS permission as well.


    A possible alternative is available starting in Lollipop. The URI of the sent message will be attached as a String extra to the Intent from the PendingIntent passed as the fourth argument in the sendTextMessage() method. The extra will have the key "uri", and can be parsed as a Uri, which can then be used in a query on ContentResolver to retrieve the thread ID as shown above.

    For example, if using a BroadcastReceiver for the result, the sendTextMessage() call would be like so:

    Intent sentIntent = ...
    PendingIntent sentPi = PendingIntent.getBroadcast(context, 0, sentIntent, 0);
    
    SmsManager smsManager = SmsManager.getDefault();
    smsManager.sendTextMessage(address, null, body, sentPi, null);
    

    And retrieving the extra in the Receiver would be like so:

    public class SmsResultReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            ...
    
            String uriString = data.getStringExtra("uri");
            Uri uri = Uri.parse(uriString);
    
            // Query as shown above in the ContentObserver
            ...
        }
    }
    
    0 讨论(0)
提交回复
热议问题