Declaring receivers&services on the manifest - android

My receiver is declared in this way:
<receiver android:name=".receiverName"
android:enabled="true"/>
And here's my service:
<service android:name=".serviceName"
android:enabled="true"/>
But I was wondering: to make them work must I add an <intent-filter> in each one?

to make them work must I add an <intent-filter> in each one?
That depends on what you are using them for.
An <intent-filter> is to allow other apps, or sometimes the operating system, to communicate with your components. That is why you have an <activity> with an <intent-filter> for the MAIN action and the LAUNCHER category — home screen launchers know to look for those and give the user the ability to display those activities.
So, if your plan is to use the service purely within your own app, you do not need an <intent-filter>. The same thing holds true for your receiver. If, on the other hand, you are expecting other apps to start the service, bind to the service, or send you a broadcast, then you will want an <intent-filter>.

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.

Sending a broadcast to an activity that is not in the activity stack

I have an application with many activities.
the application's state is saved by data i receive from the internet- via web service
at one time or another, my webservice will tell me that i need to perform login, after i have already logged in, in the past, and the login activity is not on the activity stack.
I want, when i receive the info to relogin (in http related classes), to send a broadcast to the system, to open the login activity.
where do i need to register this broadcast receiver, as i may be in any activity, when this broadcast arrives ?
If you don't know a priori which Activity will be running when the signal is sent, the best way is defining it in the Manifest file, like this:
<receiver android:name="YourReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
You can register you BroadcastReceiver in AndroidManifest.xml like this
<receiver android:name=".YourBroadcastReceiver" android:exported="false">
<intent-filter>
<action android:name="YOUR_PACKAGE_NAME.INETENT_NAME" />
</intent-filter>
</receiver>
If your broadcast is for handling internal intents only, make sure you declare it as exported false else some other applications can interrupt and open your login anytime just by sending a broadcast.
EDIT :
Here name is the exact path of your BroacastReceiver with package name. If it resides in your main package dot(.) is enough because the reference is taken from package defined inside manifest tag but if it reside in some other package like yourcommonapppackage.broadcastreceiver.YourBroadcastReceiver you have to give the name accordingly.
You can give whether full full with package or with reference to your main package.

How to start service using external intent?

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

Exported service does not require permission: what does it mean?

I created a service that is bound by other applications through AIDL, and I add it to the manifest as follows:
<service android:name=".MyService">
<intent-filter>
<action android:name="org.example.android.myservicedemo.IService" />
</intent-filter>
</service>
where IService is the AIDL interface.
In this way, Eclipse show me the warning Exported service does not require permission. If I remove the intent-filter, the warning disappear, but obviously the applications are unable to bind to the service.
What does this warning mean?
I had the same issue when I updated SDK to version 20. I removed it adding android:exported property android:exported="false" like so:
<service android:name=".MyService"
android:exported="false">
<intent-filter>
<action android:name="org.example.android.myservicedemo.IService" />
</intent-filter>
</service>
See this doc
If you want to restrict you activity usage to your own application, then you should add exported=false to your activity's manifest statement.
If you want to allow other applications to use it (explicitly through its class name or, better, by using an intent with a data type or action) then you have two choices :
restrict those applications by using a permission
allow all applications to use it, then you can add tools:ignore="ExportedActivity" to your activity's manifest statement.
--
Same reasonning applies to a service, with tools:ignore="ExportedService" and content providers with tools:ignore="ExportedContentProvider".
As Jens said, "It means that other (arbitrary) applications the user has on his phone can bind to your Service and call whatever method they please that is exposed through your AIDL interface."

Categories

Resources