2011/03/21

Android - ログイン & ログアウト処理 (スタックの問題点)

ログイン & ログアウト処理があるアプリケーションを作成する際にはまった内容をメモ

最初にはまった内容を、説明します。
問題点とかどうでもいいから、ログイン & ログアウト処理 の方法だけ教えてくれればいいんだよ!って方は, ログアウト処理の実装の方を参照してください

流れとして,
① MainActivity においてログイン済みかどうかの判定を行う (MainAvtivity は, レイアウトを持たないActivityで, アプリケーション起動時の処理などを行うものとする。)
② ログインがされていない場合は, LoginActivity に遷移し, その後ログインが完了したら HogeActivity に遷移
③ ログイン済みの場合は HogeActivity に直接遷移
④ HogeActivity においてログアウト処理が行われたら LoginActivity に遷移する。

ということを考える。
※ ちなみに, ログイン済みか否かは プリファレンスを利用して判断する。また, MainAvtivity はレイアウトを持たないので, android:nohistory 属性をtrueにして, バックキーで戻れないようにしておく。

この流れで作成したファイルは以下

< AndroidManifest.xml >

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="com.dev_grafr.app.logintest"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  7.         <activity android:name=".MainActivity"  
  8.                   android:label="@string/app_name"  
  9.                   android:noHistory="true"  
  10.                  android:launchMode="singleTask"  
  11.                   >  
  12.             <intent-filter>  
  13.                 <action android:name="android.intent.action.MAIN" />  
  14.                 <category android:name="android.intent.category.LAUNCHER" />  
  15.             </intent-filter>  
  16.         </activity>  
  17.         <activity android:name=".LoginActivity"  
  18.                   android:label="@string/app_name"  
  19.                  android:launchMode="singleTask"  
  20.                   android:noHistory="true">  
  21.         </activity>  
  22.         <activity android:name=".HogeActivity"  
  23.                   android:label="@string/app_name">  
  24.         </activity>  
  25.     </application>  
  26. </manifest>  

< MainActivity.java >
  1. package com.dev_grafr.app.logintest;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.content.SharedPreferences;  
  6. import android.os.Bundle;  
  7.   
  8. public class MainActivity extends Activity {  
  9.     public static final String PREFERENCES_FILE_NAME = "preference";  
  10.     /** Called when the activity is first created. */  
  11.     @Override  
  12.     public void onCreate(Bundle savedInstanceState) {  
  13.         super.onCreate(savedInstanceState);  
  14.   
  15.         if(loginCheck()){ // HogeActivity に遷移  
  16.             Intent intent = new Intent(getApplicationContext(), HogeActivity.class);  
  17.             startActivity(intent);  
  18.         }else// LoginActivity に遷移  
  19.             Intent intent = new Intent(getApplicationContext(), LoginActivity.class);  
  20.             startActivity(intent);  
  21.         }  
  22.     }  
  23.   
  24.     // ログイン判定  
  25.     public Boolean loginCheck(){  
  26.         SharedPreferences settings = getSharedPreferences(PREFERENCES_FILE_NAME, 0); // 0 -> MODE_PRIVATE  
  27.         if(settings == nullreturn false;  
  28.         int login = (int) settings.getLong("logged-in"0);  
  29.         if(login == 1return true;  
  30.         else return false;  
  31.     }  
  32. }  

< LoginActivity.java >

  1. package com.dev_grafr.app.logintest;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.content.SharedPreferences;  
  6. import android.os.Bundle;  
  7. import android.view.View;  
  8. import android.widget.Button;  
  9.   
  10. public class LoginActivity extends Activity {  
  11.     public static final String PREFERENCES_FILE_NAME = "preference";  
  12.     /** Called when the activity is first created. */  
  13.     @Override  
  14.     public void onCreate(Bundle savedInstanceState) {  
  15.         super.onCreate(savedInstanceState);  
  16.         setContentView(R.layout.login);  
  17.   
  18.         ((Button) findViewById(R.id.loginBtn)).setOnClickListener(new View.OnClickListener() {  
  19.             @Override  
  20.             public void onClick(View v) {  
  21.                 login();  
  22.                 // ログイン後は HogeActivity に遷移  
  23.                 Intent intent = new Intent(getApplicationContext(), HogeActivity.class);  
  24.                 startActivity(intent);  
  25.             }  
  26.         });  
  27.     }  
  28.      
  29.     // ログイン処理  
  30.     public void login(){  
  31.         SharedPreferences settings = getSharedPreferences(PREFERENCES_FILE_NAME, 0); // 0 -> MODE_PRIVATE  
  32.         SharedPreferences.Editor editor = settings.edit();  
  33.         editor.putLong("logged-in"1);  
  34.         editor.commit();  
  35.     }  
  36. }  

< HogeActivity.java >   ← 失敗例(正しいものは次回のブログで)

  1. package com.dev_grafr.app.logintest;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.content.SharedPreferences;  
  6. import android.os.Bundle;  
  7. import android.view.View;  
  8. import android.widget.Button;  
  9.   
  10. public class HogeActivity extends Activity {  
  11.     public static final String PREFERENCES_FILE_NAME = "preference";  
  12.     /** Called when the activity is first created. */  
  13.     @Override  
  14.     public void onCreate(Bundle savedInstanceState) {  
  15.         super.onCreate(savedInstanceState);  
  16.         setContentView(R.layout.hoge);  
  17.         ((Button) findViewById(R.id.logoutBtn)).setOnClickListener(new View.OnClickListener() {  
  18.             @Override  
  19.             public void onClick(View v) {  
  20.                 logout();  
  21.                 Intent intent = new Intent(getApplicationContext(), LoginActivity.class);  
  22.                 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // ← FLAG_ACTIVITY_CLEAR_TOPを設定  
  23.                 startActivity(intent);  
  24.             }  
  25.         });  
  26.     }  
  27.      
  28.     // ログアウト処理  
  29.     public void logout(){  
  30.         SharedPreferences settings = getSharedPreferences(PREFERENCES_FILE_NAME, 0); // 0 -> MODE_PRIVATE  
  31.         SharedPreferences.Editor editor = settings.edit();  
  32.         editor.putLong("logged-in"0);  
  33.         editor.commit();  
  34.     }  
  35. }  


[ 場合① ]
MainActivity -> LoginActivity -> HogeActivity と遷移した場合の Activityのスタックは, もちろん以下の通り
MainActivity は nohistory 属性が付いているので () をつけている
____________________________________
| ( MainActivity ) , LoginActivity , HogeActivity
____________________________________

そして, この時 HogeActivity において ログアウト処理を行い, LoginActivity に遷移する。その際にインテントに対して FLAG_ACTIVITY_CLEAR_TOP のフラグを付加することにより, HogeActivity が破棄されて遷移後のスタックは
____________________________________
| ( MainActivity ) , LoginActivity
____________________________________

となる。この場合は問題ない。

[ 場合② ]
しかし!!一度ログインを行い, ログイン済みの場合にアプリケーションを起動した際は, LoginActivity を介さないため,
____________________________________
| ( MainActivity ) , HogeActivity
____________________________________

というスタックになる。ここで ログアウト処理を行って LoginActivity に遷移した場合,
____________________________________
| ( MainActivity ) , HogeActivity , LoginActivity
____________________________________

となってしまうのである。つまり, ログアウトしたにも関わらず、LoginActivityにおいてバックキーを押すと, HogeActivityに戻ってしまう
そこで, HogeActivity でログアウト処理 ----> MainActivity ----> ログイン判定 ----> LoginActivity という遷移で,
FLAG_ACTIVITY_CLEAR_TOPフラグを付加したインテントにより MainActivity を経由すれば, MainActivity 以外がスタックから廃棄され上手くいくのではないか?と考えたのだが, MainActivity にはnohistory属性がついており, これがあるとうまくいかないという現象に陥った。

つまり, nohistory属性 がついていると, スタックに積まれないないため, FLAG_ACTIVITY_CLEAR_TOPを利用してもActivityが破棄されないのではないかという結論に至る(間違ってたらすいません)


実際には, ログインごはログイン画面にはバックキーでは戻れないようにするため, LoginActivityにもnohistory属性をつけるので, そうすると場合①もできないんですよね。笑
だって, MainActivity と LoginActivity が nohistory でスタックが
____________________________________
| HogeActivity
____________________________________

となると考えられるわけですから。。。


つまり, この方法だと上手なログアウト処理ができませんでした。

ログアウトした場合, LoginActivity を除いた全ての Activity をスタックから排除するにはどうすればいいのか・・・。
ということで、次回はこの解決法を説明します。

0 コメント:

コメントを投稿

 
;