Hey everyone, The requirement was to make a custom notification since the android's default notification only allows for an image. So I went through on how to attach a custom UI for notification when expanded, the ready answer was to create a custom view and pass to the notification manager and allowed from API level 16. So I did one and here the my layout xml code - filename: notification_custom_view_new:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/GhostWhite"> <RelativeLayout android:id="@+id/header" android:layout_width="match_parent" android:layout_height="65dp"> <ImageView android:id="@+id/big_icon" android:layout_width="40dp" android:layout_height="40dp" android:layout_centerVertical="true" android:layout_marginLeft="12dp" android:scaleType="fitCenter" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignBottom="@+id/big_icon" android:layout_alignTop="@+id/big_icon" android:layout_toRightOf="@+id/big_icon" android:gravity="center_vertical" android:orientation="horizontal" android:paddingLeft="16dp" android:paddingRight="16dp" android:weightSum="2"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1.6" android:orientation="vertical"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="1" android:text="Title" android:textColor="@color/colorBlackDimText" android:textSize="16sp" android:textStyle="bold" /> <TextView android:id="@+id/message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="2" android:paddingTop="2dp" android:text="message" android:textColor="@color/colorBlackDimText" android:textSize="14sp" /> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="0.4" android:gravity="center"> <TextView android:id="@+id/time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="2" android:padding="8dp" android:text="24:59" android:textColor="@color/colorBlackDimText" android:textSize="12sp" /> </LinearLayout> </LinearLayout> </RelativeLayout> <View android:id="@+id/shadow" android:layout_width="match_parent" android:layout_height="5dp" android:layout_below="@+id/header" android:background="@drawable/shadow" /> <ImageView android:id="@+id/big_picture" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/header" android:src="@drawable/vector_icon_collections" android:minHeight="240dp" android:scaleType="fitCenter" /></RelativeLayout> The way I referenced it in code: private RemoteViews assignRemote(Bitmap bitmap, String title, String message ){ RemoteViews expandedView = new RemoteViews(Application.getInstance(). getPackageName(), R.layout.notification_custom_view_new); expandedView.setTextViewText(R.id.title, title); expandedView.setTextViewText(R.id.message, message); expandedView. setImageViewBitmap(R.id.big_picture, bitmap); expandedView.setImageViewResource(R.id.big_icon, R.mipmap.ic_launcher); expandedView.setTextViewText(R.id.time, getOnlyHrsMin()); return expandedView; } assigning customview to notification manager: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { notification.bigContentView = assignRemote(bitmap, title, message); } But this gave me error saying bad notification, I have identified over 15+ same question here on stackoverflow without a right answer.. Some suggest it to be a resource missing and hence the error. I am sure from my end none of the values are null nor resources missing errors are not there in my remote view that is passed. Any help will be appreciated and also I have tried for around a couple of days to track the error but nothing good seems to happen. Please help me! Screenshot attached for layout UI.. also find the NotificatioUtils and layout xml files attached for reference. Thanks DJphy -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to android-developers+unsubscr...@googlegroups.com. To post to this group, send email to android-developers@googlegroups.com. Visit this group at https://groups.google.com/group/android-developers. To view this discussion on the web visit https://groups.google.com/d/msgid/android-developers/1cc8ccad-f636-4558-9be8-5a83d5598012%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
notification_custom_view_new.xml
Description: XML document
package com.goldadorn.main.dj.support.gcm; import android.app.ActivityManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; import android.support.v7.app.NotificationCompat; import android.text.Html; import android.text.TextUtils; import android.util.Log; import android.util.Patterns; import android.widget.RemoteViews; import com.goldadorn.main.R; import com.goldadorn.main.activities.Application; import com.goldadorn.main.dj.utils.Constants; import com.goldadorn.main.dj.utils.DateTimeUtils; import com.goldadorn.main.dj.utils.IntentKeys; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; /** * Created by COMP on 2/25/2016. */ public class NotificationUtils { private static String TAG = NotificationUtils.class.getSimpleName(); private static Context mContext; public NotificationUtils() { } public NotificationUtils(Context mContext) { this.mContext = mContext; } public void showNotificationMessage(String title, String message, String timeStamp, Intent intent) { showNotificationMessage(title, message, timeStamp, intent, null); } public void showNotificationMessage(final String title, final String message, final String timeStamp, Intent intent, String imageUrl) { // Check for empty push message if (TextUtils.isEmpty(message)) return; // notification icon final int icon = R.mipmap.ic_launcher; intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.putExtra(IntentKeys.PUSH_NOTIFICATION_CALL, Constants.GCM_CALL); final PendingIntent resultPendingIntent = PendingIntent.getActivity( mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT ); final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder( mContext); final Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + mContext.getPackageName() + "/raw/notification"); if (!TextUtils.isEmpty(imageUrl)) { if (imageUrl != null && imageUrl.length() > 4 && Patterns.WEB_URL.matcher(imageUrl).matches()) { Bitmap bitmap = getBitmapFromURL(imageUrl); if (bitmap != null) { showBigNotification(bitmap, mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound); } else { showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound); } } } else { showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound); playNotificationSound(); } } private void showSmallNotification(NotificationCompat.Builder mBuilder, int icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) { NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); if (Config.appendNotificationMessages) { // store the notification in shared pref first Application.getInstance().getPrefManager().clearNotificationMsgs(); Application.getInstance().getPrefManager().addNotification(message); // get the notifications from shared preferences String oldNotification = Application.getInstance().getPrefManager().getNotifications(); List<String> messages = Arrays.asList(oldNotification.split("\\|")); for (int i = messages.size() - 1; i >= 0; i--) { Log.d("djgcm","messgaes: "+messages.get(i)); inboxStyle.addLine(messages.get(i)); } } else { inboxStyle.addLine(message); } Notification notification; notification = mBuilder.setSmallIcon(iconToUse()).setTicker(title).setWhen(0) .setAutoCancel(true) .setContentTitle(title) .setContentIntent(resultPendingIntent) .setSound(alarmSound) .setLights(Color.WHITE, 1500, 2000) .setStyle(inboxStyle) .setWhen(getTimeMilliSec(timeStamp)) .setSmallIcon(iconToUse()) .setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon)) .setContentText(message) .build(); NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(Config.NOTIFICATION_ID, notification); } private void showBigNotification(Bitmap bitmap, NotificationCompat.Builder mBuilder, int icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) { NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle(); bigPictureStyle.setBigContentTitle(title); bigPictureStyle.setSummaryText(Html.fromHtml(message).toString()); bigPictureStyle.bigPicture(bitmap); Notification notification; notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0) .setAutoCancel(true) .setContentTitle(title) .setContentIntent(resultPendingIntent) .setSound(alarmSound) .setLights(Color.WHITE, 1500, 2000) //.setStyle(bigPictureStyle) .setWhen(getTimeMilliSec(timeStamp)) .setSmallIcon(iconToUse()) .setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon)) .setContentText(message) .build(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { notification.bigContentView = assignRemote(bitmap, title, message); } NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(Config.NOTIFICATION_ID_BIG_IMAGE, notification); } private RemoteViews assignRemote(Bitmap bitmap, String title, String message){ RemoteViews expandedView = new RemoteViews(Application.getInstance().getPackageName(), R.layout.notification_custom_view_new); Log.d("djgcm","title, msg, big_pic, time: "+title+" "+message+" "+bitmap+" "+getOnlyHrsMin()); expandedView.setTextViewText(R.id.title, title); expandedView.setTextViewText(R.id.message, message); expandedView.setImageViewBitmap(R.id.big_picture, bitmap); expandedView.setImageViewResource(R.id.big_icon, R.mipmap.ic_launcher); expandedView.setTextViewText(R.id.time, getOnlyHrsMin()); return expandedView; } private int iconToUse(){ if (Constants.CURRENT_API_LEVEL >= Build.VERSION_CODES.LOLLIPOP){ return R.mipmap.ic_launcher_silhoute; } return R.mipmap.ic_launcher; } /*private int getNotificationIcon() { boolean useWhiteIcon = (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP); return useWhiteIcon ? R.drawable.icon_silhouette : R.drawable.ic_launcher; }*/ /** * Downloading push notification image before displaying it in * the notification tray */ public 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; } } // Playing notification sound public void playNotificationSound() { try { Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + Application.getInstance().getApplicationContext().getPackageName() + "/raw/notification"); Ringtone r = RingtoneManager.getRingtone(Application.getInstance().getApplicationContext(), alarmSound); r.play(); } catch (Exception e) { e.printStackTrace(); } } /** * Method checks if the app is in background or not */ public static boolean isAppIsInBackground(Context context) { boolean isInBackground = true; ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) { List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses(); for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) { if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { for (String activeProcess : processInfo.pkgList) { if (activeProcess.equals(context.getPackageName())) { isInBackground = false; } } } } } else { List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1); ComponentName componentInfo = taskInfo.get(0).topActivity; if (componentInfo.getPackageName().equals(context.getPackageName())) { isInBackground = false; } } return isInBackground; } // Clears notification tray messages public static void clearNotifications() { NotificationManager notificationManager = (NotificationManager) Application.getInstance().getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.cancelAll(); } public static long getTimeMilliSec(String timeStamp) { //SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { return System.currentTimeMillis(); } catch (Exception e) { e.printStackTrace(); } return 0; } public static String getOnlyHrsMin(){ Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); int hour = calendar.get(Calendar.HOUR_OF_DAY); int min = calendar.get(Calendar.MINUTE); return hour+":"+min; } }