Android如何實現(xiàn)短信的讀取與恢復?

我最近有個短信讀取與恢復的需求,現(xiàn)在對其核心實現(xiàn)進行以下總結(jié)。

一、短信讀取

    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()
    }

二、設置系統(tǒng)默認短信APP

從Android5.0開始,默認短信應用外的軟件不能以寫入短信數(shù)據(jù)庫的形式(write sms)發(fā)短信,也就是說插入短信到短信數(shù)據(jù)庫方法行不通了。

我的解決方法是將應用設置為默認短信(事實上,并沒有成為真正的短信App,只是應用現(xiàn)在具有了創(chuàng)建短信的能力了,就滿足我的需求了),操作如下:

0、首先要進行如下配置

這些配置是系統(tǒng)任務一個短信App應該有的功能,要想設置成默認短信App,就必須得有這些。當然創(chuàng)建一個空的就可以,因為我目前的需求是設置成默認短信App,然后能創(chuàng)建短信就行。

        <!-- 接收SMS -->
        <receiver
            android:name=".SmsReceiver"
            android:exported="false"
            android:permission="android.permission.BROADCAST_SMS">
            <intent-filter>
                <action android:name="android.provider.Telephony.SMS_DELIVER" />
            </intent-filter>
        </receiver>
        <!-- 接收MMS-->
        <receiver
            android:name=".MmsReceiver"
            android:exported="false"
            android:permission="android.permission.BROADCAST_WAP_PUSH">
            <intent-filter>
                <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
                <data android:mimeType="application/vnd.wap.mms-message" />
            </intent-filter>
        </receiver>
        <service
            android:name=".HeadlessSmsSendService"
            android:exported="true"
            android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
            <intent-filter>
                <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="sms" />
                <data android:scheme="smsto" />
                <data android:scheme="mms" />
                <data android:scheme="mmsto" />
            </intent-filter>
        </service>

        <activity
            android:name=".activity.MainActivity"
            android:exported="true"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
                <category android:name="android.intent.category.DEFAULT" />
                <action android:name="android.intent.action.SEND" />
                <action android:name="android.intent.action.SENDTO" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="sms" />
                <data android:scheme="smsto" />
                <data android:scheme="mms" />
                <data android:scheme="mmsto" />
            </intent-filter>
        </activity>

這里我還遇到了一個問題:我在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)
        }

三、創(chuàng)建短信

    fun addSms(context: Context) {
        val cv = context.contentResolver
        var value = ContentValues()
        value.put(Telephony.Sms.BODY, "測試短信創(chuàng)建")
        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)
    }

小結(jié)

1、需要注意的是,像上面這樣設置過后,我們的應用就有了創(chuàng)建短信的能力,但事實上,我們的App還不是默認應用。(有需求的朋友可以繼續(xù)探索一下)

參考

1、Android 讀取所有短信
2、android黑科技之讀取用戶短信+插入短信到系統(tǒng)短信數(shù)據(jù)庫
3、Android設為系統(tǒng)默認的短信應用

在 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.
這個權限申請不到,因此這兩種方案不適合。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容