« オープンセミナー2011@岡山に参加しました。 | トップページ | XAMPP on WindowsでMySQLの文字化け対策 »

2011年6月 8日 (水)

Activity#finishActivityを解析した

今日、ある方がTwitter上で起動元のActivityを閉じるにはどうするか?
みたいな事をつぶやかれていたので、色々試したことを記述しておくことにする。

で、ドキュメント的にはActivity#finishActivity()を呼び出せば、呼び出し元の
Activityをfinish()する事ができるようだが、実際に1.6 on HT-03Aで動かしてみると
想定した動きにならなかった。

で、finishActivity()のソースコード(v1.6_r2)を見てみると、以下のソースコードだった。

    /**
     * Force finish another activity that you had previously started with
     * {@link #startActivityForResult}.
     * 
     * @param requestCode The request code of the activity that you had
     *                    given to startActivityForResult().  If there are multiple
     *                    activities started with this request code, they
     *                    will all be finished.
     */
    public void finishActivity(int requestCode) {
        if (mParent == null) {
            try {
                ActivityManagerNative.getDefault()
                    .finishSubActivity(mToken, mEmbeddedID, requestCode);
            } catch (RemoteException e) {
                // Empty
            }
        } else {
            mParent.finishActivityFromChild(this, requestCode);
        }
    }

mParentという変数は、呼び出し元Activityと思われるが、この変数に

Activityのインスタンスがセットされていれば、呼び出し元Activityが

無事finishできるようです。

しかし、mParentにインスタンスがセットされるような箇所が存在しませんでした。バグなんですかね…?

ついでに、ドキュメント上、呼び出せと言われているstartActivityForResult()の

ソースコードは以下です。

   /**
     * Launch an activity for which you would like a result when it finished.
     * When this activity exits, your
     * onActivityResult() method will be called with the given requestCode. 
     * Using a negative requestCode is the same as calling 
     * {@link #startActivity} (the activity is not launched as a sub-activity).
     * 
     * 

Note that this method should only be used with Intent protocols      * that are defined to return a result.  In other protocols (such as      * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may      * not get the result when you expect.  For example, if the activity you      * are launching uses the singleTask launch mode, it will not run in your      * task and thus you will immediately receive a cancel result.      *      *

As a special case, if you call startActivityForResult() with a requestCode      * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your      * activity, then your window will not be displayed until a result is      * returned back from the started activity.  This is to avoid visible      * flickering when redirecting to another activity.      *      *

This method throws {@link android.content.ActivityNotFoundException}      * if there was no Activity found to run the given Intent.      *      * @param intent The intent to start.      * @param requestCode If >= 0, this code will be returned in      *                    onActivityResult() when the activity exits.      *      * @throws android.content.ActivityNotFoundException      *      * @see #startActivity      */     public void startActivityForResult(Intent intent, int requestCode) {         if (mParent == null) {             Instrumentation.ActivityResult ar =                 mInstrumentation.execStartActivity(                     this, mMainThread.getApplicationThread(), mToken, this,                     intent, requestCode);             if (ar != null) {                 mMainThread.sendActivityResult(                     mToken, mEmbeddedID, requestCode, ar.getResultCode(),                     ar.getResultData());             }             if (requestCode >= 0) {                 // If this start is requesting a result, we can avoid making                 // the activity visible until the result is received.  Setting                 // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the                 // activity hidden during this time, to avoid flickering.                 // This can only be done when a result is requested because                 // that guarantees we will get information back when the                 // activity is finished, no matter what happens to it.                 mStartedActivity = true;             }         } else {             mParent.startActivityFromChild(this, intent, requestCode);         }     }

すでにmParent変数を参照して動作を振り分けるようになっています。

しかも、mParent変数に値をセットしている場所もない…。

これはどういう事なんだろうか…。

最後にmParent変数へのsetterを見つけたので転載しておきます。

    // ------------------ Internal API ------------------
    
    final void setParent(Activity parent) {
        mParent = parent;
    }

どうやら、setterは非公開APIのようですので、普通にアプリケーションを

作成するためにはfinishActivity()を使って呼び出し元Activityを閉じるという

事はできなさそうです。

|

« オープンセミナー2011@岡山に参加しました。 | トップページ | XAMPP on WindowsでMySQLの文字化け対策 »

Android」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/50625/51885426

この記事へのトラックバック一覧です: Activity#finishActivityを解析した:

« オープンセミナー2011@岡山に参加しました。 | トップページ | XAMPP on WindowsでMySQLの文字化け対策 »