ログインしていないとアクセスできないActivityの実装とログアウト処理


タイトルの通りログインしていないとアクセスできないActivityの実装とログアウト処理について試行錯誤したので共有します。前提としてActivityの設定において都度破棄・生成をする設定になっていないといけないです。

ログイン状態の定義

  • SharedPreferenceにuserIdがセットされている (またはAccessToken)

実装

AppCompatActivityを継承したBaseActivityを作成し、利用するActivityは全てBaseActivityを継承します。

BaseActivityはそのActivityが認証が必要かどうかを決めるフラグ (isAuthorizationRequired) を持ちます。子Activityは #allowGuestAccess を呼ぶことによりログインしていないユーザによるアクセスを許可できます。

ログインしていないとアクセスできないようにするにはそのフラグをチェックするだけです。

ログアウト処理は、IntentをBroadcastできる仕組みを使います。BaseActivityの #logout を実行すると全体に "ログアウトしたよ" というイベントを発行し、存在するActivityはそれを受け (ActivityはすべてBaseActivityを継承しているからレシーブできる) 自身の生命を絶ちます。

認証に関するさまざまなアクションを発行できるようになっているので、ログインした瞬間に各Activityに何かさせたいってケースにも対応できますね。

BaseActivity

public class BaseActivity extends AppCompatActivity implements AuthEventsReceiver.Receivable {
  private boolean isAuthorizationRequired = true;
  private int userId;
  private BroadcastReceiver broadcastReceiver;

  // readable setter
  public void allowGuestAccess() {
    this.isAuthorizationRequired = false;
  }
  // define getter for isAuthorizationRequired

  // define accessor for userId
  // set null if the userId is a negative number

  protected void onCreate(Bundle savedInstanceState) {
    // 略

    if (getIsAuhorizationRequired()) {
        registerReceivers();
        ensureAuthorized();
    }
  }

  private void ensureAuthorized() {
    setUserId(getDefaultSharedPreferences(this).getInt(USER_ID, -1));
    if (getUserId == null) {
      // do that what you want to do with unauthorized user
    }
  }

  protected void logout() {
    // ensure nullify the userId on the shared preferences

    Intent broadcastIntent = new Intent();
    broadcastIntent.setAction(AuthEventsReceiver.ACTION_LOGOUT);
    sendBroadcast(broadcastIntent);

    startLoginActivity();
  }

  @Override
  protected void onLogout() {
    finish();
  }

  protected void startLoginActivity() {
    // start your activity
  }

  private void registerReceivers() {
      IntentFilter intentFilter = new IntentFilter(AuthEventsReceiver.ACTION_LOGOUT);
      broadcastReceiver = new AuthEventsReceiver(this);
      registerReceiver(broadcastReceiver, intentFilter);
  }

  @Override
  protected void onDestroy() {
      super.onDestroy();
      unregisterReceiver(broadcastReceiver);
  }
}

public class AuthEventsReceiver extends BroadCastReceiver {
  public static final String ACTION_LOGOUT = "com.example.sozu.hoge.action_logout";
  private Activity activity;

  public AuthEventsReceiver(Activity activity) { this.activity = activity; }

  @Override
  public void onReceive(Context context, Intent intent) {
    try {
      AuthReceiver receiver = (Receivable) activity;
      switch (intent.getAction()) {
        case ACTION_LOGOUT:
          receivable.onLogout();
          break;
        case default:
          break;
      }
    } catch (ClassCastException e) {
      throw new ClassCastException("Activity must implement AuthEventsReceiver.AuthReceivable");
    }
  }

  public interface Receivable {
    void onLogout();
  }
}