33

I decompiled my system music app (from Sony Ericsson for Android GB 2.3.7) because I want to change the notification layout. I found the method which creates the notification with this code:

private void sendStatusBarNotification(Track paramTrack)
{
    if (paramTrack != null)
    {
        NotificationManager localNotificationManager = (NotificationManager)this.mContext.getSystemService("notification");
        String str = paramTrack.getArtist();

        if ((str == null) || (str.equals(this.mContext.getString(2131361954))))
            str = this.mContext.getString(2131361798);

        Notification localNotification = new Notification(2130837696, paramTrack.getTitle() + " - " + str, System.currentTimeMillis());
        localNotification.flags = (0x2 | localNotification.flags);
        localNotification.flags = (0x20 | localNotification.flags);

        PendingIntent localPendingIntent = PendingIntent.getActivity(this.mContext, 0, new Intent(this.mContext, MusicActivity.class), 268435456);
        localNotification.setLatestEventInfo(this.mContext, paramTrack.getTitle(), str, localPendingIntent);
        localNotificationManager.notify(0, localNotification);
    }
}

My question now is: How can I change the notification layout? I want to build a layout which looks like the original android notification layout but with an extra image on the right of the notification. How can I do this?

Cilenco
  • 6,951
  • 17
  • 72
  • 152

4 Answers4

85

First create an xml for your notification.

custom_notification.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp" >
    <ImageView android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentLeft="true"
        android:layout_marginRight="10dp" />
    <TextView android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/image"
        style="Custom Notification Title" />
    <TextView android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/image"
        android:layout_below="@id/title"
        style="Custom Notification Text" />
</RelativeLayout>

Now the java code:

public class MainActivity extends Activity {

    @SuppressWarnings("deprecation")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int icon = R.drawable.ic_launcher;
        long when = System.currentTimeMillis();
        Notification notification = new Notification(icon, "Custom Notification", when);

        NotificationManager mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);

        RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification);
        contentView.setImageViewResource(R.id.image, R.drawable.ic_launcher);
        contentView.setTextViewText(R.id.title, "Custom notification");
        contentView.setTextViewText(R.id.text, "This is a custom layout");
        notification.contentView = contentView;

        Intent notificationIntent = new Intent(this, MainActivity.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
        notification.contentIntent = contentIntent;

        notification.flags |= Notification.FLAG_NO_CLEAR; //Do not clear the notification
        notification.defaults |= Notification.DEFAULT_LIGHTS; // LED
        notification.defaults |= Notification.DEFAULT_VIBRATE; //Vibration
        notification.defaults |= Notification.DEFAULT_SOUND; // Sound

        mNotificationManager.notify(1, notification);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}

Hope this thing works for you.

Edit: You can also visit if you come across problem like this.

Also, you can visit here for more information.

Edit April 26 2016 You can use NotificationCompat.Builder for creating Notification instance as below:

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(icon)
            .setContent(contentView)
            .setContentTitle("Custom Notification")
            .setWhen(when);
...
mNotificationManager.notify(1, notificationBuilder.build());
Community
  • 1
  • 1
Chintan Soni
  • 24,761
  • 25
  • 106
  • 174
  • Thanks for that. You will get the bounty but I can give it to you in one hour ;) – Cilenco Aug 24 '13 at 23:45
  • 2
    @Cilenco No problem dear. I didn't help you for bounty at all. I just feel happy that my Solution worked for you, thats it...:) I love to help people with whatever i have knowledge of. Happy Coding...! – Chintan Soni Aug 25 '13 at 06:06
  • @shree202 gives me a suggestion. I build a notification big view using RemoteView to control play/pause like this link (stackoverflow.com/questions/14508369/…) All are right but when i click device back button and out from the application click event(Play/Pause/Forward/Close) button doesn't work.Please help me. – Helal Khan Mar 11 '14 at 13:57
  • how to update TextView in this method every 10 secound ? – Meysam May 03 '15 at 11:41
  • I thought it is better to use `NotificationCompat.Builder` instead of creating a new instance of `Notification`? – IgorGanapolsky Apr 26 '16 at 13:17
  • 1
    @IgorGanapolsky Thanks for pointing out the old code. Sir I have updated the answer. Feel free to correct me if I am wrong. – Chintan Soni Apr 26 '16 at 13:59
  • @ChintanSoni How do you fetch layout files from Resources inside a service class? I am using FCM notifications and can not fetch the layout file inside the service class! If you could guide me then It would be a great help! – Dhara Vamja Dec 06 '19 at 09:45
5

Here I have attached a screenshots, the first screen contents a title of the post and when we click on the down arrow on right side of the app name it leads to the second screenshot which is custom layout for push notification.The following is sample layout that I have designed for mine.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
card_view:cardCornerRadius="5dp"
card_view:cardUseCompatPadding="true">

<LinearLayout
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:background="#80000000"
    android:layout_height="wrap_content">

    <ImageView
        android:src="@mipmap/ic_launcher"
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:padding="10dp"
        android:layout_marginLeft="5dp"
        android:background="@null"
        android:layout_gravity="center_vertical|center_horizontal"
        android:scaleType="centerCrop"/>
    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:minHeight="48dp"
        android:paddingBottom="16dp"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:paddingTop="16dp"
        android:background="@android:color/transparent"
        android:textColor="@android:color/white"
        tools:text="Test"/>
</LinearLayout>
<ImageView
    android:id="@+id/image"
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:adjustViewBounds="true"
    android:contentDescription="@null"
    android:scaleType="centerCrop"
    android:src="@drawable/placeholder"/>
</LinearLayout>

Method for creating Notification with custom layout,

public static void createNotification(String title, String body,String image_url, Context context, int notificationsId, String single_id) {
    Intent notificationIntent;

    long when = System.currentTimeMillis();
    int id = (int) System.currentTimeMillis();

    Bitmap bitmap = getBitmapFromURL(image_url);
    NotificationCompat.BigPictureStyle notifystyle = new NotificationCompat.BigPictureStyle();
    notifystyle.bigPicture(bitmap);
    RemoteViews contentView = new RemoteViews(context.getPackageName(), R.layout.custom_notification_layout);
    contentView.setImageViewBitmap(R.id.image, bitmap);
    contentView.setTextViewText(R.id.title, body);

    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
            .setSmallIcon(R.drawable.ic_launcher)
            .setStyle(notifystyle)
            .setCustomBigContentView(contentView)
            .setContentText(body);
    NotificationManager mNotificationManager = (NotificationManager) context
            .getSystemService(Context.NOTIFICATION_SERVICE);

    notificationIntent = new Intent(context, SinglePost.class);
    notificationIntent.putExtra("single_id",single_id);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
    PendingIntent contentIntent = PendingIntent.getActivity(context, id, notificationIntent, 0); 

    Notification notification = mBuilder.build();
    notification.contentIntent = contentIntent;
    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    notification.defaults |= Notification.DEFAULT_SOUND;
    notification.defaults |= Notification.DEFAULT_VIBRATE;


    mNotificationManager.notify(notificationsId, notification);

}

public static Bitmap getBitmapFromURL(String strURL) {
    try {
        URL url = new URL(strURL);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.connect();
        InputStream input = connection.getInputStream();
        Bitmap myBitmap = BitmapFactory.decodeStream(input);
        return myBitmap;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}
Jayakumar
  • 303
  • 4
  • 5
3

To create custom notification layouts look at the Android API Guide on the subject. It looks like you're going to use the RemoteViews class.

cade
  • 563
  • 4
  • 15
0

It would be nice if we could get the layout data, whether it is dictated in code or xml.

going off of what is provided though, I can say that you have to get the image and put it in the new Notification(2130837696, paramTrack.getTitle() + " - " + str, System.currentTimeMillis()); declaration.

Honestly that is all I can give you with what you have provided. Best of luck!

Funkyguy
  • 628
  • 2
  • 10
  • 31