記動態注冊廣播權限問題

最近在開發過程中遇到一個需求,就是跨進程的廣播通信,一番嘗試之后發現首先好像靜態注冊廣播的方式行不通了,因為Android 8.0的改動中,限制了大部分的隱式廣播注冊,常見的解決方案有兩種:一種是通過intent.setComponent方法將意圖改為顯式的。另一種方法就是改為動態注冊了。

ps:關于Android 8.0中關于廣播的改動可以查看官方文檔Android 8.0 行為變更中的后臺執行限制部分。

跨進程的廣播發送與接收解決了之后,我還想添加一個權限限制,讓其他程序如果碰巧發送了同樣Action的廣播后我自己注冊的接收器不會接受,其他程序注冊的接收器不會收到我自己發出的同樣Action的廣播。但是經過一番想當然的嘗試之后失敗了,于是再次去翻文檔,然后通過demo測試實踐了一番。這里先簡單小結一下=:

  1. 簡單的權限限制分為兩類,一類是帶有權限的發送,用于限制接收器的,只有申請了相應權限的接收器才能接收到廣播。另一類是帶有權限的接收,用于限制發送廣播的一方,在發送廣播時使用sendBroadcast(Intent,String)方法發送廣播。
  2. 如果想要實現A應用發送的廣播只有B應用可以接收到,B應用只能接收到A應用發出的廣播(注意這里雖然兩句話表述好像一致,但是其實包含的情況是不同的),應該就需要在注冊廣播時通過permissionGroup以及protectionLevel等屬性去做更近一步的限制了,具體的實現這里就沒有再繼續下去了,后面有時間的話可以通過文檔permission對這兩個屬性的介紹嘗試一下。

下面根據官方文檔廣播概況以及具體的Demo實際感受一下兩種通過權限限制的廣播:

帶權限的發送

這種方式可以用來限制廣播接收器,在發送廣播的一方通過sendBroadcast(Intent,String)方法發送他廣播,然后聲明了相應權限的的一方中注冊的廣播接收器才能收到廣播。使用這種方式權限需要聲明在廣播發送方

Project A -- (BroadcastTest1):

<!-- AndroidManifest.xml  -->
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.broadcasttest1">

    <!--    聲明權限 -->
    <permission android:name="com.yu.hu.permissions.BUGREPORT"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        ...
    </application>

</manifest>
class MainActivity : AppCompatActivity() {
    companion object {
        const val TAG = "MainActivity"
        const val ACTION = "com.yu.hu.action.BUGREPPORT"
        const val PERMISSION = "com.yu.hu.permissions.BUGREPORT"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val button = findViewById<Button>(R.id.send_btn)
        //添加button點擊事件
        button.setOnClickListener {
            val intent = Intent(ACTION)
            intent.putExtra("test", "test")
            Log.d(TAG, "send BroadcastReceiver with permission")
            //帶有權限的發送 接收方必須申請相應權限才能正常接受到
            sendBroadcast(intent,PERMISSION)
        }
    }
}

Project B -- (BroadcastTest2):

<!-- AndroidManifest.xml -->
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.broadcasttest2">

    <!-- 申請權限 -->
    <uses-permission android:name="com.yu.hu.permissions.BUGREPORT" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        ...
    </application>

</manifest>
class BugReportReceiver : BroadcastReceiver() {

    companion object {
        const val TAG = "BugReportReceiver"
        const val ACTION = "com.yu.hu.action.BUGREPPORT"
        const val PERMISSION = "com.yu.hu.permissions.BUGREPORT"
    }

    override fun onReceive(context: Context?, intent: Intent?) {

        val value = intent?.getStringExtra("test")
        Log.d(TAG, "onReceive: msg = $value")
        Toast.makeText(context, "msg2 = $value", Toast.LENGTH_SHORT).show()
    }
}
class MainActivity : AppCompatActivity() {

    companion object {
        const val TAG = "MainActivity2"
        const val ACTION = "com.yu.hu.action.BUGREPPORT"
        const val PERMISSION = "com.yu.hu.permissions.BUGREPORT"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val ifl = IntentFilter()
        ifl.addAction(BugReportReceiver.ACTION)
        registerReceiver(BugReportReceiver(), ifl)
    }
}

Project C -- (BroadcastTest3):

class BugReportReceiver : BroadcastReceiver() {

    companion object {
        const val TAG = "BugReportReceiver"
        const val ACTION = "com.yu.hu.action.BUGREPPORT"
        const val PERMISSION = "com.yu.hu.permissions.BUGREPORT"
    }

    override fun onReceive(context: Context?, intent: Intent?) {=

        val value = intent?.getStringExtra("test")
        Log.d(TAG, "onReceive: msg = $value")
        Toast.makeText(context, "msg2 = $value", Toast.LENGTH_SHORT).show()
    }
}
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        registerReceiver(BugReportReceiver(), IntentFilter(BugReportReceiver.ACTION))
    }
}

點擊Button后輸出結果:

2020-07-10 12:51:27.155 25951-25951/com.example.broadcasttest1 D/MainActivity: send BroadcastReceiver with permission
2020-07-10 12:51:27.157 31322-31336/? W/BroadcastQueue: Permission Denial: receiving Intent { act=com.yu.hu.action.BUGREPPORT flg=0x10 (has extras) } to ProcessRecord{3b20417 25865:com.example.boradcasttest3/u0a164} (pid=25865, uid=10164) requires com.yu.hu.permissions.BUGREPORT due to sender com.example.broadcasttest1 (uid 10155)
2020-07-10 12:51:27.161 25907-25907/com.example.broadcasttest2 D/BugReportReceiver: onReceive: msg = test

可以看到只有B收到了廣播了而C沒有收到,因為BAndroidManifest.xml中申請了權限,而C沒有,所以報了Permission Denial的錯誤。在C中也申請了權限后就同樣能接收到廣播了。

帶權限的接收

這種方式可以用來限制發送廣播的一方,只有申請了相應的權限才能成功發送廣播。使用這種方式權限需要聲明在廣播接收器的注冊方
Project A -- (BroadcastTest1): - 申請權限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.broadcasttest1">

    <uses-permission android:name="com.test.permission.receiver"/>
    ...
</manifest>
class MainActivity : AppCompatActivity() {
    companion object {
        const val TAG = "MainActivity"
        const val ACTION = "com.yu.hu.action.BUGREPPORT"
        const val PERMISSION = "com.yu.hu.permissions.BUGREPORT"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val button = findViewById<Button>(R.id.send_btn)
        button.setOnClickListener {
            val intent = Intent(ACTION)
            intent.putExtra("test", "test")
            Log.d(TAG, "send Broadcast with permission")
            sendBroadcast(intent)
        }
    }
}

Project B -- (BroadcastTest2): - 不申請權限

class MainActivity : AppCompatActivity() {

    companion object {
        const val TAG = "MainActivity2"
        const val ACTION = "com.yu.hu.action.BUGREPPORT"
        const val PERMISSION = "com.yu.hu.permissions.BUGREPORT"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val button = findViewById<Button>(R.id.send_btn)
        button.setOnClickListener {
            val intent = Intent(ACTION)
            intent.putExtra("test", "test")
            Log.d(TAG, "send Broadcast without permission")
            //不申請權限發送
            sendBroadcast(intent)
        }
    }
}

Project C -- (BroadcastTest3): - 聲明權限并在注冊時添加權限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.boradcasttest3">

    <permission android:name="com.test.permission.receiver"/>
    ...

</manifest>
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        registerReceiver(BugReportReceiver(), IntentFilter(BugReportReceiver.ACTION), "com.test.permission.receiver", null)
    }
}

A中發送廣播:

2020-07-10 14:07:36.187 12843-12843/com.example.broadcasttest1 D/MainActivity: send Broadcast with permission
2020-07-10 14:07:36.191 12600-12600/com.example.boradcasttest3 D/BugReportReceiver: onReceive2: msg = test

成功發送也成功接收處理。下面是在B中發送廣播的日志:

2020-07-10 14:08:04.368 13003-13003/com.example.broadcasttest2 D/MainActivity2: send Broadcast without permission
2020-07-10 14:08:04.370 31322-31336/? W/BroadcastQueue: Permission Denial: broadcasting Intent { act=com.yu.hu.action.BUGREPPORT flg=0x10 (has extras) } from com.example.broadcasttest2 (pid=13003, uid=10162) requires com.test.permission.receiver due to registered receiver BroadcastFilter{37dbe8b u0 ReceiverList{7706c5a 12600 com.example.boradcasttest3/10164/u0 remote:8530405}}

發送之后報了Permission Denial,所以接收器沒有接收到這條廣播。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。