2020 */
2121package com .leanplum ;
2222
23+ import android .app .Notification ;
24+ import android .app .PendingIntent ;
2325import android .content .Context ;
26+ import android .content .res .Resources ;
27+ import android .graphics .Bitmap ;
28+ import android .os .Build ;
2429import android .os .Bundle ;
2530import android .support .v4 .app .NotificationCompat ;
2631import android .text .TextUtils ;
32+ import android .util .TypedValue ;
33+ import android .widget .RemoteViews ;
2734
35+ import com .leanplum .internal .Constants ;
2836import com .leanplum .internal .JsonConverter ;
2937import com .leanplum .internal .Log ;
3038import com .leanplum .utils .BuildUtil ;
3745 * @author Anna Orlova
3846 */
3947class LeanplumNotificationHelper {
48+
49+ private static final int BIGPICTURE_TEXT_TOP_PADDING = -14 ;
50+ private static final int BIGPICTURE_TEXT_SIZE = 14 ;
51+
4052 /**
4153 * If notification channels are supported this method will try to create
4254 * NotificationCompat.Builder with default notification channel if default channel id is provided.
@@ -49,7 +61,7 @@ class LeanplumNotificationHelper {
4961 */
5062 // NotificationCompat.Builder(Context context) constructor was deprecated in API level 26.
5163 @ SuppressWarnings ("deprecation" )
52- static NotificationCompat .Builder getDefaultNotificationBuilder (Context context ,
64+ static NotificationCompat .Builder getDefaultCompatNotificationBuilder (Context context ,
5365 boolean isNotificationChannelSupported ) {
5466 if (!isNotificationChannelSupported ) {
5567 return new NotificationCompat .Builder (context );
@@ -63,6 +75,32 @@ static NotificationCompat.Builder getDefaultNotificationBuilder(Context context,
6375 }
6476 }
6577
78+ /**
79+ * If notification channels are supported this method will try to create
80+ * Notification.Builder with default notification channel if default channel id is provided.
81+ * If notification channels not supported this method will return Notification.Builder for
82+ * context.
83+ *
84+ * @param context The application context.
85+ * @param isNotificationChannelSupported True if notification channels are supported.
86+ * @return Notification.Builder for provided context or null.
87+ */
88+ // Notification.Builder(Context context) constructor was deprecated in API level 26.
89+ @ SuppressWarnings ("deprecation" )
90+ private static Notification .Builder getDefaultNotificationBuilder (Context context ,
91+ boolean isNotificationChannelSupported ) {
92+ if (!isNotificationChannelSupported ) {
93+ return new Notification .Builder (context );
94+ }
95+ String channelId = LeanplumNotificationChannel .getDefaultNotificationChannelId (context );
96+ if (!TextUtils .isEmpty (channelId )) {
97+ return new Notification .Builder (context , channelId );
98+ } else {
99+ Log .w ("Failed to post notification, there are no notification channels configured." );
100+ return null ;
101+ }
102+ }
103+
66104 /**
67105 * If notification channels are supported this method will try to create a channel with
68106 * information from the message if it doesn't exist and return NotificationCompat.Builder for this
@@ -76,7 +114,7 @@ static NotificationCompat.Builder getDefaultNotificationBuilder(Context context,
76114 */
77115 // NotificationCompat.Builder(Context context) constructor was deprecated in API level 26.
78116 @ SuppressWarnings ("deprecation" )
79- static NotificationCompat .Builder getNotificationBuilder (Context context , Bundle message ) {
117+ static NotificationCompat .Builder getNotificationCompatBuilder (Context context , Bundle message ) {
80118 NotificationCompat .Builder builder = null ;
81119 // If we are targeting API 26, try to find supplied channel to post notification.
82120 if (BuildUtil .isNotificationChannelSupported (context )) {
@@ -94,7 +132,7 @@ static NotificationCompat.Builder getNotificationBuilder(Context context, Bundle
94132 }
95133 } else {
96134 // If channel isn't supplied, try to look up for default channel.
97- builder = LeanplumNotificationHelper .getDefaultNotificationBuilder (context , true );
135+ builder = LeanplumNotificationHelper .getDefaultCompatNotificationBuilder (context , true );
98136 }
99137 } catch (Exception e ) {
100138 Log .e ("Failed to post notification to specified channel." );
@@ -104,4 +142,111 @@ static NotificationCompat.Builder getNotificationBuilder(Context context, Bundle
104142 }
105143 return builder ;
106144 }
145+
146+ /**
147+ * If notification channels are supported this method will try to create a channel with
148+ * information from the message if it doesn't exist and return Notification.Builder for this
149+ * channel. In the case where no channel information inside the message, we will try to get a
150+ * channel with default channel id. If notification channels not supported this method will return
151+ * Notification.Builder for context.
152+ *
153+ * @param context The application context.
154+ * @param message Push notification Bundle.
155+ * @return Notification.Builder or null.
156+ */
157+ static Notification .Builder getNotificationBuilder (Context context , Bundle message ) {
158+ Notification .Builder builder = null ;
159+ // If we are targeting API 26, try to find supplied channel to post notification.
160+ if (BuildUtil .isNotificationChannelSupported (context )) {
161+ try {
162+ String channel = message .getString ("lp_channel" );
163+ if (!TextUtils .isEmpty (channel )) {
164+ // Create channel if it doesn't exist and post notification to that channel.
165+ Map <String , Object > channelDetails = JsonConverter .fromJson (channel );
166+ String channelId = LeanplumNotificationChannel .createNotificationChannel (context ,
167+ channelDetails );
168+ if (!TextUtils .isEmpty (channelId )) {
169+ builder = new Notification .Builder (context , channelId );
170+ } else {
171+ Log .w ("Failed to post notification to specified channel." );
172+ }
173+ } else {
174+ // If channel isn't supplied, try to look up for default channel.
175+ builder = LeanplumNotificationHelper .getDefaultNotificationBuilder (context , true );
176+ }
177+ } catch (Exception e ) {
178+ Log .e ("Failed to post notification to specified channel." );
179+ }
180+ } else {
181+ builder = new Notification .Builder (context );
182+ }
183+ return builder ;
184+ }
185+
186+ /**
187+ * Gets Notification.Builder with 2 lines at BigPictureStyle notification text.
188+ *
189+ * @param context The application context.
190+ * @param message Push notification Bundle.
191+ * @param contentIntent PendingIntent.
192+ * @param title String with title for push notification.
193+ * @param messageText String with text for push notification.
194+ * @param bigPicture Bitmap for BigPictureStyle notification.
195+ * @return Notification.Builder or null.
196+ */
197+ static Notification .Builder getNotificationBuilder (Context context , Bundle message ,
198+ PendingIntent contentIntent , String title , final String messageText , Bitmap bigPicture ) {
199+ if (Build .VERSION .SDK_INT < 16 ) {
200+ return null ;
201+ }
202+ Notification .Builder notificationBuilder =
203+ getNotificationBuilder (context , message );
204+ notificationBuilder .setSmallIcon (context .getApplicationInfo ().icon )
205+ .setContentTitle (title )
206+ .setContentText (messageText );
207+ Notification .BigPictureStyle bigPictureStyle = new Notification .BigPictureStyle () {
208+ @ Override
209+ protected RemoteViews getStandardView (int layoutId ) {
210+ RemoteViews remoteViews = super .getStandardView (layoutId );
211+ // Modifications of stanxdard push RemoteView.
212+ try {
213+ int id = Resources .getSystem ().getIdentifier ("text" , "id" , "android" );
214+ remoteViews .setBoolean (id , "setSingleLine" , false );
215+ remoteViews .setInt (id , "setLines" , 2 );
216+ if (Build .VERSION .SDK_INT < 23 ) {
217+ // Make text smaller.
218+ remoteViews .setViewPadding (id , 0 , BIGPICTURE_TEXT_TOP_PADDING , 0 , 0 );
219+ remoteViews .setTextViewTextSize (id , TypedValue .COMPLEX_UNIT_SP , BIGPICTURE_TEXT_SIZE );
220+ }
221+ } catch (Throwable throwable ) {
222+ Log .e ("Cannot modify push notification layout." );
223+ }
224+ return remoteViews ;
225+ }
226+ };
227+
228+ bigPictureStyle .bigPicture (bigPicture )
229+ .setBigContentTitle (title )
230+ .setSummaryText (message .getString (Constants .Keys .PUSH_MESSAGE_TEXT ));
231+ notificationBuilder .setStyle (bigPictureStyle );
232+
233+ if (Build .VERSION .SDK_INT >= 24 ) {
234+ // By default we cannot reach getStandardView method on API>=24. I we call
235+ // createBigContentView, Android will call getStandardView method and we can get
236+ // modified RemoteView.
237+ try {
238+ RemoteViews remoteView = notificationBuilder .createBigContentView ();
239+ if (remoteView != null ) {
240+ // We need to set received RemoteView as a custom big content view.
241+ notificationBuilder .setCustomBigContentView (remoteView );
242+ }
243+ } catch (Throwable t ) {
244+ Log .e ("Cannot modify push notification layout." , t );
245+ }
246+ }
247+
248+ notificationBuilder .setAutoCancel (true );
249+ notificationBuilder .setContentIntent (contentIntent );
250+ return notificationBuilder ;
251+ }
107252}
0 commit comments