How can I read SMS messages from the device programmatically in Android?

后端 未结 11 2361
情深已故
情深已故 2020-11-22 02:48

I want to retrieve the SMS messages from the device and display them?

相关标签:
11条回答
  • 2020-11-22 03:12

    From API 19 onwards you can make use of the Telephony Class for that; Since hardcored values won't retrieve messages in every devices because the content provider Uri changes from devices and manufacturers.

    public void getAllSms(Context context) {
    
        ContentResolver cr = context.getContentResolver();
        Cursor c = cr.query(Telephony.Sms.CONTENT_URI, null, null, null, null);
        int totalSMS = 0;
        if (c != null) {
            totalSMS = c.getCount();
            if (c.moveToFirst()) {
                for (int j = 0; j < totalSMS; j++) {
                    String smsDate = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.DATE));
                    String number = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.ADDRESS));
                    String body = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.BODY));
                    Date dateFormat= new Date(Long.valueOf(smsDate));
                    String type;
                    switch (Integer.parseInt(c.getString(c.getColumnIndexOrThrow(Telephony.Sms.TYPE)))) {
                        case Telephony.Sms.MESSAGE_TYPE_INBOX:
                            type = "inbox";
                            break;
                        case Telephony.Sms.MESSAGE_TYPE_SENT:
                            type = "sent";
                            break;
                        case Telephony.Sms.MESSAGE_TYPE_OUTBOX:
                            type = "outbox";
                            break;
                        default:
                            break;
                    }
    
    
                    c.moveToNext();
                }
            }
    
            c.close();
    
        } else {
            Toast.makeText(this, "No message to show!", Toast.LENGTH_SHORT).show();
        }
    }
    
    0 讨论(0)
  • 2020-11-22 03:12

    The easiest function

    To read the sms I wrote a function that returns a Conversation object:

    class Conversation(val number: String, val message: List<Message>)
    class Message(val number: String, val body: String, val date: Date)
    
    fun getSmsConversation(context: Context, number: String? = null, completion: (conversations: List<Conversation>?) -> Unit) {
            val cursor = context.contentResolver.query(Telephony.Sms.CONTENT_URI, null, null, null, null)
    
            val numbers = ArrayList<String>()
            val messages = ArrayList<Message>()
            var results = ArrayList<Conversation>()
    
            while (cursor != null && cursor.moveToNext()) {
                val smsDate = cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Sms.DATE))
                val number = cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Sms.ADDRESS))
                val body = cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Sms.BODY))
    
                numbers.add(number)
                messages.add(Message(number, body, Date(smsDate.toLong())))
            }
    
            cursor?.close()
    
            numbers.forEach { number ->
                if (results.find { it.number == number } == null) {
                    val msg = messages.filter { it.number == number }
                    results.add(Conversation(number = number, message = msg))
                }
            }
    
            if (number != null) {
                results = results.filter { it.number == number } as ArrayList<Conversation>
            }
    
            completion(results)
        }
    

    Using:

    getSmsConversation(this){ conversations ->
        conversations.forEach { conversation ->
            println("Number: ${conversation.number}")
            println("Message One: ${conversation.message[0].body}")
            println("Message Two: ${conversation.message[1].body}")
        }
    }
    

    Or get only conversation of specific number:

    getSmsConversation(this, "+33666494128"){ conversations ->
        conversations.forEach { conversation ->
            println("Number: ${conversation.number}")
            println("Message One: ${conversation.message[0].body}")
            println("Message Two: ${conversation.message[1].body}")
        }
    }
    
    0 讨论(0)
  • 2020-11-22 03:14
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            final String myPackageName = getPackageName();
            if (!Telephony.Sms.getDefaultSmsPackage(this).equals(myPackageName)) {
    
                Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
                intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, myPackageName);
                startActivityForResult(intent, 1);
            }else {
                List<Sms> lst = getAllSms();
            }
        }else {
            List<Sms> lst = getAllSms();
        }
    

    Set app as default SMS app

        @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == 1) {
        if (resultCode == RESULT_OK) {
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                final String myPackageName = getPackageName();
                if (Telephony.Sms.getDefaultSmsPackage(mActivity).equals(myPackageName)) {
    
                    List<Sms> lst = getAllSms();
                }
            }
        }
    }
    }
    

    Function to get SMS

    public List<Sms> getAllSms() {
        List<Sms> lstSms = new ArrayList<Sms>();
        Sms objSms = new Sms();
        Uri message = Uri.parse("content://sms/");
        ContentResolver cr = mActivity.getContentResolver();
    
        Cursor c = cr.query(message, null, null, null, null);
        mActivity.startManagingCursor(c);
        int totalSMS = c.getCount();
    
        if (c.moveToFirst()) {
            for (int i = 0; i < totalSMS; i++) {
    
                objSms = new Sms();
                objSms.setId(c.getString(c.getColumnIndexOrThrow("_id")));
                objSms.setAddress(c.getString(c
                        .getColumnIndexOrThrow("address")));
                objSms.setMsg(c.getString(c.getColumnIndexOrThrow("body")));
                objSms.setReadState(c.getString(c.getColumnIndex("read")));
                objSms.setTime(c.getString(c.getColumnIndexOrThrow("date")));
                if (c.getString(c.getColumnIndexOrThrow("type")).contains("1")) {
                    objSms.setFolderName("inbox");
                } else {
                    objSms.setFolderName("sent");
                }
    
                lstSms.add(objSms);
                c.moveToNext();
            }
        }
        // else {
        // throw new RuntimeException("You have no SMS");
        // }
        c.close();
    
        return lstSms;
    }
    

    Sms class is below:

    public class Sms{
    private String _id;
    private String _address;
    private String _msg;
    private String _readState; //"0" for have not read sms and "1" for have read sms
    private String _time;
    private String _folderName;
    
    public String getId(){
    return _id;
    }
    public String getAddress(){
    return _address;
    }
    public String getMsg(){
    return _msg;
    }
    public String getReadState(){
    return _readState;
    }
    public String getTime(){
    return _time;
    }
    public String getFolderName(){
    return _folderName;
    }
    
    
    public void setId(String id){
    _id = id;
    }
    public void setAddress(String address){
    _address = address;
    }
    public void setMsg(String msg){
    _msg = msg;
    }
    public void setReadState(String readState){
    _readState = readState;
    }
    public void setTime(String time){
    _time = time;
    }
    public void setFolderName(String folderName){
    _folderName = folderName;
    }
    
    }
    

    Don't forget to define permission in your AndroidManifest.xml

    <uses-permission android:name="android.permission.READ_SMS" />
    
    0 讨论(0)
  • 2020-11-22 03:14

    Step 1: first we have to add permissions in manifest file like

    <uses-permission android:name="android.permission.RECEIVE_SMS" android:protectionLevel="signature" />
    <uses-permission android:name="android.permission.READ_SMS" />
    

    Step 2: then add service sms receiver class for receiving sms

    <receiver android:name="com.aquadeals.seller.services.SmsReceiver">
        <intent-filter>
            <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
        </intent-filter>
    </receiver>
    

    Step 3: Add run time permission

    private boolean checkAndRequestPermissions()
    {
        int sms = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS);
    
        if (sms != PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_SMS}, REQUEST_ID_MULTIPLE_PERMISSIONS);
            return false;
        }
        return true;
    }
    

    Step 4: Add this classes in your app and test Interface class

    public interface SmsListener {
       public void messageReceived(String messageText);
    }
    

    SmsReceiver.java

    public class SmsReceiver extends BroadcastReceiver {
        private static SmsListener mListener;
        public Pattern p = Pattern.compile("(|^)\\d{6}");
        @Override
        public void onReceive(Context context, Intent intent) {
            Bundle data  = intent.getExtras();
            Object[] pdus = (Object[]) data.get("pdus");
            for(int i=0;i<pdus.length;i++)
            {
                SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
                String sender = smsMessage.getDisplayOriginatingAddress();
                String phoneNumber = smsMessage.getDisplayOriginatingAddress();
                String senderNum = phoneNumber ;
                String messageBody = smsMessage.getMessageBody();
                try{
                    if(messageBody!=null){
                        Matcher m = p.matcher(messageBody);
                        if(m.find()) {
                            mListener.messageReceived(m.group(0));
                        }
                    }
                }
                catch(Exception e){}
            }
        }
        public static void bindListener(SmsListener listener) {
            mListener = listener; 
        }
    }
    
    0 讨论(0)
  • 2020-11-22 03:15

    Kotlin Code to read SMS :

    1- Add this permission to AndroidManifest.xml :

        <uses-permission android:name="android.permission.RECEIVE_SMS"/>
    

    2-Create a BroadCastreceiver Class :

    package utils.broadcastreceivers
    
    import android.content.BroadcastReceiver
    import android.content.Context
    import android.content.Intent
    import android.telephony.SmsMessage
    import android.util.Log
    
    class MySMSBroadCastReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        var body = ""
        val bundle = intent?.extras
        val pdusArr = bundle!!.get("pdus") as Array<Any>
        var messages: Array<SmsMessage?>  = arrayOfNulls(pdusArr.size)
    
     // if SMSis Long and contain more than 1 Message we'll read all of them
        for (i in pdusArr.indices) {
            messages[i] = SmsMessage.createFromPdu(pdusArr[i] as ByteArray)
        }
          var MobileNumber: String? = messages[0]?.originatingAddress
           Log.i(TAG, "MobileNumber =$MobileNumber")         
           val bodyText = StringBuilder()
            for (i in messages.indices) {
                bodyText.append(messages[i]?.messageBody)
            }
            body = bodyText.toString()
            if (body.isNotEmpty()){
           // Do something, save SMS in DB or variable , static object or .... 
                           Log.i("Inside Receiver :" , "body =$body")
            }
        }
     }
    

    3-Get SMS Permission if Android 6 and above:

       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && 
        ActivityCompat.checkSelfPermission(context!!,
                Manifest.permission.RECEIVE_SMS
            ) != PackageManager.PERMISSION_GRANTED
        ) { // Needs permission
    
                requestPermissions(arrayOf(Manifest.permission.RECEIVE_SMS),
                PERMISSIONS_REQUEST_READ_SMS
            )
    
        } else { // Permission has already been granted
    
        }
    

    4- Add this request code to Activity or fragment :

     companion object {
        const val PERMISSIONS_REQUEST_READ_SMS = 100
       }
    

    5- Override Check permisstion Request result fun :

     override fun onRequestPermissionsResult(
        requestCode: Int, permissions: Array<out String>,
        grantResults: IntArray
    ) {
        when (requestCode) {
    
            PERMISSIONS_REQUEST_READ_SMS -> {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.i("BroadCastReceiver", "PERMISSIONS_REQUEST_READ_SMS Granted")
                } else {
                    //  toast("Permission must be granted  ")
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题