Bagaimana saya bisa membaca pesan SMS dari perangkat secara terprogram di Android?

249

Saya ingin mengambil pesan SMS dari perangkat dan menampilkannya?

Manoj Perumarath
sumber
@ David Freitas Tautan tepercaya +1
Shahzad Imam
3
@DavidFreitas tautan ini tidak berfungsi, bisakah Anda membagikan tautan yang paling indah?
Khobaib
3
@ Khobaib, seperti biasa hal-hal di internet cepat berlalu. Saya menemukan salinan di archive.org stackoverflow.com/a/19966227/40961 , terima kasih Tuhan untuk mereka (saya telah menyumbang baru-baru ini agar tetap berjalan). Tetapi kita harus mempertimbangkan untuk mengonversi konten halaman dari web.archive.org/web/20121022021217/http://mobdev.olin.edu/… menjadi markdown sintaksis dalam jawaban atas pertanyaan ini. Mungkin kerja satu jam.
David d C e Freitas

Jawaban:

157

Gunakan Penyelesai Konten ( "konten: // sms / kotak masuk" ) untuk membaca SMS yang ada di kotak masuk.

// public static final String INBOX = "content://sms/inbox";
// public static final String SENT = "content://sms/sent";
// public static final String DRAFT = "content://sms/draft";
Cursor cursor = getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, null);

if (cursor.moveToFirst()) { // must check the result to prevent exception
    do {
       String msgData = "";
       for(int idx=0;idx<cursor.getColumnCount();idx++)
       {
           msgData += " " + cursor.getColumnName(idx) + ":" + cursor.getString(idx);
       }
       // use msgData
    } while (cursor.moveToNext());
} else {
   // empty box, no SMS
}

Harap tambahkan READ_SMS izin .

Semoga bermanfaat :)

Suryavel TR
sumber
7
Terima kasih! Anda salah mengeja "getColumnName", selain itu itu berfungsi seperti pesona. Oh, dan jika ada yang akan menggunakan ini, jangan lupa untuk menambahkan izin android.permission.READ_SMS.
qwerty
1
Terima kasih. Saya memodifikasinya :)
Suryavel TR
5
Apakah ini juga menggunakan api tidak berdokumen yang ditentukan @CommonsWare dalam komentarnya untuk jawaban yang diterima?
Krishnabhadra
1
Perhatian! Jangan ketinggalan moveToFirstseperti saya.
Alexandr Priymak
4
@ Krishnabhadra Ya. Ia menggunakan penyedia konten "konten: // sms / inbox" yang tidak berdokumen.
pm_labs
79
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();
    }

Tetapkan aplikasi sebagai aplikasi SMS default

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

Berfungsi untuk mendapatkan 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;
}

Kelas sms di bawah ini:

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

}

Jangan lupa untuk menentukan izin di AndroidManifest.xml Anda

<uses-permission android:name="android.permission.READ_SMS" />
Atif Mahmood
sumber
2
Sepotong kode yang bagus. Hanya satu hal, waktu diperoleh dalam milidetik. Saya pikir akan lebih baik untuk membuatnya menjadi format yang dapat dibaca manusia sepertiString receiveDayTime = Functions.dateFromMilisec(Long.valueOf(c.getColumnIndexOrThrow("date")), "hh:mm a MMM dd, yyyy");
Bibaswann Bandyopadhyay
1
apa tujuan membuat semuanya dengan pengambil dan penyetel, saya benar-benar tidak mengerti mengapa tidak hanya menggunakan array assoc atau kelas yang elemen-elemennya diakses secara langsung
michnovka
1
@TomasNavara: Periksa kode ini untuk memahami penggunaan pengambil dan penyetel. pastebin.com/Nh8YXtyJ
Bugs Terjadi
@BibaswannBandyopadhyay Jika Anda tidak ingin menggunakan apa pun kecuali perpustakaan android & perpustakaan java. new SimpleDateFormat("hh:mm", Locale.US).format(new Date(Long.parseLong(_time)));Ini akan memberi Anda waktu 24 jam.
Chris - Jr
mActivitytak terdefinisi. Apa ini?
dthree
61

Ini adalah proses yang sepele. Anda dapat melihat contoh yang baik di kode sumber SMSPopup

Periksa metode berikut:

SmsMmsMessage getSmsDetails(Context context, long ignoreThreadId, boolean unreadOnly)
long findMessageId(Context context, long threadId, long _timestamp, int messageType
void setMessageRead(Context context, long messageId, int messageType)
void deleteMessage(Context context, long messageId, long threadId, int messageType)

ini adalah metode untuk membaca:

SmsMmsMessage getSmsDetails(Context context,
                            long ignoreThreadId, boolean unreadOnly)
{
   String SMS_READ_COLUMN = "read";
   String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0" : null;
   String SORT_ORDER = "date DESC";
   int count = 0;
   // Log.v(WHERE_CONDITION);
   if (ignoreThreadId > 0) {
      // Log.v("Ignoring sms threadId = " + ignoreThreadId);
      WHERE_CONDITION += " AND thread_id != " + ignoreThreadId;
   }
   Cursor cursor = context.getContentResolver().query(
                      SMS_INBOX_CONTENT_URI,
                      new String[] { "_id", "thread_id", "address", "person", "date", "body" },
                      WHERE_CONDITION,
                      null,
                      SORT_ORDER);
   if (cursor != null) {
      try {
         count = cursor.getCount();
         if (count > 0) {
            cursor.moveToFirst();
            // String[] columns = cursor.getColumnNames();
            // for (int i=0; i<columns.length; i++) {
            // Log.v("columns " + i + ": " + columns[i] + ": " + cursor.getString(i));
            // }                                         
            long messageId = cursor.getLong(0);
            long threadId = cursor.getLong(1);
            String address = cursor.getString(2);
            long contactId = cursor.getLong(3);
            String contactId_string = String.valueOf(contactId);
            long timestamp = cursor.getLong(4);

            String body = cursor.getString(5);                             
            if (!unreadOnly) {
                count = 0;
            }

            SmsMmsMessage smsMessage = new SmsMmsMessage(context, address,
                          contactId_string, body, timestamp,
                          threadId, count, messageId, SmsMmsMessage.MESSAGE_TYPE_SMS);
            return smsMessage;
         }
      } finally {
         cursor.close();
      }
   }               
   return null;
}
Ömer
sumber
47
Ini bukan bagian dari SDK Android. Kode ini membuat asumsi yang salah bahwa semua perangkat mendukung penyedia konten yang tidak berdokumen dan tidak didukung ini. Google telah secara eksplisit menunjukkan bahwa mengandalkan ini bukan ide yang baik: android-developers.blogspot.com/2010/05/…
CommonsWare
1
@ Janusz: Tidak ada sarana yang terdokumentasi dan didukung yang berfungsi di semua klien SMS di semua perangkat.
CommonsWare
9
@CommonsWare sedih mendengar. Mungkin harus hidup dengan API ini kalau begitu.
Janusz
@Omer Tahu bagaimana Anda akan menghitung jumlah pesan SMS per kontak?
SpicyWeenie
4
Kode telah dipindahkan. Mencari SmsPopupUtils.java memberi saya tautan baru untuk itu dalam kode google. Jika mereka memindahkannya lagi atau menghentikannya sama sekali, inilah tautan cadangan - pastebin.com/iPt7MLyM
KalEl
25

Dari API 19 dan seterusnya, Anda dapat menggunakan Kelas Telephony untuk itu; Karena nilai hardcored tidak akan mengambil pesan di setiap perangkat karena penyedia konten Uri berubah dari perangkat dan pabrikan.

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();
    }
}
Manoj Perumarath
sumber
9
Tampaknya menjadi satu-satunya jawaban yang tidak menggunakan API tidak berdokumen dan tidak merujuk ke perpustakaan pihak ketiga.
Ishamael
Saya mencoba menggunakan kode ini untuk mendapatkan pesan SMS dari Hangouts (yang merupakan aplikasi SMS default saya). Alih-alih, ia mengambil pesan keluar terakhir yang saya kirim melalui Messenger ... Apakah Anda tahu apa yang menyebabkan ini?
Miki P
@MikiP menggunakan kekuatan tebakan saya, saya akan mengatakan bahwa Aplikasi Messenger meminta Anda untuk mengganti manajemen SMS dengan Messenger. Ini terjadi dengan beberapa aplikasi perpesanan lainnya. Saya tidak punya penjelasan lain.
m3nda
2
Jangan lupa menelepon c.close ();
Cícero Moura
1
@SardarAgabejli Jika kita menggunakan nilai-nilai hardcored seperti "contenturi: sms" itu tidak akan sama untuk setiap perangkat, tetapi jika kita menggunakan kelas Telephony, kita mendapatkan akses langsung ke conetnt uri atau jalur sms db perangkat itu, Ini kelas pembantu untuk menunjuk ke db sms
Manoj Perumarath
23

Posting ini agak lama, tetapi di sini ada solusi mudah lain untuk mendapatkan data yang terkait dengan SMSpenyedia konten di Android:

Gunakan lib ini: https://github.com/EverythingMe/easy-content-providers

  • Dapatkan semua SMS:

    TelephonyProvider telephonyProvider = new TelephonyProvider(context);
    List<Sms> smses = telephonyProvider.getSms(Filter.ALL).getList();

    Setiap Sms memiliki semua bidang, sehingga Anda bisa mendapatkan info apa pun yang Anda butuhkan:
    alamat, isi, tanggal, jenis (INBOX, SENT, DRAFT, ..), threadId, ...

  • Gel semua MMS:

    List<Mms> mmses = telephonyProvider.getMms(Filter.ALL).getList();
  • Gel semua Thread:

    List<Thread> threads = telephonyProvider.getThreads().getList();
  • Gel semua Conversation:

    List<Conversation> conversations = telephonyProvider.getConversations().getList();

Ini bekerja dengan ListatauCursor dan ada aplikasi sampel untuk melihat tampilannya dan bekerja.

Bahkan, ada dukungan untuk semua penyedia konten Android seperti: Kontak, Log panggilan, Kalender, ... Dok lengkap dengan semua opsi: https://github.com/EverythingMe/easy-content-providers/wiki/Android- penyedia layanan

Semoga bermanfaat juga :)

sromku
sumber
1
Kode sumber dan contoh di github cukup berguna. Ini adalah pembungkus / fasad yang baik untuk penyedia paling umum. Terima kasih.
m3nda
14

Langkah 1: pertama kita harus menambahkan izin dalam file manifes seperti

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

Langkah 2: kemudian tambahkan kelas penerima sms layanan untuk menerima sms

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

Langkah 3: Tambahkan izin run time

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

Langkah 4: Tambahkan kelas ini di aplikasi Anda dan uji kelas Antarmuka

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));  }
 else {}}  }
        catch(Exception e){} } }
public static void bindListener(SmsListener listener) {
    mListener = listener; }}
Venkatesh
sumber
Apa yang dilakukan polanya?
Mark Buikema
Nah ... apakah itu ("com.aquadeals.seller.services.SmsReceiver") nama layanan umum?
m3nda
Ya itu bukan nama layanan, itu adalah jalur kelas SmsReceiver di aplikasi saya
Venkatesh
Mengapa perlu izin untuk LOCATION?
Zam Sunk
1
saya mencoba membuat aplikasi yang muncul konten sms kepada pengguna bahkan jika aplikasi telah terbunuh
Anjani Mittal
11

Ada banyak jawaban yang sudah tersedia tetapi saya pikir semuanya kehilangan bagian penting dari pertanyaan ini. Sebelum membaca data dari database internal atau tabelnya kita harus memahami bagaimana data disimpan di dalamnya dan kemudian kita dapat menemukan solusi dari pertanyaan di atas yaitu:

Bagaimana saya bisa membaca pesan SMS dari perangkat secara terprogram di Android?

Jadi, dalam tabel SMS Android seperti terlihat seperti ini

masukkan deskripsi gambar di sini

Tahu, kita bisa memilih apa pun yang kita inginkan dari database. Dalam kasus kita, kita hanya perlu

id, alamat dan isi

Dalam hal membaca SMS:

1. Mintalah izin

int REQUEST_PHONE_CALL = 1;

   if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_SMS}, REQUEST_PHONE_CALL);
        }

atau

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

2. Sekarang kode Anda seperti ini

// Create Inbox box URI
Uri inboxURI = Uri.parse("content://sms/inbox");

// List required columns
String[] reqCols = new String[]{"_id", "address", "body"};

// Get Content Resolver object, which will deal with Content Provider
ContentResolver cr = getContentResolver();

// Fetch Inbox SMS Message from Built-in Content Provider
Cursor c = cr.query(inboxURI, reqCols, null, null, null);

// Attached Cursor with adapter and display in listview
adapter = new SimpleCursorAdapter(this, R.layout.a1_row, c,
        new String[]{"body", "address"}, new int[]{
        R.id.A1_txt_Msg, R.id.A1_txt_Number});
lst.setAdapter(adapter);

Saya harap yang ini akan membantu. Terima kasih.

Nitin Khanna
sumber
7

Layanan Google Play memiliki dua API yang dapat Anda gunakan untuk merampingkan proses verifikasi berbasis SMS

API Retriever SMS

Memberikan pengalaman pengguna yang sepenuhnya otomatis, tanpa mengharuskan pengguna untuk mengetik kode verifikasi secara manual dan tanpa memerlukan izin aplikasi tambahan dan harus digunakan jika memungkinkan. Namun, itu mengharuskan Anda untuk menempatkan kode hash khusus di badan pesan, jadi Anda harus memiliki kontrol atas sisi server juga .

  • Persyaratan pesan - kode hash 11 digit yang secara unik mengidentifikasi aplikasi Anda
  • Persyaratan pengirim - Tidak ada
  • Interaksi pengguna - Tidak ada

Minta Verifikasi SMS di Aplikasi Android

Lakukan Verifikasi SMS di Server

API Persetujuan Pengguna SMS

Tidak memerlukan kode hash khusus, namun mengharuskan pengguna untuk menyetujui permintaan aplikasi Anda untuk mengakses pesan yang berisi kode verifikasi. Untuk meminimalkan kemungkinan munculnya pesan yang salah kepada pengguna,SMS User Consent akan menyaring pesan dari pengirim dalam daftar Kontak pengguna.

  • Persyaratan pesan - 4-10 digit kode alfanumerik yang mengandung setidaknya satu nomor
  • Persyaratan pengirim - Pengirim tidak boleh ada dalam daftar Kontak pengguna
  • Interaksi pengguna - Satu ketukan untuk menyetujui

The SMS User Consent APIadalah bagian dari Layanan Google Play. Untuk menggunakannya, Anda memerlukan setidaknya versi 17.0.0perpustakaan ini:

implementation "com.google.android.gms:play-services-auth:17.0.0"
implementation "com.google.android.gms:play-services-auth-api-phone:17.1.0"

Langkah 1: Mulai mendengarkan pesan SMS

Persetujuan Pengguna SMS akan mendengarkan pesan SMS yang masuk yang berisi kode satu kali hingga lima menit. Itu tidak akan melihat pesan apa pun yang dikirim sebelum dimulai. Jika Anda tahu nomor telepon yang akan mengirim kode satu kali, Anda dapat menentukan senderPhoneNumber, atau jika Anda tidak nullakan cocok dengan nomor apa pun.

 smsRetriever.startSmsUserConsent(senderPhoneNumber /* or null */)

Langkah 2: Minta izin untuk membaca pesan

Setelah aplikasi Anda menerima pesan yang berisi kode satu kali, itu akan diberitahukan oleh siaran. Pada titik ini, Anda tidak memiliki izin untuk membaca pesan - alih-alih Anda diberi Intentizin untuk mulai meminta izin kepada pengguna. Di dalam Anda BroadcastReceiver, Anda menampilkan prompt menggunakan Intentdi extras. Ketika Anda mulai niat itu, itu akan meminta pengguna untuk izin untuk membaca satu pesan. Mereka akan ditampilkan seluruh teks yang akan mereka bagikan dengan aplikasi Anda.

val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
startActivityForResult(consentIntent, SMS_CONSENT_REQUEST)

masukkan deskripsi gambar di sini

Langkah 3: Mengurai kode satu kali dan menyelesaikan Verifikasi SMS

Ketika pengguna mengklik “Allow”- saatnya untuk benar-benar membaca pesan! Di dalam diri onActivityResultAnda bisa mendapatkan teks lengkap dari Pesan SMS dari data:

val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)

Anda kemudian mengurai pesan SMS dan meneruskan kode satu kali ke backend Anda!

Levon Petrosyan
sumber
4-10 digit alphanumeric code containing at least one numberBisakah Anda menjelaskan apa artinya itu? Apakah itu berarti panjang seluruh pesan harus 4-10 karakter hanya dari kode sms?
Zeeshan Shabbir
Terima kasih juga
Levon Petrosyan
Ini hanya berfungsi untuk verifikasi OTP, bukan? Bagaimana dengan membaca semua pesan lain di dalam telepon, semua SMS, dll? Apakah ada API baru untuk itu, Tolong beri tahu saya. Selamat coding! :)
Manoj Perumarath
Kami selalu mendapat kesalahan batas waktu. Tolong bantu saya
Manikandan K
2
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0" : null;

diubah oleh:

String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0 " : SMS_READ_COLUMN + " = 1 ";
Van Hau Hoang
sumber
2

Kode Kotlin untuk membaca SMS:

1- Tambahkan izin ini ke AndroidManifest.xml:

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

2-Buat Kelas BroadCastreceiver:

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-Dapatkan Izin SMS jika Android 6 ke atas:

   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- Tambahkan kode permintaan ini ke Aktivitas atau fragmen:

 companion object {
    const val PERMISSIONS_REQUEST_READ_SMS = 100
   }

5- Override Periksa permisstion Permintaan hasil menyenangkan:

 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  ")
            }
        }
    }
}
Hamed Jaliliani
sumber
1

Fungsi termudah

Untuk membaca sms saya menulis fungsi yang mengembalikan objek Percakapan:

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

Menggunakan:

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

Atau hanya dapatkan percakapan dari nomor tertentu:

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}")
    }
}
Mickael Belhassen
sumber