I use android 10 [android Q, galaxy 10],
I use android studio 3.3,
using AVD, and made a api 29 [android 10] virtual phone.
at the virtual machine, I
With Android Q, it is impossible to start an activity from the background automatically if your app does not include those exceptions listed in the link below.
https://developer.android.com/guide/components/activities/background-starts
Possible Solutions:
1- You can choose just show a service notification, and start pending intent with a click
2- You can use full-screen intents to show your intent immediately as shown in the other answer and suggested by Google.
For full-screen intent solution, as described in the official document
The system UI may choose to display a heads-up notification, instead of launching this intent, while the user is using the device.
3- To start the activity automatically in the background, The most possible solution in my view is adding "SYSTEM_ALERT_WINDOW" to the manifest file. And ask for user permission once when the app opened the first time. (The user can give this permission manually - (Settings-Apps-Your App-Advanced- Draw over other apps))
Example code to request permission :
In Manifest:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Somewhere in app:
public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE= 2323;
//if the user already granted the permission or the API is below Android 10 no need to ask for permission
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
!Settings.canDrawOverlays(getContext()))
{RequestPermission()}
private void RequestPermission() {
// Check if Android M or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Show alert dialog to the user saying a separate permission is needed
// Launch the settings activity if the user prefers
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getActivity().getPackageName()));
startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(getContext())) {
PermissionDenied();
}
else
{
// Permission Granted-System will work
}
}
}
}
I'm open activity using the below logic. as google, blog says if you want to open activity in background service for use notification on android 10 or higher.
In Manifest:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Example:
private void startActivity() {
Uri sound = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.siren);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
AudioAttributes attributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build();
String CHANNEL_ID = BuildConfig.APPLICATION_ID.concat("_notification_id");
String CHANNEL_NAME = BuildConfig.APPLICATION_ID.concat("_notification_name");
assert notificationManager != null;
NotificationChannel mChannel = notificationManager.getNotificationChannel(CHANNEL_ID);
if (mChannel == null) {
mChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
mChannel.setSound(sound, attributes);
notificationManager.createNotificationChannel(mChannel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
builder.setSmallIcon(R.drawable.logo)
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.login))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setFullScreenIntent(openScreen(Constants.NOTIFICATION_ID), true)
.setAutoCancel(true)
.setOngoing(true);
Notification notification = builder.build();
notificationManager.notify(Constants.NOTIFICATION_ID, notification);
} else {
startActivity(new Intent(BackgroundService.this, LoginActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
}
private PendingIntent openScreen(int notificationId) {
Intent fullScreenIntent = new Intent(this, LoginActivity.class);
fullScreenIntent.putExtra(Constants.NOTIFICATION_IDS, notificationId);
return PendingIntent.getActivity(this, 0, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}