Can't start activity from BroadcastReceiver on android 10
Asked Answered
V

3

13

I updated my OS version to android 10 last night, and since then the startActivity function inside the broadcast receiver is doing nothing. This is how I try to start the activity based on the answer of CommonsWare:

Intent i = new Intent(context, AlarmNotificationActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // This is at least android 10...

                Log.d("Debug", "This is android 10");
                // Start the alert via full-screen intent.
                PendingIntent startAlarmPendingIntent = PendingIntent.getBroadcast(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
                String CHANNEL_ID = "my_channel_02";
                NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                        context.getString(R.string.notification_channel_name_second),
                        NotificationManager.IMPORTANCE_HIGH);
                NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
                notificationManager.createNotificationChannel(channel);
                NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
                        .setContentTitle("Um, hi!")
                        .setAutoCancel(true)
                        .setPriority(NotificationCompat.PRIORITY_HIGH)
                        .setFullScreenIntent(startAlarmPendingIntent, true);
                Log.d("Debug", "Try to load screen");
                notificationManager.notify(0, builder.build());

            }

The log shows that I am getting to the notify command but nothing happens. I am asking for USE_FULL_SCREEN_INTENT permission on the manifest so I should be able to use full-screen intents. My app is useless now because of that issue. Does anyone know how to solve it?

Villiform answered 7/9, 2019 at 11:22 Comment(0)
W
14

Android 10's restriction on background activity starts was announced about six months ago. You can read more about it in the documentation.

Use a high-priority notification, with an associated full-screen Intent, instead. See the documentation. This sample app demonstrates this, by using WorkManager to trigger a background event needing to alert the user. There, I use a high-priority notification instead of starting the activity directly:

val pi = PendingIntent.getActivity(
  appContext,
  0,
  Intent(appContext, MainActivity::class.java),
  PendingIntent.FLAG_UPDATE_CURRENT
)

val builder = NotificationCompat.Builder(appContext, CHANNEL_WHATEVER)
  .setSmallIcon(R.drawable.ic_notification)
  .setContentTitle("Um, hi!")
  .setAutoCancel(true)
  .setPriority(NotificationCompat.PRIORITY_HIGH)
  .setFullScreenIntent(pi, true)

val mgr = appContext.getSystemService(NotificationManager::class.java)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
  && mgr.getNotificationChannel(CHANNEL_WHATEVER) == null
) {
  mgr.createNotificationChannel(
    NotificationChannel(
      CHANNEL_WHATEVER,
      "Whatever",
      NotificationManager.IMPORTANCE_HIGH
    )
  )
}

mgr.notify(NOTIF_ID, builder.build())
Whorehouse answered 7/9, 2019 at 11:31 Comment(20)
Thank you very much. Can you show a Java version of this code?Villiform
@SimpleUXApps: I do not have that particular book sample in Java. Here is a whole directory of notification samples in Java from an older book.Whorehouse
Thank you for your quick replay. I implemented your code but still nothing happens. Can you please check my edited question to see whether I have missed something in my new code?Villiform
@SimpleUXApps: If you are trying to start an activity, do not use PendingIntent.getBroadcast(). Use PendingIntent.getActivity().Whorehouse
im trying to start an activity not a notification and i am not using pendingintent. Im confused on how to do thisCamus
@steller: I assume that you are referring to this question. You cannot start an activity from the background in Android 10, except in very limited cases involving user interaction. This is covered in the documentation.Whorehouse
I need to do it. I am making an alarm app and i need to show an alarm screen. How the hell can i do this on a broadcast receiver? from the broadcast reciever i am navigating to an activity so i can show an activity. This is a dumb decision by google.Camus
@steller: "I am making an alarm app and i need to show an alarm screen" -- alarm clock apps have used high-priority notifications with full-screen intents for years. This is covered in the documentation. Your activity will be displayed immediately if the user's device is locked, as Android knows that it is safe to show an activity then. And, in other cases, it will not take over the screen from what the user is using it for, as that may cause harm to the user.Whorehouse
im a bit confused by "high-priority notifications with full-screen intents for years" I have never seen an example of this. Do you have a proper link that shows an example of what your talking about? Also "our activity will be displayed immediately if the user's device is locked," im a bit confused by this as my pixel 2 with android 10 is on lock and the intent doesnt fire. I need to show a screen and play sounds. I was doing this with an activity. Im not sure how this can be done with a notification.Camus
@steller: "im a bit confused by this as my pixel 2 with android 10 is on lock and the intent doesnt fire" -- my guess is that you have not implemented a high-priority notification with a full-screen intent. That is what I was referring to. "Do you have a proper link that shows an example of what your talking about?" -- this is covered in the answer and in the documentation.Whorehouse
Will i be able to show notification that has a button to snooze the alarm or stop the sounds from playing?Camus
@steller: Yes. You might use a pair of actions for that, with associated icons. For example, this activity raises a notification with a full-screen intent and an action. This particular example is not very practical, but it shows how the APIs work.Whorehouse
@CommonsWare: I am running the this example and this one on my device Samsung Galaxy A20 with Android Pie and neither of them show the activity if the screen is turned off. The notification is displayed. Can you help me debug this? Because I am also having this issue in my own app...Av
@amp: At least on a Samsung Galaxy S9, I need to tap on the notification on the lockscreen, then swipe, in order to get the activity to show. Device manufacturers might be tinkering with the mechanics. However, I don't have any advice about how to improve the process.Whorehouse
@CommonsWare: Thanks for the reply. I also tried with a Pixel 2 Android 10 emulator and the screen is still off when the notification is triggered. So I am not sure it is something to do with device manufacturers modifications... I am wondering how Whatsapp is able to display the incoming call screen... Or other apps like alarms and native phone call... It should be possible to do...Av
@Whorehouse I essentially copied your code and the notification works, but I have to tap the notification to start the activity. I am testing on a Pixel 2Q emulator.Jungjungfrau
@Hong: The notification will only launch the activity directly if the device is known to be idle (e.g., the screen is off). If the device might be in use, you just get the "heads-up" presentation, so the user will clearly see the notification but otherwise is not interrupted.Whorehouse
@Whorehouse Thank you for the clarification. I am trying to start an app automatically on reboot. This is an enterprise app targeting a specific Samsung device, so there are no other apps interfering with it. I am not clear whether the device is regarded as idle after reboot? We have 100% control of the device and can do whatever is needed. Do you have any suggestions for this scenario?Jungjungfrau
@Hong: "We have 100% control of the device and can do whatever is needed" -- modify the OS to start your process on device boot. Or, write a launcher and use that in place of the existing launcher.Whorehouse
@Whorehouse Thank you. OS modification is out of the question for now but a custom launcher sounds very appealing and we will look into it.Jungjungfrau
R
11

You can use SYSTEM_ALERT_WINDOW to force launch activity window in android 10, refer to this settingsuperposition setting:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>  
</activity>  
    <receiver
        android:name=".OnBootReceiver"
        android:enabled="true"
        android:exported="true"
        android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>

in launched app check permissions:

private void RequestPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!Settings.canDrawOverlays(this)) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + this.getPackageName()));
            startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
        } else {
            //Permission Granted-System will work
        }
    }
}

you will can user intent as android older versions

public class OnBootReceiver extends BroadcastReceiver {
    private static final String TAG = OnBootReceiver.class.getSimpleName();

    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            Intent activity = new Intent(context, MainActivity.class);
            activity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(activity);
        } catch (Exception e){
            Log.d(TAG,e.getMessage()+"");
        }
    }
}
Renata answered 21/5, 2020 at 15:51 Comment(1)
this opens the activity even when the app is killed and screen is locked. Thanks.Prebendary
D
2

Android 10's restriction on background activity starts was announced about six months ago. You can read more about it in the documentation.

So you need to have a high-level notification and when the user clicks on the notification your activity will be opened notifications

public class UIExampleReceiver extends BroadcastReceiver {

    public static final String TAG_NOTIFICATION = "NOTIFICATION_MESSAGE";
    public static final String CHANNEL_ID = "channel_1111";
    public static final int NOTIFICATION_ID = 111111;
    private static final String TAG = "Receiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            // If android 10 or higher
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
                startActivityNotification(
                    context,
                    NOTIFICATION_ID,
                    context.getResources().getString(R.string.open_app),
                    context.getResources().getString(R.string.click_app)
                );
            } else {
                // If lower than Android 10, we use the normal method ever.
                Intent activity = new Intent(context, ExampleActivity.class);
                activity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(activity);
            }
        } catch (Exception e) {
            Log.d(TAG, e.getMessage() + "");
        }
    }


    // notification method to support opening activities on Android 10
    public static void startActivityNotification (Context context, int notificationID,
    String title, String message) {

        NotificationManager mNotificationManager =
        (NotificationManager)
        context.getSystemService(Context.NOTIFICATION_SERVICE);
        //Create GPSNotification builder
        NotificationCompat.Builder mBuilder;

        //Initialise ContentIntent
        Intent ContentIntent = new Intent(context, ExampleActivity.class);
        ContentIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
        Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent ContentPendingIntent = PendingIntent . getActivity (context,
        0,
        ContentIntent,
        PendingIntent.FLAG_UPDATE_CURRENT);

        mBuilder = new NotificationCompat . Builder (context)
            .setSmallIcon(R.drawable.ic_launcher)
            .setContentTitle(title)
            .setContentText(message)
            .setColor(context.getResources().getColor(R.color.colorPrimaryDark))
            .setAutoCancel(true)
            .setContentIntent(ContentPendingIntent)
            .setDefaults(Notification.DEFAULT_LIGHTS | Notification . DEFAULT_VIBRATE)
        .setCategory(NotificationCompat.CATEGORY_MESSAGE)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            NotificationChannel mChannel = new NotificationChannel(
                CHANNEL_ID,
                "Activity Opening Notification",
                NotificationManager.IMPORTANCE_HIGH
            );
            mChannel.enableLights(true);
            mChannel.enableVibration(true);
            mChannel.setDescription("Activity opening notification");

            mBuilder.setChannelId(CHANNEL_ID);

            Objects.requireNonNull(mNotificationManager).createNotificationChannel(mChannel);
        }
        Objects.requireNonNull(mNotificationManager).notify(
            TAG_NOTIFICATION, notificationID,
            mBuilder.build()
        );
    }
}
Demetrademetre answered 15/4, 2020 at 8:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.