androidandroid-tabhostactivitygrouponkeydownandroid-1.6-donut

Navigate Between Activities in an ActivityGroup


I'm developing an app which contain TabHost ,in one of those tabs i have an ActivityGroup , and from this ActivityGroup, i launch another SubActivity ( let's say that i Launch an Activity A ), and until this , everything is OK.

The problem is when i press the BackButton ,the CurrentActivity( Activity A ) is destroyed, but the ParentActivity( The ActivityGroup ) is not resumed , and the app show just a null Window with the Title of My App ( "My Application Title" ) .

The Code to launch the Activity A from my ActivityGroup is :

View view = getLocalActivityManager().startActivity(id,newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)) .getDecorView();
this.setContentView(view);

and i have overrided the method onKeyDown like this in my ActivityGroup :

@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        Log.i(TAG, "onKeyDown");
        if(keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0){
            Activity current = getLocalActivityManager().getCurrentActivity();
            Log.i(TAG, current.getIntent().getStringExtra("id"));
            current.finish();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

but it seems that the method onKeyDown is never called because a i didn't get the Log "onKeyDown" displayed.

and the logcat display just this :

01-05 11:04:38.012: W/KeyCharacterMap(401): No keyboard for id 0
01-05 11:04:38.012: W/KeyCharacterMap(401): Using default keymap: /system/usr/keychars/qwerty.kcm.bin

what i want is to display the ActivityGroup when my Activity A is Destroyed.

NB : my app level is 4 : *Android 1.6* , so i can't override the method onBackPressed()

Thank you all for your help

-----------------------------------EDIT ----------------------------------------

I have added the code of my onKeyDown like this on my Activity A :

@Override public boolean onKeyDown(int keyCode, KeyEvent event) {

    if(keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0){
        ParentActivity parentActivity = (ParentActivity) this.getParent();
        parentActivity.onKeyDown(keyCode, event);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

And in my ParentActivity , i have :

@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if(keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0){
            Log.i(TAG, "onKeyDown");
            int len = idOfSubActivities.size();
            String idOfCurrentActivity = idOfSubActivities.get(len-1);
            Activity currentActivity = getLocalActivityManager().getActivity(idOfCurrentActivity);
            currentActivity.finish();
            idOfSubActivities.remove(len - 1);
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

I got the same result , the Activity A is stopped , but it still give me the null window with the title of my app , and it doesn't display my ActivityGroup (ParentActivity)


Solution

  • I faced a problem similar to this when I first started experimenting with ActivityGroups. The issue is that you need to place your onKeyDown() in your Activity. However, you need the Activity to have a reference to the ActivityGroup. Then, when you press back, just call your own onBack() in the ActivityGroup.

    (EDIT) Here's a Sample for you

    Below is the stripped down ActivityGroup code that handles navigation and history in my apps. It has been adjusted on the fly, so there might be an error. Notice a couple of finer points.

    public class MyGroup extends ActivityGroup
    {
    /** Static Reference to this Group. */
        static MyGroup instance;
    /** Keeps Track of the History as a Stack. */
        private ArrayList<View> myActivityHistory;
    
        @Override protected void onCreate(final Bundle savedInstanceState)
        {//Call the Base Implementation
            super.onCreate(savedInstanceState);
    
        // Initialize the Activity History
            myActivityHistory = new ArrayList<View>();
    
        // Build the Intent
            Intent _root = null;
        //Lists the Applications
            _root = new Intent(this, MyActivity.class);
        // Send the Index to the Child Activity
            _root.setAction(Intent.ACTION_VIEW);
        // Forward the Extras, if they are there
        // Start the root Activity within the Group and get its View
            final View _view = getLocalActivityManager().startActivity("App Preferences", _root).getDecorView();
        // Start the History
            addNewLevel(_view);
        }
    
        /**
         * Gets the instance of the {@link ApplicationGroup} that the child Activity
         * belongs to.
         *
         * @param index
         *  The Group that was passed to the child in the {@link android.content.Intent
         *  Intent} via an Extra (int).
         * @return
         *  <b>ApplicationGroup -</b> The group that this child was assigned to.
         */
        static public ApplicationGroup getGroup()
        {   if (instance != null)
                return instance;
        }
    
        /**
         * Allows the Child to replace the {@link ApplicationGroup}'s current
         * {@link android.view.View View} with the specified View. This is
         * intended to be used specifically by the Child.
         *
         * @param withView
         *  The View to use for replacement.
         */
        public void addNewLevel(final View withView)
        {//Adds the old one to history
            myActivityHistory.add(withView);
        // Changes this Groups View to the new View.
            setContentView(withView);
        }
    
        /**
         * Takes the specified {@link android.app.ActivityGroup ActivityGroup} back
         * one step in the History to the previous {@link android.view.View View}.
         */
        public void back()
        {   Log.d("Group", "Back overridden");
            //If there are more than one screen
            if (myActivityHistory.size() > 1)
            {   Log.d("Group", "History called");
            // Remove the most recent View
                myActivityHistory.remove(myActivityHistory.size()-1);
            // Change the View back.
                setContentView(myActivityHistory.get(myActivityHistory.size()-1));
            }
        // Otherwise Exit
            else
            {   Log.d("Group", "Program finished");
                finish();
            }
        }
    
    }
    

    Next is the pertinent code for the Activity:

    public boolean onKeyDown(int keyCode, KeyEvent event)
    {//If back was pressed
        if (keyCode==KeyEvent.KEYCODE_BACK)
        {   MyGroup.getGroup().back();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
    

    Just make sure that you aren't setting the KeyDownListener to anything funny and it should work fine. :) The changes that I made are because I actually have them in an array of Groups (3 at one time). Essentially, just make the Group a Singleton so you can always have the same instance, and keep an array of your Views so that you have a History. Then reference the History when you click Back or when you add a View.

    Hope this helps, FuzzicalLogic