I have two activity activityA and activityB.
activityA is starting a background process and mean while it will also start activityB
background process started by activityA will finish after sometime. Is it possible to notify activityB when process is finish by activityA if activiyB in foreground and activotyA is background.
Yes it is definitely possible and LocalbroadcastMaanager is a good choice here is how you do it.
In the long running process, write this at the end of the process
LocalBroadcastManager.getInstance(context).sendBroadcast(
new Intent("backgroundProcessCallBack"));
And in your activity you should have this (inside oncreate):
LocalBroadcastManager.getInstance(context)
.registerReceiver(mTaskListener, new IntentFilter("backgroundProcessCallBack"));
where mTaskListener is a class level variable (BroadcastReceiver):
private BroadcastReceiver mTaskListener = new BroadcastReceiver() {
#Override
public void onReceive(Context cxt, Intent intent) {
// Do you stuff here. You got the callBack in your activity
}
};
then unregister this receiver in activity's onDestroy() method.
You cannot have two activities running at the same time.
If your background process runs in a Service, you can subsribe to broadcasts in Activity A and in Activity B.
When the work in Service is finished, it sends broadcast - and whatever Activity (A or B) is in foreground - it will receive a Broadcast.
Sample code here: Programmatically register a broadcast receiver
Related
I am trying to create an application that calls the sender of an SMS as soon as the smartphone receives an SMS.
This is my code:
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
// ... (Managing SMS)
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:" + sender));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
}
But it dials and calls the sender only when the application is in foreground, while I'd like it to work always. Using the debugger, the execution flows, but it is unable to start the ACTION_CALL activity somehow. Am I missing anything? Thank you very much in advance
Since Android 10, there are limitations on when/how background processes (Service, BroadcastReceiver) can launch activities. This is your problem.
See this guide for more details.
while I'd like it to work always
That is not an option on modern versions of Android. You cannot start an activity from the background, because you do not know what is going on in the foreground at the time. For example, if the user is relying on a navigation app for driving, taking over the foreground could cause the user to crash.
You could raise a high-priority Notification instead.
I am trying to update my homescreen widget when there is a Do not Disturb change. Because WidgetProvider is a BroadcastReceiver in itself, I thought it would be simple. But I am not seeing any Toast when I switch Dnd on or off. Does it mean that the WidgetProvider can only send broadcasts but not receive them?
Here is my code:
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
String action = intent.getAction();
assert action != null;
if (action.equals(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED)) {
System.out.println("Success!");
}
}
You do not show how you are registering for that broadcast. If it is in the manifest, the broadcast that you are trying to receive is not listed on the implicit broadcast exceptions "whitelist", so you may not receive it on Android 8.0+. The only way that you would be able to receive that broadcast on Android 8.0+ is if you have a foreground service running all the time, and that has costs.
Also:
I am not familiar with that specific broadcast and so I am uncertain if it is sent on a DND change (though it certainly seems plausible)
You are not showing a Toast; instead, you are printing a message to stdout, which should get redirected to Logcat on Android
I have a service which controls my mediaplayer object and when i close my app, a notification is still shown to control playback.
Now when a song is done playing i want update the UI in my activity and i did this with a broadcastreceiver, but this only works when my app is visible and not in the background/closed. (unregistered broadcastreceiver in onPause)
But how do i keep listening for these events when my application is not visible and when the user opens my application again it has the updated UI (new song).
Service
#Override
public void onCompletion(MediaPlayer mp) {
Log.d(TAG, "OnCompletion called!");
Intent broadCastReceiverIntentUpdateSong = new Intent(Constants.ACTIONS.BROADCAST_UPDATE_SONG);
sendBroadcast(broadCastReceiverIntentUpdateSong);
}
When your app starts, it should ask the Service for the current state of the player and show that.
While the app is running and in the foreground, it can listen for the broadcast events and update the UI (or its own internal state) accordingly.
When your app goes to the background, it doesn't need to do anything. When it comes again to the foreground (in onResume()) it can again ask the Servicefor the current state of the player.
You can have the Activity bind to the Service and use AIDL to get the current state OR you can just call startService() with an Intent that contains an ACTION or an EXTRA that indicates that you want to know the current state, and the Service can ract to that by sending a broadcast Intent containing the current state, which your Activity can listen for.
Suppose I have one activity , MainActivity and one service MyService in my android studio project.
MainActivity.class
Toast.makeText(this,"Point 1",Toast.LENGTH_SHORT).show();
startService( new Intent(this,MyService.class) ) ;
Toast.makeText(this,"Point 3",Toast.LENGTH_SHORT).show();
MyService.class
Toast.makeText(this,"Point 2",Toast.LENGTH_SHORT).show();
The flow of execution is Point 1 -> Point 3 -> Point 2 & not 1->2->3
Since service runs in main ui thread only , so what actually happens in background ? since all 3 points execute on same thread .
EDIT:
What can I do to make execution like 1->2->3 ?
Using a static variable in MyService(and setting a value there) and importing that variable in MainActivity to check if service has been started successfully ,doesnt work( causes ANR- reason: Starting .MyService ).
In MainActivity
while(! staticvar.hasBeenSetInMyService){ }
It gets stuck in endless while loop . So is the static variable never updated in MainActivity or MyService's onStartCommand() doesnt get executed ??
There are several ways to let components exchange information. In your case, the Activity could register a BroadcastReceiver with the LocalBroadcastManager before starting the Service.
private BroadcastReceiver myReceiver = new BroadcastReceiver(){
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Received broadcast from Service",Toast.LENGTH_SHORT).show();
MainActivity.this.doPointThree();
}
}
The Activity has to register and (never forget!) unregister the BroadcastReceiver, but I won't go into details here and link instead to this post on Stack Overflow.Let's just assume the BroadcastReceiver will be registered with an
IntentFilter if = new IntentFilter();
if.addAction("your.package.com.POINT_2");
The Service on the other hand can send a local broadcast once it has reached "Point 2".
Intent intent = new Intent();
intent.setAction("your.package.com.POINT_2");
LocalBroadcastManager.getInstance().sendBroadcast(intent);
This local broadcast will trigger the BroadcastReceiver's onReceive()
Please note that I'm talking about local broadcasts as opposed to system wide, inter-app broadcasts. Local broadcasts are easy on the system and totally private to your app.
I have a service which plays music when the page is loaded, and carries on to all the other pages as it should. It still played when the application was destroyed, so i put a onDestroy method and an onResume method.
#Override
public void onDestroy(){
super.onDestroy();
Intent ServiceMusic = new Intent(this, BackgroundMusic.class);
stopService(ServiceMusic);
}
#Override
public void onResume(){
super.onResume();
Intent ServiceMusic = new Intent(this, BackgroundMusic.class);
startService(ServiceMusic);
}
Now the problem is when the user clicks the home button the service carries on, so I implemented a onPause and it worked fine, just when the user goes to another page the music restarts.
#Override
public void onPause(){
super.onPause();
Intent ServiceMusic = new Intent(this, BackgroundMusic.class);
stopService(ServiceMusic);
}
How can i overcome this so the music carries on playing when going through the application but when the Home Button is clicked i pause the service?
I would remove the code that is in individual activities and use the registerActivityLifecycleCallbacks mechanism in your application subclass. This will allow you to keep the code in one place and be smarter about starting and stopping your service.
Be aware that with these callbacks, you'll be notified that an Activity has stopped before another activity has started, so you will need some kind of delay when you decide to stop your service. You can use a handler with a delayed runnable to account for this issue.
https://developer.android.com/reference/android/app/Application.html#registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks)