我想从设备中检索并显示SMS消息?


当前回答

第一步:首先我们必须在清单文件中添加权限 就像

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

步骤2:添加服务短信接收类,用于接收短信

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

第四步:在应用程序中添加这些类并进行测试 接口类

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

其他回答

谷歌Play服务有两个api,可用于简化基于短信的验证过程

短信检索器接口

提供完全自动化的用户体验,不需要用户手动输入验证码,也不需要任何额外的应用权限,应该在可能的情况下使用。但是,它要求您在消息体中放置自定义哈希代码,因此您还必须控制服务器端。

消息要求-唯一标识应用程序的11位哈希码 发件人要求—无 用户交互—无

在Android应用程序中请求短信验证

在服务器上进行短信验证

短信用户同意API

不需要自定义哈希码,但需要用户批准你的应用程序的请求,以访问包含验证码的消息。为了最大限度地减少向用户显示错误消息的机会,SMS用户同意将从用户的联系人列表中过滤出发件人的消息。

消息要求-至少包含一个数字的4-10位字母数字代码 发件人要求-发件人不能在用户的联系人列表中 用户交互-一键批准

短信用户同意API是谷歌播放服务的一部分。要使用它,你至少需要这些库的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"

第一步:开始监听短信

SMS用户同意将监听包含一次性代码的传入SMS消息长达五分钟。它不会查看在启动之前发送的任何消息。如果知道发送一次性代码的电话号码,则可以指定senderPhoneNumber,如果不指定,则null将匹配任何号码。

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

步骤2:请求同意阅读消息

一旦你的应用程序接收到包含一次性代码的消息,它就会被广播通知。在这一点上,你没有同意阅读消息-相反,你给了一个意图,你可以开始提示用户同意。在你的BroadcastReceiver内部,你使用extras中的Intent来显示提示。 当您启动该意图时,它将提示用户允许读取单个消息。他们将会看到与你的应用共享的全部文本。

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

第三步:解析一次性代码,完成短信验证

当用户点击“允许”-是时候真正阅读消息了!在onActivityResult内部,你可以从数据中获得短信的全文:

val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)

然后解析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}")
    }
}
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();
    }

将app设置为默认短信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();
            }
        }
    }
}
}

获取短信的功能

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

短信类如下:

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

从API 19开始,你可以使用Telephony类;因为硬核值不会在每个设备中检索消息,因为内容提供程序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();
    }
}

Hier是一个很棒的视频教程!!!!效果非常好!!

这是一个组合从谷歌表列表与数字和一个Android应用程序。(非常容易遵循教程也没有编码员!!

点击链接进入教程:

https://www.youtube.com/watch?v=PReU4ITp37I&list=PLuB9drjjGa0QvFzWq_bwO8bOTRaWpdP_d&index=2

下面是谷歌应用程序脚本的代码:

const SHEET_URL = "https://docs.google.com/spreadsheets/d/16_fp7lQsnaMLaDYMVsE5YxsohQBANllEVcZeMP5ZpiU/edit#gid=0";
const SHEET_NAME = "SMS";

const doGet = () => {
  const sheet = SpreadsheetApp.openByUrl(SHEET_URL).getSheetByName(SHEET_NAME);
  const [header, ...data] = sheet.getDataRange().getDisplayValues();
  

  const PHONE = header.indexOf("Phone");
  const TEXT = header.indexOf("Text");
  const STATUS = header.indexOf("Status");

  const output = [];

 data.forEach((row, index) => {
  if (row[STATUS] === "") {
    output.push([index+1, row[PHONE], row[TEXT]]);
  }
});

const json = JSON.stringify(output);

return ContentService.createTextOutput(json).setMimeType(ContentService.MimeType.TEXT);
}

const doPost = (e) => {
  const sheet = SpreadsheetApp.openByUrl(SHEET_URL).getSheetByName(SHEET_NAME);
  const [header] = sheet.getRange("A1:1").getValues();
  const STATUS = header.indexOf("Status");
  var rowId = Number(e.parameter.row);
  sheet.getRange(rowId + 1, STATUS +1).setValue("SMS Sent");
  return ContentService.createTextOutput("").setMimeType(ContentService.MimeType.TEXT);
}

然后你只需要跟随视频的第二部分他在MIT APP Inventer中构建Android应用程序。我做了一个截图来看看这个项目