Android Application onCreate not called for homescreen launcher app during reboot - android

I am having a strange problem in an Android application that I am building, the application is basically a Homescreen replacement app which will be put as a default homescreen in a device. To do some initialization work I have extended Android Application class and in the onCreate() method I am basically registering some observer and starting a service, here's the code:
public class MyApplication extends Application implements ExternalStorageListener {
private ExternalStorageObserver externalStorageObserver;
public void onCreate() {
Log.i("MyApplication", "Starting application");
super.onCreate();
externalStorageObserver = new ExternalStorageObserver(this);
if(externalStorageObserver.isExternalStorageAvailable()) {
// this builds a list of files present in the SD card
// which is being used through the application to do
// some work
buildData();
File externalFileDir = getApplicationContext().getExternalFilesDir(null);
if(externalFileDir != null && externalFileDir.isDirectory()) {
// do something...
}
}
//Register listener to observe external storage state
registerExternalStorageObserver();
Log.i("SyncService", "Starting sync service...");
ComponentName cmp = startService(new Intent(getApplicationContext(), SyncService.class));
Log.i("SyncService", cmp.toString());
}
private void registerExternalStorageObserver() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
filter.addAction(Intent.ACTION_MEDIA_REMOVED);
registerReceiver(externalStorageObserver, filter);
}
private void buildData() {
// builds a list
}
}
Content of Manifest file:
<application android:persistent="true" android:icon="#drawable/icon"
android:label="#string/app_name" android:name="com.webgyani.android.MyApplication"
android:debuggable="true">
<activity android:name=".HomeTabActivity" android:launchMode="singleInstance"
android:stateNotNeeded="true" android:theme="#style/LightTabsTheme"
android:screenOrientation="landscape" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
This works fine when I install the app either using Eclipse or manually installing the apk onto the device. Once the app is installed things work fine, I mean the above onCreate() method gets called and service is also started normally, but if I reboot the device this time the onCreate() method does not get called(none of the log statements appear and also the services are not started). After some debugging I noticed that this only happens if I set my app as the default launcher/homescreen app and thereafter reboots the device, because once you set the app as the default launcher, Android should automatically launch your app as the homescreen after reboot. In my case the app is launched but that code is not executed.
I tried to use debugger but that didn't work because when I reboot the device the debugger gets disconnected and by the time USB debugging gets enabled my app is already started.
I even double checked the Logcat but didn't see any error. I thought of having a BOOT_COMPLETED intent to initialize that part, but that will require some code refactoring which I am not willing to do at this point of time unless there is a solution.
So I am curious to know that whether this is a standard behavior, or is there a known bug which causes this, because my assumption is the onCreate method of the Application will always get called whenever the app is started. I have tried whatever I could since morning, but nothing worked, couldn't pinpoint the issue, if any of you could shed some light into this then that would be highly appreciated.
Thanks

Well, finally I figured out the problem, and it was in my code itself. I initially suspected that the MyApplication's onCreate() method was not getting called, I had that assumption because I was not able to see any logs. To know whether the method is getting called or not, instead of using Log.i() I was also appending some additional log messages in an ArrayList and printing them later, this revealed that the methods were indeed getting called and even the Service was instantiating properly but the data or filelist is not being populated because the SDCard was not ready by that time. I am also pretty sure that the logs were not available on Logcat due to the fact that the USB debugger becomes ready after my app is started(as it's a homescreen app).
The actual problem becomes obvious when you see that my overridden MyApplication class implements a listener called ExternalStorageListener which basically extends BroadcastReceiver, I have created that class to receive SDCard related Intents for example ACTION_MEDIA_MOUNTED, ACTION_MEDIA_REMOVED to rebuild the data(file list). In my case the ExternalStorageListener class was not receiving the Intents because I forgot to add this filter.addDataScheme("file") in the registerExternalStorageObserver method above in the code sample.
I do agree that my question was based on a false assumption and the code example I posted it's kind of hard to figure out the actual issue. I am not sure what to do with the question whether to mark this as answer or leave it as it is.

Related

How can I set my WatchFaceService as the default launch activity in Android Studio

I have a WatchFaceService (WatchFace) and every time I run my application it switches to the SimpleFace and then I have to set mine as the watchFace which ends up to be quite frustrating after many restarts.
To notice this does happen with the new Android Studio 2
I read around S.O. how to set the default activity but that does not do the same job as my WatchFaceService is not an activity but a service.
Also via the UI of Android Studio 2 it cannot be selected.
Is there a way to achieve this ? I think it might be difficult because actually it's not running an app, but setting the watch's Watchface at every run.
Any ideas?
The short answer is that this isn't possible. Your watch face is a Service, after all, so there's no way that it can be the default (launch) Activity for your app. They're completely different component classes.
But you can get close.
What you need to do is create a tiny little shell Activity that contains only the following code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER)
.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
new ComponentName(getPackageName(),
MyWatchFaceService.class.getName()));
startActivity(intent);
finish();
}
...where MyWatchFaceService is the class name of your watch face service (surprise). You'll also need to declare it in your manifest, of course:
<activity android:name=".FaceActivity"
android:enabled="true"
android:exported="true">
</activity>
Finally, configure your Wear module in Android Studio to launch FaceActivity when you run the app. This is under the Run menu, in Edit Configurations.
Having done that, run your app from AS onto the watch, and it'll open the watch face chooser on-device, with your face selected. From there, one tap will start it.
I can't see a way to eliminate that single tap, though.

Android: Sharing Data and Receiving text from 3rd party app. Why doesn't my app receive new text?

Summary
I am attempting to get data sent from the user via the Share menu. In this case, I'll use the basic Android web browser to select text and then share it to my app.
Problem
The first time the user shares the text my app gets the text as expected and displays it via Log.d() -- see the handleSendText() method in the code below.
However, each time thereafter even though the user has selected new text in the web browser and shared it with my app, I still get the original text the user selected (previous value).
Question
How do you reset the Intent -- or whatever it is -- so that I can obtain the new text the user has selected after the first time?
Details
My application has a MainActivity and I've followed the Google docs at :
http://developer.android.com/training/sharing/receive.html
With code like the following in my MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
if ("text/plain".equals(type)) {
handleSendText(intent, "onCreate"); // Handle text being sent
}
}
}
#Override
public void onResume(){
super.onResume();
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
if ("text/plain".equals(type)) {
handleSendText(intent, "onResume"); // Handle text being sent
}
}
}
void handleSendText(Intent intent, String callingMethodName) {
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
if (sharedText != null) {
Log.d("MainActivity", "sharedText : " + sharedText + " called from : " + callingMethodName);
}
}
}
My AndroidManifest section for the activity has the filter added like:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
Walk-Thru With Screens and Log
NOTE: Please notice that I've implemented the onResume() in my app also to insure that I don't only get the Intent when onCreate() is called (only one time when the app is started).
Start up browser and grab the text "hurricane".
Choose the app to share with (our test app).
View the log and notice that onCreate() and onResume() are called and value is 'hurricane'
Go back to browser again to share more text...
Select a new word, Atlantic, to share.
Extra note: When we click that Share link this time the Android MenuChooser doesn't display, instead, it automatically opens GrabText again. I found that behavior somewhat odd.
Notice that the Intent text still has the value of hurricane. You can see that there are now two new entries in the logcat.
Attempted Workaround Solutions
I have found that I can destroy the app entirely by overriding onPause() and calling finish() on my Activity (thus closing the entire app) and that seems to work, but isn't there some other way to reset that Intent or the associated text or something?
Do you know of any other way to insure that the new data is retrieved?
I appreciate any help.
UPDATE
Note:I'm updating because there's not a great way to show additional code tried, however, I wouldn't have know to try this without input from other SO User, CommonsWare.
The first answer I received was that I should add an #Override onNewIntent() so I added the following code to my MainActivity:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d("MainActivity", "onNewIntent()...");
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
if ("text/plain".equals(type)) {
handleSendText(intent, "onNewIntent"); // Handle text being sent
}
}
}
Upon adding that code and running and attempting the copy and then second copy of the new word, I still saw the following in logcat:
It doesn't even look as if the onNewItent() method is even called.
EDIT 2
I altered the emulator Settings...Developer Options... and turned off the "Don't keep activities" setting. It was previously turned on (checked).
After that, I ran the app which contains the onNewIntent() override but now it shows just the one onCreate() gone (which makes sense because the activity is still loaded) but still does not show the onNewIntent() call.
In this sample, I captured the word "remnants".
Edit 3
I built the app and created an APK and deployed it to my Samsung Galaxy Core Prime and I ended up with the same results. onNewIntent() is never called.
I just looked up onNewIntent in Google docs and it states:
onNewIntent(Intent intent) This is called for activities that set
launchMode to "singleTop" in their package, or if a client used the
FLAG_ACTIVITY_SINGLE_TOP flag when calling startActivity(Intent).
I haven't set singleTop so I will try it now. Hmm....
EDIT 4
I have now tried the singleTop variation. I was previously testing on API 15 (v4.0.4)on an emulator so I switched to API 21 (v5.0) to see if there'd be any different.
Here's what the addition of singleTop did to my AndroidManifest.xml:
<activity android:name=".MainActivity" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
Notice I also collapsed the two intent-filter nodes into the one.
Selected Text Did Change
On Android API Level 21 the Intent text was now coming in different each time I selected text in the browser.
onNewIntent Is Never Called
However, onNewIntent is NEVER called. I don't ever see it fire.
Share Menu Displayed Every Time
Also, now (on API 21) I see the Share menu every time I select text.
However, I also see an interesting thing when I switch to the browser. You can see multiple copies of the Activity in the list. What?!
Notice also that I implemented the MainActivity as a ListView (scrollable) so I could see the entries even without logcat (for running on real device). That made something else apparent: that the ListView was being updated on each newly shown Activity. But really, it should be the original Activity being appended to.
Creates Numerous GrabText Activities
Yes, now it creates a new GrabText Activity window each time I select text. I thought maybe that was because I had the singleTop set so I removed it but they still appear even after removing singleTop on API LEVEL 21.
Now that I saw it work -- provide different text each time on API 21 I decided to switch back to API Level 15 emulator and try it.
I will report back after I try some things back on API Level 15 again.
API Level 15 : Test Again
I started my other emulator running API Level 15 again and ran the app and even with singleTop set the value is never updated.
You can see this in the logcat and on the updated ListView:
You can also see that the code acts completely different, though I've not changed anything since it appends to the ListView of the one running Activity on api level 15.
I've written a book on this terribly documented thing. I hope this helps someone and that a Google Android dev sees this and explains it.
If your activity already exists, it will be called with onNewIntent() instead of onCreate(). onNewIntent() will be passed the Intent that you need to use for your message.
Try changing the android:launchMode of your activity in the manifest.xml to
singleTop
this way if the activity is already launched, new intents will be received in onNewIntent() method
There is only one answer that actually works, but it could cause other problems.
You just have to decide to call finish() whenever the Activity goes into onPause().
Here's the exact code I implemented which works on all API LEVELS.
#Override
public void onPause(){
super.onPause();
finish();
}
Destroy the Activity
When you add that code then every time you switch back to the app you are sharing from (the web browser in our case) then the onPause will fire on your MainActivity and the finish() method will set the Activity for destruction.
Share Menu Displayed Every Time After This
With this solution every time you select text from your sharing app (web browser) then the Share menu will be displayed and will display GrabText as one of the choices (instead of automatically forcing GrabText to the front again).
Shared Text Is Always the New Text
Since the MainActivity is completely destroyed it then has to be completely loaded (onCreate()) again and so it receives the new Intent text which was sent.
Not A Great Workaround
This isn't a great workaround however, because I believe dialog boxes in your app would also create onPause() to be called and your Activity would be destroyed. Obviously destroying your Activity onPause() just isn't great either because you are beginning to manage "memory" in a way that really should be left to the OS. However, in this case it seems to be the only way around the issue.

Service stops on clearing data from settings

in my app i run a service in which i keep record of incoming and out going calls on text file(saved it on internal storage) using broadcastReciever. but when i press clear data button(settings=>apps=>Myapp=>clear data) my service also stops. i used Log.d() in onDestroy() method but it is not logged in logcat when i press clear data.
i read this question having same problem but i didn't find any solution. then i went through Developer Guide. i am really confused.
The data associated the the app will no longer persist on clearing. To avoid this you need to sign your app as a system app.
Clear Data does kill the app, and always has.
"Force Stop" has gone through various iterations of meanings. It used
to mean to just kill all processes and services, and clearing data
would also do the same as a force stop. There were also older
iterations of the platform that were not as good as figuring out when
to disable the button, which is probably why you are seeing it remain
enabled in 2.2.
However in 3.2 I believe the meaning of "Force Stop" change to put the
application in a state where it would not be able to run until the
user had done something to explicitly start it (such as launching it
from launcher, selecting it as an input method, etc). When that change
was made, "Clear Data" continued to just kill the processes and stop
its services, so the app was not in the full stopped state so the
button remains enabled.
Edit:
Example of working code:
Step 1) Create one Android BroadCastReciever and register it for two action
Manifest
<service android:name="ServiceTest" >
</service>
<receiver android:name="ReceiverCall" >
<intent-filter>
<action android:name="com.android.techtrainner" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
com.android.techtrainner is the custom action. BroadCastReceiver Class contain code to restart service again
public class ReceiverCall extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Service Stops", "Ohhhhhhh");
context.startService(new Intent(context, ServiceTest.class));;
}
}
Step 2) Create Android service class , do some task there (I have taken one Timer to print Log) and in onDestory()
public void onDestroy() {
try {
mTimer.cancel();
timerTask.cancel();
} catch (Exception e) {
e.printStackTrace();
}
Intent intent = new Intent("com.android.techtrainner");
intent.putExtra("yourvalue", "torestore");
sendBroadcast(intent);
}

Android AppWidget does not show up in the menu in honeycomb until reboot

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.

Android launches system settings instead of my app

For some reason whenever I (try to) start my app the phone decides to launch system settings instead of my "main activity". And yes, I am referring to the "Android system settings", and not something from my app.
This only happens on my phone, and I suppose it probably could be related to the fact that my app had just opened system settings when I decided to re-launch with a new version from Eclipse.
It is possible to start the app from within Eclipse, but when I navigate back from the app it returns to the system settings rather than the home screen, as if the settings activity was started first and then my activity. If I then start the app from the phone all I get is system settings yet again.
The app is listening to the VIEW-action for a specific URL substring, and when I start the app using a matching URL I get the same result as when I start it from Eclipse, app starts, but when I return I return to settings.
I have tried googling for this problem, and all I could find was something about Android saving state when an app gets killed, but without any information on how to reset this state. I have tried uninstalling the app, killing system settings, rebooting the phone, reinstalling, clearing application data.. no luck..
For what it's worth, here's the definition of my main activity from the manifest,
<activity android:name=".HomeActivity" android:label="#string/app_name" android:screenOrientation="portrait" android:clearTaskOnLaunch="true" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:pathPrefix="/isak-web-mobile/smart/" android:scheme="http" android:host="*"></data>
</intent-filter>
</activity>
And here is the logcat-line from when I try to start my app, nothing about any settings anywhere.
I/ActivityManager( 1301): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=se.opencare.isak/.HomeActivity }
When I launch from Eclipse I also get this line (as one would expect),
I/ActivityManager( 1301): Start proc se.opencare.isak for activity se.opencare.isak/.HomeActivity: pid=23068 uid=10163 gids={3003, 1007, 1015}
If it matters the phone is a HTC Desire Z running 2.2.1.
Currently, this is my HomeActivity,
public class HomeActivity extends Activity {
public static final String TAG = "HomeActivity";
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult(" + requestCode + ", " + resultCode + ", " + data + ")");
super.onActivityResult(requestCode, resultCode, data);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate(" + savedInstanceState + ")");
super.onCreate(savedInstanceState);
}
#Override
protected void onDestroy() {
Log.d(TAG, "onDestroy()");
super.onDestroy();
}
#Override
protected void onPause() {
Log.d(TAG, "onPause()");
super.onPause();
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
Log.d(TAG, "onPostCreate(" + savedInstanceState + ")");
super.onPostCreate(savedInstanceState);
}
#Override
protected void onPostResume() {
Log.d(TAG, "onPostResume()");
super.onPostResume();
}
#Override
protected void onRestart() {
Log.d(TAG, "onRestart()");
super.onRestart();
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
Log.d(TAG, "onRestoreInstanceState(" + savedInstanceState + ")");
super.onRestoreInstanceState(savedInstanceState);
}
#Override
protected void onResume() {
Log.d(TAG, "onResume()");
super.onResume();
}
#Override
protected void onStart() {
Log.d(TAG, "onStart()");
super.onStart();
}
#Override
protected void onStop() {
Log.d(TAG, "onStop()");
super.onStop();
}
#Override
protected void onUserLeaveHint() {
Log.d(TAG, "onUserLeaveHint()");
super.onUserLeaveHint();
}
}
Nothing (of the above) is written to the log.
After reading Blundell's response I have tried changing the launchMode/clearTaskOnLaunch settings, with the following results,
Situation A - I remove launchMode and clearTaskOnLaunch: same problem as before
Situation B - I remove clearTaskOnLaunch and keeps launchMode="singleInstance": another problem
Open app - My HomeActivity is showing
Click on a button to open another activity within my app - it opens as it should
Click on the system back-button - it returns me to system settings
Click on the system back-button again - I am returned to my HomeActivity
Another click on the back-button brings me back to the Android home screen
Situation C - I remove only launchMode and keeps clearTaskOnLaunch: same problem as before
Sitatuion D - I remove clearTaskOnLaunch and set launchMode="singleInstance": same as situation B
You are not calling setContentView() from the HomeActivity (as per the code added by you). And when it is not present, different device behave differently, like on emulator you will see "Application not installed on your phone". Try setting content view.
I've tested this on my phone, but this seems to work correctly here...
What if you try to create a new project, and then just copy the code into it?
It worked for me, maybe it will work for you to...
I suspect it has something to do with your change of version of Eclipse, which might use some different setting from the version you used before, therefore rendering your initial set-up as useless...
My 2Cents
You could look into the launch activity of the Application.
Basically what I think might be happening is, your app is being launched in the same 'Stack' as the settings was, therefore the OS will push the settings to the screen and then load your activity on top of that stack.
You could try adding:
android:launchMode="singleInstance"
into your <activity /> tag of your manifest file. This will start a new stack for your application and only your application
This may fix the issue but there may be another cause and this may cause adverse effects depending on how your app works. Have a look at the documentation for further info:Android:LaunchMode
EDIT
Reading your manifest, why not just remove android:launchMode="singleTop" and let it launch with the default?
Also you are pairing this with:android:clearTaskOnLaunch , because the OS has the settings activity and your activity as the same task it may be clearing it down to the 'root' activity which is the settings and not your app. Is there a reason you have this, remove it and try again?
Please note that I am not an Android developer, but I own an Android phone and think this issue is quite interesting.
To sum it up what I have read about this issue so far here it looks for me that following may be the root cause of this issue:
You use clearTaskOnLaunch, which wipes out all intents/activities/tasks/whatever_buzzword_is_used_for_this when your application starts.
Android then seems to remember permanently the last state of the application in some (what I now will call) global internal state database (GISD for brevity) which cannot be wiped that easily (at least not with uninstalling the application, rebooting, clearing intents, etc.).
Android tries to reopen the application with it's last state. If there is no current activity then this info is taken from the GISD, hence in your case it is "system settings".
There is no way (or it is unknown how) to wipe the state held in the GISD. (Your question is how to do that.)
If this is true this is clearly a phone issue, a major bug in Android, as you then can probably brick applications! All you must do is following:
Somehow provoke a similar thing like clearTaskOnLaunch - which should be possible - for the application you want to brick.
Trick the application to launch to some other application like "System settings" - many applications do this to enable WiFi or similar, but I think some clever people (read: not me) will find a way to do this for virtually any application
Now kill the application in this state.
Android will remember that state then in the GISD and if you try to launch the application from Home screen this will fail in future. Nice.
However even in the absence of a fix hopefully it is possible to bring back the application the same way:
Start your application with an Activity such that it launches. As you write, this works for you.
Apply what clearTaskOnLaunch does. (I really have no idea how, but you as Android developer probably know.)
Let your application launch a third application such that this third application becomes the global state.
Kill your application.
Perhaps timing and sequence is important, so perhaps you have to leave the third application after your application is killed, perhaps you have to pull the battery of your phone at the right time, perhaps you must use some weird ADB stuff to prevent your phone to do the right thing, perhaps you need another sequence of actions or somethign still is missing, whatever, even finding out how to provoke your type of error can be difficult - but thanks to your finding we know there is such a thing.
If you can make Android launch the third application from Home screen instead of your app this would confirm, that you indeed can fix that issue. If this does not work, so it is impossible to prevent Android to invoke system settings instead of your app, then Android certainly has a big problem, as it is likely someone finds a way to permanently brick apps in all those precious phones out there (ab)using that bug.
If the previous step works, however, the last step now is to let this third application launch back into the main screen of your application:
Start your application.
This will launch the third application.
Apply what clearTaskOnLaunch does.
Let the third application launch your application's main screen (or whatever you want)
Kill the third application (and perhaps your application).
Now the global activity state shall be set back to your application again - if everything goes well third application should not be harmed either.
Note that I am not sure this really can be done, as I am not able to test it myself. And having said that all, I agree that we certainly need be a better way to repair this issue!
But interesting would be to see what happens, if your app has the state of the third app and the third app has the state of your app. Does this lead to an endless loop?
Interesting too is, what happens if you deinstall the third app. Does this clean the automatic launch into that application or does it leave you helpless?
As an Android Phone onwer (only), I must say, that's quite a nice mess you have found. And that's why I am highly interested if there is a fix, as doing a factory reset cannot be considered a solution. Read: This is not only a developer problem, it affects Android users as well.
PS: Please forgive me my bad English, the length of this post, not using the right Buzzwords and posting on an issue which I am not an expert of so that my answer is a little bit OT. However I do this with HTH.

Categories

Resources