Here's the problem. I have an <activity-alias> in my manifest defined as follows:
<activity
android:name=".HomeActivity"/>
<activity-alias
android:name=".MainActivity"
android:targetActivity=".HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
Now, user starts MainActivity using a launcher icon, it forwards to the HomeActivity.
I also have an Intent to start HomeActivity from the navigation drawer. It is started with Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP flags - to reuse existing instance of activity.
The problem is that this does not work as intended and it actually creates a new instance of HomeActivity (even though it is currently on top and visible!).
This happens because an activity backstack contains an entry for .MainActivity, not the HomeActivity it forwarded to in the end.
Question: I suspect this might or might not be the bug in Android, but I have a difficult time of figuring out a decent workaround. Asking for help here! :)
I need only single activity started, and when user selects an item in navdrawer, that single activity should get onNewIntent(), not the new activity spawning!
Getting rid of an activity-alias fixes things, but this is not an acceptable option for me...
Here's the adb dumpsys result after the activity is started from launcher and then user selects 'Home' in navdrawer which starts activity directly, not through the alias (this dump confirms that there are two entries with different names):
Main stack:
TaskRecord{4181c408 #61 A ru.treto.tile U 0}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=ru.treto.tile/.HomeActivity }
Hist #2: ActivityRecord{412514b8 ru.treto.tile/.HomeActivity}
Intent { flg=0x24000000 cmp=ru.treto.tile/.HomeActivity }
ProcessRecord{412b06e0 10165:ru.treto.tile/u0a63}
Hist #1: ActivityRecord{41723200 ru.treto.tile/.MainActivity}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=ru.treto.tile/.MainActivity }
ProcessRecord{412b06e0 10165:ru.treto.tile/u0a63}
Instead of referencing your HomeActivity in the classes that are launching it, you'll need to alter those intents to start "MainActivity" instead.
EX:
Intent intent = new Intent();
intent.setClassName(mContext, "ru.treto.tile.MainActivity");
Alternately, if you're using another IntentFilter scheme, you can move those IntentFilter elements to your alias entry in the manifest:
<activity-alias
android:name=".MainActivity"
android:target="ru.treto.tile.HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="ru.treto.tile.ACTION_OF_AWESOME" />
</intent-filter>
</activity-alias>
Related
I have activity 1 (SplashActivity) running in foreground.
This splash activity is starting another Activity2 in its onStart() callback.
From elswhere (a singleton running in application context) I want to start Activity3 and to clear the task to make it the new root. This call is done several milliseconds after the other startActivity in onStart() and it fails with this exception:
java.lang.IllegalArgumentException: setTaskFromReuseOrCreateNewTask: task=TaskRecord{df9fb2e #10 A=com.example.myapp.myflavor U=0 StackId=1 sz=0} is in a different stack (1) than the parent of r=ActivityRecord{3b14930 u0 com.example.myapp.myflavor/com.example.myapp.SplashActivity t11} (0)
at com.android.server.am.ActivityRecord.reparent(ActivityRecord.java:971)
at com.android.server.am.ActivityStarter.addOrReparentStartingActivity(ActivityStarter.java:1992)
at com.android.server.am.ActivityStarter.setTaskFromReuseOrCreateNewTask(ActivityStarter.java:1808)
at com.android.server.am.ActivityStarter.startActivityUnchecked(ActivityStarter.java:1187)
at com.android.server.am.ActivityStarter.startActivity(ActivityStarter.java:1002)
at com.android.server.am.ActivityStarter.startActivity(ActivityStarter.java:567)
at com.android.server.am.ActivityStarter.startActivityLocked(ActivityStarter.java:272)
at com.android.server.am.ActivityStarter.startActivityMayWait(ActivityStarter.java:824)
at com.android.server.am.ActivityManagerService.startActivityAsUser(ActivityManagerService.java:4497)
at com.android.server.am.ActivityManagerService.startActivity(ActivityManagerService.java:4464)
at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:121)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2935)
at android.os.Binder.execTransact(Binder.java:674)
Activities are defined in AndroidManifest.xml in that way:
<activity
android:launchMode="singleTask"
android:name=".SplashActivity"
android:noHistory="true"
android:theme="#style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>
<activity
android:launchMode="singleTask"
android:name=".Activity2"/>
<activity
android:launchMode="singleTask"
android:name=".Activity3"
android:noHistory="true"/>
Activity2 and Activity3 are started with flag:
Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK
When the first startActivity is called, the only one task has id 14, and it contains only one activity: the SplashActivity.
When the second startActivity is called, the only one task has id -1 and it contains 0 activities.
So, what would be the solution to have the startActivity robust to the situation where another startActivity is in progress ?
Any idea ?
From what I understand, I would avoid this error by removing the singleTask launchmode, but I need it because my application can be started in different ways...
Other point: The exception is thrown when the application is updated from ADB. When the application is automatically starting at the device start, the exception is not thrown. (My application is the default launcher, so it automatically starts). --> That can probably be explained by a different sequence in the start of the two activities.
I'm developing two applications, AppA and AppB, and I want to start AppB from AppA.
In AppA, I am using
Intent initIntent = getPackageManager().getLaunchIntentForPackage("com.example.appB.ActivityB");
in AppB, I am adding an intent filter to the manifest file :
<activity
android:name="com.example.appB.ActivityB"
android:label="#string/title_activity_init" >
<intent-filter>
<action android:name="com.example.appB.ActivityB" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
But I got a java.lang.NullPointerException on the intent...
Any ideas would be welcome.
Your intent filter isn't complete for this API:
The current implementation looks first for a main activity in the category CATEGORY_INFO, and next for a main activity in the category CATEGORY_LAUNCHER. Returns null if neither are found.
So you need to modify Activity B's intent filter to include:
<action android:name="android.intent.action.MAIN" />
You are trying to specify an Activity in the Intent, even though you are creating a Intent meant to launch a package; this is not neccesary. Simply remove the Activity from your Intent like so:
Intent initIntent = getPackageManager().getLaunchIntentForPackage("com.example.appB");
And then just make sure that you have the following two lines in whichever Activity you wish to start when the application is launched:
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
They should be already be in there for your main Activity, although it looks like you were missing the android.intent.action.MAIN intent filter in your ActivityB.
I have this Activity defined in my AndroidManifest.xml:
<activity
android:name=".Splash"
android:label="#string/app_name"
android:noHistory="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
When I am trying to call it in this way:
Intent splashActivity = new Intent("android.intent.action.Splash");
mainAppContext.startActivity(splashActivity);
I get:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.Splash }
And when I try to start it in this way:
Intent splashActivity = new Intent("android.intent.action.MAIN ");
mainAppContext.startActivity(splashActivity);
It open a Complete action using dialog with many options there like play store etc.
Please help in starting this Activity.
From some other Activity:
startActivity(new Intent(this, Splash.class));
Intent splashActivity = new Intent("android.intent.action.Splash");
No-no-no! It should to
Intent splashActivity = new Intent(context, Splash.class);
If you use action - it seem that you want activity for some type of action, for example, view webpage on browser.
In your situation you have to use concrete activity and set it to intent
<action android:name="android.intent.action.MAIN" />
this action is not for your app, it is needed to android's launcher, that find activity in your application to launch it
Official documentation about intent mechanism
Where are you trying to launch this activity from? The following lines imply that Splash is your main Activity:
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Are you trying to launch the Splash Activity from Splash itself? This would be problematic. If you are launching from another Activity then you can use the following to launch Splash:
Intent intent = new Intent();
intent.setClass(YourCurrentActivity.this, Splash.class);
startActivity(intent);
Activity not found exception is occurred when u are trying to use or start activity that is not declared into the Mainfeast.xml file.
And When you want to start any activity then you need to start that activity by using intent. but in android "android.intent.action.Splash" Intent Action exist. And you have declared the following intent filter
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
"android.intent.action.MAIN" this is the action name that indicate the this is the activity to be started first. and android send this intent and an activity that is registered with this intent action is the first activity to be started first.
So to start splash activity you doesn't need any intent. You just need to simply run this project. but If u want to Start Another activity from splash actiivty then u need to do following things.
Intent intent = new Intent(Context, ActivityName.class);
startActivity(intent);
or
startActivityForResult(intent, requestCode);
and remember that You have to declare that activity into the mainfeast.xml
I have an activity registered on APPWIDGET_CONFIGURE:
<activity android:name="com.tahanot.activities.NearbyStops">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
However this activity does not behave as expected. It opens inside of an existing stack, and when I press the Back button, it takes me to other activities instead of closing the task. Ideally, I would like the APPWIDGET_CONFIGURE intent to include FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_MULTIPLE_TASK.
Is it possible to specify flags in AndroidManifest.xml, and if not, what workaround would you suggest?
Consider specifying launchMode attribute to the activity element.
<activity android:launchMode="singleTask" android:name="com.tahanot.activities.NearbyStops">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
As per the official docs,
FLAG_ACTIVITY_NEW_TASK
Start the activity in a new task. If a task is already running for
the activity you are now starting, that task is brought to the
foreground with its last state restored and the activity receives the
new intent in onNewIntent().
This produces the same behavior as the "singleTask" launchMode value,
discussed in the previous section.
Since you mention you want FLAG_ACTIVITY_NEW_TASK behavior so singleTask launchMode might work for you.
USe this java code when you start your activity
Intent intent = new Intent(this,
activityname.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Here you can add flag with your intent object like this.
And you can also add multiple flag.
This is the manifest declaration that I used, following appsroxcom's idea for android:launchMode:
<activity
android:name="com.tahanot.activities.NearbyStops"
android:configChanges="orientation"
android:label="#string/title_activity_stops_nearby"
android:launchMode="singleTop"
android:taskAffinity="com.tahanot.tasks.widgetConfiguration" >
<!-- android:launchMode makes sure the Back button doesn't navigate to another NearbyStops activity.
android:taskAffinity makes sure the Back button doesn't navigate to some other activity. -->
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
I am trying to launch an activity by specifying only its action(custom) defined in its intent filter from an activity in other application. The activity to be launched is the main activity of its application thus have android.intent.action.MAIN & android.intent.category.LAUNCHER set as action and category in its intent filter. Now according to android doc on Intent and Intent Filter, i do not need to specify DEFAULT category at all in this case. But doing the same i am i am unable to launch the activity.
LogCat says, Activity could not be found...
Am i misinterpreting the text or is there something else missing...?
Code, used for calling the activity
Intent i=new Intent();
i.setAction("android.AddressBookV4.firstActivity");
startActivity(i);
Definition of Activity being called in the manifest file
<activity android:name=".AddressBook"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.AddressBookV4.firstActivity" />
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
You need to add the LAUNCHER category to your Intent, since the <intent-filter> says that it matches the following Intents (in pseudocode):
((action IS "android.AddressBookV4.firstActivity")
OR (action IS "android.intent.action.MAIN"))
AND (category IS "android.intent.category.LAUNCHER")