Android如何实现短信的读取与恢复?

我最近有个短信读取与恢复的需求,现在对其核心实现进行以下总结。

一、短信读取

    fun getAllSms(context: Context) {
        val cv = context.contentResolver
        val cursor =
            cv.query(Telephony.Sms.CONTENT_URI, null, null, null, Telephony.Sms.DEFAULT_SORT_ORDER)
        if (cursor == null) {
            Log.e(TAG, "cursor is null")
            return
        }

        while (cursor.moveToNext()) {
            val type = cursor.getInt(cursor.getColumnIndex(Telephony.Sms.TYPE))
            val address = cursor.getString(cursor.getColumnIndex(Telephony.Sms.ADDRESS))
            val date = cursor.getLong(cursor.getColumnIndex(Telephony.Sms.DATE))
            val body = cursor.getString(cursor.getColumnIndex(Telephony.Sms.BODY))
            val person = cursor.getInt(cursor.getColumnIndex(Telephony.Sms.PERSON))
            val protocol = cursor.getInt(cursor.getColumnIndex(Telephony.Sms.PROTOCOL))
            Log.i(TAG, "sms = " + Sms(type, address, date, body, person, protocol).toString())
        }

        cursor.close()
    }

二、设置系统默认短信APP

从Android5.0开始,默认短信应用外的软件不能以写入短信数据库的形式(write sms)发短信,也就是说插入短信到短信数据库方法行不通了。

我的解决方法是将应用设置为默认短信(事实上,并没有成为真正的短信App,只是应用现在具有了创建短信的能力了,就满足我的需求了),操作如下:

0、首先要进行如下配置

这些配置是系统任务一个短信App应该有的功能,要想设置成默认短信App,就必须得有这些。当然创建一个空的就可以,因为我目前的需求是设置成默认短信App,然后能创建短信就行。

        
        
            
                
            
        
        
        
            
                
                
            
        
        
            
                
                
                
                
                
                
            
        

        
            
                
                
                
                
                
                
                
                
                
                
            
        

这里我还遇到了一个问题:我在MainActivity中添加了一系列配置后,图标消失了。解决方法是将这些配置移到另一个Activity中就可以了。

然后开始设置应用为默认短信。在进行了一系列搜索后与试验后,最后终于在Rolemanager的源码注释中找到了答案:

1、Android29及以上

Then the application will need user consent to become a role holder, which can be requested using android.app.Activity.startActivityForResult(Intent, int) with the Intent obtained from createRequestRoleIntent(String).

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                val rm = SystemServiceHelper.getRoleManager() as RoleManager
                val intentSms = rm.createRequestRoleIntent(RoleManager.ROLE_SMS)
                startActivityForResult(intentSms, REQUEST_CODE_DEFAULT_SMS)
            }

/**
         * 获取 RoleManager,用于指定默认的应用
         */
        @RequiresApi(Build.VERSION_CODES.Q)
        fun getRoleManager(): RoleManager? {
            val rm =
                AppContext.appContext.getSystemService(Context.ROLE_SERVICE) as RoleManager?
            if (rm == null) {
                Log.e(TAG, "[RoleManager is null]")
            }
            return rm
        }

核心在于:createRequestRoleIntent。

2、低版本设置

val defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(this)
        if (packageName != defaultSmsApp) {
            val intent = Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT)
            intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, packageName)
            startActivity(intent)
        }

三、创建短信

    fun addSms(context: Context) {
        val cv = context.contentResolver
        var value = ContentValues()
        value.put(Telephony.Sms.BODY, "测试短信创建")
        value.put(Telephony.Sms.PERSON, 11111111111)
        value.put(Telephony.Sms.ADDRESS, "11111111111")
        value.put(Telephony.Sms.DATE, System.currentTimeMillis())
        value.put(Telephony.Sms.TYPE, 1)
        value.put(Telephony.Sms.READ, 0)
        cv.insert(Telephony.Sms.CONTENT_URI, value)
    }

小结

1、需要注意的是,像上面这样设置过后,我们的应用就有了创建短信的能力,但事实上,我们的App还不是默认应用。(有需求的朋友可以继续探索一下)

参考

1、Android 读取所有短信
2、android黑科技之读取用户短信+插入短信到系统短信数据库
3、Android设为系统默认的短信应用

在 Android11(小米)上,没有生效

4、Android如何将第三方信息应用设置为默认信息应用?
5、Android10.0(Q) 默认应用设置(电话、短信、浏览器、主屏幕应用)

4/5反射方式,都报错:Caused by: java.lang.SecurityException: addRoleHolderAsUser: Neither user 10318 nor current process has android.permission.MANAGE_ROLE_HOLDERS.
这个权限申请不到,因此这两种方案不适合。

你可能感兴趣的:(Android如何实现短信的读取与恢复?)