项目结构
public class ActivityCollector {
// 创建一个静态的Activity列表,用于存储所有的Activity实例
public static List<Activity> activities = new ArrayList<>();
// 添加Activity实例到列表中
public static void addActivity(Activity activity){
activities.add(activity);
}
// 从列表中移除指定的Activity实例
public static void removeActivity(Activity activity){
activities.remove(activity);
}
// 结束所有存储在列表中的Activity实例
public static void finishAll(){
for (Activity activity:activities){
activity.finish();
}
}
}
public class BaseActivity extends AppCompatActivity {
private ForceOfflineReceiver receiver;
// 在Activity创建时将其添加到ActivityCollector的活动列表中
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
ActivityCollector.addActivity(this);
}
// 在Activity恢复时注册ForceOfflineReceiver广播接收器
protected void onResume(){
super.onResume();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.example.OFF"); // 指定广播的Action
receiver = new ForceOfflineReceiver();
registerReceiver(receiver, intentFilter);
}
// 在Activity暂停时注销ForceOfflineReceiver广播接收器
protected void onPause(){
super.onPause();
if(receiver != null){
unregisterReceiver(receiver);
receiver = null;
}
}
// 在Activity销毁时从ActivityCollector的活动列表中移除该活动
protected void onDestroy(){
super.onDestroy();
ActivityCollector.removeActivity(this);
}
// 内部类,继承自BroadcastReceiver用于接收ForceOffline广播
class ForceOfflineReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// 创建一个弹窗对话框,显示禁止登录的提示信息
AlertDialog.Builder builder =new AlertDialog.Builder(context);
builder.setTitle("禁止登陆");
builder.setMessage("您的账号已在另一台设备登陆、请重新登录");
builder.setCancelable(false);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCollector.finishAll(); // 销毁所有活动
Intent intent = new Intent(context, LoginActivity.class);
context.startActivity(intent); // 重启登录页
}
});
builder.show();
}
}
}
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.accountEdit);
passwordEdit = (EditText) findViewById(R.id.passwordEdit);
login = (Button) findViewById(R.id.login);
// 设置按钮的点击事件监听器
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String user = accountEdit.getText().toString();
String paw = passwordEdit.getText().toString();
// 检查用户输入的账号和密码
if (user.equals("admin") && paw.equals("123")) {
// 账号密码正确,跳转到MainActivity
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
} else {
// 账号密码错误,显示错误提示信息
Toast.makeText(LoginActivity.this, "账户或密码错误", Toast.LENGTH_SHORT).show();
}
}
});
}
}
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取布局中的按钮实例
Button offView = (Button) findViewById(R.id.but_off);
// 为按钮设置点击事件监听器
offView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 创建一个意图并指定广播的Action为"com.example.OFF"
Intent intent = new Intent("com.example.OFF");
// 发送广播
sendBroadcast(intent);
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LoginActivity">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="账户:"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_bias="0.1"
app:layout_constraintVertical_bias="0.3"/>
<EditText
android:id="@+id/accountEdit"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintVertical_bias="0.3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/textView1"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密码:"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_bias="0.1"
app:layout_constraintVertical_bias="0.4"/>
<EditText
android:id="@+id/passwordEdit"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintVertical_bias="0.4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/textView2"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/login"
android:text="login"
android:layout_width="222dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/but_off"
android:layout_width="222dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:text="强制下线"/>
</androidx.constraintlayout.widget.ConstraintLayout>
AndroidManifest.xml中添加如下代码
?<activity
android:name=".LoginActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>