Android開發(fā)中強(qiáng)制下線功能實(shí)現(xiàn)

強(qiáng)制下線的應(yīng)用場(chǎng)景很多, 比如我們好多賬號(hào)都有搶登的顯現(xiàn), 會(huì)被擠下線.


實(shí)現(xiàn)效果:

源碼:

https://github.com/junzaivip/BroadcastBestPractice

詳細(xì)實(shí)現(xiàn):

其實(shí)實(shí)現(xiàn)強(qiáng)制下線功能的思路也比較簡單, 只需要在界面彈出一個(gè)對(duì)話框, 讓用戶無法進(jìn)行其他操作, 必須點(diǎn)擊對(duì)話框中的確定按鈕, 然后回到登錄界面即可.

但是又有一個(gè)問題, 我們通知用戶強(qiáng)制下線, 用戶可能正處于任何一個(gè)界面, 難道需要在每個(gè)界面上都編寫一個(gè)彈出對(duì)話框的邏輯? 當(dāng)然不是! 我們可以借助本章中所學(xué)的廣播知識(shí)來輕松實(shí)現(xiàn)這一功能.


public class ActivityConllector {
    public static List<Activity> activities = new ArrayList<>();

    public static void addActivity(Activity activity){
        activities.add(activity);
    }

    public static void removeActivity(Activity activity){
        activities.remove(activity);
    }

    public static void finishAll(){
        for (Activity activity : activities){
            if(!activity.isFinishing()){
                activity.finish();
            }
        }
    }

創(chuàng)建BaseActivity類作為所有活動(dòng)的父類, 代碼如下:

public class BaseActivity  extends AppCompatActivity{
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityConllector.addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityConllector.removeActivity(this);
    }
}

首先編寫布局文件activity_login文件:

<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:text="User Name"
            android:textSize="18sp"
            android:layout_gravity="center_vertical"/>
        <EditText
            android:id="@+id/account"
            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:text="Password"
            android:textSize="18sp"
            android:layout_gravity="center_vertical"/>
        <EditText
            android:id="@+id/password"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_vertical"
            android:inputType="textPassword"/>
    </LinearLayout>
    <Button
        android:id="@+id/login"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="Login"/>
</LinearLayout>

LoginActivity.java中代碼:

public class LoginActivity extends BaseActivity implements View.OnClickListener{
    private EditText userName;
    private EditText passWord;
    private Button login;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        userName = (EditText)findViewById(R.id.account);
        passWord = (EditText)findViewById(R.id.password);
        login = (Button) findViewById(R.id.login);
        login.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.login:
                String username = userName.getText().toString();
                String password = passWord.getText().toString();
                if(username.equals("admin") && password.equals("123")){
                    Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                    startActivity(intent);
                    finish();
                } else {
                    Toast.makeText(this, "用戶名或者密碼錯(cuò)誤!", Toast.LENGTH_SHORT).show();
                }

        }

    }
}

我們這時(shí)可以理解成, 登錄界面之后, 進(jìn)入的activity_main.xml就是主界面. 主界面沒有其他功能, 只有一個(gè)用于顯示的TextView和一個(gè)用作下線功能的按鈕

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="這是主頁面"
        android:layout_gravity="center_horizontal"/>

    <Button
        android:id="@+id/force_offline"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="強(qiáng)制下線"/>
</LinearLayout>
MainActivity.java中代碼:
public class MainActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button forceOffline = (Button) findViewById(R.id.force_offline);
        forceOffline.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("com.junzaivip.broadcastbestpractice.FORCE_OFFLINE");
                sendBroadcast(intent);
            }
        });
    }
}

我們按鈕的點(diǎn)擊事件里面發(fā)送了一條廣播, 廣播的值為com.junzaivip.broadcastbestpractice.FORCE_OFFLINE, 這條廣播就是用于通知程序強(qiáng)制用戶下線的.

也就是說強(qiáng)制用戶下線的邏輯并不是寫在MainActivity里的, 而是應(yīng)該寫在接收這條廣播的接收器里面. 這樣的好處是, 強(qiáng)制下線的功能就不會(huì)依附于任何的界面, 不管是在程序的任何地方, 只需要發(fā)出一條這樣的廣播,就可以完成強(qiáng)制下線的操作了.

那么, 需要?jiǎng)?chuàng)建一個(gè)廣播接收器, 用于接收這條強(qiáng)制下線的廣播, 唯一的問題就是, 應(yīng)該在哪里創(chuàng)建呢? 由于廣播接收器里面需要彈出一個(gè)對(duì)話框來阻塞用戶的正常操作. 但如果創(chuàng)建的是一個(gè)靜態(tài)注冊(cè)的廣播接收器, 是沒有辦法在onReceive()方法里彈出對(duì)話框這樣的UI控件的, 而我們顯然不能也不可能在每個(gè)活動(dòng)中注冊(cè)一個(gè)動(dòng)態(tài)的廣播接收器.

那么到底應(yīng)該怎么辦呢? 其實(shí)很明顯, 只需要在BaseActivity中動(dòng)態(tài)注冊(cè)一個(gè)廣播接收器就可以了. 因?yàn)樗械幕顒?dòng)都繼承自BaseActivity的.

BaseActivity中的代碼:

public class BaseActivity  extends AppCompatActivity{
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityConllector.addActivity(this);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityConllector.removeActivity(this);
    }
    class ForceOffLineReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(final Context context, final Intent intent) {
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setTitle("warning");
            builder.setMessage("您被強(qiáng)制下線, 請(qǐng)您重新登錄!");
            builder.setCancelable(false); // 將對(duì)話框設(shè)置為不可取消
            // 給按鈕添加注冊(cè)監(jiān)聽
            builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // 點(diǎn)擊按鈕所調(diào)用的方法
                    ActivityConllector.finishAll();//銷毀所有的活動(dòng)
                    Intent intent1 = new Intent(context, LoginActivity.class);
                    context.startActivity(intent);
                }
            });
            builder.show();
        }
    }

}

我們需要設(shè)置主活動(dòng)為LoginActivity, 而不再是MainActivity, 模擬訪問一個(gè)程序首先在登錄頁面.

修改AndroidManifest.xml文件:

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        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>

運(yùn)行效果如下:

參考: 郭霖: <<第一行代碼>>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子珊佣,更是在濱河造成了極大的恐慌贡未,老刑警劉巖裂垦,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恢恼,死亡現(xiàn)場(chǎng)離奇詭異扼褪,居然都是意外死亡舱污,警方通過查閱死者的電腦和手機(jī)呀舔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扩灯,“玉大人媚赖,你說我怎么就攤上這事≈椴澹” “怎么了惧磺?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長捻撑。 經(jīng)常有香客問我磨隘,道長缤底,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任番捂,我火速辦了婚禮个唧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘设预。我一直安慰自己徙歼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布鳖枕。 她就那樣靜靜地躺著魄梯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宾符。 梳的紋絲不亂的頭發(fā)上酿秸,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音吸奴,去河邊找鬼允扇。 笑死缠局,一個(gè)胖子當(dāng)著我的面吹牛则奥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播狭园,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼读处,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了唱矛?” 一聲冷哼從身側(cè)響起罚舱,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绎谦,沒想到半個(gè)月后管闷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡窃肠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年包个,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冤留。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碧囊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出纤怒,到底是詐尸還是另有隱情糯而,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布泊窘,位于F島的核電站熄驼,受9級(jí)特大地震影響像寒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瓜贾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一萝映、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧阐虚,春花似錦序臂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至咸灿,卻和暖如春构订,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背避矢。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工悼瘾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人审胸。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓亥宿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親砂沛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子烫扼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容