开发者

Android入门之BroadCast模拟实现异地登录事件发生后的主动退出

开发者 https://www.devze.com 2022-12-14 10:35 出处:网络 作者: TGITCIC
目录简介设计全代码activity_main.XMLactivity_login.xmlBroadCastReceiver.JavaandroidManifest.xmlBroadCastReceiver.javaMainActivity.java运行效果简介
目录
  • 简介
  • 设计
  • 全代码
    • activity_main.XML
    • activity_login.xml
    • BroadCastReceiver.Java
    • androidManifest.xml
    • BroadCastReceiver.java
    • MainActivity.java
  • 运行效果

    简介

    随着对BroadCast的越来越深入,我们今天要实现一个稍微复杂一点的BroadCast。即我们常用来有时APP打开时如果多个设备同时登录一个帐号,而我们只允许一个设备登录一个帐号时,此时我们的APP会弹一个对话框如:您的账号在别处登录,请重新登陆!。

    Android入门之BroadCast模拟实现异地登录事件发生后的主动退出

    设计

    要制作这样的效果我们依旧是采用BroadCast,而且是一个自定义的Broadcast。此处需要:

    1.自定义send一个broadcast;

    2.注册一个receiver,使得它监听我们这个自定义的broadcast;

    3.在receiver的onReceive事件中,弹出一个“无窗体悬浮alert dialog”;

    4.由于Android6及以后的相应权限问题,你还要添加这个无窗体的悬浮alert dialog的权限;

    5.又由于我们用的是SDK27及以后版本,因此光添加权限还没有用,还要使用代码唤出android关于这个app的一个“授权”系统窗口,在这个授权窗口内,用户自己点:allow后再进行打开这个app操作,此时这个悬浮alert dialog才能正确被唤起否则当这个alert dialog一旦被唤出你会得到一个permission denied 2038的错误,然后Android App自动退出;

    好了,说了这么多我们来看代码

    全代码

    activity_main.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">
     
        <Button
            android:id="@+id/buttonLoginInOtherPlace"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="模拟异地登录" />
    </LinearLayout>
    

    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="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
     
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="login_id:" />
     
            <EditText
                android:width="120dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </LinearLayout>
     
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
     
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="password:" />
     
            <EditText
                android:width="120dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </LinearLayout>
     
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
     
            <Button
                android:id="@+id/buttonLoginSubmit"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="点一下代表登录了" />
        </LinearLayout>
    </LinearLayout>

    以上定义了两个窗体,运行顺序如下:

    • activity_main先运行,上面显示一个“模拟异地登录”按钮,点一下会弹出一个alert dialog告诉你你现在要登出;
    • 用户点一下这个alert dialog上的【确定】,登录出登录,跳转到一个登录的activity_login界面;
    • 在这个activity_login界面直接点【登录】又登进activity_main

    先来看我们的Receiver,它接受来自activity_main的【模拟异地登录】按钮发送过来的broad cast。

    BroadCastReceiver.java

    package org.mk.android.demo.broadcast;
     
    import android.app.AlertDialog;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.graphics.PixelFormat;
    import android.os.Build;
    import android.provider.Settings;
    import android.util.Log;
    import android.view.Window;
    import android.view.WindowManager;
     
    public class BroadCastReceiver extends BroadcastReceiver {
        private final String TAG = "BroadCastWithActivity";
     
        @Override
        public void onReceive(final Context context, Intent intent) {
     
            Log.i(TAG, "receive broadcast->" + intent.getAction());
            AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
            dialogBuilder.setTitle("警告:");
            dialogBuilder.setMessage("您的账号在别处登录,请重新登陆!");
            dialogBuilder.setCancelable(false);
            dialogBuilder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    ActivityCollector.getInstance().finishAll();
                    Intent intent = new Intent(context, LoginActivity.class);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(intent);
                }
            });
            AlertDialog alertDialog = dialogBuilder.create();
            alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
            alertDialog.show();
        }
    }

    接着,我们来看AndroidManifest.xml文件中的注册以及相应的静态权限申请(这个对话框除了静态权限还需要代码在弹出对话框前申请动态权限,这块代码我们写在了MainActivity.java里的)。

    AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8js"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
        <uses-peandroidrmission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
        <application
            android:allowBackup="true"
            android:dataExtractionRules="@xml/data_extraction_rules"
            android:fullBackupContent="@xml/backup_rules"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/Theme.DemoBroadCastWithActivity"
            tools:targetApi="31">
            <activity
                android:name=".LoginActivity"
                android:exported="false">
                <meta-data
                    android:name="android.app.lib_name"
                    android:value="" />
            </activity>
            <activity
                android:name=".MainActivity"
                android:exported="true">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
     
                    <cat开发者_Python学习egory android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
     
                <meta-data
                    android:name="android.app.lib_name"
                    android:value="" />
            </activity>
            <receiver android:name=".BroadCastReceiver"
                android:enabled="true"
                android:exported="true">
                <intent-filter>
                    <action android:name="android.intent.action.BOOT_COMPLETED"/>
                </intent-filter>
        javascript        <intent-filter>
                    <action android:name="ANDROID.INTENT.ACTION.MEDIA_MOUNTED"/>
                    <action android:name="ANDROID.INTENT.ACTION.MEDIA_UNMOUNTED"/>
                    <data android:scheme="file"/>
                </intent-filter>
            </receiver>
        </application>
     
    </manifest>

    接着我们来看我们的BroadCastReceiver写法。

    BroadCastReceiver.java

    package org.mk.android.demo.broadcast;
     
    import android.app.AlertDialog;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.graphics.PixelFormat;
    import android.os.Build;
    import android.provider.Settings;
    import android.util.Log;
    import android.view.Window;
    import android.view.WindowManager;
     
    public class BroadCastReceiver extends BroadcastReceiver {
        private final String TAG = "BroadCastWithActivity";
        private static final String BROADCAST_ACTON = "org.mk.android.demo.broadcast";
        @Override
        public void onReceive(final Context context, Intent intent) {
            if(intent.getAction().equals(BROADCAST_ACTON)) {
                Log.i(TAG, "receive broadcast->" + intent.getAction());
                AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
                dialogBuilder.setTitle(python"警告:");
                dialogBuilder.setMessage("您的账号在别处登录,请重新登陆!");
                dialogBuilder.setCancelable(false);
                dialogBuilder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ActivityCollector.getInstance().finishAll();
                        Intent intent = new Intent(context, LoginActivity.class);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        context.startActivity(intent);
                    }
                });
                AlertDialog alertDialog = dialogBuilder.create();
                alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
                alertDialog.show();
            }
        }
    }

    我们可以看到,它里面定义了一个alert dialog,这个dialog在弹出时没有context因此我们把它叫作无activity(窗体)依托dialog,因此这种dialog是必须要申请权限的,这是Android的规定。然后这个alert dialog有一个【确定】按钮,点一下这个【确定】按钮,就会以startActivity的方式再次打开activity_main界面,此处我们需要注意的是,这个startActivity里的intent的类型必须为Intent.FLAG_ACTIVITY_NEW_TASK),否则你死活从这个登录界面跳不回activity_main的界面了。

    接着看来MainActivity以及里面发生消息的部分(含代码动态申请Android权限)。

    MainActivity.java

    package org.mk.android.demo.broadcast;
     
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.localbroadcastmanager.content.LocalBroadcastManager;
     
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.os.Bundle;
    import android.provider.Settings;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
     
    public class MainActivity extends BaseActivity {
        private BroadCastReceiver localReceiver;
        private LocalBroadcastManager localBroadcastManager;
        private IntentFilter intentFilter;
        private static final String BROADCAST_ACTON = "org.mk.android.demo.broadcast";
        private final String TAG = "BroadCastWithActivity";
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button buttonLoginInOtherPlace = (Button) findViewById(R.id.buttonLoginInOtherPlace);
            localBroadcastManager = LocalBroadcastManager.getInstance(this);
     
            //初始化广播接收者,设置过滤器
            localReceiver = new BroadCastReceiver();
            intentFilter = new IntentFilter();
            intentFilter.addAction(BROADCAST_ACTON);
            localBroadcastManager.registerReceiver(localReceiver, intentFilter);
            buttonLoginInOtherPlace.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (!Settings.canDrawOverlays(MainActivity.this)) {
                        Intent mintent = new Intent();
                        mintent.setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
                        startActivity(mintent);
                    }
     
                    Log.i(TAG, ">>>>>>MainActivity->onClick");
                    Intent intent = new Intent(BROADCAST_ACTON);
                    localBroadcastManager.sendBroadcast(intent);
                }编程
            });
        }
     
        @Override
        protected void onDestroy() {
            super.onDestroy();
            localBroadcastManager.unregisterReceiver(localReceiver);
        }
    }

    这边核心注意点:

    代码动代申请权限

    if (!Settings.canDrawOverlays(MainActivity.this)) {
        Intent mintent = new Intent();
        mintent.setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
        startActivity(mintent);
    }
    

    代码运行到这,Android会打开一个该APP相应的系统权限对话框

    Android入门之BroadCast模拟实现异地登录事件发生后的主动退出

    Android入门之BroadCast模拟实现异地登录事件发生后的主动退出

    然后把这边的Allow手动启用。

    接着我们重新运行这个APP,效果如下。

    运行效果

    Android入门之BroadCast模拟实现异地登录事件发生后的主动退出

    点击【确定】登出activity_main切换到activity_login

    Android入门之BroadCast模拟实现异地登录事件发生后的主动退出

    在这个界面点击【点一下代表登录了】按钮,再次回到activity_main

    Android入门之BroadCast模拟实现异地登录事件发生后的主动退出

    到此这篇关于Android入门之BroadCast模拟实现异地登录事件发生后的主动退出的文章就介绍到这了,更多相关Android BroadCast异地登录事件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号