BroadcastReceiver instead of Activity - android

I have an application that doesn't have any activities. All it does is show a notification. Is it possible to put launcher filter on the BroadcastReceiver instead of the main activity?
Here is what I've tried:
<receiver android:name=".LaunchReceiver">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</receiver>
It doesn't work. The app installs, but there is no icon in the launcher.
If it's not possible, are there any other ways to not show the activity? Currently I just have an empty activity and call finish() from onCreate(), but the it still shows up for a split second, which doesn't look nice.

A Receiver receives broadcasts only. Only an activity belongs in the launcher. Intents and filters explains much of this.
To make an invisible activity (to not see it while you quickly finish() it) declare it with this theme:
#android:style/Theme.Translucent.NoTitleBar
But you better also add the following if you have an invisible activity (to avoid confusing the user):
android:noHistory="true"

Related

SingleTask activity is created multiple times within the same process

I have a launcher app which has a singleTask activity as the main entry point. When the user navigates away to another activity or to a 3rd party app and then hits the home button, then this activity should be brought to the front. However what I experience is that for the first home button press only, another instance is created instead (a new task is created, onCreate() is called). In the meantime the old task is still alive, containing the original instance of this activity, but it is impossible to navigate back to that task/activity or to bring it to the foreground.
After the first home button press, the next home button press brings the 2nd instance of this activity to the foreground. Not sure why not the very first instance's onNewIntent() method is called for the first time... So this only happens once, after that always the 2nd instance's onNewIntent() method is called. This means that the original activity will be not accessible..
I tried to bring the task to the foreground, nothing was happening... Like if it never existed (but the task is there with the activity, it is not killed at any point). I can find the task from code and also using a shell script. It contains the original activity
This is happening on Android TV (Os: Pie). Any idea what can be the reason for this? I do not really understand how this is happening... BTW the result is the same if I set the activity to singleInstance.
The activity looks like this:
<activity
android:name=".activities.MainActivity"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:theme="#style/AppTheme">
<intent-filter android:priority="2">
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.ALL_APPS"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
I tried alternating the above attributes (priority, excludeFromRecents, taskAffinity), also removed them completely, they had no effect...
The home button press sends the following intent:
action: "android.intent.action.MAIN"
category:
"android.intent.category.HOME"
component: the above activity
it has also some extras but I do not think it is relevant
You are experiencing this nasty long-standing Android bug:
Re-launch of Activity on Home button, but...only the first time
You say in a comment that it doesn't happen with real users. That is not actually true. If a real user would install your app from the Play store and then launch it immediately (click the OPEN APP button after installation) then the problem would be reproduced exactly as you describe it.
I was struggling with the exactly same issue for the last couple of hours and I've read many similar Q&A about this topic/bug on StackOverflow. No solution really worked for me until, out of mere curiosity, I did the following.
If you're building a launcher and using onNewIntent() in your MainActivity (although OP doesn't mention that he's using this method), then simply comment out this line:
super.onNewIntent(intent);
Uninstall your app and install it again.
I don't know how this works, but EVEN when you then uncomment the very same line, it still behaves in a proper manner, that is: the app has really only single instance of its main activity all the time. And how I know that? My MainActivity is doing some database operations, and previously I saw in my Logcat that these operations were done twice every time, but now they are done only once.
And BTW my MainActivity tag in AndroidManifest.xml is nothing special:
<activity
android:name=".activities.MainActivity"
android:exported="true"
android:excludeFromRecents="true"
android:launchMode="singleTask">
<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" />
</intent-filter>
</activity>

Why do activities have their own Icon?

Is there a specifici reason why if I have MainActivity, it has it's own Icon, yet if I create SecondActivity it has a separate icon? If I download an app from the Play store it's all from one icon. Am I just being dumb? Or is there a specific reason why this is. Thanks so much!
Any activity that declares the following intent filter will have an icon in the system's app listing:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
If you only want one icon then only put this intent filter inside your main activity.
Each activity can be launched independently - and thereby can have its own icon - in the Launcher. Also, I think in later APIs, the icon can be displayed inside the Activity itself.

Child Activity gets killed after parent activity is finished

I have 2 apps, one of them is calling an activity from the second one through an intent filter like so:
Call in App1 (Parent app)
Intent openApp = new Intent("com.app.intent.Activity2");
startActivity(openApp );
Intent filter in App2 (child app)
<activity
android:name=".app.activity.Activity2"
android:label="#string/app_name"
android:launchMode="singleInstance"
>
<intent-filter>
<action android:name="com.app.intent.Activity2" />
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
At one point the Parent application has to close but the problem is the Activity2 from the second application gets killed as well. I can see that Activity2 is actually running under the same package, is there any way to have the Activity2 persist and run even after the parent applicaiton is closed ?
Thank you
This discussion seems to have what you need. Seems like you need to get the launch intent from the package you want to launch and use that in your intent.
Launch an application from another application on Android
Android will generally run all components from the same APK in a single process, so if one of those crashes the process then they will all be gone.
You can however tell it to put an activity or service in its own process.
<activity
android:name=".app.activity.Activity2"
android:label="#string/app_name"
android:launchMode="singleInstance"
android:process=":my_unique_process">
Of course if your process is dieing unexpectedly, that's a problem that needs to be understood and fixed - this would just be a temporary workaround.

How can I make sure Android Beam doesn't start a new instance of my 'singleTop' activity?

First, the use case : 2 phones have my app opened on the same screen. I want one user to be able to share the screen content (data) with the other one without necessarily opening a new instance of the activity when beaming using NFC.
(both Android devices are running Ice Cream Sandwich)
So I have a singleTop activity declared like this in the manifest.
<activity android:name=".activity.MyActivity" android:configChanges="orientation|keyboardHidden" android:launchMode="singleTop">
<intent-filter android:label="#string/activityLabel">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="a.b.c/x.y.z" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/x.y.z"/>
</intent-filter>
</activity>
When a VIEW action is fired and the activity is already on top, the onNewIntent() method is called in the same instance if the activity.
When a NDEF_DISCOVERED action is fired and the activity is already on top, the onCreate() method is called in a new instance of the activity.
You describe the case that the app is already open and the proper Activity is in the foreground. In that case, you can make use of the foreground-dispatching of NFC intents by calling NfcAdapter.enableForegroundDispatch() in your Activity's onResume() (and disableForegroudDispatch() in onPause()). This will force all NFC Intents to be delivered to your Activity (via onNewIntent()).
I don't have an answer for you. But I have a workaround: have the NDEF_DISCOVERED start a new activity. Make that activity invisible (Theme.NoBackground) and in the onCreate, make it start the MyActivity with singleTop and finish immediately. MyActivity should now appear with onNewIntent.
Have you looked at the Android Beam sample:
http://developer.android.com/resources/samples/AndroidBeamDemo/index.html
It implements this behavior that you want (minus VIEW intent filtering). I'm not sure if that intent will affect the NDEF_DISCOVERED one, but it would be interesting to maybe modify the Android Beam sample to see if you can cause the same behavior as your app.
You should use: android:launchMode="singleInstance"
Works for me.

How to launch a Android Service when the app launches?

I'm still fresh to Android and Id think the below config works for launching my service when the app launches.
<service android:name=".PlaylistUpdaterService">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</service>
But this is not the case. What did I miss?
Wrong! extend the Application class (IE make your own), then in the onCreate() method do this.
//Service is below
Intent serviceIntent = new Intent(getApplicationContext(), PlaylistUpdaterService.class);
startService(serviceIntent);
And take that intent filter crap out of your declaration in the manifest file. Leave it as
<service android:name=".PlaylistUpdaterService">
The intent filter following needs to be in your home activity only
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
The reason you do this is because the Application class is started up as soon as the app is, and acts as kind of a global class the the android framework manages.
Actually if you want the service to run every time you go back to your home screen, you should start the service in your home classes onResume(). Putting it in the applications onCreate() will only start the service if the user is launching for the first time, or after the running process has been killed. Or you could put it in your home classes onCreate() but that is not even guaranteed to run every time.
Correct me if I am wrong, but android.intent.category.LAUNCHER is valid only for Activity. So, does not look like valid way to start Service. The same you can achieve if you do the following:
create transparent Activity that will be used only to start Service
for that Activity, you do not need to specify GUI layout. So, you do not need to setContentView() in the activity's onCreate(). The only thing you need is to put
#android:style/Theme.NoDisplay
under Theme tag for this Activity in AndroidManifest.xml.
start Service from onCreate() of your Activity.
call finish() in onStart() of your Activity to close it.
So, your Activity will be invisible to the user, last shortly and nobody will notice that it was used to start the service.

Categories

Resources