1. 程式人生 > >《第一行程式碼Android》學習總結第四章 廣播機制實踐——強制下線功能

《第一行程式碼Android》學習總結第四章 廣播機制實踐——強制下線功能

        強制下線功能需要在任何一個介面上彈出一個對話方塊,讓使用者必須點選對話方塊中的確定按鈕,關閉所有活動,然後回到登入介面即可。

          

1、建立ActivityCollector類用於管理活動。

public class ActivityCollector {
    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();
            }
        }
        activities.clear();
    }
}

2、建立BaseActivity類作為所有活動的父類。

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

3、建立一個登入介面的Activity,並編輯修改生成的activity_login.xml。

        該佈局外層為一個垂直LinearLayout,包含三個子元素,第一行與第二行為一個橫向LinearLayout,分別用於輸入賬戶資訊與密碼,第三行為一個登入按鈕。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="60dp">
       <TextView
           android:layout_width="90dp"
           android:layout_height="wrap_content"
           android:layout_gravity="center_vertical"
           android:textSize="18sp"
           android:text="Account:"/>
        <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:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="60dp">
        <TextView
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:textSize="18dp"
            android:text="Password:"/>
        <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>

4、修改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 view) {
                String account = accountEdit.getText().toString();
                String password = passwordEdit.getText().toString();
//當賬號為admin,密碼為123456時登入成功,進入主介面
                if(account.equals("admin") && password.equals("123456")){
                    Intent intent = new Intent(LoginActivity.this,MainActivity.class);
                    startActivity(intent);
                    finish();
                }else{
                    Toast.makeText(LoginActivity.this,"invalid",Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

5、修改activity_main.xml,新增一個按鈕,用於觸發強制下線功能。

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/force_offline"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send force offline broadcast"/>
</LinearLayout>

6、修改MainActivity中程式碼,設定Button的監聽,傳送廣播通知使用者強制下線。

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 view) {
                Intent intent = new 
                               Intent("com.launcher.broadcastbestpractice.FORCE_OFFLINE");
                sendBroadcast(intent);
            }
        });
    }
}

7、在BaseActivity中註冊廣播接收器來接受強制下線的廣播,因為所有Activity都繼承自BaseActivity,所以該操作可以完成在所有Activity中都實現該廣播的註冊。

public class BaseActivity extends AppCompatActivity {
    private ForceOfflineReceiver receiver;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityCollector.addActivity(this);
    }
    @Override
    protected void onResume() {
        super.onResume();
//註冊廣播接收器
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.launcher.broadcastbestpractice.FORCE_OFFLINE");
        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對話方塊
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setTitle("Warning");
            builder.setMessage("you are forced to be offline");
            builder.setCancelable(false);
            builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    ActivityCollector.finishAll();
                    Intent intent=new Intent(context,LoginActivity.class);
                    context.startActivity(intent);
                }
            });
            builder.show();
        }
    }
}

注意:因為要始終保持只有處在棧頂的Activity才能接受到強制下線的廣播,非棧頂的Activity不應該也沒必要接收到此條廣播,所以此次將註冊廣播與登出廣播寫在了onResume()  與onPause()方法中(見activity的生命週期),當一個活動失去棧頂位置會自動失去廣播接收器的註冊。

8、修改AndroidManifest.xml,將主活動設定為LoginActivity而不是MainActivity。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.launcher.broadcastbestpractice">

    <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>

</manifest>