How to update activity UI when app is in background/closed - java

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.

Related

StartActivity method from background

The problem seems to be known, but I could not find the right solution.
I will describe the scenario:
There is an application making requests to the API. In some FirstActivity, a request is made to the API, upon positive result of which startActivity () is called in SecondActivity. The problem is that if, while sending the request, the application is minimized to the background (that is, startActivity () will be called in the background), then:
If android version> = 29 then startActivity () basically won't work. The one following startActivity () finish () will work and upon restarting the application will restart (which is logical)
If the android version is < 29, then startActivity () will fire and bring this SecondActivity to the foreground.
Based on this, the question is. How can I force the application, regardless of version, to transition between activities and not bring them to the front?
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
finish();
As per documentation
Android 10 (API level 29) and higher place restrictions on when apps
can start activities when the app is running in the background.
Workaround : In specific situations, your app might need to get the user's attention urgently, such as an ongoing alarm or incoming call. You might have previously configured your app for this purpose by launching an activity while your app was in the background.
To provide similar behavior on a device running Android 10 (API level 29) or higher, complete the steps described in this guide.
you can show a high-priority notification with a full-screen intent.
More Details
Updated answer for new requirement: For your comment
(Well, please tell me how to make startActivity () in the background start the activity also in the background, and not raise the application from the background)
you can add a LifecycleObserver that will be notified when the LifecycleOwner changes state.
Inside your activity api response callback use the following condition
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
// Activity is in resumed state, Open new activity immediately
} else {
// else add a LifecycleObserver that will be notified when the LifecycleOwner changes state
lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
super.onStart(owner)
// remove observer immediately so that it will not get triggered all the time
lifecycle.removeObserver(this)
// Activity is in start state again, Open new activity here
}
})
}

How to lock Android device after unlocking with setShowWhenLocked(true);

I am creating a video calling app and have the following code which is called when the application receives a push notification - it unlocks the screen and presents an 'incoming call' user interface:
public class MainActivity extends ReactActivity {
#Override
protected String getMainComponentName() {
return "x";
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(true);
setTurnScreenOn(true);
}
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}
}
This works fine when a call is incoming - the user can interact with the app using the UI presented. However, the problem is is that if the app is in the foreground and the phone is then locked, when the unlock button is pressed on the side of the phone, the app is displayed, instead of the keyguard / lock screen being displayed. It permanently allows access to the app if it is in the foreground and the phone is locked and the unlock button is pressed.
I want the app to appear when the it receives a push notification and the screen is locked, but I also want the user to be able to lock the device fully and not give the user access to the app after pressing the lock button.
How can I achieve this?
As far as I know the best solution to that problem is having multiple types of activities.
In the first activity (calling activity) you set setShowWhenLocked and setTurnScreenOn to true (like you did).
When a call comes in, you start the calling activity which handles the call, because you set the two attributes, the activitiy will be shown to the user even if the device is locked.
Furthermore, while the call activitiy is active, the user will be able to "lock" his device (i.e. press the power button), and when he unlocks he will be presented with the calling activity again (without entering the code).
This is the same behaviour as most default android calling/phone apps have.
The second activity is used for your other logic, that should only be accessible when the user really unlocks his phone. (i.e. enter the code)
So, when the phone call is ended, you start the second activity from the calling activity, e.g. like this:
Intent intent = new Intent(this, SecondActivity.class);
this.startActivity(intent);
where this is the instance of the calling activity
The just started SecondActivity will then automatically be locked behind the lockscreen (i.e. not accessible without unlock) if the phone was locked before.
I just tested this behaviour in a small test project, if you need further assistance, just ask.
In my VoIP app (baresip), I solved the problem by calling requestDismissKeyguard() function also when power button is pressed to unlock the device. That can be detected by registering a broadcast receiver with IntentFilter(Intent.ACTION_SCREEN_ON). Then if the device is locked with secured keyguard, requestDismissKeyguard() will ask for a PIN code or password before the user can access the app.

How do I refresh Webview everytime the app is brought back from background?

I have a webview application, and I need to refresh(using webview.Reload()) the webview whenever the app has been running in the background (has not been killed) and is brought back.How would I do that?
As a user navigates through, out of, and back to your app, the Activity instances in your app transition through different states in their lifecycle. The Activity class provides a number of callbacks that allow the activity to know that a state has changed: that the system is creating, stopping, or resuming an activity, or destroying the process in which the activity resides.
#Override
public void onResume() {
super.onResume();
webView.reload();
}
https://developer.android.com/guide/components/activities/activity-lifecycle

Retrofit response after activity finish

After user logged in successfully, there will be another api call to get the user information.
But before the response I will close the activity and start the home activity.
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
//save token
// call REST service to get user info and update the user records on DB.
// update the notification token info
//go to home page
Intent intent = new Intent(SigninActivity.this, HomeActivity.class);
startActivity(intent);
finish();
}
How can I make the call REST calls outside the activity. So App can handle the onReponse even after I close the Activity.
In General How can we call the API to do the background activity (eg: update database.) without any interaction . (response doesn't depend on activity)
The easiest solution would be to use static method. You can call those methods from anywhere.
If you want to update UI elements inside that method, pass the UI elements as parameters to the static method.
You could run a service(async) in the background minimize the first app and onResponse kill the first app and start the 2nd. And just access the data from the first.
There are two ways of doing this
Calling the user information API from the home activity (This is what I prefer).
While logging in, start a Service which makes the user information API call. Since Services are independent of UI and can run in the background starting the home activity and stopping the current one doesn't have any effect on the service. Once you get the response in the Service, create a broadcast(Or use EventBus) to send the response to home activity.

Stopping a service when home button is clicked?

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)

Categories

Resources