{"id":1914,"date":"2023-05-04T15:59:32","date_gmt":"2023-05-04T07:59:32","guid":{"rendered":"https:\/\/badgameshow.com\/fly\/?p=1914"},"modified":"2023-05-04T15:59:32","modified_gmt":"2023-05-04T07:59:32","slug":"%e3%80%90android%e3%80%91%e8%ae%80%e5%8f%96%e6%89%8b%e6%a9%9f%e7%b0%a1%e8%a8%8a-%e9%a1%af%e7%a4%ba%e5%88%b0%e8%87%aa%e5%b7%b1%e7%9a%84-app-%e4%b8%8a-%e7%af%84%e4%be%8b","status":"publish","type":"post","link":"https:\/\/badgameshow.com\/fly\/%e3%80%90android%e3%80%91%e8%ae%80%e5%8f%96%e6%89%8b%e6%a9%9f%e7%b0%a1%e8%a8%8a-%e9%a1%af%e7%a4%ba%e5%88%b0%e8%87%aa%e5%b7%b1%e7%9a%84-app-%e4%b8%8a-%e7%af%84%e4%be%8b\/","title":{"rendered":"\u3010Android\u3011\u8b80\u53d6\u624b\u6a5f\u7c21\u8a0a \u986f\u793a\u5230\u81ea\u5df1\u7684 APP \u4e0a \u7bc4\u4f8b"},"content":{"rendered":"<h1>\u3010Android\u3011\u8b80\u53d6\u624b\u6a5f\u7c21\u8a0a \u986f\u793a\u5230\u81ea\u5df1\u7684 APP \u4e0a \u7bc4\u4f8b<\/h1>\n<h4>\u5728Android\u4e2d\uff0ccontent:\/\/sms\/inbox \u662f\u4e00\u500bURI\uff0c\u5b83\u8868\u793a\u624b\u6a5f\u6536\u4ef6\u7bb1\u4e2d\u7684\u6240\u6709\u77ed\u4fe1\u6d88\u606f\u3002\u958b\u767c\u8005\u53ef\u4ee5\u4f7f\u7528\u6b64URI\u4f86\u8b80\u53d6\u624b\u6a5f\u4e0a\u7684\u77ed\u4fe1\u6d88\u606f\uff0c\u4f8b\u5982\u7528\u65bc\u77ed\u4fe1\u5099\u4efd\u3001\u6d88\u606f\u63d0\u9192\u7b49\u61c9\u7528\u5834\u666f\u3002<\/h4>\n<h4>\u4f7f\u7528\u6b64URI\uff0c\u958b\u767c\u8005\u53ef\u4ee5\u67e5\u8a62\u6536\u4ef6\u7bb1\u4e2d\u7684\u6240\u6709\u77ed\u4fe1\u6d88\u606f\uff0c\u4e26\u8b80\u53d6\u6bcf\u500b\u6d88\u606f\u7684\u767c\u9001\u8005\u3001\u63a5\u6536\u8005\u3001\u6642\u9593\u6233\u548c\u6d88\u606f\u5167\u5bb9\u7b49\u4fe1\u606f\u3002\u4f8b\u5982\uff0c\u53ef\u4ee5\u4f7f\u7528\u4ee5\u4e0b\u4ee3\u78bc\u8b80\u53d6\u6536\u4ef6\u7bb1\u4e2d\u7684\u77ed\u4fe1\u6d88\u606f\u3002<\/h4>\n<hr \/>\n<h4>\u6587\u7ae0\u76ee\u9304<\/h4>\n<ol>\n<li><a href=\"#a\">Manifest \u7533\u8acb\u6b0a\u9650<\/a><\/li>\n<li><a href=\"#b\">\u8b80\u53d6\u7c21\u8a0a<\/a><\/li>\n<li><a href=\"#c\">\u7c21\u8a0a projection<\/a><\/li>\n<li><a href=\"#d\">\u986f\u793a\u6240\u6709\u7c21\u8a0a<\/a><\/li>\n<li><a href=\"#e\">SMSReadDemo Github<\/a><\/li>\n<\/ol>\n<hr \/>\n<p><a id=\"a\"><\/a><\/p>\n<h4>1.Manifest \u7533\u8acb\u6b0a\u9650<\/h4>\n<pre data-language=XML><code class=\"language-markup line-numbers\">&lt;uses-permission android:name=\"android.permission.RECEIVE_SMS\" \/&gt;\n&lt;uses-permission android:name=\"android.permission.READ_SMS\" \/&gt;\n<\/code><\/pre>\n<h5>build.gradle<\/h5>\n<pre><code class=\"language-gradle line-numbers\">buildFeatures {\n    viewBinding true\n}\n<\/code><\/pre>\n<h5>MainActivity.kt<\/h5>\n<pre><code class=\"language-kotlin line-numbers\">class MainActivity : AppCompatActivity() {\n\n    private lateinit var binding: ActivityMainBinding\n    private val readPermission = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {}\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        binding = ActivityMainBinding.inflate(layoutInflater)\n        setContentView(binding.root)\n\n        readPermission.launch(\n            arrayOf(\n                android.Manifest.permission.RECEIVE_SMS,\n                android.Manifest.permission.READ_SMS\n            )\n        )\n    }\n}\n<\/code><\/pre>\n<p><a id=\"b\"><\/a><\/p>\n<h4>2.\u8b80\u53d6\u7c21\u8a0a<\/h4>\n<h5>MainActivity.kt<\/h5>\n<pre><code class=\"language-kotlin line-numbers\">private fun querySMS(): MutableList&lt;SMS&gt; {\n    val uri = Uri.parse(\"content:\/\/sms\/inbox\")\n    val projection = arrayOf(\"_id\", \"address\", \"body\", \"date\")\n    val smsList = mutableListOf&lt;SMS&gt;()\n\n    contentResolver.query(uri, projection, null, null, null)?.apply {\n        if (moveToFirst()) {\n            do {\n                val id = getInt(getColumnIndexOrThrow(\"_id\"))\n                val sender = getString(getColumnIndexOrThrow(\"address\"))\n                val body = getString(getColumnIndexOrThrow(\"body\"))\n                val timestamp = getLong(getColumnIndexOrThrow(\"date\"))\n                val dateFormat = SimpleDateFormat(\"yyyy\/MM\/dd HH:mm:ss\", Locale.TAIWAN)\n                val dateTime = dateFormat.format(Date(timestamp))\n                smsList.add(SMS(id, sender, body, dateTime))\n            } while (moveToNext())\n        }\n        close()\n    }\n\n    return smsList\n}\n<\/code><\/pre>\n<p><a id=\"c\"><\/a><\/p>\n<h4>3.\u7c21\u8a0a projection<\/h4>\n<pre><code class=\"language-Data line-numbers\">_id\uff1a\u77ed\u4fe1 ID\nthread_id\uff1a\u8207\u8a72\u689d\u77ed\u4fe1\u76f8\u95dc\u806f\u7684\u6703\u8a71 ID\naddress\uff1a\u767c\u9001\u8005\u6216\u63a5\u6536\u8005\u7684\u96fb\u8a71\u865f\u78bc\nperson\uff1a\u767c\u9001\u8005\u6216\u63a5\u6536\u8005\u5728\u806f\u7cfb\u4eba\u5217\u8868\u4e2d\u7684 ID\ndate\uff1a\u77ed\u4fe1\u7684\u6642\u9593\u6233\uff0c\u4ee5\u6beb\u79d2\u70ba\u55ae\u4f4d\ndate_sent\uff1a\u77ed\u4fe1\u767c\u9001\u7684\u6642\u9593\u6233\uff0c\u4ee5\u6beb\u79d2\u70ba\u55ae\u4f4d\nprotocol\uff1a\u77ed\u4fe1\u5354\u8b70\nread\uff1a\u77ed\u4fe1\u662f\u5426\u5df2\u8b80\nstatus\uff1a\u77ed\u4fe1\u72c0\u614b\ntype\uff1a\u77ed\u4fe1\u985e\u578b\uff0c1 \u8868\u793a\u6536\u5230\u7684\u77ed\u4fe1\uff0c2 \u8868\u793a\u767c\u9001\u7684\u77ed\u4fe1\nbody\uff1a\u77ed\u4fe1\u5167\u5bb9\n<\/code><\/pre>\n<p><a id=\"d\"><\/a><\/p>\n<h4>4.\u986f\u793a\u6240\u6709\u7c21\u8a0a<\/h4>\n<h5>MainActivity.kt<\/h5>\n<pre><code class=\"language-kotlin line-numbers\">class MainActivity : AppCompatActivity() {\n\n    private lateinit var binding: ActivityMainBinding\n    private val readPermission = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {}\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        binding = ActivityMainBinding.inflate(layoutInflater)\n        setContentView(binding.root)\n\n        readPermission.launch(\n            arrayOf(\n                android.Manifest.permission.RECEIVE_SMS,\n                android.Manifest.permission.READ_SMS\n            )\n        )\n\n        binding.recyclerView.apply {\n            layoutManager = LinearLayoutManager(this@MainActivity)\n            setHasFixedSize(true)\n            adapter = SMSAdapter(querySMS())\n\n            val divider = DividerItemDecoration(this@MainActivity, DividerItemDecoration.VERTICAL)\n            addItemDecoration(divider)\n        }\n    }\n\n    private fun querySMS(): MutableList&lt;SMS&gt; {\n        val uri = Uri.parse(\"content:\/\/sms\/inbox\")\n        val projection = arrayOf(\"_id\", \"address\", \"body\", \"date\")\n        val smsList = mutableListOf&lt;SMS&gt;()\n\n        contentResolver.query(uri, projection, null, null, null)?.apply {\n            if (moveToFirst()) {\n                do {\n                    val id = getInt(getColumnIndexOrThrow(\"_id\"))\n                    val sender = getString(getColumnIndexOrThrow(\"address\"))\n                    val body = getString(getColumnIndexOrThrow(\"body\"))\n                    val timestamp = getLong(getColumnIndexOrThrow(\"date\"))\n                    val dateFormat = SimpleDateFormat(\"yyyy\/MM\/dd HH:mm:ss\", Locale.TAIWAN)\n                    val dateTime = dateFormat.format(Date(timestamp))\n\n                    smsList.add(SMS(id, sender, body, dateTime))\n                } while (moveToNext())\n            }\n            close()\n        }\n\n        return smsList\n    }\n\n}\n<\/code><\/pre>\n<h5>SMSAdapter.kt<\/h5>\n<pre><code class=\"language-kotlin line-numbers\">class SMSAdapter(private var smsList: List&lt;SMS&gt;) : RecyclerView.Adapter&lt;SMSAdapter.SMSHolder&gt;() {\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SMSHolder {\n        return SMSHolder(SmsItemBinding.inflate(LayoutInflater.from(parent.context), parent, false))\n    }\n\n    override fun onBindViewHolder(holder: SMSHolder, position: Int) {\n        holder.onBind(position)\n    }\n\n    override fun getItemCount() = smsList.size\n\n    inner class SMSHolder(private val smsItemBinding: SmsItemBinding) : RecyclerView.ViewHolder(smsItemBinding.root) {\n        fun onBind(position: Int) {\n            smsItemBinding.sender.text = smsList[position].sender\n            smsItemBinding.body.text = smsList[position].body\n            smsItemBinding.date.text = smsList[position].dateTime\n        }\n    }\n\n}\n<\/code><\/pre>\n<h5>SMS.kt<\/h5>\n<pre><code class=\"language-kotlin line-numbers\">data class SMS(\n    val id: Int,\n    val sender: String,\n    val body: String,\n    val dateTime: String\n)\n<\/code><\/pre>\n<h5>sms_item.xml<\/h5>\n<pre data-language=XML><code class=\"language-markup line-numbers\">&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\n&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\n    xmlns:app=\"http:\/\/schemas.android.com\/apk\/res-auto\"\n    xmlns:tools=\"http:\/\/schemas.android.com\/tools\"\n    android:background=\"#C4E1FF\"\n    android:padding=\"5dp\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"&gt;\n\n    &lt;androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_marginBottom=\"10dp\"\n        android:id=\"@+id\/smsLayout\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"&gt;\n\n        &lt;androidx.appcompat.widget.AppCompatTextView\n            android:id=\"@+id\/sender\"\n            android:layout_width=\"0dp\"\n            android:textColor=\"#008000\"\n            android:textStyle=\"bold\"\n            android:layout_height=\"wrap_content\"\n            android:gravity=\"center\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:text=\"sender\" \/&gt;\n\n        &lt;androidx.appcompat.widget.AppCompatTextView\n            android:id=\"@+id\/body\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:textColor=\"@color\/black\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"@+id\/sender\"\n            app:layout_constraintTop_toBottomOf=\"@+id\/date\"\n            tools:text=\"body\" \/&gt;\n\n        &lt;androidx.appcompat.widget.AppCompatTextView\n            android:id=\"@+id\/date\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:textColor=\"#9FA2A4\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:text=\"date\" \/&gt;\n\n\n    &lt;\/androidx.constraintlayout.widget.ConstraintLayout&gt;\n&lt;\/androidx.constraintlayout.widget.ConstraintLayout&gt;\n<\/code><\/pre>\n<h5>activity_main.xml<\/h5>\n<pre data-language=XML><code class=\"language-markup line-numbers\">&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\n&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\n    xmlns:app=\"http:\/\/schemas.android.com\/apk\/res-auto\"\n    xmlns:tools=\"http:\/\/schemas.android.com\/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".MainActivity\"&gt;\n\n    &lt;androidx.recyclerview.widget.RecyclerView\n        android:id=\"@+id\/recyclerView\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:background=\"#C4E1FF\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        tools:listitem=\"@layout\/sms_item\" \/&gt;\n\n&lt;\/androidx.constraintlayout.widget.ConstraintLayout&gt;\n<\/code><\/pre>\n<p><a id=\"e\"><\/a><\/p>\n<h4>5.SMSReadDemo Github<\/h4>\n<p><a class=\"wp-editor-md-post-content-link\" href=\"https:\/\/github.com\/MuHongWeiWei\/SMSReadDemo\" title=\"SMSReadDemo Github\" target=\"_blank\" rel=\"noopener\">SMSReadDemo Github<\/a><\/p>\n\n<div style=\"font-size: 0px; height: 0px; line-height: 0px; margin: 0; padding: 0; clear: both;\"><\/div>","protected":false},"excerpt":{"rendered":"<p>\u3010Android\u3011\u8b80\u53d6\u624b\u6a5f\u7c21\u8a0a \u986f\u793a\u5230\u81ea\u5df1\u7684 APP \u4e0a \u7bc4\u4f8b \u5728Android\u4e2d\uff0ccontent:\/\/sms &hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"pgc_sgb_lightbox_settings":"","footnotes":""},"categories":[5],"tags":[13,15,242],"class_list":["post-1914","post","type-post","status-publish","format-standard","hentry","category-android","tag-android","tag-kotlin","tag-242"],"_links":{"self":[{"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/posts\/1914","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/comments?post=1914"}],"version-history":[{"count":1,"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/posts\/1914\/revisions"}],"predecessor-version":[{"id":1915,"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/posts\/1914\/revisions\/1915"}],"wp:attachment":[{"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/media?parent=1914"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/categories?post=1914"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/badgameshow.com\/fly\/wp-json\/wp\/v2\/tags?post=1914"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}