Philipp
Philipp

Reputation: 11833

Notification action button not clickable in lock screen

In order to better support Android 5 notifications, I am now setting my app's notification visibilty to "public". After considering the answers on Lollipop Notification setVisibility() Does Not Work?, the notification is now displayed as expected. However, when I want to click the action button of the notification, I first have to unlock the device which should not be required. (The action shows that a password database is unlocked and the action button will lock the database.)

This is the code I am using the creating the notification (using Xamarin's Mono for Android):

NotificationCompat.Builder builder =
                new NotificationCompat.Builder(this)
                    .SetOngoing(true)
                    .SetSmallIcon(Resource.Drawable.ic_notify)
                    .SetLargeIcon(...)
                    .SetVisibility((int)Android.App.NotificationVisibility.Public)
                    .SetContentTitle(...)
                    .SetContentText(...);

builder.AddAction(Resource.Drawable.ic_action_lock, GetString(Resource.String.menu_lock), PendingIntent.GetBroadcast(this, 0, new Intent(Intents.LockDatabase), PendingIntentFlags.UpdateCurrent));

where this is a Service instance.

I know that MediaStyle notifications have clickable buttons, but it feels like a hack to use MediaStyle even though it's not about media. Is there any way I can make my action usable from the lock screen?

Upvotes: 4

Views: 5159

Answers (2)

Jeroen Mols
Jeroen Mols

Reputation: 3464

Instead of adding an action, define your own notification layout and connect a pendingIntent to fire to that via RemoteView. (The example below is based on the Holo look and feel and would still need to updated for lollipop. You can find all te correct resources in the android-21/data/res folder of your sdk)

// NOTE: while creating pendingIntent: requestcode must be different!
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(myService)
        .setSmallIcon(R.drawable.notification_icon).setContentTitle("My Title")
        .setContentText("Service running in the background");
Intent openIntent = new Intent(MainActivity.this, MainActivity.class);
PendingIntent pOpenIntent = PendingIntent.getActivity(this, 0, openIntent, 0);
mBuilder.setContentIntent(pOpenIntent);

// Notification with exit button if supported
String ACTION_NOTIFICATION_EXITACTIVITY = "com.jmols.example.exitactivity";
Intent exitIntent = new Intent();
exitIntent.setAction(ACTION_NOTIFICATION_EXITACTIVITY);
PendingIntent pExitIntent = PendingIntent.getBroadcast(this, 1, exitIntent, 0);
RemoteViews view = new RemoteViews(getPackageName(), R.layout.notification_discoveryservice);
view.setOnClickPendingIntent(R.id.notification_closebtn_ib, pExitIntent);
mBuilder.setContent(view);

With a notification layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
    android:id="@+id/status_bar_latest_event_content"
    android:layout_width="match_parent"
    android:layout_height="64dp"
    internal:layout_maxHeight="64dp"
    internal:layout_minHeight="64dp" >

    <ImageView
        android:id="@+id/notification_icon_iv"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:padding="10dp"
        android:layout_alignParentLeft="true"
        android:scaleType="center"
        android:src="@drawable/notification_icon"
        android:background="#3333B5E5" />

    <ImageButton
        android:id="@+id/notification_closebtn_ib"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:scaleType="centerInside"
        android:src="@drawable/notification_exitbtn"
        android:background="@drawable/notification_imagebtn_bg"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="fill_vertical"
        android:gravity="top"
        android:minHeight="64dp"
        android:layout_toRightOf="@id/notification_icon_iv"
        android:layout_toLeftOf="@id/notification_closebtn_ib"
        android:orientation="vertical"
        android:paddingBottom="2dp"
        android:paddingEnd="8dp"
        android:paddingTop="2dp" >

        <TextView
            android:id="@+id/notification_title_tv"
            style="@android:style/TextAppearance.StatusBar.EventContent.Title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:ellipsize="marquee"
            android:paddingTop="6dp"
            android:singleLine="true"
            android:text="JMols Service" />

        <TextView
            android:id="@+id/notification_contenttext_tv"
            style="@android:style/TextAppearance.StatusBar.EventContent"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:ellipsize="marquee"
            android:singleLine="true"
            android:text="Service running in the background" />

    </LinearLayout>

</RelativeLayout>

And the notification background is:

<selector xmlns:android="http://schemas.android.com/apk/res/android"
    android:exitFadeDuration="@android:integer/config_mediumAnimTime">

    <item android:state_pressed="true"  android:drawable="@drawable/notification_bg_normal_pressed" />
    <item android:state_pressed="false" android:drawable="@drawable/notification_bg_normal" />
</selector>

notification_bg_normal.9 notification_bg_normal_pressed.9

And the notification imagebutton background is:

<selector xmlns:android="http://schemas.android.com/apk/res/android"
    android:exitFadeDuration="@android:integer/config_mediumAnimTime">

    <item android:state_pressed="true"  android:drawable="@drawable/notification_imagebtn_bg_normal_pressed" />
    <item android:state_pressed="false" android:drawable="@drawable/notification_imagebtn_bg_normal" />
</selector>

notification_imagebtn_bg_normal.9.png notification_imagebtn_bg_normal_pressed.9.png

Upvotes: 4

user3416844
user3416844

Reputation:

I think Android only allows Media Playback can be controlled from the lock screen, other notifications have to unlock the screen first to start the activity is for security purposes. For example, you may want to know you get new mails, you may even want to show some content of the mails just arrive, but you may not want a loophole for others to access your email account when the device is locked. In media playback control use cases don't have such security issues.

Upvotes: 0

Related Questions