I'm in the process of trying to make a release build of my first android app to send to a few testers. However, I ran into a problem with it. When you exit the app and then re-enter it by launching it via its icon, it restarts the whole app instead of returning to it's previous location. This occurs even if you re-enter right after exiting. However, it does not happen if I hold the Home button and launch it through the recent apps list.
I've searched online for others having this problem and there are a few, but no one has ever had a solid answer as to why it's happening to them. It's been suggested in old questions to set the launchmode to singletask or singleinstance in the manifest file, but that hasn't helped me, and besides - from what I understand, the default behavior for android is to return to the previous state of the task in this situation, so I don't know why I would need special manifest options to make it do that.
The most bizarre thing about this problem is that if I use eclipse and the debugger to put the app on my phone, this problem does not occur. I don't even need to be connected to the debugger, it seems like as long as I have a debug version of the app, the problem doesn't occur. But if I use a release version (I create it using the Android Tools - Export Signed Application Package menu option in Eclipse), the problem happens.
If anyone has any insight as to what is causing this, I'd love to hear your thoughts.
I had the same problem with an application and I resolved this behavior adding flag "android:launchMode="singleTop"" instead of "android:launchMode="singleTask"" in the <activity> declaration of your AndroidManifest.xml file. Hope this will help somebody.
So far I've found out that it's an issue based on how you install it in your real device, specifically:
If you simply copy and paste the APK to your device's local storage and install it from the device, regardless of whether it's signed or unsigned or taken from bin folder, it shows this behavior, app restarts from menu icon.
If you install it using one of the following options, This issue does not appear:
Go to sdk/tools/ using a terminal or command prompt then type
adb install <FILE PATH OF .APK FILE>
In Linux, type:
./adb install <FILE PATH OF .APK FILE>
Simply run your project from Eclipse.
I would be pleased to know if there's any possible way to distribute correct APKs for beta testing. I already tried exporting a signed APK because when you copy and paste an APK and install it manually it shows the rogue behavior.
Update:
I found out a solution. Follow these two Steps:
Set android:launchMode="singleTask" = true for all activities of your app in the AndroidMainifest.xml inside the activity tag.
Put this code in your Launcher Activity's onCreate().
if (!isTaskRoot())
{
final Intent intent = getIntent();
final String intentAction = intent.getAction();
if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
finish();
return;
}
}
This behavior is a bug in Android. Not a special case.
// To prevent launching another instance of app on clicking app icon
if (!isTaskRoot()
&& getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
&& getIntent().getAction() != null
&& getIntent().getAction().equals(Intent.ACTION_MAIN)) {
finish();
return;
}
write the above code in your launcher activity before calling setContentView. This will solve the problem
You could use launchMode as singleTop to the Launcher Activity in AndroidManifest.xml
<activity
android:name="<YOUR_ACTIVITY>"
android:label="#string/app_name"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
It is the default behavior in Android. For the debug builds it works differently for some reason. It can be solved by adding android:launchMode="singleInstance" to the activity, you want to restart after you launch from the icon.
Add this to your first activity:
if (!isTaskRoot()) {
finish();
return;
}
super.onCreate(savedInstanceState);
Try using android:alwaysRetainTaskState as shown in the following example:
<activity
android:name="com.jsnider.timelineplanner.MainActivity"
android:alwaysRetainTaskState="true"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
For me, I found that I had erroneously posted NoHistory = true in my activity attribute
[Activity(NoHistory = true, ScreenOrientation = ScreenOrientation.Landscape)]
This prevented the app resuming into this activity and restarted
You can try to set android:alwaysRetainTaskState="true" for your launcher activity in AndroidManifest.xml.
<activity
android:name=".YourMainActivity"
android:alwaysRetainTaskState="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
For details you can see https://developer.android.com/guide/topics/manifest/activity-element.html#always
I see this issue on Android TV in 2019. Is there a better fix for it? other than
if (!isTaskRoot()) {
finish();
}
It works but looks like a hack more than the actual solution.
All of the solutions above didn't work consistently on all of my devices. It worked on some Samsung but not all.
The cause of the problem for me was installing the APK manually.
For me the fix was adding LaunchMode = LaunchMode.SingleTop to my Activity attribute over the Main Activity:
/// <summary>
/// The main activity of the application.
/// </summary>
[Activity(Label = "SilhuettePhone",
Icon = "#drawable/icon",
Theme = "#style/MainTheme",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation,
ScreenOrientation = ScreenOrientation.Portrait,
LaunchMode = LaunchMode.SingleTop,
WindowSoftInputMode = SoftInput.AdjustResize)]
I had a problem with a restarting app, my problem was in themes:
I have differents fragments and I would have one background for all. But this cause a restarting app in some devices(.
I've deleted this line in themes and this helped:
item name ="android:windowBackground">#drawable/background /item
Removing task affinity rather than launch mode has worked somewhat for as it has its own demerits
When you press the back button in Android, the onDestroy method is invoked (as opposed to pressing the home button, where only the onPause() method is invoked).
If you need your app to continue where it left off, save the state of the app in your onDestroy() method and load that state in the onCreate() method.
Related
Our application has a splash activity (main activity for launcher) and many other activities. In most cases, when the user switches the application into background and resumes it from launcher, the old activity stack is resumed and top activity in that stack is shown as expected.
However, when the apk is just installed on the phone, or a new apk (with higher version) of the same application is installed, its behavior is strange. When the application is switched to background and resumed from launcher, the previous activity stack is not resumed and the splash activity is always shown. If we resume the application from recent applications list, the activity stack is resumed as expected. Only after killing the task from recent applications list, everything becomes normal again. The previous activity stack will always be resumed correctly until it is replaced by another apk installation again.
My Android version is 4.1.2 and I am using its default launcher.
Following is configuration of the splash activity.
<activity android:name=".welcome.activity.SplashActivity" android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Who has any idea about the strange behavior? Thanks in advance!
Finally I have found this is an issue of Android system. It has already been discussed in Activity history stack wrong upon first install on device?.
I have adopted a workaround stated in https://code.google.com/p/android/issues/detail?id=2373#c40 and it works well, i.e. adding the following code in SplashActivity.onCreate():
if (!isTaskRoot()) {
Intent intent = getIntent();
String action = intent.getAction();
if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && action != null && action.equals(Intent.ACTION_MAIN)) {
finish();
return;
}
}
I'm not really able to tell what's going on without knowing more about your app. I would look into:
The launchMode manifest element: android:launchMode
Check your activities are not being destroyed and recreated by the system: Recreating an Activity
If you are doing anything with fragments and if these are maintaining state correctly
Sorry, bit of a guess!
Since you only want to show your Splash Activity once, you can use finish() after you launched the Main Activity, that should solve your problem.
I have an industrial app which is remotely controlled from a PC. The app has 2 slightly different versions - one for a Honeycomb tablet and the other for a Gingerbread phone. The differences are to take advantage of unique features in the hardware (e.g., the phone has a better camera, the tablet can display bigger graphics) but the Activity-starting code is the same.
A thread in the app receives commands from the PC and displays different screens (i.e., starts different Activities). It works fine on the phone but on the tablet one activity won't start, but throws no exceptions. Breakpoints and logging in that activity's onResume() are never hit, even though they are on the phone. Here's how I try to start the activity . . .
try {
Intent svc = new Intent(ctx, RemoteControlActivity.class);
ctx.startActivity(svc);
}
catch (Exception e) { // or ActivityNotFoundException e
Log.d("ShowButtons(normal)", "startActivity failed");
}
(ctx is a Context - in the debugger the Context is the same for both the working on non-working cases)
The activity which is failing to start on the tablet is defined like this in the manifest . . .
<activity
android:launchMode="singleTask"
android:label="#string/app_name"
android:windowNoTitle="false"
android:configChanges="orientation"
android:screenOrientation="landscape"
android:name="RemoteControlActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
This is driving me batty - thanks in advance for any help!
Try this
Intent svc = new Intent(ctx, RemoteControlActivity.class);
svc.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(svc);
According to the docs
When using this flag, if a task is already running for the activity you are now starting, then a new activity will not be started; instead, the current task will simply be brought to the front of the screen with the state it was last in
I found a solution. I'm posting it this way so I can mark it as "answered" incase anyone else runs into this and is searching for a workaround. But I admit I don't understand why it works.
The breakthrough was discovering that it mattered what activity was currently on the screen when I was trying to start RemoteControlActivity. The failure was happening when I had an activity that displayed some graphics on the screen. I substituted a different activity that displayed some buttons and the problem went away.
Looking at the Manifest I noticed that the "good" activity was set to:
Android:launchMode="singleTask"
and the "bad" one was set to:
Android:launchMode="singleInstance"
When I changed the graphics activity to "singleTask" the problem went away.
Well, just like the title suggests, every activity within my application is being added to the app drawer.... Im really hating this new ADT. First it was a problem with the app name appearing as the first activity name, now all the activities are showing up on the application list. If I go to uninstall it only shows 1. Anyone else having this problem and has figured out a work around?
for future cases specifically you can change in the android manifest under :
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
change to:
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
This will remove the activities' icon from the app drawer. As the OP says: sometimes the wizard puts this in the manifest for you.
Ok, figured it out... Everytime you create a new activity through the adt wizard (New -> Android Activity) it creates the code in your manifest for you.... the problem is that it added intent filters to it as well. Just remove those and they dont show up.... stupid adt.
I know when I am using IntelliJ as my IDE for Android programming, there is a box you can check when using the wizard to create a new Activity that says "Mark as start-up Activity".
Be aware of these types of things because that is what caused me to have the same problem you had Shaun.
I wouldn't completely erase the intent filters, simply have only the Activity you want as the "start-up" Activity marked as the "Launcher" in the Manifest file. All other Activities get "Default".
I have developed a new release of an application and I have changed the name of the activity which is launched.
Before the upgrade, in the manifest was:
<activity
android:name=".Splash"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#android:style/Theme.NoTitleBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
and then I only changed the name and the package of the activity and now it is:
<activity
android:name=".view.SplashActivity"
... >
...
</activity>
what happens is that after people download the application from the market, the launcher is not refreshing and it still calls to the old path to the activity.
Do you know how to solve this?
Refer Things That Cannot Change
It says,
A subtle but important aspect of what constitutes a break in compatibility is the android:name attribute of your activity, service, and receiver components. This can be surprising because we think of android:name as pointing to the private code implementing our application, but it is also (in combination with the manifest package name) the official unique public name for that component, as represented by the ComponentName class.
Changing the component name inside of an application can have negative consequences for your users. Some examples are:
If the name of a main activity of your application is changed, any shortcuts the user made to it will no longer work. A shortcut is an Intent that directly specifies the ComponentName it should run.
If the name of a service implementing a Live Wallpaper changes, then a user who has enabled your Live Wallpaper will have their wallpaper revert to the system default when getting the new version of your app. The same is true for Input Methods, Accessibility Services, Honeycomb’s new advanced Widgets, and so on.
If the name of a receiver implementing a Device Admin changes, then as with the live wallpaper example, the device admin will be disabled when the application is updated. This also applies to other kinds of receivers, such as App Widgets.
So if possible, don't change the name of components declared in the manifest, or remove any icon pointing to that component using below code.
ComponentName componentToDisable = new ComponentName("application.package.name", "packagename.ActivityClassName");
getPackageManager().setComponentEnabledSetting(componentToDisable, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
Also specify new launcher activity in manifest using <intent-filter>...</intent-filter> so that your new activity will be launched when user clicks launcher icon.
Does the activity is called correctly if you start the activity in debug mode on your phone.
If so check if you did something of the following:
you changed the whole package name
you signed it not at all or not correctly
Also you might check out http://developer.android.com/guide/publishing/publishing_overview.html
Anyway. If the application runs correctly on your debugging phone there is something wrong with your publishing parameters and you should go through the page above step by step.
If not you might check the path values, like package and name of the activity and the filters.
I have created an AppWidget for Honeycomb which is working well, except that when first installed, it does not show up in the Widgets menu so it can not be added to a home screen. Rebooting the device will allow it to show up, or during development, sending it twice from Eclipse will cause it to show up.
Any ideas?
Thanks!
Appearently EboMike was right, setting android:installLocation="internalOnly" did fix the issue. Without specifying an install location, it should have defaulted to internalOnly, but did not seem to for me. Perhaps something changed in Honeycomb?
Also, even with internalOnly set, I was still seeing the issue when installing from Eclipse (widget would not show up in the selection menu until the second run) but when installing from the android market, it seems to be working fine which was my major concern.
Thanks!
The reason for this is actually described here and it is by design as of Android 3.1. By default, the installLocation will already be set to "internalOnly" so that should not fix the problem and neither should a reboot.
To work around this, an activity needs to be triggered in your widget. This will activate it and it will then appear in the widget list.
To do this, you can add an activity that essentially does nothing like this:
1) In your AndroidManifest.xml, add this inside your "application" tag:
<activity
android:name=".DummyActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
2) Then create a "DummyActivity.java" class in your "src" like this:
package com.domain.app;
import android.app.Activity;
import android.os.Bundle;
public class DummyActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
finish();
}
}
Now, when you deploy the widget to your device, that activity will be launched automatically (you'll see a message in your Eclipse console saying "starting activity ...") and it will immediately "finish" without showing anything visual on the device. And now your widget will be listed in the widget list!
Spooky,
I did this installLocation fix and it worked first time.
But from then on I still have to reboot every time I update my widget on my Xoom with 3.01 to see it in the list.
To solve this problem with my widget I send widget update broadcast, like this in my WidgetController.class:
Intent intent = new Intent();
intent.setClassName(context, context.getPackageName() + ".WidgetProvider");
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,
getWidgetIds(context));
context.sendBroadcast(intent);
then to provide stable widget initialization in the system I send this broadcast from Application object when application or widget start:
public class MyApp extends Application {
#Override
public void onCreate() {
WidgetController.getInstance().updateWidget(getApplicationContext());
}
}
!!! Important: when AppWidget hosts in application it's enough, but when AppWidget separated from it you should use way proposed by #John above in this topic.