ฉันจะอ่านข้อความ SMS จากอุปกรณ์โดยใช้โปรแกรมใน Android ได้อย่างไร


249

ฉันต้องการรับข้อความ SMS จากอุปกรณ์และแสดงข้อความเหล่านั้น


@David Freitas ลิงก์ที่เชื่อถือได้ +1
Shahzad Imam

3
@DavidFreitas ลิงค์นี้ไม่ทำงานคุณช่วยแบ่งปันลิงค์ล่าสุดได้ไหม?
Khobaib

3
@Khobaib ตามปกติสิ่งต่างๆบนอินเทอร์เน็ตจะหายวับไป ฉันพบสำเนาบน archive.org stackoverflow.com/a/19966227/40961ขอบคุณพระเจ้าสำหรับพวกเขา (ฉันเพิ่งบริจาคเมื่อไม่นานมานี้เพื่อให้พวกเขาทำงานต่อไป) แต่เราควรพิจารณาการแปลงเนื้อหาของหน้าเว็บจากweb.archive.org/web/20121022021217/http://mobdev.olin.edu/…เพื่อทำเครื่องหมายไวยากรณ์ในคำตอบสำหรับคำถามนี้ อาจเป็นชั่วโมงทำงาน
David d C e Freitas

คำตอบ:


157

ใช้ตัวแก้ไขเนื้อหา ( "เนื้อหา: // sms / กล่องจดหมาย" ) เพื่ออ่าน SMS ที่อยู่ในกล่องจดหมาย

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

โปรดเพิ่มสิทธิ์READ_SMS

ฉันหวังว่ามันจะช่วย :)


7
ขอบคุณ! คุณสะกดคำว่า "getColumnName" ไม่ใช่อย่างอื่นที่ใช้งานได้ดี โอ้และถ้าใครจะใช้สิ่งนี้อย่าลืมที่จะเพิ่มการอนุญาต android.permission.READ_SMS
qwerty

1
ขอบคุณ ฉันแก้ไขมัน :)
Suryavel TR

5
นี่ใช้ api ที่ไม่มีเอกสารที่ @CommonsWare ระบุไว้ในความคิดเห็นของเขากับคำตอบที่ยอมรับหรือไม่
Krishnabhadra

1
ความสนใจ! อย่าพลาดmoveToFirstเหมือนที่ฉันทำ
Alexandr Priymak

4
@ Krishnabhadra ใช่ จะใช้ผู้ให้บริการเนื้อหา "เนื้อหา: // sms / inbox" ที่ไม่มีเอกสาร
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();
    }

ตั้งค่าแอพเป็นแอพ SMS เริ่มต้น

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

ฟังก์ชั่นรับ 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 อยู่ด้านล่าง:

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

}

อย่าลืมกำหนดสิทธิ์ใน AndroidManifest.xml ของคุณ

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

2
นั่นเป็นโค้ดที่ดี มีเพียงสิ่งเดียวเท่านั้นที่ได้รับเวลาเป็นมิลลิวินาที ฉันคิดว่ามันจะเป็นการดีกว่าถ้าจะทำให้มันเป็นรูปแบบที่มนุษย์อ่านได้เช่นString receiveDayTime = Functions.dateFromMilisec(Long.valueOf(c.getColumnIndexOrThrow("date")), "hh:mm a MMM dd, yyyy");
Bibaswann Bandyopadhyay

1
อะไรคือจุดประสงค์ของการทำทุกอย่างด้วย getter และ setter ฉันไม่เข้าใจว่าทำไมไม่เพียงแค่ใช้อาร์เรย์ assoc หรือคลาสที่เข้าถึงองค์ประกอบโดยตรง
michnovka

1
@TomasNavara: ตรวจสอบรหัสนี้เพื่อทำความเข้าใจการใช้งาน getter และ setter pastebin.com/Nh8YXtyJ
บั๊กเกิดขึ้น

@BibaswannBandyopadhyay หากคุณไม่ต้องการใช้อะไรยกเว้นห้องสมุด Android และห้องสมุด java new SimpleDateFormat("hh:mm", Locale.US).format(new Date(Long.parseLong(_time)));นี่จะทำให้คุณเวลา 24 ชั่วโมง
Chris - Jr

mActivityไม่ได้กำหนดไว้ นี่คืออะไร?
dthree

61

มันเป็นกระบวนการที่ไม่สำคัญ คุณสามารถดูตัวอย่างที่ดีในซอร์สโค้ดSMSPopup

ตรวจสอบวิธีการต่อไปนี้:

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)

นี่คือวิธีการอ่าน:

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

47
นี่ไม่ใช่ส่วนหนึ่งของ Android SDK รหัสนี้ทำให้สมมติฐานที่ไม่ถูกต้องที่อุปกรณ์ทั้งหมดสนับสนุนผู้ให้บริการเนื้อหาที่ไม่มีเอกสารและไม่สนับสนุนนี้ Google ได้ระบุอย่างชัดเจนว่าการใช้สิ่งนี้ไม่ใช่ความคิดที่ดี: android-developers.blogspot.com/2010/05/…
CommonsWare

1
@Janusz: ไม่มีเอกสารและวิธีการรองรับที่ใช้ได้กับไคลเอนต์ SMS ทั้งหมดในทุกอุปกรณ์
CommonsWare

9
@CommonsWare ที่เสียใจที่ได้ยิน อาจจะต้องใช้งานกับ API นี้แล้ว
Janusz

@Omer คุณคิดว่าจะนับจำนวนข้อความ SMS ต่อผู้ติดต่ออย่างไร
SpicyWeenie

4
รหัสย้ายแล้ว การค้นหา SmsPopupUtils.java ทำให้ฉันมีลิงค์ใหม่ใน google code ในกรณีที่พวกเขาย้ายมันอีกครั้งหรือหยุดมันอย่างสมบูรณ์นี่คือลิงค์สำรอง - pastebin.com/iPt7MLyM
KalEl

25

จาก API 19 เป็นต้นไปคุณสามารถใช้ Telephony Class สำหรับสิ่งนั้น เนื่องจากค่า hardcored จะไม่ดึงข้อความในทุกอุปกรณ์เนื่องจาก Uri ของผู้ให้บริการเนื้อหาเปลี่ยนแปลงจากอุปกรณ์และผู้ผลิต

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

9
ดูเหมือนจะเป็นคำตอบเดียวที่ไม่ได้ใช้ API ที่ไม่มีเอกสารและไม่อ้างถึงห้องสมุดบุคคลที่สาม
Ishamael

ฉันพยายามใช้รหัสนี้เพื่อรับข้อความ SMS จากแฮงเอาท์ (ซึ่งเป็นแอป SMS เริ่มต้นของฉัน) แต่จะดึงข้อความขาออกล่าสุดที่ฉันส่งผ่านทาง Messenger ... คุณรู้หรือไม่ว่าเกิดจากอะไร
Miki P

@MikiP ใช้การคาดเดาของฉันฉันจะบอกว่า Messenger App ขอให้คุณแทนที่การจัดการ SMS ด้วย Messenger มันเกิดขึ้นกับแอพส่งข้อความอื่น ๆ ฉันไม่มีคำอธิบายอื่น ๆ
m3nda

2
อย่าลืมโทร c.close ();
Cícero Moura

1
@SardarAgabejli หากเราใช้ค่า hardcored เช่น "contenturi: sms" จะไม่เหมือนกันสำหรับทุกอุปกรณ์ แต่ถ้าเราใช้คลาส Telephony เราจะได้รับการเข้าถึงโดยตรงไปยัง conetnt uri หรือเส้นทางของ sms db ของอุปกรณ์นั้น ชั้นผู้ช่วยชี้ไปที่ฐานข้อมูลของ SMS
Manoj Perumarath

23

โพสต์นี้ค่อนข้างเก่า แต่นี่เป็นอีกวิธีง่ายๆในการรับข้อมูลที่เกี่ยวข้องกับSMSผู้ให้บริการเนื้อหาใน Android:

ใช้ lib นี้: https://github.com/EverythingMe/easy-content-providers

  • รับทั้งหมดSMS:

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

    แต่ละSmsมีฟิลด์ทั้งหมดเพื่อให้คุณสามารถรับข้อมูลใด ๆ ที่คุณต้องการ: ที่
    อยู่, ร่างกาย, วันที่ได้รับ, ประเภท (กล่องจดหมาย, ส่ง, ร่าง, .. ), threadId, ...

  • เจลทั้งหมดMMS:

    List<Mms> mmses = telephonyProvider.getMms(Filter.ALL).getList();
  • เจลทั้งหมดThread:

    List<Thread> threads = telephonyProvider.getThreads().getList();
  • เจลทั้งหมดConversation:

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

มันทำงานร่วมกับListหรือCursorมีแอพตัวอย่างเพื่อดูว่ามันมีลักษณะและทำงานอย่างไร

ในความเป็นจริงมีการสนับสนุนสำหรับผู้ให้บริการเนื้อหา Android ทุกคนเช่น: ผู้ติดต่อ, บันทึกการโทร, ปฏิทิน, ... เอกสารฉบับเต็มพร้อมตัวเลือกทั้งหมด: https://github.com/EverythingMe/easy-content-providers/wiki/Android- ผู้ให้บริการ

หวังว่ามันจะช่วยด้วย :)


1
ซอร์สโค้ดและตัวอย่างบน github นั้นค่อนข้างมีประโยชน์ นี่คือเสื้อคลุม / ซุ้มที่ดีสำหรับผู้ให้บริการทั่วไป ขอบคุณ.
m3nda

14

ขั้นตอนที่ 1:ก่อนอื่นเราต้องเพิ่มการอนุญาตในไฟล์รายการเช่น

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

ขั้นตอนที่ 2:เพิ่มคลาสผู้รับบริการ sms สำหรับรับ SMS

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

ขั้นตอนที่ 3:เพิ่มสิทธิ์การใช้งาน

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

ขั้นตอนที่ 4:เพิ่มคลาสนี้ในแอปของคุณและทดสอบ คลาสอินเตอร์เฟส

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

รูปแบบการทำอะไร?
Mark Buikema

อืม ... นั่นคือ ("com.aquadeals.seller.services.SmsReceiver") ชื่อบริการทั่วไปใช่ไหม
m3nda

ยานั่นไม่ใช่ชื่อบริการนั่นคือเส้นทางคลาส SmsReceiver ในแอพของฉัน
Venkatesh

ทำไมต้องได้รับอนุญาตสำหรับ LOCATION
Zam Sunk

1
ฉันพยายามสร้างแอพที่ปรากฏเนื้อหา sms ให้กับผู้ใช้แม้ว่าแอปจะถูกฆ่าแล้ว
Anjani Mittal

11

มีคำตอบมากมายอยู่แล้ว แต่ฉันคิดว่าพวกเขาทั้งหมดหายไปเป็นส่วนสำคัญของคำถามนี้ ก่อนที่จะอ่านข้อมูลจากฐานข้อมูลภายในหรือตารางเราต้องเข้าใจว่าข้อมูลถูกเก็บไว้ในฐานข้อมูลจากนั้นเราสามารถหาคำตอบของคำถามข้างต้นนั่นคือ:

ฉันจะอ่านข้อความ SMS จากอุปกรณ์โดยใช้โปรแกรมใน Android ได้อย่างไร

ดังนั้นใน Android SMS table ก็เป็นแบบนี้

ป้อนคำอธิบายรูปภาพที่นี่

รู้ว่าเราสามารถเลือกสิ่งที่เราต้องการจากฐานข้อมูลในกรณีของเราเราจำเป็นเท่านั้น

รหัสที่อยู่และร่างกาย

ในกรณีที่อ่าน SMS:

1. ขออนุญาต

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

หรือ

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

2. ตอนนี้รหัสของคุณเป็นแบบนี้

// 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);

ฉันหวังว่าอันนี้จะเป็นประโยชน์ ขอบคุณ


7

บริการ Google Play มี API สองตัวที่คุณสามารถใช้เพื่อปรับปรุงกระบวนการยืนยันทาง SMS

SMS Retriever API

มอบประสบการณ์ผู้ใช้แบบอัตโนมัติอย่างสมบูรณ์โดยไม่ต้องให้ผู้ใช้พิมพ์รหัสยืนยันด้วยตนเองและไม่ต้องมีการอนุญาตแอพพิเศษใด ๆ และควรใช้เมื่อเป็นไปได้ มันไม่ แต่คุณต้องวางโค้ดกัญชาที่กำหนดเองในเนื้อหาของข้อความเพื่อให้คุณจะต้องมีการควบคุมด้านเซิร์ฟเวอร์เช่นกัน

  • ข้อกำหนดเกี่ยวกับข้อความ - รหัสแฮช 11 หลักที่ระบุแอปของคุณโดยเฉพาะ
  • ข้อกำหนดของผู้ส่ง - ไม่มี
  • การโต้ตอบกับผู้ใช้ - ไม่มี

ขอการยืนยันทาง SMS ในแอพ Android

ทำการตรวจสอบ SMS บนเซิร์ฟเวอร์

API การยินยอมของผู้ใช้ SMS

ไม่ต้องการรหัสแฮชที่กำหนดเองอย่างไรก็ตามผู้ใช้ต้องอนุมัติคำขอแอปของคุณเพื่อเข้าถึงข้อความที่มีรหัสยืนยัน เพื่อลดโอกาสในการแสดงข้อความผิดให้กับผู้ใช้SMS User Consentจะกรองข้อความจากผู้ส่งในรายการที่ติดต่อของผู้ใช้

  • ข้อกำหนดของข้อความ - รหัสตัวอักษรและตัวเลข 4-10 ตัวมีอย่างน้อยหนึ่งหมายเลข
  • ข้อกำหนดของผู้ส่ง - ผู้ส่งไม่สามารถอยู่ในรายชื่อผู้ติดต่อของผู้ใช้ได้
  • การโต้ตอบกับผู้ใช้ - แตะครั้งเดียวเพื่ออนุมัติ

The SMS User Consent APIเป็นส่วนหนึ่งของบริการ Google Play หากต้องการใช้งานคุณจะต้องมี17.0.0ไลบรารีเหล่านี้เป็นเวอร์ชันอย่างน้อย:

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

ขั้นตอนที่ 1: เริ่มฟังข้อความ SMS

การยินยอมของผู้ใช้ SMS จะรับฟังข้อความ SMS ขาเข้าที่มีรหัสครั้งเดียวนานถึงห้านาที มันจะไม่ดูข้อความใด ๆ ที่ส่งก่อนที่จะเริ่ม หากคุณทราบหมายเลขโทรศัพท์ที่จะส่งรหัสแบบครั้งเดียวคุณสามารถระบุsenderPhoneNumberหรือถ้าคุณไม่nullตรงกับหมายเลขใด ๆ

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

ขั้นตอนที่ 2: ขอความยินยอมให้อ่านข้อความ

เมื่อแอปของคุณได้รับข้อความที่มีรหัสแบบครั้งเดียวรายการนั้นจะได้รับการแจ้งเตือนจากการออกอากาศ ณ จุดนี้คุณไม่ได้รับความยินยอมให้อ่านข้อความ แต่คุณได้รับข้อความIntentว่าคุณสามารถเริ่มให้ผู้ใช้แสดงความยินยอมได้ ภายในของคุณBroadcastReceiver, คุณแสดงพรอมต์ที่ใช้ในIntent extrasเมื่อคุณเริ่มเจตนานั้นผู้ใช้จะได้รับอนุญาตให้อ่านข้อความเดียว พวกเขาจะแสดงข้อความทั้งหมดที่พวกเขาจะแบ่งปันกับแอพของคุณ

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

ป้อนคำอธิบายรูปภาพที่นี่

ขั้นตอนที่ 3: วิเคราะห์รหัสแบบครั้งเดียวและการยืนยันทาง SMS แบบสมบูรณ์

เมื่อผู้ใช้คลิก“Allow”- ถึงเวลาที่จะอ่านข้อความ! ภายในตัวonActivityResultคุณสามารถรับข้อความเต็มของข้อความ SMS จากข้อมูล:

val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)

จากนั้นคุณแยกวิเคราะห์ข้อความ SMS และส่งรหัสครั้งเดียวไปที่แบ็กเอนด์ของคุณ!


4-10 digit alphanumeric code containing at least one numberคุณช่วยอธิบายสิ่งนี้ได้อย่างไร มันหมายความว่าความยาวของข้อความทั้งหมดควรเป็น 4-10 ตัวอักษรของรหัส SMS หรือไม่?
Zeeshan Shabbir

ขอบคุณเช่นกัน
Levon Petrosyan

ใช้งานได้กับการยืนยัน OTP เท่านั้นใช่ไหม สิ่งที่เกี่ยวกับการอ่านข้อความอื่น ๆ ทั้งหมดภายในโทรศัพท์ SMS ฯลฯ ทั้งหมด? มี API ใหม่สำหรับสิ่งนั้นโปรดแจ้งให้เราทราบ การเข้ารหัสที่มีความสุข! :)
Manoj Perumarath

เราพบข้อผิดพลาดการหมดเวลาเสมอ โปรดช่วยฉันด้วย
Manikandan K

2
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0" : null;

เปลี่ยนโดย:

String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0 " : SMS_READ_COLUMN + " = 1 ";

2

รหัส Kotlin เพื่ออ่าน SMS:

1- เพิ่มสิทธิ์นี้ให้กับ AndroidManifest.xml:

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

สร้างคลาส BroadCastreceiver 2:

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 - รับสิทธิ์ SMS หาก Android 6 ขึ้นไป:

   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- เพิ่มรหัสคำขอนี้ลงในกิจกรรมหรือส่วน:

 companion object {
    const val PERMISSIONS_REQUEST_READ_SMS = 100
   }

5- แทนที่ตรวจสอบใบอนุญาตสนุกขอผลลัพธ์:

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

1

ฟังก์ชั่นที่ง่ายที่สุด

หากต้องการอ่าน sms ฉันเขียนฟังก์ชั่นที่คืนค่าออบเจกต์การสนทนา:

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

โดยใช้:

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

หรือรับเฉพาะการสนทนาของจำนวนเฉพาะ:

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}")
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.