How to reference child activity from TabHost to call a public function?
Asked Answered
V

6

17

I have a TabHost with two child activities in it (in two tabs). I also implemented a public function in one of these activities that i would like to call from my parent (TabHost), to trigger some action within the tab.

Is it possible to reference the activity itself from the TabHost to call a public function?

Thanks

here is my tabhost setup:

    res = getResources(); 
    tabHost = getTabHost(); 

    TabHost.TabSpec spec; 
    Intent intent;  

    intent = new Intent().setClass(this, home.class);
    spec = tabHost.newTabSpec("home").setIndicator("Groups", res.getDrawable(R.drawable.groups)).setContent(intent);
    tabHost.addTab(spec);
    intent = new Intent().setClass(this, messages.class);
    spec = tabHost.newTabSpec("messages").setIndicator("Messages", res.getDrawable(R.drawable.messages)).setContent(intent);    
    tabHost.addTab(spec);
Verge answered 22/3, 2011 at 23:53 Comment(0)
T
23

My approach would be to define a nested 'listener' class in the child activity which extends BroadcastReceiver.

I would then simply broadcast an Intent from my TabActivity which would then trigger the BroadcastReceiver to perform the action.

EDIT: To give example code...

The steps are...

  1. Define the intent filter in the manifest
  2. Add the nested 'listener' to the child activity
  3. Set onResume()/onPause() in child activity to register/unregister the listener
  4. Create intent in TabActivity and broadcast it when you want child to do something

In AndroidManifest.xml

<activity
    android:name=".MyActivity"
    android:label="@string/app_name"
    <intent-filter>
        <action android:name="com.mycompany.myApp.DO_SOMETHING" />
    </intent-filter>
</activity>

In MyActivity.java

public class MyActivity extends Activity {

    private MyListener listener = null;
    private Boolean MyListenerIsRegistered = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreated(savedInstanceState);

        listener = new MyListener();
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (!MyListenerIsRegistered) {
            registerReceiver(listener, new IntentFilter("com.mycompany.myApp.DO_SOMETHING"));
            MyListenerIsRegisterd = true;
        }
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (MyListenerIsRegistered) {
            unregisterReceiver(listener);
            MyListenerIsRegistered = false;
        }
    }

    // Nested 'listener'
    protected class MyListener extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            // No need to check for the action unless the listener will
            // will handle more than one - let's do it anyway
            if (intent.getAction().equals("com.mycompany.myApp.DO_SOMETHING")) {
                // Do something
            }
        }
    }
}

In the main TabActivity

private void MakeChildDoSomething() {

    Intent i = new Intent();
    i.setAction("com.mycompany.myApp.DO_SOMETHING");
    sendBroadcast(i);
}
Tavares answered 23/3, 2011 at 0:21 Comment(6)
well i would like to avoid that if possible. i am able to access public function of the parent from the child activity without any problems, i should be able to do the same the other way, i hopeVerge
@android-developer: Your choice but it's trivial to do and works. It also means the 'parent' TabActivity doesn't need to know specific method names of its children - all it has to do is send an intent saying 'Do this' and the child activity then handles it internally. It's also the commonest way for activities to communicate with each other.Tavares
@MisterSquonk: would you provide me with some code on how to accomplish this or point me to the right direction? i would appreciate it.Verge
@android-developer: See my EDIT - it looks more than it really is because I had to frame it properly for the example. In reality there's less than 30 lines of extra code.Tavares
@MisterSquonk - that works flawlessly, exactly what i needed - THANK YOU!Verge
@android-developer: Good to hear, glad I could help. Get to know a bit more about Intents and BroadcastReceivers, they're powerful stuff. :)Tavares
V
16

I've found another, probably simpler solution. I'm sure OP doesn't need this any more, but maybe someone from the future will be glad to find it.

So, basically, to run a public method in your child activity, you just need this little piece of code in your parent (tabHost, home and message are taken from OP's TabHost configuration):

tabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
    @Override
    public void onTabChanged(String tabId) {
        Activity currentActivity = getCurrentActivity();
        if (currentActivity instanceof home) {
            ((home) currentActivity).aPublicMethodFromClassHome();
        }
        if (currentActivity instanceof messages) { 
            ((messages) currentActivity).aPublicMethodFromClassMessages();
        }
    }
});

I use it in my application. Works as a charm;)

Viol answered 3/12, 2011 at 15:49 Comment(0)
S
6

I'm currently debugging an Android application and came across the same need. I found a much straightforward answer to this with this code snippet :

String currentActivityId = getLocalActivityManager().getCurrentId();
Activity currentActivity = getLocalActivityManager().getActivity(currentActivityId);

The identifier here is the identifier given when creating the TabSpec :

tabHost.newTabSpec("id").setIndicator(indicator).setContent(intent);
Schoolhouse answered 24/11, 2011 at 10:11 Comment(1)
I also like your solution, in fact I just replaced what I had with it as it allows me to get the Activities for multiple tabs, and call a common interface that each activity implements. I wonder if for my use case, however, a tab listener (via broadcastreciever) is a better design pattern?Filiation
M
5

Thank you, this helped me to solve a simular problem!

Activity currentActivity = getLocalActivityManager().getActivity(_TabHost.getCurrentTabTag());
if(currentActivity != null && currentActivity instanceof iMyActivity)
{
// pass to children
((iMyActivity)currentActivity).onLaunchDelegate();
}
Metatarsal answered 2/12, 2011 at 15:38 Comment(0)
B
1

From this link, I found this simple solution (http://androidactivity.wordpress.com/2012/08/17/two-way-communication-between-tabactivity-and-its-child-tabs/):

Well, the trick is to store the TAG associated with each tab, and use it to call the respective activity.

When you create the tab, you associate it with a tag like following:

yourTabHost.newTabSpec("Tab1");

Lets say we want to invoke a method “refreshContent()” that is inside the Tab1 Activity.

It’s simple as calling these lines from the MainActivity:

ActivityTab1 activity = (ActivityTab1) getLocalActivityManager().getActivity("Tab1");
 activity.refreshContent();

And that’s it!

Now for the opposite direction, we want to call some method “updateMain()” inside MainActivity, from the child tab TabActivity1.

At the TabActivity1 you will only need to call

((MainActivity)getParent()).updateMain();
Billingsgate answered 27/8, 2014 at 12:2 Comment(0)
M
0

find it simple, use it in app ActivityTab class:

if(getCurrentActivity() instanceof YourSearchActivity){
            log("onClick: instance found");
            ((YourSearchActivity)getCurrentActivity()).activityPublicFuntion();
        }
Mudpack answered 2/3, 2014 at 18:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.