Android-浅谈广播机制,实现强制下线功能(下)

简介: 为了便于进行系统级别的消息通知,Android也有自己的一套类似的广播消息机制。

接下来修改LoginActivity中的代码,如下所示:

public class LoginActivity extends BaseActivity {
    private EditText accountEdit;
    private EditText passwordEdit;
    private Button login;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        accountEdit=(EditText)findViewById(R.id.account);
        passwordEdit=(EditText) findViewById(R.id.password);
        login=(Button) findViewById(R.id.login);
        login.setOnClickListener(new View.OnClickListener() {   //按钮注册事件
            @Override
            public void onClick(View v) {
                String account=accountEdit.getText().toString();    //获取账号输入框的信息
                String password=passwordEdit.getText().toString();  //获取密码输入框的信息
                if(account.equals("admin")&&password.equals("password")){     //判断输入是否正确
                    Intent intent=new Intent(LoginActivity.this,MainActivity.class);
                    startActivity(intent);
                    finish();
                }
                else{
                    Toast.makeText(LoginActivity.this, "输入有误,请重新输入", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

这里我们模拟登录时的界面,首先将  LoginActivity  的继承结构改为继承自  BaseActivity  ,然后调用了  findViewById()  方法分别获取到输入框中的信息,然后再登录按钮里使用了一个简单的if判断,这里并没有用到数据库等知识。

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

修改activity_main.xml文件中的代码。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/force_offline"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="强制下线按钮"/>
</LinearLayout>

非常简单,只有一个按钮而已,用于出发强制下线功能。然后修改MainActivity中的代码。

public class MainActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button=(Button) findViewById(R.id.force_offline);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent("com.example.xiaxian");
                sendBroadcast(intent);      //发送广播
            }
        });
    }

同样也很简单,这里我们给按钮注册了个监听事件,并且在点击事件里发送了一条广播,广播的值为com.example.xiaxian,这条广播就是通知程序强制用户下线的。也就是说,强制下线的功能并不是写在MainActivity里的,而是应该写在接收这条广播的广播接收器里面,这样强制用户下线的功能就不会依附于任何界面,不管是在程序的任何地方,只需要发出这样一条广播,可以完成强制下线的操作了。

那么接下来的操作,毫无疑问就是需要创建一个广播接收器来接收这条强制下线广播,唯一的问题就是,应该在哪里创建呢?由于广播接收器需要弹出一个对话框来阻塞用户的正常操作,但如果创建的是一个静态注册的广播接收器,是没有办法在  onReceive() 方法里弹出对话框的这样的UI操作的,而我没问显然也不可能在每个活动中都去注册一个动态的广播接收器。

解决办法就是,只需要在BaseActivity中动态注册一个广播接收器就可以了,因为所有的活动都是继承自BaseActivity的。

修改BaseActivity中的代码,如下所示:

public class BaseActivity extends AppCompatActivity {
    private ForceOfflineReceiver receiver;
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityCollector.addActivity(this);
    }
    protected void onResume(){
        super.onResume();
        IntentFilter intentFilter=new IntentFilter();
        intentFilter.addAction("com.example.xiaxian");
        receiver=new ForceOfflineReceiver();
        registerReceiver(receiver,intentFilter);
    }
    @Override
    protected void onPause() {
        super.onPause();
        if(receiver!=null){
            unregisterReceiver(receiver);
            receiver=null;
        }
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.removeActivity(this);     //取消广播
    }
    class ForceOfflineReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(final Context context, Intent intent) {
            AlertDialog.Builder builder=new AlertDialog.Builder(context);       //构建一个对话框
            builder.setTitle("warning");            //对话框标题
            builder.setMessage("You are forced to be offline. Please try to login agaun");      //内容
            builder.setCancelable(false);       //不可取消活动(即无法通过返回键取消活动)
            builder.setPositiveButton("OK",new DialogInterface.OnClickListener(){   //对话框注册确定按钮
                @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ActivityCollector.finish(); //强制下线,即销毁所有活动
                        Intent intent=new Intent(context,LoginActivity.class);
                        context.startActivity(intent);      //重新启动LoginActivity
                    }
                });
            builder.show();
        }
    }
}

先看一下ForceOfflineReceiver中的代码吧,这次,我们先用 AlertDialog.Builder来构建了一个对话框,注意这一定要调用 setCancelable() 方法将对话框设置为不可取消,否则用户点一下返回键就可以关闭对话框并据需使用程序了。然后使用setPositiveButton()方法来给用户对话框注册确定按钮,当用户点击了确定按钮时,就调用强制下线功能来销毁所有活动,并重新启动登录界面。

再来看一下我们是怎么注册ForeOfflineReceiver这个广播接收器,可以看到,这里重写了onResume()和 onPause() 这两个活动得生命周期函数,然后分别在这两个方法里面注册和取消注册了 ForeOfflineReceiver。

为什么要这样写呢?

因为我们要始终保证只有处于栈顶的活动才能接受到这条强制下线广播,非栈顶的活动没必要去接受这条广播,所以写 onRemove 和 onPause() 方法里就可以很好的解决这个问题,当一个活动失去栈顶位置是就会自动取消广播接收器的注册。

这样的话,所有强制下线的逻辑就已经完成了,接下来我们换需要对AndroidManifest.xml文件进行修改,代码如下所示。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.a15094.broadcastbestpractice">
    <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">
        <activity android:name=".MainActivity">
        </activity>
        <activity android:name=".LoginActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

好了,现在我们来试一下吧。

2345_image_file_copy_7.jpg

初学Android,互相学习啦。。

目录
相关文章
|
12天前
|
数据库 Android开发 数据安全/隐私保护
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
59 2
|
14天前
|
Android开发
Android中如何快速的实现RecycleView的拖动重排序功能
使用`ItemTouchHelper`和自定义`Callback`,在`RecyclerView`中实现拖动排序功能。定义`ItemTouchHelperAdapter`接口,`Adapter`实现它以处理`onItemMove`方法。`SimpleItemTouchHelperCallback`设置拖动标志,如`LEFT`或`RIGHT`(水平拖动),并绑定到`RecyclerView`以启用拖动。完成这些步骤后,即可实现拖放排序。关注公众号“AntDream”获取更多内容。
16 3
|
26天前
|
安全 算法 数据安全/隐私保护
探索iOS与Android的隐私保护机制
【6月更文挑战第5天】在数字时代,隐私保护已成为用户最关心的问题之一。iOS和Android作为两大主流操作系统,各自发展出了独特的隐私保护技术。本文将深入探讨这两个平台在隐私保护方面的策略、技术和挑战。
22 3
|
29天前
|
Android开发
38. 【Android教程】Handler 消息传递机制
38. 【Android教程】Handler 消息传递机制
16 2
|
29天前
|
XML Android开发 数据格式
37. 【Android教程】基于监听的事件处理机制
37. 【Android教程】基于监听的事件处理机制
25 2
|
2月前
|
移动开发 监控 Android开发
构建高效Android应用:从内存优化到电池寿命代码之美:从功能实现到艺术创作
【5月更文挑战第28天】 在移动开发领域,特别是针对Android系统,性能优化始终是关键议题之一。本文深入探讨了如何通过细致的内存管理和电池使用策略,提升Android应用的运行效率和用户体验。文章不仅涵盖了现代Android设备上常见的内存泄漏问题,还提出了有效的解决方案,包括代码级优化和使用工具进行诊断。同时,文中也详细阐述了如何通过减少不必要的后台服务、合理管理设备唤醒锁以及优化网络调用等手段延长应用的电池续航时间。这些方法和技术旨在帮助开发者构建更加健壮、高效的Android应用程序。
|
14天前
|
存储 数据库 Android开发
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
16 0
|
2月前
|
Android开发 数据安全/隐私保护 iOS开发
ios和安卓测试包发布网站http://fir.im的注册与常用功能
ios和安卓测试包发布网站http://fir.im的注册与常用功能
30 0
ios和安卓测试包发布网站http://fir.im的注册与常用功能
|
28天前
|
Android开发 虚拟化 异构计算
一文搞定Android VSync机制来龙去脉
一文搞定Android VSync机制来龙去脉
37 0
|
2月前
|
存储 API Android开发
Android 11 中的存储机制更新,面试心得体会
Android 11 中的存储机制更新,面试心得体会