Android call Activity in background - java

I'm currently trying to place a call in the background.
Therefore I call this in my Main-Activity:
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:123456789"));
startActivity(callIntent);
I also wrote an Outgoing Call Receiver which changes the activity:
Intent myIntent = new Intent(context, DisplayCalcActivity.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
The problem is now, that the call-screen is in the foreground. If I switch manually from the call screen to my app, the activity has changed as I wanted, but how is it possible to start the activity in the foreground, so that the call-screen won't be shown at all?

The Android SDK does not allow to make a call in "foreground" maybe you can do accessing to private members but this is not recommended. The only way to call is by dialer app.

Got the solution!
I used another Receiver to listen to "android.intent.action.PHONE_STATE".
The outgoing call, activates the receiver which starts the other activity.

Related

startActivity() in BroadcastReceiver

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.

Opening Android app using notification & getLaunchIntentForPackage doesn't go through LauncherActivity

I am using Firebase (FCM) to show Push Notifications to the user and I am running into a weird problem.
The code I have works for the following scenarios (using FirebaseMessagingService):
App in foreground - Receiving data in onReceive() and showing a popup inside app.
App in background - Receiving data in onReceive() and showing a notification for the user. If this is clicked the app will be brought back to front. The intent from this is received in LauncherActivity followed by a finish() call which takes me to whatever activity I already had open.
App completely closed - same as background. App will be started and intent will be handled in LauncherActivity before calling finish() on that.
And here is where it gets interesting:
App completely closed -> open it through notification (intent received in LauncherActivity) -> put the app in background and send another notification -> when this notification is clicked the LauncherActivity is completely ignored (onCreate is no longer called) and I get taken straight to whatever activity I already had. The intent here has no extras or categories.
Why is LauncherActivity being bypassed in this specific case? Keep in mind that this works fine if the app was initially started normally (not by clicking on a notification)
Intent mainIntent = getPackageManager().getLaunchIntentForPackage(getPackageName());
if (mainIntent != null) {
mainIntent.addCategory(NOTIFICATION_CATEGORY);
mainIntent.putExtra(.........);
}
PendingIntent pendingMainIntent = PendingIntent.getActivity(this, SERVICE_NOTIFICATION_ID, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, context.getString(R.string.default_notification_channel_id));
notificationBuilder.setContentIntent(pendingMainIntent);
//.....icon, color, pririty, autoCancel, setDefaults, setWhen, setShowWhen, contentText, setStyle
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
getString(R.string.default_notification_channel_id),
getString(R.string.default_notification_channel),
NotificationManager.IMPORTANCE_HIGH
);
notificationManager.createNotificationChannel(channel);
notificationBuilder.setChannelId(getString(R.string.default_notification_channel_id));
}
notificationManager.notify(SERVICE_NOTIFICATION_ID, notificationBuilder.build());
}
I'd appreciate any ideas. Thank you.
When you launch an app for the first time, Android remembers the Intent that was used to launch it. Normally, when you launch an app from the HOME screen, this is an Intent that contains ACTION=MAIN and CATEGORY=LAUNCHER. If your app then goes to the background (for whatever reason), and the user later taps the icon on the HOME screen, the same launch Intent is used. Android matches this against the Intent used to launch the app for the first time, and if these match, Android doesn't launch a new Activity, it just brings the task containing the app from the background to the foreground in whatever state it was in when it got moved to the background. Under normal circumstances, this is exactly the behaviour that you want (and that the user expects).
However, when the app is launched for the first time from a Notification, this can mess things up. In your case, this is what you are seeing. You launch the app from a Notification and Android remembers the Intent used (from the Notification), when you later launch the app (again from a Notification), android matches the Intent in the Notification with the Intent used to launch the app for the first time, and thinks you want to bring the existing app task from the background to the foreground.
There are several ways to deal with this, depending on the behaviour that you want to have. The best thing to do is probably not to launch your root Activity (the one with ACTION=MAIN and CATEGORY=LAUNCHER) from the Notification. Instead launch a different Activity and have that Activity determine what it should do next (ie: redirect to the root Activity or something else, depending on the state of your app). You should also set the NO_HISTORY and EXCLUDE_FROM_RECENTS flags on the Intent that you put in the Notification. This will ensure that Android won't remember this Intent as the one that launched the app.

After Activity started?

Is there any event, method, flag or something else which tells me, that the next Activity has been started successfully and is shown on the screen.
MyCode to start an Activity class:
Intent intent = new Intent(this, nextActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Thanks in advance
onCreate() is called when the activity is created, I would strongly recommend reading up on the Activity Lifecycle if you're not sure about this.
If you can modify the started activity why not just send an broadcast once new activity's onStart() called?
or do something else you need upon activity start

Start a Fragment from a Service

My Activityhosts 3 tabs and each tab is a Fragment.
I also have a Service which query a database perdiodically. Depending on the result of the query, I raise a Notification (from the Service).
When I click on the Notification, is it possible to launch a specific fragment? If yes, how can I do so?
Here is what I've done so far, in my Service class:
// When notification is clicked, go back to TabOperations Fragment
Intent i = new Intent(this, TabOperations.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, i,PendingIntent.FLAG_UPDATE_CURRENT); // Give the phone access to the app
notification.setContentIntent(pi);
// Issue notification
NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
nm.notify(UNIQUE_ID, notification.build());
Of course, this does not work.
Any advice?
Instead of the Service sending a Notification, perhaps you would be better off with a different messaging system. For example, you can utilize the Observer pattern (or third-party libraries like EventBus) to send a message from the Service to the Activity that cares about such events. The activity can then use the event to start and attach the Fragment as necessary.

How to find out which activity started the intent that triggered your BroadCastReceiver?

I have an app, where some calls can be made when you press a button.
I call a number with:
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:"+o.getTel()));
startActivity(callIntent);
I have a broadcast receiver that detects end of call.
But this broadcast receiver also receives calls started from other apps (e.g. dialer app).
How can i differentiate calls started from other apps from calls started in mine?
Tnx
Before you call sendBroadcast(intent), add an extra to the intent,
e.g i.putExtra("sender", "my identifier")
Then in the onReceive of the receiver
String encodedType = intent.getStringExtra("sender");
Then you can test for this string.

Categories

Resources