zoukankan      html  css  js  c++  java
  • Android发送短信

    获取OR创建ThreadId

    private long getOrCreateThreadId() {
        Set<String> recipients = new HashSet<String>();
        String[] numbers = mNumber.split(",");
        for(int i=0;i<numbers.length;i++) {
            recipients.add(numbers[i]);
        }
        return Threads.getOrCreateThreadId(mContext, recipients);
    }

    参考资料

    android 中调用接口发送短信

    发送短信代码判断

    private void sendMsg(String destAddress, String content,
            PendingIntent sentIntent, PendingIntent deliveryIntent) {
        SmsManager smsManager = SmsManager.getDefault();
        List<String> divideContents = smsManager.divideMessage(content);
        for (String text : divideContents) {
            smsManager.sendTextMessage(destAddress, null, text, sentIntent,
                    deliveryIntent);
        }
    }

    查看发送短信有关API

    1. android.telephony.SmsManager

    Manages SMS operations such as sending data, text, and pdu SMS messages. Get this object by calling the static method SmsManager.getDefault().

    2. android.telephony.SmsManager.sendTextMessage()

    void android.telephony.SmsManager.sendTextMessage(String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)

    Send a text based SMS.

    Parameters:
    destinationAddress the address to send the message to
    scAddress is the service center address or null to use the current default SMSC
    text the body of the message to send
    sentIntent if not NULL this PendingIntent is broadcast when the message is sucessfully sent, or failed. The result code will be Activity.RESULT_OK for success, or one of these errors: RESULT_ERROR_GENERIC_FAILURE, RESULT_ERROR_RADIO_OFF, RESULT_ERROR_NULL_PDU
    For RESULT_ERROR_GENERIC_FAILURE the sentIntent may include the extra "errorCode" containing a radio technology specific value, generally only useful for troubleshooting.
    The per-application based SMS control checks sentIntent. If sentIntent is NULL the caller will be checked against all unknown applications, which cause smaller number of SMS to be sent in checking period.
    deliveryIntent if not NULL this PendingIntent is broadcast when the message is delivered to the recipient. The raw pdu of the status report is in the extended data ("pdu").
    Throws:
    IllegalArgumentException - if destinationAddress or text are empty

    3. android.app.PendingIntent.getBroadcast()

    PendingIntent android.app.PendingIntent.getBroadcast(Context context, int requestCode, Intent intent, int flags)

    Retrieve a PendingIntent that will perform a broadcast, like calling Context.sendBroadcast().

    Parameters:
    context The Context in which this PendingIntent should perform the broadcast.
    requestCode Private request code for the sender (currently not used).
    intent The Intent to be broadcast.
    flags May be FLAG_ONE_SHOT, FLAG_NO_CREATE, FLAG_CANCEL_CURRENT, FLAG_UPDATE_CURRENT, or any of the flags as supported by Intent.fillIn() to control which unspecified parts of the intent that can be supplied when the actual send happens.
    Returns:
    Returns an existing or new PendingIntent matching the given parameters. May return null only if FLAG_NO_CREATE has been supplied.

    4. android.content.Context.sendBroadcast()

    void android.content.Context.sendBroadcast(Intent intent)

    Broadcast the given intent to all interested BroadcastReceivers. This call is asynchronous; it returns immediately, and you will continue executing while the receivers are run. No results are propagated from receivers and receivers can not abort the broadcast. If you want to allow receivers to propagate results or abort the broadcast, you must send an ordered broadcast using sendOrderedBroadcast(Intent, String).

    See BroadcastReceiver for more information on Intent broadcasts.

    Parameters:
    intent The Intent to broadcast; all receivers matching this Intent will receive the broadcast.
    See Also:
    android.content.BroadcastReceiver
    registerReceiver
    sendBroadcast(Intent, String)
    sendOrderedBroadcast(Intent, String)
    sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)

    5. Telephony.Sms.Outbox.addMessage()

    Uri com.txrj.sms.system.Telephony.Sms.Outbox.addMessage(ContentResolver resolver, String address, String body, String subject, Long date, boolean deliveryReport, long threadId)

    Add an SMS to the Out box.

    Parameters:
    resolver the content resolver to use
    address the address of the sender
    body the body of the message
    subject the psuedo-subject of the message
    date the timestamp for the message
    deliveryReport whether a delivery report was requested for the message
    threadId
    Returns:
    the URI for the new message

    发送短信给10010和10011出错

    07-14 16:55:53.023: E/AndroidRuntime(4078): FATAL EXCEPTION: main
    07-14 16:55:53.023: E/AndroidRuntime(4078): java.lang.SecurityException: Sending SMS message: Neither user 10110 nor current process has android.permission.SEND_SMS.

    调用Telephony.Sms.Outbox.addMessage()出现异常

    07-14 22:18:53.465: E/AndroidRuntime(8912): FATAL EXCEPTION: main
    07-14 22:18:53.465: E/AndroidRuntime(8912): java.lang.SecurityException: Permission Denial: writing com.android.providers.telephony.SmsProvider uri content://sms/outbox from pid=8912, uid=10110 requires android.permission.WRITE_SMS

    发送信息到10010日志

    07-14 22:21:36.935: I/txrjsms(9352): send msg to 10010, content:
    07-14 22:21:36.935: I/txrjsms(9352): 1314649
    07-14 22:21:39.857: I/txrjsms(9352): send Msg success.
    07-14 22:21:43.171: I/txrjsms(9352): message arrived.

    将发送的信息添加到outBox中

    Uri uri = Telephony.Sms.Outbox.addMessage(getContentResolver(), "13146491234", content,
            null, System.currentTimeMillis(), false, getOrCreateThreadId());
    onOutboxAddMessage(uri);

    //…

    private void onOutboxAddMessage(Uri uri) {
        Cursor cursor = getContentResolver().query(uri,
                new String[]{Sms._ID, Sms.THREAD_ID, Sms.TYPE, Sms.BODY, Sms.DATE},
                null, null, null);
        TxrjMessage msg = null;
        if(cursor != null) {
            if(cursor.moveToFirst()) {
                msg = new TxrjMessage();
                msg.setMessageId(cursor.getInt(cursor.getColumnIndex(Sms._ID)));
                msg.setThreadId(cursor.getInt(cursor.getColumnIndex(Sms.THREAD_ID)));
                msg.setType(cursor.getInt(cursor.getColumnIndex(Sms.TYPE)));
                msg.setBody(cursor.getString(cursor.getColumnIndex(Sms.BODY)));
                msg.setTime(cursor.getLong(cursor.getColumnIndex(Sms.DATE)));
                mMessages.add(msg);
                mListAdapter.notifyDataSetChanged();
                if(!uriMap.containsKey(msg.getMessageId())){
                    uriMap.put(msg.getMessageId(), uri);
                }
            }
            cursor.close();
        }
    }

    注册ContentObserver需要API至少是16

    Call requires API level 16 (current min is 11): android.database.ContentObserver#onChange

    private void onMsgStatusChanged(Uri uri, int msgId) {
        ContentObserver observer = new ContentObserver(null) {
            @Override
            public void onChange(boolean selfChange, Uri uri) {
                super.onChange(selfChange, uri);
            }
        };
        getContentResolver().registerContentObserver(uri, false, observer);
    }

    实现onMsgStatusChanged()

    private void onMsgStatusChanged(final Uri uri, final int msgId) {
        final Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                mListAdapter.notifyDataSetChanged();
                mListView.setSelection(mListView.getBottom());
            }
        };
        ContentObserver observer = new ContentObserver(null) {
            @Override
            public void onChange(boolean selfChange) {
                super.onChange(selfChange);
                Cursor cursor = getContentResolver().query(uri,
                        new String[]{Sms._ID, Sms.THREAD_ID, Sms.TYPE, Sms.BODY, Sms.DATE},
                        null, null, null);
                if(cursor != null) {
                    if(cursor.moveToFirst()) {
                        int type = cursor.getInt(cursor.getColumnIndex(Sms.TYPE));
                        for (int i = mMessages.size() - 1; i >= 0; i--) {
                            if(mMessages.get(i).getMessageId() == msgId) {
                                mMessages.get(i).setType(type);
                                break;
                            }
                        }
                        handler.sendMessage(handler.obtainMessage());
                        getContentResolver().unregisterContentObserver(this);
                    }
                    cursor.close();
                }
            }
        };
        getContentResolver().registerContentObserver(uri, false, observer);
    }

    发送信息成功或失败时修改信息状态

    private void updateMsgType(Uri uri, int type) {
        ContentValues values = new ContentValues();
        values.put(Sms.TYPE, type);
        getContentResolver().update(uri, values, null, null);
    }

    private PendingIntent getSentIntent(final Uri uri) {
        BroadcastReceiver receiver = new BroadcastReceiver(){

            @Override
            public void onReceive(Context context, Intent intent) {
                int resultCode = getResultCode();
                if(resultCode == RESULT_OK) {
                    Toast.makeText(context, "send message success.", Toast.LENGTH_SHORT).show();
                    Log.i("txrjsms", "send message success.");
                    updateMsgType(uri, Sms.MESSAGE_TYPE_SENT);
                } else if(resultCode == SmsManager.RESULT_ERROR_GENERIC_FAILURE) {
                    Toast.makeText(context, "Generic failure.", Toast.LENGTH_SHORT).show();
                    updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
                } else if(resultCode == SmsManager.RESULT_ERROR_NO_SERVICE) {
                    Toast.makeText(context, "service is currently unavailable.", Toast.LENGTH_SHORT).show();
                    updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
                } else if(resultCode == SmsManager.RESULT_ERROR_NULL_PDU) {
                    Toast.makeText(context, "no pdu provided.", Toast.LENGTH_SHORT).show();
                    updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
                } else if(resultCode == SmsManager.RESULT_ERROR_RADIO_OFF) {
                    Toast.makeText(context, "radio was explicitly turned off.", Toast.LENGTH_SHORT).show();
                    updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
                }
            }
        };
        IntentFilter filter = new IntentFilter(TxrjConstant.ACTION_SEND_SMS);
        mContext.registerReceiver(receiver, filter);
        Intent sentIntent = new Intent(TxrjConstant.ACTION_SEND_SMS);
        return PendingIntent.getBroadcast(mContext, 0, sentIntent, 0);
    }


    发送短信代码

    private void sendMessage(String destAddr, String content) {
        SmsManager smsManager = SmsManager.getDefault();
        List<String> divideContents = smsManager.divideMessage(content);
        for (String text : divideContents) {
            Log.i("txrjsms", "send msg to " + destAddr + ", content: " + text);
            smsManager.sendTextMessage(destAddr, null, text, getSentIntent(),
                    getDeliveryIntent());
        }
    }

    private PendingIntent getSentIntent() {
        Intent sentIntent = new Intent(TxrjConstant.ACTION_SEND_SMS);
        BroadcastReceiver receiver = new BroadcastReceiver(){

            @Override
            public void onReceive(Context context, Intent intent) {
                int resultCode = getResultCode();
                if(resultCode == RESULT_OK) {
                    Toast.makeText(context, "send Msg success.", Toast.LENGTH_SHORT).show();
                    Log.i("txrjsms", "send Msg success.");
                } else if(resultCode == SmsManager.RESULT_ERROR_GENERIC_FAILURE) {
                } else if(resultCode == SmsManager.RESULT_ERROR_NO_SERVICE) {
                } else if(resultCode == SmsManager.RESULT_ERROR_NULL_PDU) {
                } else if(resultCode == SmsManager.RESULT_ERROR_RADIO_OFF) {
                }
            }
        };
        IntentFilter filter = new IntentFilter(TxrjConstant.ACTION_SEND_SMS);
        mContext.registerReceiver(receiver, filter);
        return PendingIntent.getBroadcast(mContext, 0, sentIntent, 0);
    }

    private PendingIntent getDeliveryIntent() {
        Intent deliveryIntent = new Intent(TxrjConstant.ACTION_DELIVERY_SMS);
        BroadcastReceiver receiver = new BroadcastReceiver(){

            @Override
            public void onReceive(Context context, Intent intent) {
                Toast.makeText(context, "message arrived.", Toast.LENGTH_SHORT).show();
                Log.i("txrjsms", "message arrived.");
            }
        };
        IntentFilter filter = new IntentFilter(TxrjConstant.ACTION_DELIVERY_SMS);
        mContext.registerReceiver(receiver, filter);
        return PendingIntent.getBroadcast(mContext, 0, deliveryIntent, 0);
    }

    发送短信LOG

    07-14 16:58:29.746: I/txrjsms(4782): send msg to 10010, content:
    07-14 16:58:29.746: I/txrjsms(4782): 102
    07-14 16:58:29.906: I/txrjsms(4782): send msg to 10011, content:
    07-14 16:58:29.906: I/txrjsms(4782): 102
    07-14 16:58:33.620: I/txrjsms(4782): send Msg success.
    07-14 16:58:33.650: I/txrjsms(4782): send Msg success.
    07-14 16:58:36.583: I/txrjsms(4782): message arrived.
    07-14 16:58:36.583: I/txrjsms(4782): message arrived.
    07-14 16:58:37.554: I/txrjsms(4782): send Msg success.
    07-14 16:58:37.564: I/txrjsms(4782): send Msg success.

  • 相关阅读:
    String类的intern()方法,随常量池发生的变化
    JDK8的JVM内存结构,元空间替代永久代成为方法区及常量池的变化
    wait()、notify()方法原理,以及使用注意事项--丢失唤醒、虚假唤醒
    消费者、生产者Java代码示例,wait-notify实现
    volatile、Synchronized实现变量可见性的原理,volatile使用注意事项
    CAS及其ABA问题
    JUC包Lock机制的支持--AQS
    JUC包实现的同步机制,原理以及简单用法总结
    Synchronized机制下偏向锁、轻量级锁、重量级锁的适用场景
    临时表循环插入
  • 原文地址:https://www.cnblogs.com/fengzhblog/p/3189739.html
Copyright © 2011-2022 走看看