如何在Android中使用带有自定义线程ID的SmsManager发送短信?

时间:2016-03-19 03:35:38

标签: java android android-intent

我想创建一个带有自定义线程ID的短信,说" 10001"。我怎样才能做到这一点 ?原因是因为我需要实现删除短信功能,删除特定短信线程的唯一方法是通过线程ID或电话号码,并且在这个时间点获取电话号码是不可能的,因此需要定义自定义线程ID在发送短信时。

到目前为止,我只能获得正常的SMS工作代码:

    SmsManager smsManager = SmsManager.getDefault();
    smsManager.sendTextMessage("+1 203 514 6584", null, "HI Greg! ", null, null);

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

SmsObserver类是ContentObserver,它在content://sms/ Uri上注册自己,并根据收件人的地址和邮件正文检查SMS表中的更改检索传出SMS消息的已分配线程ID。该类提供了一个接口,您的发送类需要实现该接口,以便在确定后接收线程ID,因为这将异步发生。

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();
            }
        }
    }
}

这个实例需要在发送消息之前启动,并且线程ID将被传递到发送类的接口方法实现中。例如,如果您在点击Activity时从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.
    }
}

请注意,您还需要READ_SMS权限。

从Lollipop开始,可以选择其他替代品。已发送邮件的URI将作为String附加内容附加到Intent,作为PendingIntent方法中第四个参数传递的sendTextMessage()。额外的密钥为"uri",可以解析为Uri,然后可以在ContentResolver的查询中使用它来检索线程ID,如上所示。

例如,如果使用BroadcastReceiver作为结果,那么sendTextMessage()调用就是这样:

Intent sentIntent = ...
PendingIntent sentPi = PendingIntent.getBroadcast(context, 0, sentIntent, 0);

SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(address, null, body, sentPi, null);

在Receiver中检索额外内容就像这样:

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
        ...
    }
}