我想从设备中检索并显示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}")
}
}
其他回答
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应用程序。我做了一个截图来看看这个项目
读取短信的Kotlin代码:
1-将此权限添加到AndroidManifest.xml:
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
创建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-获得短信权限如果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-将此请求代码添加到Activity或fragment:
companion object {
const val PERMISSIONS_REQUEST_READ_SMS = 100
}
5- Override检查权限请求结果fun:
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 ")
}
}
}
}
目前已有多种答案,但我认为所有答案都忽略了这个问题的一个重要部分。 在从内部数据库或其表中读取数据之前,我们必须了解数据是如何存储在其中的,只有这样我们才能找到上述问题的解决方案:
如何在Android系统下以编程方式从设备上读取短信?
在android中,短信表是这样的
现在您可以从数据库中选择您想要的任何内容。在我们的例子中,我们只需要
身份,地址和正文
阅读短信时:
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);
}
or
<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);
我希望这对你有所帮助。 谢谢。
谷歌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消息并将一次性代码传递到后端!
这篇文章有点老了,但这里有另一个简单的解决方案来获得Android中与SMS内容提供商相关的数据:
使用这个lib: https://github.com/EverythingMe/easy-content-providers
Get all SMS: TelephonyProvider telephonyProvider = new TelephonyProvider(context); List<Sms> smses = telephonyProvider.getSms(Filter.ALL).getList(); Each Sms has all fields, so you can get any info you need: address, body, receivedDate, type(INBOX, SENT, DRAFT, ..), threadId, ... Gel all MMS: List<Mms> mmses = telephonyProvider.getMms(Filter.ALL).getList(); Gel all Thread: List<Thread> threads = telephonyProvider.getThreads().getList(); Gel all Conversation: List<Conversation> conversations = telephonyProvider.getConversations().getList();
它与列表或光标一起工作,有一个示例应用程序来查看它的外观和工作方式。
事实上,有一个支持所有Android内容提供者,如:联系人,呼叫日志,日历,… 完整的文档,所有选项:https://github.com/EverythingMe/easy-content-providers/wiki/Android-providers
希望它也有帮助:)
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 碎片中的onCreateOptionsMenu
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- DSL元素android.dataBinding。enabled'已过时,已被'android.buildFeatures.dataBinding'取代
- ConstraintLayout:以编程方式更改约束
- PANIC: AVD系统路径损坏。检查ANDROID_SDK_ROOT值
- 如何生成字符串类型的buildConfigField
- Recyclerview不调用onCreateViewHolder
- Android API 21工具栏填充
- Android L中不支持操作栏导航模式
- 如何在TextView中添加一个子弹符号?
- PreferenceManager getDefaultSharedPreferences在Android Q中已弃用
- 在Android Studio中创建aar文件