Sending an intent from broadcast receiver to a running service in android - android

Here is a my broadcast receiver.
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context ctx, Intent intent) {
Log.d(DEBUG_TAG, SmsReceiver.class.getSimpleName()+ " action: " + intent.getAction());
// here is codes for sending intent to my running service
} }
here is broadcast receiver and service nodes in my manifest xml file.
<service android:name=".SMSGatewayService" />
<receiver android:name=".SmsReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
How can i send intent from broadcast receiver to my running service.
thanks in advance.

Ideally, you don't have a running service. Services should only be in memory when they are doing something, and odds are your code won't be doing anything when an SMS arrives.
That being said, your receiver can call startService(). This passes an Intent to onStartCommand() of the service, whether it is already running or not. Ideally, your service is an IntentService, one designed to work with the command pattern and to shut down when it is done processing a command.
Also, since SMS messages can arrive while the device is asleep, you will probably need to employ a WakeLock to ensure the device stays awake long enough for control to pass to the service and for the service to do whatever it is it is doing. One approach for this is to use my WakefulIntentService, which wraps up the IntentService+WakeLock pattern.

Related

BOOT_COMPLETED Broadcast not received when app was killed

I'm stuck at the development of our app. I want to receive the BOOT_COMPLETED broadcast so I can reschedule some Alarms. So I start my app, schedule the alarms and then reboot my device (Android 10). Everything works as expected, ie after reboot, my BroadcastReceiver is started and my alarms are rescheduled.
But if I stop my app before reboot (ie not just put it in background, really kill it), it doesn't receive the BOOT_COMPLETED broadcast anymore ...
I have the respective permissions in my manifest
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
I have the receiver in my manifest enabled with the respective actions
<receiver
android:name=".receivers.CustomBroadcastReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
android:enabled="true"
android:exported="true"
android:directBootAware="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
And this is my CustomBroadcastReceiver class
class CustomBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Log.d(javaClass.simpleName, "onReceive ${intent.action}")
... //reschedule alarms read from SQLite
}
}
I can see the respective Log message after reboot, when the app was running before reboot. But I don't see the log, when the app was killed before the reboot ... Anything I'm missing here?
Yes, I'm aware, there are many other questions regarding BOOT_COMPLETED but they all more or less say, do it like shown above, then it will work. And, well, I know it in principle does work, because I see the receiver being called. But just not, when the app was once killed. If I start the app manually, put it in background and reboot the device, it works as expected ...
Use JobScheduler instead of alarms for this. JobScheduler jobs can be set as persistent across boot, so you don't have to do the bootup wiring yourself.

How chat apps (e. g. Messenger) listen to incoming messages even if their activity haven't been started yet

How chat apps (e. g. Messenger) listen to incoming messages even if their activity haven't been started yet since in android 3.1 and later this is not possible:
Manifest:
<service android:name=".ManagerService" android:enabled="true" />
<receiver
android:name=".BootFinishedReceiver"
android:directBootAware="true"
android:enabled="true"
android:exported="false"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Receiver:
public class BootFinishedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, ManagerService.class);
context.startService(serviceIntent);
}
}
There have to be some way around as chat apps are still working this way.
Thanks for any informations or ideas
Your question is quite open-ended and broad. But to the link that you have pointed about the broadcast receiver when the app is not running.
There is a comment on the same answer that says:
Applications are in a stopped state when they are first installed but are not yet launched and when they are manually stopped by the user (in Manage Applications). That means, the user should launch the app at least once after installation to activate the application, then the app can receive all implicit broadcast from OS as normal.
The app is stopped when it is just installed. As soon as you launch the app for the first time, The application can listen to broadcast receivers and can run background services even when the app is closed.
The chat applications basically implement socket.io that keeps up the communication on both ends. Furthermore, you may implement FCM to get notifications and messages even when the app is killed.
I hope you, understand the concept :).

Android - Is it possible to declare Local Broadcast receiver in the manifest file?

I have declared my receiver in my manifest:
<receiver
android:name=".MyTestReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.ACTION_TEST"/>
</intent-filter>
</receiver>
And here is my MyTestReceiver class:
public class MyTestReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("com.example.ACTION_TEST".equals(action)) {
Toast.makeText(context, "Test!", Toast.LENGTH_SHORT).show();
}
}
}
But when I execute this code from elsewhere within my app:
Intent intent = new Intent("com.example.ACTION_TEST");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
...the local broadcast is not received (i.e., the toast is not shown).
Questions:
Is it possible to register a local broadcast receiver in the manifest?
If so, have I declared my local broadcast receiver incorrectly?
If it's not possible to declare a local broadcast receiver in the manifest, and I declare it in my Application subclass instead, will it have the same 'scope' as a receiver declared in the manifest? (I mean, will it receive broadcasts in all the same conditions/situations as it would if it was declared in the manifest?)
If there is a difference between specifying the receiver in the manifest than in my Application subclass, would I need to use general (non-local) broadcasts rather than local broadcasts? (In the actual app, the local broadcast will be sent when my IntentService completes its work. The IntentService will be triggered by an FCM push message.)
NB - All I can seem to find about this in the documentation is:
Note: To register for local broadcasts, call
LocalBroadcastManager.registerReceiver(BroadcastReceiver,
IntentFilter) instead.
...which doesn't address the main issue of whether or not you can specify the receiver in the manifest.
Is it possible to register a local broadcast receiver in the manifest?
No.
and I declare it in my Application subclass instead, will it have the same 'scope' as a receiver declared in the manifest? (I mean, will it receive broadcasts in all the same conditions/situations as it would if it was declared in the manifest?)
Well, no. A manifest-registered receiver is for system broadcasts, originating from any process. LocalBroadcastManager is local, for "broadcasts" within your own process.
You are welcome to register a receiver with LocalBroadcastManager in your Application (e.g., in its onCreate()), but I suspect that there are better solutions for whatever problem you are trying to solve.
In the actual app, the local broadcast will be sent when my IntentService completes its work
Then the receiver should be registered in the activity or fragment that needs to know about that work being completed. Your Application is unlikely to need to know about that work being completed, as if it did, your IntentService could just call a method on the Application and bypass all this broadcast stuff.

Android start service that continue read incoming messages without app start

i want to make an application in which i start service which start broadcast reciever for sms_read and every time when new sms come and reciever detact that message. no matter app is running or not.
you don't have to use a Service for Reading and listening for SMS.
All you need to Do is just register a Broadcast receiver in your Application like this .
<receiver android:name=".IncomingSms" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
And just write whatever functionality you have to do upon receiving the SMS in the Broadcast receiver by starting an IntentService or a Thread

SMS Receiver as a Service

I have created SMS Receiver app... but i want to create it as an service, it should run in the background (i.e no separate UI for this app, want to work like alarm app) and even if mobile restarts it automatically starts... could any one help on this?
My previous SMS Receiver app code was here
Unable to instantiate activity ComponentInfo in Android Receive Sms App
it should run in the background
Your existing BroadcastReceiver for the (undocumented) android.provider.Telephony.SMS_RECEIVED already runs in the background.
and even if mobile restarts it automatically starts
Your existing BroadcastReceiver for the (undocumented) android.provider.Telephony.SMS_RECEIVED already is available after the device reboots.
If you want your service to run at phone startup, you should simply declare a broadcast receiver with this intent filter:
<receiver android:name="MyStartupIntentReceiver">
<intent-filter>
<action
android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
In the broadcast receiver onReceive() method, just launch your service:
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent();
serviceIntent.setAction("myPackage.MyService");
context.startService(serviceIntent);
}
And be sure to link the service in your manifest with the same name of the intent you launch in the broadcast receiver:
<service android:name="MyService">
<intent-filter>
<action
android:name="myPackage.MyService" />
</intent-filter>
</service>
As CommonsWare has said there is no need to actually have a "Service" run in the background for you to receiver SMS broadcasts, if registered in your manifest properly your BroadcastReceiver with "android.provider.Telephony.SMS_RECEIVED" as the intent filter will fire every time an SMS is received no other action required.
Depending on what exactly you want to do, from that broadcast receiver you can then do you work via an actual Service, or probably a better option would to be to use an IntentService. This is because the thread used for the broadcast will get killed shortly after starting, so you should not do any extensive work in it.
It is generally recommend to not use an actual "Service" unless explicitly required....BUT if that is what you need then you need Davide should get you the right direction.

Categories

Resources