Project Target API 30 Android 10, Min API 19 KitKat
I am creating a parental control app where parents can restrict certain apps.
I have a foreground service where I would I ideally trigger an activity-like notification from the service that would envelop the user's entire screen or take them to the home screen.
I have learned that starting activities, including going to the home screen, is no longer possible under normal circumstances as of API 29. https://developer.android.com/guide/components/activities/background-starts
After reading the documentation it seems creating a full screen intent notification is the most highly recommended workaround to the activity restriction.
I am currently working with the following code for my full screen intent notification:
Intent blockedIntent = new Intent(App.getContext(), BlockedItemReceiver.class);
blockedIntent.putExtra("currentApp", restrictedApp.name);
PendingIntent pendingBlockedIntent = PendingIntent.getActivity(App.getContext(), 50, blockedIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder blockedNotificationBuilder = new NotificationCompat.Builder(App.getContext(), CHANNEL_BLOCKED_FROM_ITEM)
.setSmallIcon(R.drawable.ic_baseline_lock_24)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentTitle(restrictedApp.packageName + " was Blocked!")
.setContentText(restrictedApp.name + " will be available again DAY at TIME")
.setCategory(NotificationCompat.CATEGORY_CALL)
.setFullScreenIntent(pendingBlockedIntent, true);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(5, blockedNotificationBuilder.build());
I looked at some documentation for customizing notifications, but the information I found does not have a full screen intent notification example, and when I attempt to add the methods in the documentation example for NotificationCompat.Builder such as setCustomContentView() with custom layouts, my notification fails to appear without an error message.
https://developer.android.com/training/notify-user/custom-notification
Besides, I do not want a collapsed and expanded version of my notification as the example in the link has, just one full screen view.
TLDR; I want a notification that always engulfs the screen until the user presses a button on the notification to dismiss it. How can I further customize my full screen intent notification to truly take up the full screen? Ideally with a layout. If I must have a collapsed version of my notification, I don't want the user to ever see it, because I always want my notification to engulf the screen while it's showing.
There are existing apps such as AppBlock that have found a workaround to launching an activity-like thing from a foreground service that takes up the full screen, so what I am trying to do is possible even if the specific question I'm asking won't lead me to that result. Please suggest another way of accomplishing what I am after if what I am asking to do in my question is "impossible". What I generally want to do is certainly possible.
Related
After a long search, I was not able to find exactly what I need.
I simply want : When a notification is displayed to the user, if the app is simply in background I want to reopen MainActivity. But if the app/activity has been killed, I want to restart the app completely.
My actual code :
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle(notification.getSubject())
.setContentText(notification.getMessage())
.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
mBuilder.setContentIntent(
PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_UPDATE_CURRENT));
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notif = mBuilder.build();
notif.flags = Notification.DEFAULT_VIBRATE | Notification.FLAG_AUTO_CANCEL;
Case which is not working actually is to restart the app if app or activity has been killed.
EDIT : By killed I mean the app has been closed in the app manager. Or we lost the focus and the activity is destroyed. In those cases I would like to fully restart the app.
I think you don't entirely understand how android functions. Whenever your program is needed, the program is started by android (See the Application class for an onCreate that you can override).
Whenever an activity is necessary it is (re)created or brought to the foreground.
That means that an activity restart does not necessarily imply a restart of the application. In practice, if the program was still in memory, then an application restart won't happen.
If you want to investigate this further
create an Application.onCreate method so you see whether your app is restarted or not.
trigger the notification
go to the android settings, application tab, and there select 'show cached processes'. Clear your process from the list.
tap the notification.
This should trigger a restart of the application. If this is indeed the problem then you cannot 'solve' it. Android decides when it will kill your application and when it removes it from memory.
The best solution then is to redesign your activity that whatever the application restart would trigger is also performed in the activity itself. Or so, without more detail what functionality you would like to see performed on an 'activity/application-restart' it is difficult to advice further on this matter.
I think you need to change your setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) value to setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT).
The reason is due to the way that FLAG_ACTIVITY_REORDER_TO_FRONT
works. When you use this flag, Android looks for an instance of the
desired activity in your activity stack, starting from the front of
the stack and scanning until it gets to the root/back of the stack. As
soon as it finds an instance of the specified activity, it brings that
one to the front (ie: if there are multiple instances of the specified
activity it will bring to the front the most recent instance).
Original I found here.
See android developer doc here.
I hope its help you.
At the Google I/O Bytes video How We Customized Google Apps for Android Wear (https://www.youtube.com/watch?v=o5cne6vK-eo), I saw that for the Wearable-customized Camera App, they add a button directly on the notification (not at the back of the notification as a new page which would happen if addAction or setContentAction is used).
Does any one know which API I need to use in order to do that? I don't think there are using a custom Activity for the first view cos it just looks like the first screen of Android Wear when there is at least one Notification. I've tried to find for it in the documentations but couldn't get it. I've tried setDisplayIntent which is suggested by others but it doesn't seems to be the same one.
Use WearableExtender.setContentAction(int) to add an action directly to a notification card. The int parameter refers to the index of the action you have added to the notification (using NotificationCompat.Builder.addAction(NotificationCompat.Action)). See Creating a Notification for more info on how to create notification for wearables.
The sample code you can download using the SDK manager contains a sample project Notifications (located under /samples/android-20/wearable/Notifications) that shows how to create various types of notifications. Here is an edited snippet from that sample that shows how to create a notification with an embedded action:
NotificationCompat.Action action = new NotificationCompat.Action.Builder(
R.drawable.ic_result_open, null, NotificationUtil.getExamplePendingIntent(
context, R.string.example_content_action_clicked)).build();
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Title")
.setContentText("Context Text")
.addAction(action)
.extend(new NotificationCompat.WearableExtender()
.setContentAction(0));
The video walks you though a few steps that are needed, but the main thing (and what you're asking for) is the Wearable Data Layer API. The first view (the card) is a notification, but that notification launches an Activity running on the wear device. That Activity is what displays the button and sends (through the Data Layer API) a message to the camera to take the picture.
I need to remove the notification.without affecting the foreground service of the application.thanks in advance
Notification note = new Notification(R.drawable.ic_blank,"",System.currentTimeMillis());
Intent i=new Intent(this, MyLocationListener.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pi=PendingIntent.getActivity(this, 0,i, 0);
note.setLatestEventInfo(this, "","", pi);
note.flags |= Notification.FLAG_NO_CLEAR;
startForeground(42, note);
Android OS don’t like you to do this because users are entitled to know you are running a foreground serivce on their devices.
But if you must remove notification of foreground service :
In order to remove the notification icon in the notification area (the status bar) while foreground service still running :
Just set the priority to minimum (-2) in the notification builder:
for example:
/* (Notification.PRIORITY_MIN) will remove the notification in statusbar */
builder.setPriority(Notification.PRIORITY_MIN)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Service Started")
.setTicker("Music Playing")
.setWhen(System.currentTimeMillis());
This will only remove the small notification icon in the notification area.
if you also need to get rid of the detail notification rectangle in the notification drawer :
then what you need to do is more complex:
you need to start your service as foreground, then start another foreground service with the same notification ID as you have in your original service.
Then close ( stopself() ) the new foreground service, and Android system will remove the notification (while your original service that started previously will stay in foreground without the notification).
This works fine in 5.1.1, I don’t know if android team already close this breach in marshmallow .
BTW:
In order to do this there is also a non-programmatically way :
Go to settings -> applications -> application manager find your application and press on it.
You will get inside your application info.
Disable the “show notifications” option in your application info.
This will get rid of all notifications for your app but it also disable toast messages..
I don’t think there is a way to disable this option in settings programmatically from inside the application - I think android prevent it for security reasons. If anyone knows how to change this programmatically please tell..
if while trying to avoid the notification detail rectangle in the drawer you will remove these lines in your notification builder:
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Service Started")
.setTicker("Music Playing")
.setWhen(System.currentTimeMillis());
Then Android system will keep on showing a notification rectangle about your service (with the title “This service is running, touch for more information or stop the service ” ) and pressing on this rectangle will lead the user to Your application info on settings -> applications -> application manager with option to “force stop” this service.
Regarding that you can read more here https://plus.google.com/105051985738280261832/posts/MTinJWdNL8t
hope it helps :-)
Adding this line builder.setPriority(Notification.PRIORITY_MIN) will remove the notification icon from the status bar and lock screen.
Also removing or commenting builder.setSmallIcon(R.drawable.ic_launcher) removes the notification icon even when you scroll down notifications when device is unlockedbut i m not sure how it will work in android N
I am using code similar to Creating a simple notification to create and show a notification from a network call.
The issue is that I want the activity that responds to the notification to do it's business and then on a backbutton click, put the previously active activity back in the foreground, with it's back stack intact. This is regardless of if the previously active activity was part of my app or somebody elses.
Currently it is following the generated TaskStackBuilder. Leading it back up the app hierarchy and out to the home screen. This is bad UI-design as it breaks the work-flow of anyone using the device, forcing them to manually go back to their app and spending more buttonclicks than necessary. It is also rather unintuitive.
According to the official desing guidelines this is how it should work. The implementation I linked to higher up makes back button have the same functionality as up button should have
It is also a common way to implement it in a plethora of other apps, including official google ones (google-play update notifications come to mind), so there must be a relatively standard way to do this.
Intent intent = new Intent(getApplicationContext(), MainActivity.class)
//add Intent.FLAG_ACTIVITY_CLEAR_TASK flag this will clear all activitys and
//launched activity at top. Means no other activity of this application will be running
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
or
// add Intent.FLAG_ACTIVITY_MULTIPLE_TASK which start one more task your applications
// where activity will not be cleared;
.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
Notification n = new Builder(context.getApplicationContext())
.setContentTitle("simple notification title")
.setContentText("simple message")
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.addAction(R.drawable.ic_launcher, "And more",pendingIntent ).build();
NotificationManager notificationManager =(NotificationManager) context.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, n);
I have a notification with a addidional action so user is able to go to the main activity by clicking the main notification or stop the service clicking the secondary (extented) notification. This works fine for post JellyBean Androids (4.1+). How to achieve similar functionality in older systems (API 11+)?
noti = new NotificationCompat.Builder(this)
.setContentTitle("service")
.setContentText("running")
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pendIntent)
.setPriority(Notification.PRIORITY_HIGH)
.addAction(R.drawable.ic_launcher, "Stop", pIntent)
.build();
startForeground(12345, noti);
From the docs:
Builder class for NotificationCompat objects. Allows easier control
over all the flags, as well as help constructing the typical
notification layouts.
On platform versions that don't offer expanded notifications, methods
that depend on expanded notifications have no effect.
For example, action buttons won't appear on platforms prior to Android
4.1. Action buttons depend on expanded notifications, which are only available in Android 4.1 and later.
For this reason, you should always ensure that UI controls in a
notification are also available in an Activity in your app, and you
should always start that Activity when users click the notification.
To do this, use the setContentIntent() method.
and from the addAction():
Add an action to this notification. Actions are typically displayed by
the system as a button adjacent to the notification content. Action
buttons won't appear on platforms prior to Android 4.1. Action buttons
depend on expanded notifications, which are only available in Android
4.1 and later. To ensure that an action button's functionality is always available, first implement the functionality in the Activity
that starts when a user clicks the notification (see
setContentIntent()), and then enhance the notification by implementing
the same functionality with addAction().
I found this tutorial that you might find useful.