dranfi
dranfi

Reputation: 241

Going back to previous TabActivity

How can I explain my problem?

I have an application using tabs (by Intents, not views). I have implemented navigation inside each view without trouble but I need to launch video player from a ListView inside one of the Activity in full screen and landscape mode (so without tabs). But when I want to live the player, (either by pressing back or calling finish();), my application is closed (no exceptions in the LogCat) and return to the main screen. So what I need is when I quit the fullscreen Activity(launched for the player) is to come back to my application, whith the tabs.

Here is my code :

//Main activity : 

package com.ccn;


import android.app.TabActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.TabHost;

public class CCNMain extends TabActivity {
    public static TabHost tabHost;
    static CCNMain  myActivity = null;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        myActivity = this;

        Resources res = getResources();
        tabHost = getTabHost();
        TabHost.TabSpec spec; // reusable tabspec for each tab
        Intent intent;

        intent = new Intent().setClass(this, NewsGroup.class);
        spec = tabHost.newTabSpec("nnews")
        .setIndicator("A la une",res.getDrawable(R.drawable.home))
        .setContent(intent);
        tabHost.addTab(spec);

        /*intent = new Intent().setClass(this, ArticlesGroup.class);
        spec = tabHost.newTabSpec("aarticles")
        .setIndicator("Articles",res.getDrawable(R.drawable.articles))
        .setContent(intent);
        tabHost.addTab(spec);*/

        intent = new Intent().setClass(getApplicationContext(), ContactGroup.class);
        spec = tabHost.newTabSpec("vvideos")
        .setIndicator("Vidéos",res.getDrawable(R.drawable.video))
        .setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(getApplicationContext(), ContactGroup.class);
        spec = tabHost.newTabSpec("ccontact")
        .setIndicator("Contact",res.getDrawable(R.drawable.contact))
        .setContent(intent);
        tabHost.addTab(spec);

        tabHost.setCurrentTab(0);
    }
}

//ContactGroup : 
package com.ccn;

import java.util.ArrayList;


import android.app.ActivityGroup;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class ContactGroup extends ActivityGroup {
    // Keep this in a static variable to make it accessible for all the nested activities, lets them manipulate the view  
    public static ContactGroup groupContact;  

        // Need to keep track of the history if you want the back-button to work properly, don't use this if your activities requires a lot of memory.  
    private ArrayList<View> history;  
  @Override
    protected void onCreate(Bundle savedInstanceState) {  
          super.onCreate(savedInstanceState);  
          this.history = new ArrayList<View>();  
          groupContact = this;  

              // Start the root activity within the group and get its view  
          View view = getLocalActivityManager().startActivity("idHoraireActivity", new  
                                            Intent(this,ContactActivity.class)  
                                            .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))  
                                            .getDecorView();  

              // Replace the view of this ActivityGroup  
          replaceView(view);  

       }  

    public void replaceView(View v) {  
                // Adds the old one to history  
        history.add(v);  
                // Changes this Groups View to the new View.  
        setContentView(v);  
    }  

    public void back() {  
        if(history.size() > 1) {  
            history.remove(history.size()-1);  
            setContentView(history.get(history.size()-1));  
        }else {  
            finish();  
        }  
    }  
    //@Override  
    public void onBackPressed() {  
        ContactGroup.groupContact.back();  
        return;  
    }

}

//ContactActivity:
package com.ccn;

import java.io.IOException;

import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.VideoView;

public class ContactActivity extends Activity {
    static ContactActivity bidule = null;
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.videos);
        bidule = this;
        Button btn = (Button) findViewById(R.id.button1);
        btn.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent i = new Intent();
                i.setClass(getApplicationContext(), videoPlayerActivity.class);
                //i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                bidule.startActivity(i);
                ContactActivity.this.startActivityForResult(i, 0);
            }
        });

    }

}

//VideoPlayerActivity:
package com.ccn;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.MediaController;
import android.widget.VideoView;


public class videoPlayerActivity extends Activity {

    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.videos);


        //the VideoView will hold the video
        String url = // Video url;

        Button btn = (Button) findViewById(R.id.button1);
        btn.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                // TODO Auto-generated method stub
                finish();
            }
        });
    }


}

And here my Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.ccn"
      android:versionCode="1"
      android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET"></uses-permission>


    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".CCNMain"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="ArticlesGroup"></activity>
        <activity android:name="ContactGroup"></activity>
        <activity android:name="NewsGroup"></activity>
        <activity android:name="NewsActivity"></activity>
        <activity android:name="ArticlesAvtivity"></activity>
        <activity android:name="ContactActivity"></activity>
        <activity android:name="videoPlayerActivity" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:screenOrientation="landscape"></activity>

    </application>
</manifest>

Thank you for your help. My guess : it has to do with where I call startActivity and Intent flags. What do you think?

Upvotes: 3

Views: 3797

Answers (3)

John Pang
John Pang

Reputation: 2503

I hope I understand your query correctly (please correct me). There are multiple tabs in your TabActivity, all but one tab associated with another Activity which should be "inside" the TabActivity. For the video, you want it to launch at the same level of the TabActivity (that is not inside). Such that the system can handle the back event of the VideoActivity.

|     |
|     |
|T (1)| <- tab activity with tab#1
-------

Select tab#2:

|     |
|     |
|T (2)| <- tab activity with tab#2
-------

Select tab#video:

|     |
|Video| <- video activity
|T (2)| <- tab activity with tab#2
-------

Since you can create the "sub-activity" without problem, here I just show you how to create an external activity Intent:

private void createExternalTab(Class clazz, String tag, String label, int iconResId) {
    // intent to launch the activity externally
    final Intent intent = new Intent(this, clazz);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    tabHost.addTab(tabHost.newTabSpec(tag)
            .setContent(R.id.dummy)
            .setIndicator(label, iconResId));
    // find the recently added tab
    TabWidget w = tabHost.getTabWidget();
    View view = w.getChildAt(w.getChildCount() - 1);
    // here is the magic!
    view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startActivity(intent);
        }
    });
}

Here is the TabActivity Layout:

<?xml version="1.0" encoding="utf-8"?>

<TabHost
    android:id="@android:id/tabhost"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <View
                android:id="@+id/dummy"
                android:layout_width="0dp"
                android:layout_height="0dp"/>

            </FrameLayout>

        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:orientation="horizontal"
            android:showDividers="none"/>
    </RelativeLayout>

</TabHost>

Note 1: my code works with FragmentActivity

Note 2: The key point here is: map the tab content to an invisible elements inside the R.id.tabcontent. And then modify the tab's onClickListener such that an Intent is called under the TabActivity, not launch by the TabWidget/TabHost.

Upvotes: 0

nahwarang
nahwarang

Reputation: 653

I have implemented the same kind of case. But didn't use the ActivityGroup. In tests, it became clear that its response wasn't waterproof. When I launch the Mediaplayer activity and put a new activity in the stack and the OS handles the back event properly.

public class VideoActivity extends Activity {
private ListView mListView;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    mListView = (ListView)findViewById(R.id.list);
    mListView.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Intent intent = new Intent().setClass(view.getContext(), ViewVideoActivity.class);
            startActivity(intent);
        }
    });
}

The VieoVideoActivity is a fullscreen activity forced in landscape, with no overriding key event implementations.

Upvotes: 0

Pankaj Kumar
Pankaj Kumar

Reputation: 82958

Edited

/Main activity : 

package com.ccn;


import android.app.TabActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.TabHost;

public class CCNMain extends TabActivity {
    public static TabHost tabHost;
    static CCNMain  myActivity = null;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        myActivity = this;

        Resources res = getResources();
        tabHost = getTabHost();
        TabHost.TabSpec spec; // reusable tabspec for each tab
        Intent intent;

        intent = new Intent().setClass(this, NewsGroup.class);
        spec = tabHost.newTabSpec("nnews")
        .setIndicator("A la une",res.getDrawable(R.drawable.home))
        .setContent(intent);
        tabHost.addTab(spec);

        /*intent = new Intent().setClass(this, ArticlesGroup.class);
        spec = tabHost.newTabSpec("aarticles")
        .setIndicator("Articles",res.getDrawable(R.drawable.articles))
        .setContent(intent);
        tabHost.addTab(spec);*/

        intent = new Intent().setClass(getApplicationContext(), ContactGroup.class);
        spec = tabHost.newTabSpec("vvideos")
        .setIndicator("Vidéos",res.getDrawable(R.drawable.video))
        .setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(getApplicationContext(), ContactGroup.class);
        spec = tabHost.newTabSpec("ccontact")
        .setIndicator("Contact",res.getDrawable(R.drawable.contact))
        .setContent(intent);
        tabHost.addTab(spec);

        tabHost.setCurrentTab(0);
    }
}

//ContactGroup : 
package com.ccn;

import java.util.ArrayList;


import android.app.ActivityGroup;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class ContactGroup extends ActivityGroup {
    // Keep this in a static variable to make it accessible for all the nested activities, lets them manipulate the view  
    public static ContactGroup groupContact;  

        // Need to keep track of the history if you want the back-button to work properly, don't use this if your activities requires a lot of memory.  
    private ArrayList<View> history;  
  @Override
    protected void onCreate(Bundle savedInstanceState) {  
          super.onCreate(savedInstanceState);  
          this.history = new ArrayList<View>();  
          groupContact = this;  

              // Start the root activity within the group and get its view  
          View view = getLocalActivityManager().startActivity("idHoraireActivity", new  
                                            Intent(this,ContactActivity.class)  
                                            .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))  
                                            .getDecorView();  

              // Replace the view of this ActivityGroup  
          replaceView(view);  

       }  

    public void replaceView(View v) {  
                // Adds the old one to history  
        history.add(v);  
                // Changes this Groups View to the new View.  
        setContentView(v);  
    }  

    public void back() {  
        if(history.size() > 1) {  
            history.remove(history.size()-1);  
            setContentView(history.get(history.size()-1));  
        }else {  
            finish();  
        }  
    }  
    //@Override  
    public void onBackPressed() {  
        ContactGroup.groupContact.back();  
        return;  
    }

}

//ContactActivity:
package com.ccn;

import java.io.IOException;

import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.VideoView;

public class ContactActivity extends Activity {
    //static ContactActivity bidule = null;
      ContactGroup contactGroup = null;
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.videos);
        //bidule = this;
        contactGroup = new ContactGroup();

        Button btn = (Button) findViewById(R.id.button1);
        btn.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                // TODO Auto-generated method stub
                View view = getLocalActivityManager().startActivity("videoPlayerActivity", new  
                                            Intent(this,videoPlayerActivity.class)  
                                            .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))  
                                            .getDecorView();
                contactGroup.replaceView(view);
            }
        });

    }

}

//VideoPlayerActivity:
package com.ccn;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.MediaController;
import android.widget.VideoView;


public class videoPlayerActivity extends Activity {
     ContactGroup contactGroup = null;

    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.videos);
         ContactGroup contactGroup = new  ContactGroup();

        //the VideoView will hold the video
        String url = // Video url;

        Button btn = (Button) findViewById(R.id.button1);
        btn.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                // TODO Auto-generated method stub
                 contactGroup.back();
            }
        });
    }

Summary :

You have to call repalaceView and back methods of your activity group. When you want to start new activity use replaceView() and when you want to finish your activity use back()

Upvotes: 1

Related Questions