18

I have an activity with the translucent Theme :

android:theme="@android:style/Theme.Translucent.NoTitleBar"

Also the problem is reproduceable with just this Theme:

<style name="MyTheme" parent="@android:style/Theme">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:colorBackground">@null</item>
</style>

This activity is loaded at startup and kept in memory (when I start this activity, I ad the FLAG_ACTIVITY_REORDER_TO_FRONT flag as extra).

Problem : when I start this activity (from the menu), the activity don't show up, nothing happens. But : if I remove the translucent theme : all works fine, the activity is back to front.

Yes onNewIntent() is called.

And if I press back the translucent activity is the one below! But it needs to be the top.

An example being

A ( translucent activity) B C

Stack: A

A startActivity(B)

Stack: A,B

B startActivity(C)

Stack: A,B,C

c startActivity(A) // with flag FLAG_ACTIVITY_REORDER_TO_FRONT

Stack should be: B,C,A

but A is never brought to the front, although its onNewIntent() is called.

Any ideas?

Side notes


Interesting unanswered question: http://groups.google.com/group/android-developers/browse_thread/thread/269c67f6b39cfe45?pli=1


android:launchMode of singleTask or singleInstance are not wanted to be used. These change the backstack and move activities into their own stack. Therefore we don't have A,B,C any more.

singleTask and singleInstance — are not appropriate for most applications, since they result in an interaction model that is likely to be unfamiliar to users and is very different from most other applications.

http://developer.android.com/guide/topics/manifest/activity-element.html#lmode

Anyone who wants a visual representation of launchModes try this app : https://play.google.com/store/apps/details?id=com.novoda.demos.activitylaunchmode

Jscti
  • 14,096
  • 4
  • 62
  • 87
  • 1
    Yep repeated your scenario android 2.3 – Blundell Mar 06 '12 at 09:29
  • Check if you get the `Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT` flag in `onNewIntent()` – Ron Apr 23 '12 at 18:07
  • the `onNewIntent()` receives `FLAG_ACTIVITY_REORDER_TO_FRONT` – Blundell Apr 24 '12 at 07:00
  • I think its working as expected.. with window background set to transparent it wont be visible to eyes.. Would be clear if got to see a snapshot.. – Ron Apr 24 '12 at 07:29
  • The background is transparent, but the layout has a nested layout with margins and a red background. i.e. it makes it transparent around the edge and red in the middle. It is clearly visible in the example I show above when it first starts. Then won't come to the foreground when it is asked. – Blundell Apr 24 '12 at 13:54
  • Could it be somthing you do in `onNewIntent()`? Or the way you launch activity C, that blocks it? Or could it be the way you are launching activity A the first time..? – Ron Apr 25 '12 at 16:43
  • activity A and C are launched normally with startIntent and only the flag described above. Nothing is done in onNewIntent. I think it's an Android bug, very strange – Blundell Apr 25 '12 at 20:53
  • There is definitely a bug related to the combination of "translucent theme" and `FLAG_ACTIVITY_REORDER_TO_FRONT`. I've constructed a simple example with a main activity and 2 other activities (A and B) that have `android:theme="Theme.Dialog"`. The main activity launches activity `A`. `A` launches `B` with `FLAG_ACTIVITY_REORDER_TO_FRONT`. Now `B` launches `A` with `FLAG_ACTIVITY_REORDER_TO_FRONT`. Activity `B` is still showing on screen, but looking at the activity stack in the task using `adb shell dumpsys activity` shows that `A` is on top of the stack. – David Wasser Mar 21 '13 at 19:41
  • If you remove `android:theme="Theme.Dialog"` the problem goes away. – David Wasser Mar 21 '13 at 19:42
  • 1
    About a year and a half ago, someone posted a [similar problem](https://groups.google.com/d/msg/android-developers/1G_X1Zq-FaA/7ceAZ3QL030J) on the Android developers group. There are still no responses – David Wasser Mar 22 '13 at 20:44

6 Answers6

1

If we do not set the theme from AndroidManifest.xml, activity block and set the theme before setContentView, in onCreate method in the first translucent activity, the problem is solved, below is the code:

public class TranslucentActivityDemoActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
      this.setTheme(R.style.myTheme);
        setContentView(R.layout.main);

    }
Andro Selva
  • 53,910
  • 52
  • 193
  • 240
cjc
  • 11
  • 1
  • +1 It looks like this actually works! If you don't set the theme in the manifest, but you set the theme programatically in the activity, the problem goes away. – David Wasser Mar 21 '13 at 19:44
  • 1
    I spoke too soon :-( The problem goes away but the background is no longer transparent. Sigh... – David Wasser Mar 21 '13 at 21:46
0

The launchMode should be singleTask in the <activity> tag of your activity in the manifest file.

From Documentation :

singleTask - If, when starting the activity, there is already a task running that starts with this activity, then instead of starting a new instance the current task is brought to the front. The existing instance will receive a call to Activity.onNewIntent() with the new Intent that is being started, and with the Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT flag set. This is a superset of the singleTop mode, where if there is already an instance of the activity being started at the top of the stack, it will receive the Intent as described there (without the FLAG_ACTIVITY_BROUGHT_TO_FRONT flag set).

Update

As a better workaround you can try invalidating the whole window in onNewIntent() or in onResume..

@Override
protected void onNewIntent(Intent intent) {
   super.onNewIntent(intent);
   getWindow().getDecorView().invalidate();
}
Ron
  • 24,175
  • 8
  • 56
  • 97
  • `The other modes — singleTask and singleInstance — are not appropriate for most applications, since they result in an interaction model that is likely to be unfamiliar to users and is very different from most other applications.` Single Instance will bring it to the front, however when you then proceed to the next activity it will, that activity is in its own task i.e. it's own back stack. That is not what is wanted and not intended behaviour of the above question. – Blundell Apr 23 '12 at 20:49
  • One other thing to note is that the activity you are trying to reorder is the taskroot.. Try adding another activity as starting activity and let it launch activity A... If it works then we have probably found a bug.. but need to read docs extensively before confirming.. – Ron Apr 24 '12 at 04:07
  • 1
    Sorry thats just the example that it is the task root. Even if it isn't the root it still occurs. It's something to do with Theme, I'm guessing its the iteraction of the activity stack and the `windowIsTranslucent` property. – Blundell Apr 24 '12 at 06:56
  • I updated my answer.. Try invalidating the whole window when its reordered to front.. – Ron Apr 26 '12 at 18:29
  • Nope sorry that doesn't do it. Have you recreated the issue? I might write a little test project – Blundell Apr 27 '12 at 07:08
  • No i havnt.. Guessed it could be a problem with invalidating as the window bg is transparent..ok – Ron Apr 27 '12 at 07:18
  • I recreated it. One more thing is when I press back button it goes back to the translucent activity, but now it has lost its translucent property..what happens there? – Ron Apr 27 '12 at 10:19
  • Yeah weird huh, it's like brought to second top in the backstack. – Blundell Apr 27 '12 at 11:13
  • There seems to be more to this FLAG_ACTIVITY_REORDER_TO_FRONT flag - http://stackoverflow.com/questions/12548853/prevent-task-manager-from-recreating-last-displayed-activity-in-a-task – kellogs Sep 24 '12 at 04:57
0

As a workaround not an answer

I have done this:

public class OverlayActivity extends Activity {

   @Override
   protected void onNewIntent(Intent intent) {
       super.onNewIntent(intent);
       // Restart self when attempting to be brought to front
       Intent restartIntent = new Intent(this, OverlayActivity.class);
       startActivity(restartIntent);
       finish();
   }

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_overlay);
   }
 }

if anyone can give me an answer they win the brucey bonus!

Blundell
  • 75,855
  • 30
  • 208
  • 233
  • onNewIntent is called but the activity is not brought to the foreground – Blundell Apr 27 '12 at 06:54
  • For some reason, you should use `setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);` on your intent for it to work. – Sherif elKhatib Apr 27 '12 at 07:07
  • FLAG_ACTIVITY_SINGLE_TOP `If set, the activity will not be launched if it is already running at the top of the history stack.` IT is not at the top of the history stack, but I tried it anyway and it didn't work. – Blundell Apr 27 '12 at 07:11
  • The thing is, I had the exact same problem: my activity was singleTop in manifest and onNewIntent() was being called but the activity wasnt showing. I had to add the flag. I dont know... maybe it is related to the translucent theme (bug or sth) – Sherif elKhatib Apr 27 '12 at 07:13
  • my activities btw extend FragmentActivity. – Sherif elKhatib Apr 27 '12 at 07:14
0

I just removed the FLAG and it's all working for me,There is no any problem..First Activity Remain Transparent and getting on top when called..Just Try.

Here the code of my whole example,

FirstAct

public class FirstAct extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       Button btn = new Button(this);
       btn.setText("First Here Go To Second");
       btn.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {
            Intent intent = new Intent(FirstAct.this,SecondAct.class);
            startActivity(intent);
        }
    });
       setContentView(btn);
    }
}

SecondAct

public class SecondAct extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       Button btn = new Button(this);
       btn.setText("Second Here Go To Third");
       btn.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {
            Intent intent = new Intent(SecondAct.this,ThirdAct.class);
            startActivity(intent);
        }
    });
       setContentView(btn);
    }
}

ThirdAct

public class ThirdAct extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       Button btn = new Button(this);
       btn.setText("Third Here Go To First");
       btn.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {
            Intent intent = new Intent(ThirdAct.this,FirstAct.class);
            //intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            startActivity(intent);
        }
    });
       setContentView(btn);
    }
}

Edit Activity with LaunchMode SingleInsance *Manifest*

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.mj.temp"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".FirstAct" android:theme="@android:style/Theme.Translucent.NoTitleBar"  android:launchMode="singleInstance"
                  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="SecondAct" android:launchMode="singleInstance"></activity>
        <activity android:name="ThirdAct" android:launchMode="singleInstance"></activity>
    </application>
</manifest>
MKJParekh
  • 34,073
  • 11
  • 87
  • 98
  • What is required is that after launching the `FirstAct` from `ThirdAct` the activity stack should be (SA-TA-FA). The FA should be reordered to the top of stack, without launching a new instance of it. In your sample, a new instance will be launched and activity stack will be (FA-SA-TA-FA). – Ron Apr 28 '12 at 07:35
  • @userSeven7s That's Also done by using `launchMode="singleInstance"` .. check updated Manifest File. – MKJParekh Apr 28 '12 at 08:44
  • 1
    @Frankenstein In a more complex app where there is other navigation with this 3 stack scenario in the middle. singleInstance will not work. SingleInstance makes each activity it's own task, meaning technically we don't have have FA-SA-TA , we have Stack 1 :Fa , Stack 2: SA , Stack 3: TA. This brings it's own complexity and problems with interaction. You can check this out for a visual example: https://play.google.com/store/apps/details?id=com.novoda.demos.activitylaunchmode – Blundell Apr 28 '12 at 09:08
  • @Blundell You may be right, I have not that kind of exp or knowledge..but the question stated 3 activity so i took 3 and checked and posted what i seen..thanks for you comment will check more for singleInstance..though 1 upvote 1 downvote.. – MKJParekh Apr 28 '12 at 09:16
  • @Frankenstein , I understand, but what your answer suggests is everytime you add a new activity you would have to declare it singleInstance. If you did not, when an Activity before this would start and an Activity after we would have this scenario. A1 ABC then when you click to C1 you would get A,B,C,A1,C1. It get's weirder the more activities you add. So each activity being it's own instance of a task is not viable. – Blundell Apr 28 '12 at 09:46
  • @Blundell I couldn't understand the problem because i run the above code ..and go to next next next like a-b-c-a-b-c-a-b-c and when need to close app..i just pressed BACK 3 Times and it went out of the app..so i think its all fine..and working as expected. – MKJParekh Apr 28 '12 at 10:00
  • @Frankenstein Download the app above I recommended, that'll explain how your all singleInstance app is working with stacks. – Blundell Apr 28 '12 at 10:39
  • This can't be right. using `launchMode="singleInstance"` means that each activity will be in a separate task. Try long-pressing on the HOME button after you've got all 3 activities running. You'll see 3 separate tasks (all with the same name and icon). The user can never leave this application and return to where he started. OP also said that `singleInstance` or `singleTask` are inappropriate. – David Wasser Nov 14 '12 at 16:01
0

Here's my workaround idea. I believe the problem is triggered by requesting a translucent activity in the backstack to be brought to the front. Since we cannot do that, let's just start a new copy of the translucent activity, but instead of completely recreating one from scratch, let's reduce the amount of work by utilizing a fragment.

So if your translucent activity looked like this (copied from MKJParekh's answer):

public class FirstAct extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Button btn = new Button(this);
        btn.setText("First Here Go To Second");
        btn.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                Intent intent = new Intent(FirstAct.this, SecondAct.class);
                startActivity(intent);
            }
        });
        setContentView(btn);
    }
}

We can convert it to something like this:

public class FirstAct extends FragmentActivity {
    private static SavedState mSavedState;
    private FirstFrag mFrag;

    public static class FirstFrag extends Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            final Context context = inflater.getContext();
            Button btn = new Button(context);
            btn.setText("First Here Go To Second");
            btn.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    Intent intent = new Intent(context, SecondAct.class);
                    startActivity(intent);
                }
            });
            return btn;
        }    
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);    
        mFrag = new FirstFrag();
        if (mSavedState != null) mFrag.setInitialSavedState(mSavedState);
        getSupportFragmentManager()
            .beginTransaction()
            .add(android.R.id.content, mFrag)
            .commit();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mSavedState = getSupportFragmentManager().saveFragmentInstanceState(mFrag);
        finish();
    }    
}

With this code, we don't need to use the FLAG_ACTIVITY_REORDER_TO_FRONT flag when starting FirstAct later since it will in the background use the SavedState from its previous copy as the initial state of the new copy.

Please note that in my sample code above I simply destroyed the old copy of FirstAct (by calling finish() after saving the fragment instance state) in its onPause(). A more serious implementation would probably set a flag instead (to be checked in onResume()) whether a particular copy need to be finish()ed when revisited in the stack (if it has been "brought to front" as a newer copy).

Joe
  • 14,039
  • 2
  • 39
  • 49
-1

I had this same problem. I moved the uses-permission tag before the application tag in AndroidManifest.xml. That fixed it for me.

stevis
  • 425
  • 1
  • 4
  • 9