BroadcastReceiver 最佳实践
强制下线功能
在前面我们学过一键销毁所有Actvity的方法,同样,这次用来强制下线。因为我们不可能每一个页面都做一个返回键。
创建类ActivityCollector
object ActivityCollector {
private val activities = ArrayList<Activity>()
fun addActivity(activity: Activity){
activities.add(activity)
}
fun removeActivity(activity: Activity){
activities.remove(activity)
}
fun finishAll(){
for (a in activities){
if (!a.isFinishing)
a.finish()
}
activities.clear()
}
}
这里使用object是为了实现其静态方法的功能。代码很简单
同样,这里实现一个登陆页面,功能是只有填入正确的密码和账号才会开启下一个页面,在下一个页面设置一个按钮,点击后发送广播,实现强制下线功能。
登录页面简单
登录按钮功能实现也很简单
class LoginActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
val binding = ActivityLoginBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.login.setOnClickListener {
val account = binding.accountEdit.text.toString()
val password = binding.textPassword.text.toString()
if (account=="admin"&&password=="123456"){ //账号密码正确,则开启另一个activity
val intent = Intent(this,MainActivity::class.java)
startActivity(intent)
finish()
}else{ //错误则提示重试一遍
Toast.makeText(this,"account or password is invalid",Toast.LENGTH_SHORT).show()
}
}
}
}
发送广播的按钮实现也很简单
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.forceOffline.setOnClickListener {
val intent = Intent("com.example.broadcastbestpractive.FORCE_OFFLINE")
sendBroadcast(intent)
}
}
}
现在难点在于,要动态创建还是静态创建?
首先我们的功能实现是弹出一个对话框,不能取消只能选择“ok”,如果是静态创建是无法在onReceive中构造对话框的,因此选择动态创建!
而且只用创建一个父类便可以实现。
创建BaseActivity,要实现的功能
- 实现ActivityCollector的功能
- 实现BroadcastReceiver动态注册
open class BaseActivity: AppCompatActivity() {
lateinit var receiver: ForceOffLineReceiver
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
ActivityCollector.addActivity(this)
}
override fun onResume() {
super.onResume()
val intentFilter =IntentFilter()
intentFilter.addAction("com.example.broadcastbestpractive.FORCE_OFFLINE")
receiver=ForceOffLineReceiver()
registerReceiver(receiver,intentFilter)
}
override fun onPause() {
super.onPause()
unregisterReceiver(receiver)
}
override fun onDestroy() {
super.onDestroy()
ActivityCollector.removeActivity(this)
}
inner class ForceOffLineReceiver:BroadcastReceiver(){
override fun onReceive(context: Context?, intent: Intent?) {
AlertDialog.Builder(context!!).apply { //对话框
setTitle("Warning")
setMessage("You are forced to be offline. Please try to login again. ")
setCancelable(false) //不可取消
setPositiveButton("OK"){_,_->
ActivityCollector.finishAll()
val i = Intent(context,LoginActivity::class.java)
context.startActivity(i)
}
show()
}
}
}
}
这里要注意几点
- 一个是需要在onCreate时加入Activity Collector,在onResume时注册,因此相对应的在onDestory时调用remove,在onPause时取消注册
- 对话框设置里头的setCancelable必须是false,不然用户就可以通过back键返回了
最终效果如下: