I have am alarm manager through which i set a time to trigger on it by providing a broadcast receiver, onReceive method of broadcast receiver calls successfully but any idea how to launch app from onReceive if app is not running in foreground?
Menifest
<receiver
android:exported="true"
android:name=".AlarmReceiver" />
BroadcastReceiver
#Override
public void onReceive(Context context, Intent intent)
{
Intent scheduledIntent = new Intent(context, MainActivity.class);
scheduledIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(scheduledIntent);
}
MainActivity
AlarmManager alarmManager=(AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent=new Intent(this,AlarmReceiver.class);
PendingIntent pendingIntent=PendingIntent.getBroadcast(this,1000,intent,0);
alarmManager.set(AlarmManager.RTC_WAKEUP,timeInMillis,pendingIntent);
Kindly help
Thanks
It is basically a radio music stream using exoplayer , what we need is user set a time on which he want it to play , and when that time comes stream start playing automatically .
A background service will only run for one minute on Android 8.0+. For a music player, you will want a foreground service, where the associated Notification gives the user playback controls (e.g., pause, resume, stop).
First, you should use workManager
Also, Brodcastreciver has limits on different android versions doc
Related
I'm working on an audio app utilizing exoplayer in a foreground service to allow the audio to play with the screen off. This appears to work as intended, but somewhere I read something about adding Wake Locks.
Is that something that would be necessary with a foreground service? The Wake Lock is used to keep the CPU awake, but the foreground service seems to do that while the service is playing.
I decided to test it on the way to work and it played audio with the screen off for +20 minutes without problems. I assume ~20 mins would be long enough for the OS to shut something down without a wake lock.
Yes, Wake lock is used when you start the service again after the device has been rebooted or when the service is killed.
Use it like this:
Create BroadcastReceiver for receiving the broadcast to start a service.
public class AutoStart extends BroadcastReceiver {
LocalReceiver localReceiver = new LocalReceiver();
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Intent intent2 = new Intent(context, YourService.class);
if (Build.VERSION.SDK_INT >= 26)
context.startForegroundService(intent2);
else
context.startService(intent2);
localReceiver.startMainService(context); //It will create a receiver to receive the broadcast & start your service in it's `onReceive()`.
}
}
}
Register that receiver in the Manifest with ACTION_BOOT_COMPLETED intent-filter.
<receiver android:name="com.demo.service.service_manager.AutoStart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Now we have created the receiver which will receive a broadcast only one time when the device is rebooted. So we have to use wakelock manager to keep the register our service within a limited time.
Now, create the broadcast receiver which will be used to receive the broadcast to start the service.
public class LocalReceiver extends BroadcastReceiver {
PowerManager.WakeLock wakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).wakeLock(PowerManager.PARTIAL_WAKE_LOCK, ":YourService");
wakeLock.acquire(60 * 1L); //It will keep the device awake & register the service within 1 minute time duration.
context.getPackageManager().setComponentEnabledSetting(new ComponentName(context, YourService.class), 1, 1);
playMusic(); //Play your audio here.
wakeLock.release(); //Don't forget to add this line when using the wakelock
}
Now create a method in LocalReceiver to send the broadcast to start the service.
public void startMainService(Context context) {
PendingIntent broadcast = PendingIntent.getBroadcast(context, REQUEST_CODE, new Intent(context, LocalReceiver.class), 0);
}
That's it! We've successfully implemented the wake lock. Now, whenever you want to play a sound. Just send the broadcast to the LocalReceiver & it will get your job done.
Also, don't forget to register this receiver in the Manifest as well as add android:enabled="true" and android:exported="true" where you register your service in Manifest.
<receiver android:name="com.demo.service.service_manager.LocalReceiver">
NOTE : We have used playMusic() inside the onReceive(). So it will also play the audio when the device is rebooted & the service will be registered. If you just want to bind the service on reboot, then you can simply add startService() method inside the onReceive() instead of the playMusic().
I have an application which in turn runs a foreground service. The application has a start/stop button as part of its notification which as can be guessed starts and stops the foreground service. Upon clicking on the start button a Pending Intent gets triggered.
Consider the following scenario:
The application has been destroyed [removed from the recent items list] but the notification is still visible.
I am able to start and stop the foreground service even when the app has been destroyed, as on clicking the notification button triggers a Pending intent (which in turn call a broadcast receiver).
But, what I have observed is that after a day or two, upon clicking the buttons on the notification the pending intent is not triggered (that is the foreground service does not start). This begs the question, does pending intent have a lifetime after the encompassing application has been destroyed? Or am I missing something else here?
My pending intent call:
Intent notificationBroadcastIntent = new Intent(this, MyBroadcastReceiver.class);
PendingIntent playIntent = PendingIntent.getBroadcast(this, MY_REQUEST_CODE,
notificationBroadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
The Broadcast Receiver called by the pending intent (which in turn starts the foreground service):
#Override
public void onReceive(Context context, Intent intent) {
Log.i(MyBroadcastReceiver.class.getSimpleName(), "MyBroadcastReceiver called to update service notification");
if (isMyForegroundServiceRunning(MyForegroundService.class, context)) {
Intent stopIntent = new Intent(context, MyForegroundService.class);
stopIntent.setAction(STOP_SERVICE_ACTION);
context.startService(stopIntent);
} else {
Intent startIntent = new Intent(context, MyForegroundService.class);
startIntent.setAction(START_SERVICE_ACTION);
context.startService(startIntent);
}
}
PendingIntents do not expire. However, they are not persistent and will not survive a reboot of the device.
To see if the PendingIntent still exists, you can use the following adb command:
adb shell dumpsys activity intents
This lists all of the PendingIntents in the system. You can also look at the notifications using:
adb shell dumpsys notification
This will show all Notifications, including the PendingIntents that are set for them.
This is my requirement.
I have an application which can be force kill by user. I want this application to receive broadcast from other app to execute some task even it is forced kill.
I am trying to make another app with service which will send a broadcast in event 1 mins to my first application.
My first application should receive this broadcast even it is forced kill.
This is what I am trying to do.
in First app:
BroadcastReceiver dummy = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.e("broadcast Received","broadcast Received");
}
};
IntentFilter filter = new IntentFilter("com.action.blockapp");
registerReceiver(dummy,filter);
In my second app.
Intent intent = new Intent("com.action.blockapp");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.setPackage("com.example.myapplication2");
sendBroadcast(intent);
I am not able to receive the broadcast when my app is forced kill.
Please suggest.
My point . You need to declare revice in the service running in the background. Your specific revice declared in the manifest<receiver android:name=".service.NotifyReceiver" />
</application>
When the service is run. You can get notifications from revice like below
Intent intent1 = new Intent(context, NotifyReceiver.class);
intent1.setAction(action);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
Hope to help you!
You have registered your BroadcastReceiver dynamically, in code. When your app is force stopped, that code is no longer running and your BroadcastReceiver no longer exists. It is no longer registered.
You will need to create a proper class that extends BroadcastReceiver and create a manuifest entry <receiver> for that with an <intent-filter> that matches the broadcast Intent you are broadcasting.
I have a situation in my application. I am calling a service using an alarm. The alarm wakes up every 5 min and calls the service.
But it may so happen that the user might close my app and I am allowing the functionality of the service to work even if the user is not using my app.
To stop the service there are two ways either the user comes back to the app and presses a button which will cancel the alarm OR the second way is say after x time I want to stop the service i.e cancel the alarm from a broadcast receiver.
Now how can I do the second way ? When I tried to get reference of the AlarmManager it is giving me error of Null Pointer. (I am accessing this alarm manager from a broadcast receiver)
Can anyone give me suggestion on how to cancel repeating alarms from outside the activity context ?
Thanks :)
You can stop your service like this
context.stopService(new Intent(context, YourService.class))
Also in order to cancel the alarm you can do this
Intent intent = new Intent(this, YourClass.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 1253, intent, PendingIntent.FLAG_UPDATE_CURRENT| Intent.FILL_IN_DATA);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
I hope this might help you
In your BroadcastReceiver try this:
public void onReceive(Context context, Intent intent) {
context.stopService(new Intent(context, YourService.class));
}
I have a Service that uses a custom Connection class (extends thread) to a hardware controller. When the User prefers, I wish to maintain this connection on a permanent basis. I already have the code to handle when the Android device loses its internet connection, switches between wi-fi, etc.
In order to stay connected, the controller requires that you speak to it within every 5 minutes. I currently, within the Connection class start a thread that runs in a while(), and checks the system time and the last time it communicated, and when > 4 minutes it requests a status. For some reason, at different times the communication doesn't occur in time. i.e., occurs after 5 minutes. The Service doesn't die, as far as I can tell but the "Ping" to the controller is late. This doesn't happen when I have the phone plugged into the charger (or debugger). Additionally, the behavior is the same when I move the Service to the foreground.
Does the phone slow down it's processor when it goes to sleep?
Is there a better way?
I'm thinking it's the AlarmManger, but I'm having trouble getting it to work with an inner-class, within the Service. I tried using the API demos as a starting point, but I can't seem to figure out how to get the Broadcast receiver registered. I am trying to register the receiver programmatically, with no changes to the manifest.
public class DeviceConnectionService extends Service {
#Override
public void onCreate() {
Intent intent = new Intent(this, PingConnection.class);
intent.setAction("KEEP_CONNECTION_ALIVE");
PendingIntent sender = PendingIntent.getBroadcast(this,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// We want the alarm to go off 30 seconds from now.
long firstTime = SystemClock.elapsedRealtime();
firstTime += 15*1000;
// Schedule the alarm!
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
firstTime, 15*1000, sender);
// register to listen to the Alarm Manager
if (mPingConnectionReceiver == null) {
mPingConnectionReceiver = new PingConnection();
getApplicationContext().registerReceiver(mPingConnectionReceiver,
new IntentFilter("KEEP_CONNECTION_ALIVE"));
}
}
// ...
public class PingConnection extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (dBug) Log.i("PingConnection", "Pinging Controller");
// do real work here
}
}
}
Does the phone slow down it's processor when it goes to sleep?
The phone shuts down its processor when it goes to sleep. That is the definition of "sleep".
I'm thinking it's the AlarmManger, but I'm having trouble getting it to work with an inner-class, within the Service. I tried using the API demos as a starting point, but I can't seem to figure out how to get the Broadcast receiver registered. I am trying to register the receiver programatically, with no changes to the manifest.
That is an unusual approach for AlarmManager. That being said, since you declined to describe "having trouble" in any detail, it is difficult to help you.
Get rid of getApplicationContext() (you don't need it and really don't want it in this case). I would register the receiver before touching AlarmManager. Before you go to production, please choose an action name that has your package name in it (e.g., com.something.myapp.KEEP_CONNECTION_ALIVE).
Beyond that, check LogCat for warnings.
UPDATE
In your LogCat, you should have a warning from AlarmManager complaining about not being able to talk to your BroadcastReceiver.
Replace:
Intent intent = new Intent(this, PingConnection.class);
intent.setAction("KEEP_CONNECTION_ALIVE");
with:
Intent intent = new Intent("KEEP_CONNECTION_ALIVE");
and you may have better luck.
you can't register AlarmManager in a Service.
All you can do is declare it as global in the Manifest.xml.
You can start the alarm from service in this way, by declaring it in Manifest.xml
If you have a remote service and you close the launcher activity, the AlarmManager will still run, but don't forget to stop it on onDestroy() method of the service.
I've tried to register only in the Service the AlarmManager as I didn't used it for the main activity, but no success!
It didn't work as registering as a normal BroadCastReceiver.
that's how the things are, you have to declare it in Manifest.xml as global
I know it's late, but maybe it's useful for someone else.
You can register it, the problem is when the Intent tries to call it.
Instead of calling it like this:
Intent intent = new Intent(this, PingConnection.class);
Create an empty intent and add an action you are going to listen to:
Intent intent = new Intent();
intent.setAction("value you want to register");
Then create the pending intent and send the broadcast like you have it.
Create an attribute for the receiver so you can access it in the whole class and unregister if necessary (if the pendingIntent is also an attribute you can unregister any time):
private PingConnection pingConnection = new PingConnection();
Register it like this:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("the value you used before");
getApplicationContext().registerReceiver(pingConnection, filter);
Now you won't get any errors, and the class is not static, and it's an inner class.