Hi dudes! Today I would like to share my experience with an issue that I faced a week ago on my project. I worked on a task where the android notification had to be visible when some event happened.
Actually, for me, it looked like a trivial task. But, our customer wanted to see this notification as the high priority system notification (for ex, low battery notification). Well, after some research, I wrote the next code and called it if some required event happened:
This method showed the next notification:
I thought I was done with this particular task… But, unfortunately, one of the requirements of our app is to support Android API 17. It was a bummer because that notification was visible only in the Notification bar:
Soon, I figured out only starting from Android API 21 notifications with priorities PRIORITY_MAX and PRIORITY_HIGH became appearing on the top of the screen. So I had to find another way to show such kind of notification.
Since Notification Builder didn’t manage my problem so I decided to get rid of it and started looking for something similar, like custom Snackbar. But this example showed notification pop-up as a part of the screen… So, it seemed, only one way was here — to implement its own notification UI based on a system overlay. So I would like to tell you how I handled it step-by-step. Of course, the current solution you can clone from my repo here.
- I decided to create UI for my notification based on CardView, so, first of all, I added the corresponding dependency:
2. I created NotificationView class with the next XML layout:
3. Then I put the base parameters for our system overlay into the constructor of the current class:
mParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
Here we are interested in the next parameters:
- WindowManager.LayoutParams.TYPE_SYSTEM_ALERT — system window, such as low power alert. These windows are always on top of application windows. To use this option, please, don’t forget to add the permission in Android manifest:
- FLAG_NOT_FOCUSABLE — setting this flag implies that the window will not need to interact with a soft input method.
- FLAG_NOT_TOUCH_MODAL — this window can never receive touch events.
You can miss the last parameter because it depends on the requirements. In my case, I ignored it.
4. I wanna our future notification was on the top of the screen so:
mParams.gravity = Gravity.TOP;
5. Then, I created slide down and slide up animations to emulate default behavior:
Since windowAnimations parameter of WindowManager.LayoutParams requires style attribute then I put slide_down.xml and slide_up.xml animations into style attribute file:
and then I set it as:
mParams.windowAnimations = R.style.Animation_NotificationView;
6. I wrote method to show notification as:
It seems WindowManager doesn’t allow us to determine exactly if the current view (i.e. our view for notification) is visible or not. So I added the additional variable mState that is responsible for visibility. I bet there is a way to check this state properly. Perhaps, getWindowToken() is a good candidate for that. But anyway, as a result, we will see the next:
- Android Jelly Bean:
- Android Lollipop:
As you can see, this notification almost identically both on Jelly Bean and Kit Kat Android versions.
Generally, our customer was satisfied with this result. But as for me, I don’t really like extra paddings on Jelly Bean. Unfortunately, I couldn’t manage it and get rid of it. So if you know how to remove it, then, please, let me know. I would be so appreciated.
I hope, this article will be helpful for guys who support different Android Platform versions and I wish good luck to find non-trivial solutions.
Be safe and stay at home!