Android에서 프로그래밍 방식으로 장치에서 SMS 메시지를 읽으려면 어떻게해야합니까?


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/… 에서 마크 다운 구문으로 변환하는 것을 고려해야 합니다. 아마 1 시간의 작업 일 것입니다.
David d C e Freitas

답변:


157

받은 편지함에있는 SMS를 읽으려면 Content Resolver ( "content : // sms / inbox" )를 사용하십시오 .

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

5
이것은 @CommonsWare가 자신의 의견에 허용 된 답변에 지정한 문서화되지 않은 API를 사용합니까?
Krishnabhadra

1
주의! moveToFirst내가 한 것처럼 놓치지 마세요 .
Alexandr Priymak

4
@Krishnabhadra 예. 문서화되지 않은 "content : // 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 안드로이드 라이브러리 및 자바 라이브러리 이외의 것을 사용하지 않으려는 경우. 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 코드로 새로운 링크가 생겼습니다. 다시 이동하거나 완전히 중단하는 경우 백업 링크는 다음과 같습니다. pastebin.com/iPt7MLyM
KalEl

25

API 19부터는 Telephony Class를 사용할 수 있습니다. 콘텐츠 공급자 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 메시지를 가져 왔습니다. 대신 메신저를 통해 보낸 마지막 발신 메시지를 검색했습니다.이 문제의 원인을 알고 있습니까?
Miki P

내 추측 능력을 사용하는 @MikiP 나는 메신저 응용 프로그램이 SMS 관리를 메신저로 대체 할 것을 요청했다고 말합니다. 다른 메시징 앱에서 발생합니다. 다른 설명이 없습니다.
m3nda

2
c.close ()를 호출하는 것을 잊지 마십시오;
Cícero Moura

1
@SardarAgabejli "contenturi : sms"와 같은 하드 코어 된 값을 사용하는 경우 모든 장치에서 동일하지는 않지만 Telephony 클래스를 사용하는 경우 해당 URI 또는 ​​해당 장치의 sms db 경로에 직접 액세스 할 수 있습니다. SMS의 DB를 차례로 헬퍼 클래스
마노 Perumarath

23

이 게시물은 약간 오래되었지만 다음은 SMSAndroid의 콘텐츠 제공자 와 관련된 데이터를 가져 오는 또 다른 쉬운 솔루션입니다 .

이 라이브러리를 사용하십시오 : https://github.com/EverythingMe/easy-content-providers

  • 모두 가져 오기 SMS:

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

    Sms 에는 모든 필드가 있으므로 주소, 본문, receivedDate, 유형 (INBOX, SENT, DRAFT, ..), 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

서비스 이름이 아닌 Ya, 즉 내 응용 프로그램의 SmsReceiver 클래스 경로
Venkatesh

LOCATION에 대한 권한이 필요한 이유는 무엇입니까?
Zam Sunk

1
앱이 종료 된 경우에도 사용자에게 SMS 콘텐츠를 표시하는 앱을 만들려고합니다
Anjani Mittal

11

이미 사용할 수있는 답변이 많이 있지만 모든 질문에 중요한 부분이 빠져 있다고 생각합니다. 내부 데이터베이스 또는 테이블에서 데이터를 읽기 전에 데이터가 저장되는 방법을 이해해야하며 위의 질문에 대한 해결책을 찾을 수 있습니다.

Android에서 프로그래밍 방식으로 장치에서 SMS 메시지를 읽으려면 어떻게해야합니까?

그래서 안드로이드 SMS 테이블에서는 다음과 같습니다

여기에 이미지 설명을 입력하십시오

우리는 데이터베이스에서 원하는 것을 선택할 수 있습니다.

아이디, 주소 및 본문

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 서비스에는 SMS 기반 확인 프로세스를 간소화하는 데 사용할 수있는 두 가지 API가 있습니다.

SMS 리트리버 API

사용자가 확인 코드를 수동으로 입력하지 않아도되고 추가 앱 권한이 없어도 완전히 자동화 된 사용자 환경을 제공하며 가능한 경우 사용해야합니다. 그러나 메시지 본문에 사용자 정의 해시 코드를 배치 해야 하므로 서버 측도 제어 할 수 있어야합니다 .

  • 메시지 요구 사항 -앱을 고유하게 식별하는 11 자리 해시 코드
  • 발신자 요구 사항 -없음
  • 사용자 상호 작용 -없음

Android 앱에서 SMS 확인 요청

서버에서 SMS 확인 수행

SMS 사용자 동의 API

사용자 지정 해시 코드는 필요하지 않지만 사용자는 확인 코드가 포함 된 메시지에 액세스하기 위해 앱의 요청을 승인해야합니다. 잘못된 메시지를 사용자에게 표시 할 가능성을 최소화하기 위해 SMS User Consent사용자의 연락처 목록에서 보낸 사람의 메시지를 필터링합니다.

  • 메시지 요구 사항 -하나 이상의 숫자를 포함하는 4-10 자리 영숫자 코드
  • 발신자 요구 사항 -발신자가 사용자의 연락처 목록에있을 수 없음
  • 사용자 상호 작용 -한 번의 탭으로 승인

The SMS User Consent APIGoogle 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 사용자 동의는 최대 5 분 동안 일회성 코드가 포함 된 수신 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그게 무슨 뜻인지 설명 할 수 있습니까? 전체 메시지 길이가 SMS 코드의 4-10 자 여야합니까?
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

SMS를 읽는 Kotlin 코드 :

1-이 권한을 AndroidManifest.xml에 추가하십시오.

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

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

Android 6 이상인 경우 3-SMS 권한 받기 :

   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를 읽으려면 Conversation 객체를 반환하는 함수를 작성했습니다.

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.