ฉันต้องการรับข้อความ SMS จากอุปกรณ์และแสดงข้อความเหล่านั้น
ฉันต้องการรับข้อความ SMS จากอุปกรณ์และแสดงข้อความเหล่านั้น
คำตอบ:
ใช้ตัวแก้ไขเนื้อหา ( "เนื้อหา: // 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
ฉันหวังว่ามันจะช่วย :)
moveToFirst
เหมือนที่ฉันทำ
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" />
String receiveDayTime = Functions.dateFromMilisec(Long.valueOf(c.getColumnIndexOrThrow("date")), "hh:mm a MMM dd, yyyy");
new SimpleDateFormat("hh:mm", Locale.US).format(new Date(Long.parseLong(_time)));
นี่จะทำให้คุณเวลา 24 ชั่วโมง
mActivity
ไม่ได้กำหนดไว้ นี่คืออะไร?
มันเป็นกระบวนการที่ไม่สำคัญ คุณสามารถดูตัวอย่างที่ดีในซอร์สโค้ด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;
}
จาก 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();
}
}
โพสต์นี้ค่อนข้างเก่า แต่นี่เป็นอีกวิธีง่ายๆในการรับข้อมูลที่เกี่ยวข้องกับ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:ก่อนอื่นเราต้องเพิ่มการอนุญาตในไฟล์รายการเช่น
<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; }}
มีคำตอบมากมายอยู่แล้ว แต่ฉันคิดว่าพวกเขาทั้งหมดหายไปเป็นส่วนสำคัญของคำถามนี้ ก่อนที่จะอ่านข้อมูลจากฐานข้อมูลภายในหรือตารางเราต้องเข้าใจว่าข้อมูลถูกเก็บไว้ในฐานข้อมูลจากนั้นเราสามารถหาคำตอบของคำถามข้างต้นนั่นคือ:
ฉันจะอ่านข้อความ 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);
ฉันหวังว่าอันนี้จะเป็นประโยชน์ ขอบคุณ
บริการ Google Play มี API สองตัวที่คุณสามารถใช้เพื่อปรับปรุงกระบวนการยืนยันทาง SMS
มอบประสบการณ์ผู้ใช้แบบอัตโนมัติอย่างสมบูรณ์โดยไม่ต้องให้ผู้ใช้พิมพ์รหัสยืนยันด้วยตนเองและไม่ต้องมีการอนุญาตแอพพิเศษใด ๆ และควรใช้เมื่อเป็นไปได้ มันไม่ แต่คุณต้องวางโค้ดกัญชาที่กำหนดเองในเนื้อหาของข้อความเพื่อให้คุณจะต้องมีการควบคุมด้านเซิร์ฟเวอร์เช่นกัน
ขอการยืนยันทาง SMS ในแอพ Android
ทำการตรวจสอบ SMS บนเซิร์ฟเวอร์
ไม่ต้องการรหัสแฮชที่กำหนดเองอย่างไรก็ตามผู้ใช้ต้องอนุมัติคำขอแอปของคุณเพื่อเข้าถึงข้อความที่มีรหัสยืนยัน เพื่อลดโอกาสในการแสดงข้อความผิดให้กับผู้ใช้SMS User Consent
จะกรองข้อความจากผู้ส่งในรายการที่ติดต่อของผู้ใช้
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 หรือไม่?
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0" : null;
เปลี่ยนโดย:
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0 " : SMS_READ_COLUMN + " = 1 ";
รหัส 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 ")
}
}
}
}
ฟังก์ชั่นที่ง่ายที่สุด
หากต้องการอ่าน 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}")
}
}