Android入門(mén)之BroadCast模擬實(shí)現(xiàn)異地登錄事件發(fā)生后的主動(dòng)退出
簡(jiǎn)介
隨著對(duì)BroadCast的越來(lái)越深入,我們今天要實(shí)現(xiàn)一個(gè)稍微復(fù)雜一點(diǎn)的BroadCast。即我們常用來(lái)有時(shí)APP打開(kāi)時(shí)如果多個(gè)設(shè)備同時(shí)登錄一個(gè)帳號(hào),而我們只允許一個(gè)設(shè)備登錄一個(gè)帳號(hào)時(shí),此時(shí)我們的APP會(huì)彈一個(gè)對(duì)話框如:您的賬號(hào)在別處登錄,請(qǐng)重新登陸!。
設(shè)計(jì)
要制作這樣的效果我們依舊是采用BroadCast,而且是一個(gè)自定義的Broadcast。此處需要:
1.自定義send一個(gè)broadcast;
2.注冊(cè)一個(gè)receiver,使得它監(jiān)聽(tīng)我們這個(gè)自定義的broadcast;
3.在receiver的onReceive事件中,彈出一個(gè)“無(wú)窗體懸浮alert dialog”;
4.由于Android6及以后的相應(yīng)權(quán)限問(wèn)題,你還要添加這個(gè)無(wú)窗體的懸浮alert dialog的權(quán)限;
5.又由于我們用的是SDK27及以后版本,因此光添加權(quán)限還沒(méi)有用,還要使用代碼喚出android關(guān)于這個(gè)app的一個(gè)“授權(quán)”系統(tǒng)窗口,在這個(gè)授權(quán)窗口內(nèi),用戶自己點(diǎn):allow后再進(jìn)行打開(kāi)這個(gè)app操作,此時(shí)這個(gè)懸浮alert dialog才能正確被喚起否則當(dāng)這個(gè)alert dialog一旦被喚出你會(huì)得到一個(gè)permission denied 2038的錯(cuò)誤,然后Android App自動(dòng)退出;
好了,說(shuō)了這么多我們來(lái)看代碼
全代碼
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="點(diǎn)一下代表登錄了" /> </LinearLayout> </LinearLayout>
以上定義了兩個(gè)窗體,運(yùn)行順序如下:
- activity_main先運(yùn)行,上面顯示一個(gè)“模擬異地登錄”按鈕,點(diǎn)一下會(huì)彈出一個(gè)alert dialog告訴你你現(xiàn)在要登出;
- 用戶點(diǎn)一下這個(gè)alert dialog上的【確定】,登錄出登錄,跳轉(zhuǎn)到一個(gè)登錄的activity_login界面;
- 在這個(gè)activity_login界面直接點(diǎn)【登錄】又登進(jìn)activity_main
先來(lái)看我們的Receiver,它接受來(lái)自activity_main的【模擬異地登錄】按鈕發(fā)送過(guò)來(lái)的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("您的賬號(hào)在別處登錄,請(qǐng)重新登陸!"); 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(); } }
接著,我們來(lái)看AndroidManifest.xml文件中的注冊(cè)以及相應(yīng)的靜態(tài)權(quán)限申請(qǐng)(這個(gè)對(duì)話框除了靜態(tài)權(quán)限還需要代碼在彈出對(duì)話框前申請(qǐng)動(dòng)態(tài)權(quán)限,這塊代碼我們寫(xiě)在了MainActivity.java里的)。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <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-permission 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" /> <category 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> <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>
接著我們來(lái)看我們的BroadCastReceiver寫(xiě)法。
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("警告:"); dialogBuilder.setMessage("您的賬號(hào)在別處登錄,請(qǐng)重新登陸!"); 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(); } } }
我們可以看到,它里面定義了一個(gè)alert dialog,這個(gè)dialog在彈出時(shí)沒(méi)有context因此我們把它叫作無(wú)activity(窗體)依托dialog,因此這種dialog是必須要申請(qǐng)權(quán)限的,這是Android的規(guī)定。然后這個(gè)alert dialog有一個(gè)【確定】按鈕,點(diǎn)一下這個(gè)【確定】按鈕,就會(huì)以startActivity的方式再次打開(kāi)activity_main界面,此處我們需要注意的是,這個(gè)startActivity里的intent的類型必須為Intent.FLAG_ACTIVITY_NEW_TASK),否則你死活從這個(gè)登錄界面跳不回activity_main的界面了。
接著看來(lái)MainActivity以及里面發(fā)生消息的部分(含代碼動(dòng)態(tài)申請(qǐng)Android權(quán)限)。
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); //初始化廣播接收者,設(shè)置過(guò)濾器 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); } }
這邊核心注意點(diǎn):
代碼動(dòng)代申請(qǐng)權(quán)限
if (!Settings.canDrawOverlays(MainActivity.this)) { Intent mintent = new Intent(); mintent.setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); startActivity(mintent); }
代碼運(yùn)行到這,Android會(huì)打開(kāi)一個(gè)該APP相應(yīng)的系統(tǒng)權(quán)限對(duì)話框
然后把這邊的Allow手動(dòng)啟用。
接著我們重新運(yùn)行這個(gè)APP,效果如下。
運(yùn)行效果
點(diǎn)擊【確定】登出activity_main切換到activity_login
在這個(gè)界面點(diǎn)擊【點(diǎn)一下代表登錄了】按鈕,再次回到activity_main
到此這篇關(guān)于Android入門(mén)之BroadCast模擬實(shí)現(xiàn)異地登錄事件發(fā)生后的主動(dòng)退出的文章就介紹到這了,更多相關(guān)Android BroadCast異地登錄事件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android 2d游戲開(kāi)發(fā)之貪吃蛇基于surfaceview
這篇文章主要介紹了Android 2d游戲開(kāi)發(fā)基于surfaceview的貪吃蛇,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09Android?Camera1實(shí)現(xiàn)預(yù)覽框顯示
這篇文章主要為大家詳細(xì)介紹了Android?Camera1實(shí)現(xiàn)預(yù)覽框顯示,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05android開(kāi)發(fā)實(shí)踐之ndk編譯命令簡(jiǎn)單示例
這篇文章主要給大家介紹了在android中ndk編譯命令使用的相關(guān)資料,文中詳細(xì)介紹了ndk-build命令行參數(shù),并通過(guò)簡(jiǎn)單的示例代碼給大家介紹了如何編寫(xiě) .c 文件,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-06-06Android實(shí)現(xiàn)布局動(dòng)畫(huà)和共享動(dòng)畫(huà)的結(jié)合效果
今天給大家?guī)?lái)能夠提升用戶體驗(yàn)感的交互動(dòng)畫(huà),使用起來(lái)非常簡(jiǎn)單,體驗(yàn)效果非常贊,其中僅使用到布局動(dòng)畫(huà)和共享動(dòng)畫(huà),文章通過(guò)代碼示例介紹的非常詳細(xì),感興趣的同學(xué)可以自己動(dòng)手試一試2023-09-09HttpClient通過(guò)Post上傳文件的實(shí)例代碼
這篇文章主要介紹了HttpClient通過(guò)Post上傳文件的實(shí)例代碼的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08Android天氣預(yù)報(bào)之基于HttpGet對(duì)象解析天氣數(shù)據(jù)的方法
這篇文章主要介紹了Android天氣預(yù)報(bào)之基于HttpGet對(duì)象解析天氣數(shù)據(jù)的方法,非常實(shí)用的功能,需要的朋友可以參考下2014-08-08