详解广播机制(下)

强制下线功能应该算是比较常见的了,很多的应用程序都具备这个功能,比如你的 QQ 号在别处登录了,就会将你强制挤下线。其实实现强制下线功能的思路也比较简单,只需要 在界面上弹出一个对话框,让用户无法进行任何其他操作,必须要点击对话框中的确定按钮, 然后回到登录界面即可

强制下线功能需要先关闭掉所有的活动,然后回到登录界面,先创建一个 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(activity in activities){
            if(!activity.isFinishing){
                activity.finish()
            }
        }
        activities.clear()
    }
}

然后创建 BaseActivity 类作为所有活动的父类

open class BaseActivity:AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ActivityCollector.addActivity(this)
    }

    override fun onDestroy() {
        super.onDestroy()
        ActivityCollector.removeActivity(this)
    }
}

新建LoginActivity,用 AS 创建的默认布局 activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:textSize="18sp"
            android:text="Account:" />

        <EditText
            android:id="@+id/accountEdit"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_vertical"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:textSize="18sp"
            android:text="Password:" />

        <EditText
            android:id="@+id/passwordEdit"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_vertical"/>
    </LinearLayout>

    <Button
        android:layout_width="200dp"
        android:layout_height="60dp"
        android:layout_gravity="center_horizontal"
        android:text="Login"/>
</LinearLayout>
class LoginActivity : BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        login.setOnClickListener {
            val account = accountEdit.text.toString()
            val password = passwordEdit.text.toString()
            //如果账号是 admin ,密码是 123456 就认为登录成功
            if(account == "admin" && password == "123456"){
                val intent = Intent(this,MainActivity::class.java)
                startActivity(intent)
                finish()
            }else{
                Toast.makeText(this,"account or password is invalid",Toast.LENGTH_SHORT).show()
            }
        }
    }
}

登录成功后跳转 MainActivity,你就可以将 MainActivity理解成是登录成功后进入的程序主界面了,这里我们并 不需要在主界面里提供什么花哨的功能,只需要加入强制下线功能就可以了

我们在按钮的点击事件里面发送了一条广播,广播的值为 “com.xx.kotlinapplication.FORCE_OFFLINE”,这条广播就是用于通知程序强 制用户下线的。也就是说强制用户下线的逻辑并不是写在 MainActivity 里的,而是应该写在 接收这条广播的广播接收器里面,这样强制下线的功能就不会依附于任何的界面,不管是在 程序的任何地方,只需要发出这样一条广播,就可以完成强制下线的操作了,因此我们可以在 BaseActivity 中写接收器:

open class BaseActivity : AppCompatActivity() {
    lateinit var receiver: ForceOfflineReceiver
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ActivityCollector.addActivity(this)
    }

    override fun onResume() {
        super.onResume()
        val intentFilter = IntentFilter()
        intentFilter.addAction("com.xx.kotlinapplication.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 r forced to be offline")
                setCancelable(false)
                setPositiveButton("OK") { _, _ ->
                    ActivityCollector.finishAll()
                    var i = Intent(context, LoginActivity::class.java)
                    context.startActivity(i)
                }
                show()
            }
        }
    }
}

使用 AlertDialog.Builder来构建一个对话框,注意这里 一定要调用 setCancelable()方法将对话框设为不可取消,否则用户按一下 Back 键就可以关闭对话框继续使用程序了

我们还重写了 onResume()onPause() 两个生命周期方法,然后分别写了注册和取消注册。之所以在这两个方法里写,是因为我们始终需要保证只有处于栈顶的 Activity 才能接收到这条强制下线广播,非栈顶的 Activity 不应该也没必要接收这条广播

AndroidManifest.xml 文件进行配置

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xx.kotlinapplication">

    <application
       ......>
        <activity android:name=".MainActivity"/>
        <activity android:name=".LoginActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

运行结果
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值