1

I was wondering how I could implement a fixed toolbar in the android Status bar of any android device. I am talking about the buttons in the notification displayed below. An example is provided below. Is it possible have this running even when the user hasn't opened the application?

Can someone point me in the right direction please? Is there a library or can we implement this using the native android libraries provided?

enter image description here

Jay
  • 4,873
  • 7
  • 72
  • 137
  • You can simply create an ongoing `Notification` with a custom `View` that is started in a boot Receiver. No need for a library. – Mike M. Apr 29 '16 at 20:25
  • 1
    Can you give me an example or a reference link please? :) @MikeM. – Jay Apr 30 '16 at 01:22

1 Answers1

1

As a simple example, the following code will issue at boot an ongoing Notification with a Button to launch your app.

First, in your manifest, request the permission to get the BOOT_COMPLETED broadcast, and register a Receiver to handle it.

<manifest ...>

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    ...

    <application ...>
        ...

        <receiver android:name=".BootReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

The BootReceiver simply issues the Notification using a static method which is defined in MainActivity for this example.

public class BootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        MainActivity.setNotification(context, true);
    }
}

The setNotification() method creates a RemoteViews instance for the Notification using the simple layout below, and sets a PendingIntent on the Button with the launch Intent for your app.

public static void setNotification(Context context, boolean enabled) {
    NotificationManager manager =
        (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);

    if (enabled) {
        final RemoteViews rViews = new RemoteViews(context.getPackageName(),
                                                   R.layout.notification);

        final Intent intent = context.getPackageManager()
            .getLaunchIntentForPackage(context.getPackageName());

        if (intent != null) {
            PendingIntent pi = PendingIntent.getActivity(context,
                                                         0,
                                                         intent,
                                                         0);

            rViews.setOnClickPendingIntent(R.id.notification_button_1, pi); 
        }

        Notification.Builder builder = new Notification.Builder(context);
        builder.setContent(rViews)
            .setSmallIcon(R.drawable.ic_launcher)
            .setWhen(0)
            .setOngoing(true);

        manager.notify(0, builder.build());
    }
    else {
        manager.cancel(0);
    }
}

The Notification's layout is simply an ImageView and a Button in a horizontal LinearLayout.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView android:id="@+id/notification_image"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginRight="10dp"
        android:src="@drawable/ic_launcher" />

    <Button android:id="@+id/notification_button"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:text="Button" />

</LinearLayout>

Please note that, since API 3.1, you will have to launch your app at least once after installation to bring it out of the stopped state. Until then, the BootReceiver will not be delivered the broadcast.

Mike M.
  • 38,532
  • 8
  • 99
  • 95
  • Not as it is. I wasn't sure how you wanted to handle that, but all you need to do is call the `setNotification()` method with `true` as the second argument wherever you want to issue it. For example, if you want to show it when `MainActivity` starts, call the following line in `MainActivity`'s `onCreate()` method: `setNotification(this, true);`. Whenever you want to hide the `Notification`, call it with `false` as the second argument. – Mike M. Apr 30 '16 at 06:02
  • 1
    I took "when the user hasn't opened the application" to mean that you'd want it to show constantly, even if the user hasn't yet run your app during the current session. That's what the boot Receiver takes care of. If you install your app, run it once, then reboot, it'll show shortly after the boot process is done. It may take a little bit. – Mike M. Apr 30 '16 at 06:04
  • I ma not getting the notification when I launch the app :/ Is your code correct Mike? – Jay Apr 30 '16 at 06:13
  • Awesome solution mate, I think you solved my problem! Assuming that the user has run the app once before, Does this notification show up even after a restart? – Jay Apr 30 '16 at 06:16
  • If by restart you mean reboot, then yeah, that's what the Receiver is for. If you mean restarting the app, the `Notification` will stay there until you hide it. If you want it to show right when the user starts `MainActivity`, put a call in `onCreate()` like I describe in my first comment here. Also, calling that method with `false` will hide the `Notification`, whenever you want to get rid of it. An ongoing `Notification` has to be cancelled programmatically. You can't swipe it away. – Mike M. Apr 30 '16 at 06:18
  • Amazing! You solved my problem. I will accept this. Thanks mate :) One last clarification, I just changed my XML layout's structure and added a few buttons but the notification remains the same when I run it. The changes can't be seen. Do I need to uninstall it everytime to see the changes? – Jay Apr 30 '16 at 06:24
  • 1
    No, you shouldn't need to uninstall before you update with a new build, but sometimes IDEs fail to update the XML in layouts if you change it. You might need to clean, then rebuild the project. Also, there is only a limited subset of `View`s that you can put in `Notification`s, so you have to use only those. Gimme a second, and I'll find the list for ya. – Mike M. Apr 30 '16 at 06:27
  • OMG, can the height of the notification be changed? Everything was crammed in to a single row – Jay Apr 30 '16 at 06:27
  • Yeah, have a look at [this post](http://stackoverflow.com/questions/21237495/create-custom-big-notifications) for how to create large `Notification`s. It's just a matter of setting the `View` differently. And have a look at [this developer page](http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout) for the list of `View`s you can use. It's under the "Creating the App Widget Layout" section. Ignore the fact that it's about App Widgets. They use the same `RemoteViews` as `Notification`s. – Mike M. Apr 30 '16 at 06:33
  • I'm facing an issue with setting up a custom XML for this solution. I posted another question for it. If you are free, can you have a look Mike? http://stackoverflow.com/questions/36952090/android-notification-bad-notification-posted-from-package-couldnt-expand-remo – Jay Apr 30 '16 at 07:28
  • 1
    You were right. 'View' was causing the issue. Fixed it :) – Jay Apr 30 '16 at 07:38
  • 1
    No problem. Yeah, I'm not sure exactly why they wouldn't allow that, but that's how it is. – Mike M. Apr 30 '16 at 07:39
  • don't forget to add permission in AndroidManifest.xml android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> – MIKE PERETZ Feb 12 '18 at 20:40
  • 1
    @MIKEPERETZ Third line in the very first code block in my answer. – Mike M. Feb 12 '18 at 20:49