Start only one service on smartphone startup or application launch - android

I'm using NativeScript, just so you know, targeting Android to begin with.
I've been trying to read up on this, but it's just impossible to understand. The Android documentation coupled with all the other answers on SO are just incomplete. I have been at this for days.
Application Purpose
I want my application to do something when a new SMS is received, whether or not the user is in the application, has the application alive but not in the foreground of if the application is not even alive.
Chronological Order
User turns smartphone on.
User downloads application.
User opens application for first time.
The application should now after opening the application should work and do something whenever a SMS has come in, regardless if the user is in the application, has it alive but not in the foreground of has killed the application or even when the smartphones screen is off and the lock is on.
User has forgotten to charge smartphone so smartphone dies, the user charges the smartphone and turns the smartphone on.
The application should immediately start to work on BOOT, doing something if a new SMS is received without having to open the application.
I have yet to find information on how to solve the above situation, in a simple example.
I don't mind the service (I presume I need) being on the main UI thread for now.
What I Have Tried
Manifest:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name="com.tns.NativeScriptApplication"
android:allowBackup="true"
android:icon="#drawable/icon"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<activity
android:name="com.tns.NativeScriptActivity"
android:label="#string/title_activity_kimera"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|locale|uiMode"
android:theme="#style/NoActionBar">
<meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="#style/AppTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.tns.ErrorReportActivity"/>
<receiver android:name="io.basickarl.passer.ServiceStarter">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<service android:enabled="true" android:name="io.basickarl.passer.SMSService" />
</application>
I keep seeing the following things and they are always used differently from each other, and still, it is not clear how to use them:
Service
IntentService
JobIntentService
JobScheduler
JobService
How do I start this service only once when starting the application for the first time like in chronological step 4, preventing this service being started several times and that it works and is listening for incoming SMS's all the time?

https://developer.android.com/guide/topics/manifest/receiver-element.html
android:enabled
Whether or not the broadcast receiver can be
instantiated by the system — "true" if it can be, and "false" if not.
The default value is "true". The < application > element has its own
enabled attribute that applies to all application components,
including broadcast receivers. The < application > and < receiver >
attributes must both be "true" for the broadcast receiver to be
enabled. If either is "false", it is disabled; it cannot be
instantiated.
Since in both places it is true by default the system should register the broadcast receiver by default. I don't need a service.
android:exported
messages from sources outside its application — "true" if it can, and
"false" if not. If "false", the only messages the broadcast receiver
can receive are those sent by components of the same application or
applications with the same user ID. The default value depends on
whether the broadcast receiver contains intent filters. The absence of
any filters means that it can be invoked only by Intent objects that
specify its exact class name. This implies that the receiver is
intended only for application-internal use (since others would not
normally know the class name). So in this case, the default value is
"false". On the other hand, the presence of at least one filter
implies that the broadcast receiver is intended to receive intents
broadcast by the system or other applications, so the default value is
"true".Whether or not the broadcast receiver can receive
I needed to set it to true on the receiver.
Manifest:
<application
android:enabled="true"
...more code
<receiver
android:name="io.basickarl.passer.HandleSMS" android:exported="true" android:enabled="true">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
Code:
android.content.BroadcastReceiver.extend('io.basickarl.passer.HandleSMS', {
onReceive: async function(context, intent) {
// ...do my stuff here
}
});
Now the code runs when the application is killed or straight after a reboot.

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

How to start my application on phone shutdown event

I am making an android app, in which the app must launch just before the phone is shutting down. Is that possible?
Here i am not talking about encountering phone shutdown event when my app is running.
You will need this permission in your manifest file
<uses-permission android:name="android.permission.DEVICE_POWER" />
And you will listen to the intent like this
<receiver android:name=".ShutdownReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
</intent-filter>
</receiver>
You can look at the links here for some description and here for official documentation.
I don't know the exact application where you want to use it, but you can have a background service running with the receiver for this intent.

Does android:exported="false" restrict system calls/access?

I know that setting android:exported="false" will restrict other applications from using/accessing my application components.
Does setting this attribute will restrict the system as well from using/accessing my components? i doubt.
for example, i have the following receiver:
<receiver
android:name="ConnectivityManager"
android:label="NetworkConnection"
android:exported = "false" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
The receiver is still receiving broadcasts from the system once the connection state changes (on/of).
Does this mean that the system calls/access can never be stopped? Please illustrate.
Google‘s online document does not describe this clearly.
From the real result, the receiver can still be triggered by system broadcast even if set exported="false".
Yes, if exported="false", it will still respond to system broadcasts such as connectivity changes. This is easy to test by using your above broadcast-receiver and toggling airplane mode

Proximity Alerts not working after phone reboot

I am using proximity alerts in one of my applications, however it seems that whenever I reset my phone (via battery pull) or just in general, the proximity alerts are no longer active.
The only way they work once again is if I uncheck and recheck the checkbox (which removes, then re-adds the proximity alert)
Any idea's or reason?
You must reset the alerts. The Android OS does not persist your alerts when rebooting, that's up to your app. Create a BroadcastReceiver (I called mine BootReceiver in my example below) to handle the "android.intent.action.BOOT_COMPLETED" action (this is defined in the manifest). With the BroadcastReceiver you can then restart all of your alerts. Don't forget to add the "android.permission.RECEIVE_BOOT_COMPLETED" permission.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

Restrict Broadcast Receiver to application

I am working on broadcast receiver and stuck in a problem.
I am receiving a broadcast receiver in Manifest file.
<receiver class=".MyClass" android:name=".MyClass">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.ConnectivityManager.CONNECTIVITY_ACTION" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
</receiver>
this is working fine and it is calling MyClass whenever there is change in connectivity.
Now the problem is whenever my application is not running still this class will receive broadcast receiver. I want it to receive whenever the application is running.
I tried it by extending BroadcastReceiver registering and unregistering broadcast in that class file and it works. But i want to achieve the same by Manifest file.
My problem will solve if it is not receiving anything when application is not opened.
What you are talking is not possible. The whole purpose of having the intent filter in the manifest is being able to receive the intent whether or not your application is running. The only way to do what you want to is by registering/unregistering the receiver from the code [registerReceiver]
The question was asked a long time ago but in case some one landed on this page while searching, It is possible to register and unregister broadcast receiver from code instead of doing that from manifest file. (Checking the Networking Connectivity using BroadcastReceiver in Android)
You said "My problem will solve if it is not receiving anything when application is not opened".
Here how I understand your question and appropriate answer.
android:enabled
Whether or not the broadcast receiver can be instantiated by the system — "true" if it can be, and "false" if not. The default value is "true".
If you want to enable your receiver at runtime, you can set the state to disabled initially. You can do so in the manifest file:
<receiver
android:name=".YourReceiver"
android:enabled="false" >
<!-- your intent filter -->
</receiver>
Source:
http://developer.android.com/guide/topics/manifest/receiver-element.html#enabled
http://www.grokkingandroid.com/enabling-and-disabling-broadcastreceivers/

Categories

Resources