Android activity won't start consistently when called in service onTaskRemoved - android

On my Samsung S9 with Android 8.1 (Oreo). I am trying to start an activity on my service's onTaskRemoved(), so I can reinitialize my notifications (WorkManager) and prevent the app from force closing (saw this solution somewhere on Stack Overflow but don't remember where :(, sorry). The code would occasionally work (the application does not disconnect from Android studio, and scheduled notifications are successfully received on time). However, the activity usually does not start. I tried, with no avail, to put startActivity() in a loop to retry upon failure. Why is the activity not starting?
I know for sure that both the service and activities are properly registered in the AndroidManifest. In addition, I know that onCreate is not being called in the activity, because the logger message in the onCreate is not printing.
public void onTaskRemoved(Intent rootIntent) {
Log.d("Logtag", "Application has been closed by user");
Intent intent = new Intent(this, LaunchActivity.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
this.startActivity(intent);
}```

Related

Android - Not able to start multiple activities from background

I am facing a problem.
This is the code I have in my BroadcastReceiver extender class:
#Override
public void onReceive(Context context, Intent intent) {
// other
Intent myIntent = new Intent(context, ShowMessageActivity.class);
myIntent.putExtra(Utils.SHOW_MESSAGE_OPTION, messageToDisplay);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(lockScreenMessage);
}
which starts a new activity when a broadcast is raised.
When the application is in foreground and receives a broadcast, it starts a new Activity as many times as the code executes, but it is not the case when the app is in background. In that case it starts an Activity only once, and not each time a broadcast is received. Why? Is it possible to fix that?
that very depends on what do you expect in that receiver, is it any system-side call (declared in manifest) or your own? who an when calls it, thats very important
starting Android 10 there are some restrictions for starting Activity from onReceive, check out official DOC. basically you shouldn't start any Activity from there, and when it works for you I bet it works only for few secs after PendingIntent creation. check out exceptions list under link above, possible reasons would be:
The app has an activity in the back stack of an existing task on the Recents screen.
The app has an activity that was started very recently.
The app called finish() on an activity very recently.
you may check out your code on some emulator with Android 9, all your broadcast calls should work "always"

Unable to start service in background

I have a service that I use for listening to a socket service. I only need this service to be running whilst the app is in the foreground. However, in production I am seeing several crashes:
IllegalStateException
Not allowed to start service Intent { cmp=com.app.app/.app.sockets.EventHandlingService }: app is in background
Initially, I was calling this in the onCreate of my Activity, and according to some other SO questions, technically the app isn't foregrounded then. So I moved it into the onResume, and yet I still see it happening. This is how it is started:
#Override
protected void onResume() {
super.onResume();
Intent serviceIntent = new Intent(this, EventHandlingService.class);
startService(serviceIntent);
bindService(serviceIntent, serviceConnection, 0);
}
I am unable to reproduce this crash locally.

What is the best way to finish() an activity from a foreground service without bringing the app to the foreground?

I am trying to build an app that can be used for calling.
My CallActivity is declared singleTop in the manifest file. I have a foreground service (CallService) which is started as soon as the app goes to the background while the user is on a call, since the device must not sleep during a call.
The notification for my CallService allows the user to either resume the call or hangup. My goal is to have the user press a button on the notification and hangup the ongoing call without bringing the app to the foreground.
I have tried using PendingIntent.getActivity() to start the CallActivity once the app is in background, from the CallService. But I have not been able to hangup the call yet. Here is some code...
Intent returnToCallIntent = new Intent(this, CallActivity.class);
PendingIntent returnPendingIntent = PendingIntent.getActivity(this, 0, returnToCallIntent, 0);
Intent hangUpCallIntent = new Intent(this, CallActivity.class);
hangUpCallIntent.putExtra("ACTION_FINISH_ACTIVITY", true);
PendingIntent hangUpPendingIntent = PendingIntent.getActivity(this, 0, hangUpCallIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Right now both pending intents resolve to the same action which is hanging up the call while bring the app to the foreground. I figured out that this is happening because the 2 intents only differ in their extras and hence android does not distinguish them, i.e. intent#filterEquals() does not see any difference between them.
But the more important question is how can I finish() the CallActivity and have it pop off the backstack silently, without bringing it to the foreground. Also, after the CallActivity has been stopped, I need to stop the CallService in the background. So when the user taps the app in the recents screen, she/he should see the activity which was prior to the CallActivity on the backstack.
PS: Logic to hang up the call has been done in onNewIntent() method in CallActivity.
You can have your Activity register an anonymous BroadcastReceiver that listens for a specific broadcast Intent. When your Service wants to finish the Activity, it can just send the broadcast Intent that the Activity is listening for.
In onReceive() of the BroadcastReceiver, just call finish(). This won't bring the Activity to the foreground.

Android app seems to be duplicating when I swipe it away and start it again

I am currently having a really weird issue, and I don't know what could be causing it. Every time I close the app by swiping it away, and then start it again, the app seems to be duplicating its output to logcat, or in other words, it appears to be running multiple times.
This doesn't happen when I am connected to Android Studio, but without a cable connection, it does it without fail.
In my main activity I start my service like this:
Intent intent = new Intent(this, BluetoothService.class);
startService(intent);
bindService(intent, bluetoothServiceConnection, Context.BIND_AUTO_CREATE);
Stopping the service:
unbindService(bluetoothServiceConnection);
Intent intent = new Intent(MainActivity.this, BluetoothService.class);
stopService(intent);
EDIT I have made some changes in the way I stop and start my service, which seems to have solved my problem on Android 5.1.1, but not on Android 4.4.4, sadly.
I was thinking that maybe my logging process could be the problem, but destroying that process in my activity's onDestroy()-method didn't solve the issue either.
Starting the logging process:
logger = Runtime.getRuntime().exec(new String[]{"logcat", "-v", "time", "-f", logcatFile.getAbsolutePath(), " *:E"});
Stopping it:
logger.destroy();
If you start a service, depends how you define your service in the AndroidManifest.xml, if you have android:process=":yourProcess", if the process name start with ":" it will create a new process, that probably your log output multiple times.
Your code doesn't contains any logging information, nor did you provide a stacktrace with it. Your splash screen doesn't seem to be the issue, but you should replace the new thread with a delayed post to a handler to the looper thread (main thread) you're running in:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(getApplicationContext(), MainActivity.class);
startActivity(i);
finish();
}
}, 1500);
Instead of getApplicationContext() you could also use SplashActivity.this directly.
In your MainActivity you then need to make sure to unbind the service. Maybe also stop it, depending on what you need it for. Refer to Bound Services for more documentation and examples.
For making the Service terminate the documentation states
A service can be both started and have connections bound to it. In such a case, the system will keep the service running as long as either it is started or there are one or more connections to it with the Context.BIND_AUTO_CREATE flag. Once neither of these situations hold, the service's onDestroy() method is called and the service is effectively terminated.
That's why it works when the service isn't started at all. You try to stop the service in onDestroy() which is only called if the service is stopped. Your code looks like the service doesn't need to be started at all. But to do it correctly, just stop the service in the acivity's onDestroy() or utilize
onUnbind() or any other useful lifecycle event of the activity or service.

Calling an Activity from a broadcastreceiver, but keep it in the background

I have an alarm set to trigger every n minutes, and it works fine.
However I discovered that reading the application's SharedPreferences from a broadcast receiver caused some problems (It read an older version of those preferences, probably due to a different PID)
I were told that to do what I needed to do, I should call an Activity, that solved the SharedPreferences problem, but created a new one.
The activity must run in the background exclusively. It is essentially a heartbeat, sending off some information to a Presence solution, keeping the users presence alive.
The Alarm Receiver:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent alarmIntent = new Intent(context, AlarmActivity.class);
alarmIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(alarmIntent);
}
}
The activity in the manifest
<activity android:name=".AlarmActivity" android:theme="#android:style/Theme.Translucent.NoTitleBar"/>
The Alarm Activity only sends an HTTP update, but even if I remove all but the super.onCreate line, it still forces the application into the foreground, and focus. But it only happens if the application itself is only "minimized" via the home button. If I close it with the back button, it won't get forced into focus, while the heartbeat still fires just fine in the background.
How can I prevent this?
I'm developing for API version 7 (Android 2.1), but can update to API 8 if needed.
Consider using Service for performing background tasks.

Categories

Resources