Is there a way for Android application to detect how it is being launched? whether by a BOOT or by user launching the application from the application list?
When my application is launched on boot I don't want any activity to show at all. When the user specifically launches it from the application list, then and only then would I want the main activity to show. If I could detect whether the launch was a user launch or system boot launch I might be able to control this.
What you're looking for is the Intent that started the application. In the manifest file of your Android project you can specify which Intents will launch which Activities. The documentation page for Intent actually has a really thorough explanation of how to use this feature, with example code and everything:
http://developer.android.com/reference/android/content/Intent.html
The Intent that will be called when a user selects your application from a launcher will look like:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
If you want a different Activity to launch when the phone boots (there's an intent filter value "android.intent.action.BOOT_COMPLETED"), you just add a different IntentFilter to the Activity's tag in the manifest.
Related
I want to launch my Flutter Android App automatically, after an Ndef Tag has been discovered. I'm using an Intent filter to achieve this.
All works fine, apart that when launched via the Ndef Tag, the App has an Nfc App Icon.
Also, if the app was already opened manually before, it will have the App open twice:
a) The manually opened one with the correct logo
b) The Ndef Tag launched one
Screenshot with two instances of the app:
To exclude any side effects, I did a new Flutter project from scratch and only did the following changes in ...\android\app\src\main\AndroidManifest.xml:
Added this right after the <manifest> tag:
<uses-permission android:name="android.permission.NFC"/>
And after the existing
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
I added this filter to launch the app:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="https" android:host="developer.android.com" android:pathPrefix="/test" />
</intent-filter>
The Nfc Tag only has one record of type Uri, with the content https://developer.android.com/test
How can I avoid the app clone, and just always open the same App instance with the correct App logo?
To rely on the basic intent nfc functionality you need to add android:launchMode="singleTop" option to the Activity with the NFC intent filter in the Manifest.
From the docs
the "standard" and "singleTop" modes differ from each other in just one respect: Every time there's a new intent for a "standard" activity, a new instance of the class is created to respond to that intent. Each instance handles a single intent. Similarly, a new instance of a "singleTop" activity may also be created to handle a new intent. However, if the target task already has an existing instance of the activity at the top of its stack, that instance will receive the new intent (in an onNewIntent() call); a new instance is not created
As standard is the default launchmode then a new instance of the Activity is created when the NFC is scanned every time, hence multiple instances.
With singletop it will re-use one that is at the top of the stack BUT you will have to handle the processing the data in the onNewIntent method as well as where you are processing it now.
Using the method does have the downside that your App with be paused and resumed to receive the NFC data, so your App has to pause and resume correctly. It is generally better to use one of the Foreground NFC methods like enableReaderMode instead of the basic intent methods, for Flutter there are various flutter packages to do this.
This question may seem a trivial but I've been struggling with it.
I'm trying to start a service on boot and everything works fine if I start it at least once from the mainActivity (launch activity), something like:
AndroidManifest.xml
...
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
<activity
android:name="com.example.mainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.example.bootReceiver" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<service android:name="com.example.someService" android:enabled="true" android:exported="false"/>
...
bootReceiver.java
...
startService(new Intent(getApplicationContext(), com.example.someService.class));
...
mainActivity.java
...
startService(new Intent(getApplicationContext(), com.example.someService.class));
...
With the above code I'm able to run the service after every boot without any problems.
As a POC, I'm trying to start a service without any activity, or at least without the mainActivity, just by declaring the service on the AndroidManifest.xml or by creating new activity (invisible?) that is launched at the same time as the default launcher activity.
As far a I know, this isn't possible on android 3+ (4+?) due to security reasons.
Is there any way to achieve this ?
Can I start 2 activities from the AndroiManifest.xml when the user launches the app?
I'm sorry if my question isn't 100% clear, I've tried to explain it the best I could, if you cannot understand it, please leave a comment bellow. Tks.
As far a I know, this isn't possible on android 3+ (4+?) due to security reasons.
Android 3.1, actually, to help prevent drive-by malware.
Is there any way to achieve this ?
Something has to use an explicit Intent to invoke some form of IPC on one of your components, to move the app out of the so-called "stopped state" that is preventing you from receiving the broadcast. So, something needs to either:
start one of your activities via an explicit Intent, or
start one of your services via an explicit Intent, or
send a broadcast to one of your receivers via an explicit Intent
(I don't know if trying to connect to a ContentProvider will work, though arguably it should)
The key is the explicit Intent. That's why invoking an activity from a home screen launcher works, because the Intent used to start your activity will be an explicit one.
However, in the absence of such an activity, you would need to find something else that would use an explicit Intent to invoke one of your components. Certain specialized services (e.g., an input method) probably get invoked with an explicit Intent if and when the user activates that app's capability via the system Settings app. If you're a plugin for some other app, that other app might use an explicit Intent to work with one of your components. You can ask the user to install the Android SDK, learn how to use the command line, and invoke an adb shell am command to start one of your components. And that's about all I can think of off the top of my head. None are exactly general purpose solutions.
or by creating new activity (invisible?) that is launched at the same time as the default launcher activity
I have no idea what you think that would achieve. If the user starts up your launcher activity, you're already out of the stopped state and will receive broadcasts as normal.
i created an android application with no activity. I want to start a service using a system intent like BOOT_COMPLETED. I use the following receiver:
<receiver android:name=".autostart" >
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.SCREEN_ON" />
</intent-filter>
I got the problem, that the intent is not received when power is connected/disconnect or boot completed. Is an Application with no Activity even in stopped mode after install? How can I start the service? UI is not possible because the application has no activity...
Is an Application with no Activity even in stopped mode after install?
Yes.
UI is not possible because the applicatio has no activity...
Then add one. You need one anyway, to present your license agreement, your online help, your configuration for this background processing, and so forth. And, since your app will not run until the user launches this activity, you need to for that reason as well.
Every Android application needs to be launched at least once after installation and only then it will receive any intents from system. This means an application without any gui will not work in your case.
Many applications include only "about" activity, which is a common way to deal with that.
Please see:
http://commonsware.com/blog/2011/07/13/boot-completed-regression-confirmed.html
http://developer.android.com/about/versions/android-3.1.html#launchcontrols
I have an application without launcher activity that works properly from Android 1.5 to Android 2.3.4. It is started by my broadcast receiver. However, on Honeycomb (Motorola Xoom), my broadcast receiver doesn't work at all (it does not catch any intents). If I add launcher activity to my manifest:
<activity android:label="#string/app_name" android:name="com.myapp.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> </intent-filter>
</activity>
Then my app works properly (broadcast receiver catches all necessary intents and starts my services).
I would be very grateful for help!
Are you running Honeycomb 3.1 or above? If yes take a look here.
When your application is installed, it is in stopped state. When the application is first launched, it is moved out of stopped state.
A application in stopped state won't get started by all broadcast intents. The sender of the broadcast intent has to specify the Intent.FLAG_INCLUDE_STOPPED_PACKAGES flag if it wants to launch stopped applications too.
Intent intent = new Intent(MY_INTENT_ACTION);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
sendBroadcast(intent);
If you can't change the code which sends the intent, your best bet would be to keep the launcher activity. Whenever the user launches your application after installation, it will be moved out of the stopped state and you will start receiving broadcasts.
Note the the user can move your application back to the stopped state from Manage Applications in device settings.
On Android 3.1 and higher, BroadcastReceivers will not be invoked until the user has started the application at least once by some other means, such as launching an activity.
Since users tend to get very confused by applications that do not have an activity, you really should have had an activity in the first place, for online help if nothing else. With Android 3.1, that is even more important.
Suppose that I installed app A and app B, app A has a main activity, and app B wants to show that activity by sending a intent. My question is that how android knows I have installed app A and is able to map the intent to its activity? Is there any windows-registry-like store saving such information?
Thank You
I'm also new to android. This is how I understand Intents:
Look in your AndroidManifest.xml. There you define activities and intent filters:
<activity android:name=".Settings.SettingsView"
android:label="#string/settings">
<intent-filter>
<action android:name="at.MyApp.Settings.action.EDIT_TITLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
When you install your App those activities/services/etc get know to Android.
You tell Android, that you are able to provide an activity for "at.MyApp.Settings.action.EDIT_TITLE"
If you start an activity, you create an Intend:
startActivity(new Intent("at.MyApp.Settings.action.EDIT_TITLE"));
Anyone can try to start such an activity/service/etc throw an intent.
If two applications are able to provide some functionality for an intent, Android will ask the user which activity it should use.
That's how I understand Intents. If someone knows better I'll be happy to learn.