How to start service using external intent? - android

I'd like to know if it's possible to start service using intents sent from another app? I've a Broadcast Receiver for android.intent.action.BOOT_COMPLETEDand it works even though at the time when the intent is received BrodcastReceiver class for it is not instancionated. I did something similar for external intents from tasker but it doesn't work.
<receiver android:name="BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

I'd like to know if it's possible to start service using intents sent from another app?
Sure.
I've a Broadcast Receiver for android.intent.action.BOOT_COMPLETEDand it works even though at the time when the intent is received BrodcastReceiver class for it is not instancionated.
That is because manifest-registered BroadcastReceiver objects are not instantiated ahead of time. They are only created when a matching broadcast is sent.
I did something similar for external intents from tasker but it doesn't work.
"it doesn't work" is insufficient information for anyone to help you.
But, if you have a <service> with an <intent-filter>, other apps can create an Intent matching your <intent-filter> and use that to start (or bind to) your service. There are two exceptions:
If you add android:exported="false" to the <service>, third party apps cannot invoke it at all, though you would be better served simply getting rid of the <intent-filter> in that case
If you use android:permission on the <service> element, the other app needs to hold your stated permission in order to start or bind to your service

Related

Android: what's the meaning of exported receiver's attribute?

<receiver
android:name="MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
I don't understand if it's needed to be notified.
If it were true any app could call my receiver with those actions? So If I make it false the system can send the actions to my receiver?
I don't understand if it's needed to be notified. If it were true any
app could call my receiver with those actions? So If I make it false
the system can send the actions to my receiver?
Actually, others apps cannot "call your receiver". Other apps can just send broadcast Intents. The System will then call all registered receivers.
In general you shouldn't worry about this. Most of these broadcast Intents are protected so that only system apps can broadcast them anyway. An attempt by another app to broadcast BOOT_COMPLETED, for example, would just be ignored. What would happen if your BroadcastReceiver gets triggered by a rogue app because it broadcast CONNECTIVITY_CHANGE? Probably nothing, because your app should check the real connectivity state in onReceive() anyway, and if there isn't any change you can just ignore it.
Also, you don't need to specify android:enabled="true" because this is the default state. You also don't need to specify android:exported="true" because you have an <intent-filter> attached to your <receiver> which automatically sets android:exported to true.
If you set android:exported ="false", implies that the receiver is intended only for application-internal use.
Note: This attribute is not the only way to limit a broadcast receiver's external exposure. You can also use a permission to limit
the external entities that can send it messages
Adding to #SaravInfern's answer. Here is the relevant permission doc for limiting external entities that can send the receiver messages:
https://developer.android.com/training/permissions/restrict-interactions#broadcast-receivers

POC - Start Service on boot without an Activity - Android 4+

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.

Difference between intent-filter in activity and broadcastreceiver

can anybody tell me the difference between intent-filter in activity and broadcastreceiver? Thank you very much!
<activity>
<intent-filter></intent-filter>
</activity>
and
<receiver>
<intent-filter></intent-filter>
</receiver>
I register a BroadcastReceiver to listen event of SMS arrives. Now, I want to use intent-filter in activity. Can I do it?
You can certainly have an <intent-filter> for an <activity>. Some do, such as your launcher activity.
However, if you try using the same <intent-filter> on an <activity> that you are using on a <receiver> to "listen event of SMS arrives", that will not work. The reason it will not work has nothing to do with the <intent-filter>, but rather with the Intent.
For inter-process communication (IPC) in Android, we usually use an Intent for one of three things:
starting an activity
starting or binding to a service
sending a broadcast
These are completely independent. You can think of them as three separate channels on a TV, or three separate train tracks.
When an SMS arrives, the system will send out one (or more) broadcasts related to that event. Since they are broadcasts, you can listen for them with a <receiver>. Since they are broadcasts, you cannot listen for them using an <activity> or a <service>.
You are welcome to have a <receiver> call startActivity() to start up an activity, which is almost like having an <activity> directly respond to the broadcast. However, while this is technically possible, it is rarely the right answer, as users usually will not appreciate being interrupted in whatever they are doing by your activity popping up without warning.
When an app starts an activity using an intent, it only starts one activity (possibly showing the "Complete action using..." dialog to let you choose which app you want to open it with), and the same goes for services, but broadcasting an intent may start several broadcast receivers, possibly from different apps.
You can get a more detailed idea here.

BroadcatReceiver declared in manifest.xml not receiving LocalBroadcastManager intents

While it is possible to declare a 'Local' BroadcastReceiver via code so it receives intents published via a LocalBroadcastManager.Ex
LocalBroadcastManager.getInstance(this).registerReceiver(new FooReceiver(), new IntentFilter("foo_intent_filter"));
I wonder if it is possible to declare such receiver via the manifest.xml (cleaner) .
When I use the 'manifest way', the receiver is not 'receiving' the intents.
<receiver
android:name="FooReceiver"
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="foo_intent_filter" />
</intent-filter>
</receiver>
Am I missing something? or the code-way is the only viable solution.
Thanks
I wonder if it is possible to declare such receiver via the manifest.xml (cleaner) .
First, that is not possible.
Second, registering in the manifest has little to do with it being "cleaner". It is to allow Android to instantiate the receiver on its own, so that you can respond to broadcasts when your process is not running. And, in the specific example that you cite, it is to allow any app on the system to send you a broadcast. Neither of those are relevant for LocalBroadcastManager.

Broadcast receiver not receiving intent

I have two apps that I have complete control over. Both are signed with the same cert and both use the exact same intent filter. One sends the broadcast from a fragment, the other is suppose to receive it and do something. This however is not working:
Strings.FILTER_INIT_REGISTER = "com.app.FILTER_INIT_REGISTER"
Intent intent = new Intent(Strings.FILTER_INIT_REGISTER);
getActivity().sendBroadcast(intent);
I have registered the receiver in the Manifest app tag for the app containing the ReportingReceiver class:
<receiver
android:name=".receivers.ReportingReceiver"
android:exported="true"
>
<intent-filter>
<action android:name="com.app.FILTER_INIT_REGISTER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Curious why the ReportingReceiver class is not getting the intent call?
If your application only has a service and receivers then this won't work in Android 3.1 and later. The reason is that the system will not send broadcast Intents to application that are in the STOPPED STATE. An application is in the STOPPED STATE when it is first installed. It is removed from the STOPPED STATE when the user manually starts the application for the first time. It is returned to the STOPPED STATE if the user forces the application to stop using the application manager tool.
Since your application has no Activities, there is no way for the user to "start" it. Therefore it will never come out of the stopped state.
See http://developer.android.com/about/versions/android-3.1.html#launchcontrols
As Android Addict says in his comment to David Wasser's answer ... there is a way around this behaviour.
Just add the following flag to the calling Intent. This will ensure that you also reach broadcast receivers from "stopped" applications.
http://developer.android.com/reference/android/content/Intent.html#FLAG_INCLUDE_STOPPED_PACKAGES
You can read more about this Android 3.1 change here
http://developer.android.com/about/versions/android-3.1.html#launchcontrols
and here
http://code.google.com/p/android/issues/detail?id=18225

Categories

Resources