1976b6a8c18550ace670e0410453741d11dafa474Ian Lake/* 2976b6a8c18550ace670e0410453741d11dafa474Ian Lake * Copyright (C) 2015 The Android Open Source Project 3976b6a8c18550ace670e0410453741d11dafa474Ian Lake * 4976b6a8c18550ace670e0410453741d11dafa474Ian Lake * Licensed under the Apache License, Version 2.0 (the "License"); 5976b6a8c18550ace670e0410453741d11dafa474Ian Lake * you may not use this file except in compliance with the License. 6976b6a8c18550ace670e0410453741d11dafa474Ian Lake * You may obtain a copy of the License at 7976b6a8c18550ace670e0410453741d11dafa474Ian Lake * 8976b6a8c18550ace670e0410453741d11dafa474Ian Lake * http://www.apache.org/licenses/LICENSE-2.0 9976b6a8c18550ace670e0410453741d11dafa474Ian Lake * 10976b6a8c18550ace670e0410453741d11dafa474Ian Lake * Unless required by applicable law or agreed to in writing, software 11976b6a8c18550ace670e0410453741d11dafa474Ian Lake * distributed under the License is distributed on an "AS IS" BASIS, 12976b6a8c18550ace670e0410453741d11dafa474Ian Lake * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13976b6a8c18550ace670e0410453741d11dafa474Ian Lake * See the License for the specific language governing permissions and 14976b6a8c18550ace670e0410453741d11dafa474Ian Lake * limitations under the License 15976b6a8c18550ace670e0410453741d11dafa474Ian Lake */ 16976b6a8c18550ace670e0410453741d11dafa474Ian Lake 1766698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banespackage android.support.v7.app; 18976b6a8c18550ace670e0410453741d11dafa474Ian Lake 19976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.app.Notification; 20976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.app.PendingIntent; 21976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.content.Context; 22976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.content.res.Resources; 23976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.graphics.Bitmap; 243b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport android.graphics.Canvas; 253b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport android.graphics.Color; 263b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport android.graphics.PorterDuff; 273b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport android.graphics.PorterDuffColorFilter; 283b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport android.graphics.drawable.Drawable; 29976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.os.Build; 30976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.os.SystemClock; 31976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.support.v4.app.NotificationBuilderWithBuilderAccessor; 323b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport android.support.v4.app.NotificationCompat; 33976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.support.v4.app.NotificationCompatBase; 3466698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.appcompat.R; 35976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.util.TypedValue; 36976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.view.View; 37976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.widget.RemoteViews; 38976b6a8c18550ace670e0410453741d11dafa474Ian Lake 39976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport java.text.NumberFormat; 403b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport java.util.ArrayList; 41976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport java.util.List; 42976b6a8c18550ace670e0410453741d11dafa474Ian Lake 43976b6a8c18550ace670e0410453741d11dafa474Ian Lake/** 44976b6a8c18550ace670e0410453741d11dafa474Ian Lake * Helper class to generate MediaStyle notifications for pre-Lollipop platforms. Overrides 45976b6a8c18550ace670e0410453741d11dafa474Ian Lake * contentView and bigContentView of the notification. 46976b6a8c18550ace670e0410453741d11dafa474Ian Lake */ 4766698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesclass NotificationCompatImplBase { 48976b6a8c18550ace670e0410453741d11dafa474Ian Lake 49976b6a8c18550ace670e0410453741d11dafa474Ian Lake static final int MAX_MEDIA_BUTTONS_IN_COMPACT = 3; 50976b6a8c18550ace670e0410453741d11dafa474Ian Lake static final int MAX_MEDIA_BUTTONS = 5; 513b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek private static final int MAX_ACTION_BUTTONS = 3; 52976b6a8c18550ace670e0410453741d11dafa474Ian Lake 533b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek public static <T extends NotificationCompatBase.Action> RemoteViews overrideContentViewMedia( 54976b6a8c18550ace670e0410453741d11dafa474Ian Lake NotificationBuilderWithBuilderAccessor builder, 55976b6a8c18550ace670e0410453741d11dafa474Ian Lake Context context, CharSequence contentTitle, CharSequence contentText, 56976b6a8c18550ace670e0410453741d11dafa474Ian Lake CharSequence contentInfo, int number, Bitmap largeIcon, CharSequence subText, 573b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean useChronometer, long when, int priority, List<T> actions, 583b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int[] actionsToShowInCompact, boolean showCancelButton, 593b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek PendingIntent cancelButtonIntent, boolean isDecoratedCustomView) { 603b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek RemoteViews views = generateContentViewMedia(context, contentTitle, contentText, contentInfo, 613b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek number, largeIcon, subText, useChronometer, when, priority, actions, 623b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek actionsToShowInCompact, showCancelButton, cancelButtonIntent, 633b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek isDecoratedCustomView); 64976b6a8c18550ace670e0410453741d11dafa474Ian Lake builder.getBuilder().setContent(views); 65976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (showCancelButton) { 66976b6a8c18550ace670e0410453741d11dafa474Ian Lake builder.getBuilder().setOngoing(true); 67976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 683b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek return views; 69976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 70976b6a8c18550ace670e0410453741d11dafa474Ian Lake 713b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek private static <T extends NotificationCompatBase.Action> RemoteViews generateContentViewMedia( 72976b6a8c18550ace670e0410453741d11dafa474Ian Lake Context context, CharSequence contentTitle, CharSequence contentText, 73976b6a8c18550ace670e0410453741d11dafa474Ian Lake CharSequence contentInfo, int number, Bitmap largeIcon, CharSequence subText, 743b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean useChronometer, long when, int priority, List<T> actions, 753b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int[] actionsToShowInCompact, boolean showCancelButton, 763b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek PendingIntent cancelButtonIntent, boolean isDecoratedCustomView) { 77976b6a8c18550ace670e0410453741d11dafa474Ian Lake RemoteViews view = applyStandardTemplate(context, contentTitle, contentText, contentInfo, 783b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek number, 0 /* smallIcon */, largeIcon, subText, useChronometer, when, priority, 793b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 0 /* color is unused on media */, 803b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek isDecoratedCustomView ? R.layout.notification_template_media_custom 813b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek : R.layout.notification_template_media, 823b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek true /* fitIn1U */); 83976b6a8c18550ace670e0410453741d11dafa474Ian Lake 84976b6a8c18550ace670e0410453741d11dafa474Ian Lake final int numActions = actions.size(); 85976b6a8c18550ace670e0410453741d11dafa474Ian Lake final int N = actionsToShowInCompact == null 86976b6a8c18550ace670e0410453741d11dafa474Ian Lake ? 0 87976b6a8c18550ace670e0410453741d11dafa474Ian Lake : Math.min(actionsToShowInCompact.length, MAX_MEDIA_BUTTONS_IN_COMPACT); 88976b6a8c18550ace670e0410453741d11dafa474Ian Lake view.removeAllViews(R.id.media_actions); 89976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (N > 0) { 90976b6a8c18550ace670e0410453741d11dafa474Ian Lake for (int i = 0; i < N; i++) { 91976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (i >= numActions) { 92976b6a8c18550ace670e0410453741d11dafa474Ian Lake throw new IllegalArgumentException(String.format( 93976b6a8c18550ace670e0410453741d11dafa474Ian Lake "setShowActionsInCompactView: action %d out of bounds (max %d)", 94976b6a8c18550ace670e0410453741d11dafa474Ian Lake i, numActions - 1)); 95976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 96976b6a8c18550ace670e0410453741d11dafa474Ian Lake 97976b6a8c18550ace670e0410453741d11dafa474Ian Lake final NotificationCompatBase.Action action = actions.get(actionsToShowInCompact[i]); 98976b6a8c18550ace670e0410453741d11dafa474Ian Lake final RemoteViews button = generateMediaActionButton(context, action); 99976b6a8c18550ace670e0410453741d11dafa474Ian Lake view.addView(R.id.media_actions, button); 100976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 101976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 102976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (showCancelButton) { 103976b6a8c18550ace670e0410453741d11dafa474Ian Lake view.setViewVisibility(R.id.end_padder, View.GONE); 104976b6a8c18550ace670e0410453741d11dafa474Ian Lake view.setViewVisibility(R.id.cancel_action, View.VISIBLE); 105976b6a8c18550ace670e0410453741d11dafa474Ian Lake view.setOnClickPendingIntent(R.id.cancel_action, cancelButtonIntent); 106976b6a8c18550ace670e0410453741d11dafa474Ian Lake view.setInt(R.id.cancel_action, "setAlpha", 107976b6a8c18550ace670e0410453741d11dafa474Ian Lake context.getResources().getInteger(R.integer.cancel_button_image_alpha)); 108976b6a8c18550ace670e0410453741d11dafa474Ian Lake } else { 109976b6a8c18550ace670e0410453741d11dafa474Ian Lake view.setViewVisibility(R.id.end_padder, View.VISIBLE); 110976b6a8c18550ace670e0410453741d11dafa474Ian Lake view.setViewVisibility(R.id.cancel_action, View.GONE); 111976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 112976b6a8c18550ace670e0410453741d11dafa474Ian Lake return view; 113976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 114976b6a8c18550ace670e0410453741d11dafa474Ian Lake 1153b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek public static <T extends NotificationCompatBase.Action> void overrideMediaBigContentView( 116976b6a8c18550ace670e0410453741d11dafa474Ian Lake Notification n, Context context, CharSequence contentTitle, CharSequence contentText, 117976b6a8c18550ace670e0410453741d11dafa474Ian Lake CharSequence contentInfo, int number, Bitmap largeIcon, CharSequence subText, 1183b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean useChronometer, long when, int priority, int color, List<T> actions, 1193b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean showCancelButton, PendingIntent cancelButtonIntent, 1203b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean decoratedCustomView) { 1213b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek n.bigContentView = generateMediaBigView(context, contentTitle, contentText, contentInfo, 1223b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek number, largeIcon, subText, useChronometer, when, priority, color, 1233b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek actions, showCancelButton, cancelButtonIntent, decoratedCustomView); 124976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (showCancelButton) { 125976b6a8c18550ace670e0410453741d11dafa474Ian Lake n.flags |= Notification.FLAG_ONGOING_EVENT; 126976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 127976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 128976b6a8c18550ace670e0410453741d11dafa474Ian Lake 1293b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek public static <T extends NotificationCompatBase.Action> RemoteViews generateMediaBigView( 130976b6a8c18550ace670e0410453741d11dafa474Ian Lake Context context, CharSequence contentTitle, CharSequence contentText, 131976b6a8c18550ace670e0410453741d11dafa474Ian Lake CharSequence contentInfo, int number, Bitmap largeIcon, CharSequence subText, 1323b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean useChronometer, long when, int priority, int color, List<T> actions, 1333b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean showCancelButton, PendingIntent cancelButtonIntent, 1343b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean decoratedCustomView) { 135976b6a8c18550ace670e0410453741d11dafa474Ian Lake final int actionCount = Math.min(actions.size(), MAX_MEDIA_BUTTONS); 136976b6a8c18550ace670e0410453741d11dafa474Ian Lake RemoteViews big = applyStandardTemplate(context, contentTitle, contentText, contentInfo, 1373b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek number, 0 /* smallIcon */, largeIcon, subText, useChronometer, when, priority, 1383b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek color, /* fitIn1U */getBigMediaLayoutResource(decoratedCustomView, actionCount), 1393b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek false); 140976b6a8c18550ace670e0410453741d11dafa474Ian Lake 141976b6a8c18550ace670e0410453741d11dafa474Ian Lake big.removeAllViews(R.id.media_actions); 142976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (actionCount > 0) { 143976b6a8c18550ace670e0410453741d11dafa474Ian Lake for (int i = 0; i < actionCount; i++) { 144976b6a8c18550ace670e0410453741d11dafa474Ian Lake final RemoteViews button = generateMediaActionButton(context, actions.get(i)); 145976b6a8c18550ace670e0410453741d11dafa474Ian Lake big.addView(R.id.media_actions, button); 146976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 147976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 148976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (showCancelButton) { 149976b6a8c18550ace670e0410453741d11dafa474Ian Lake big.setViewVisibility(R.id.cancel_action, View.VISIBLE); 150976b6a8c18550ace670e0410453741d11dafa474Ian Lake big.setInt(R.id.cancel_action, "setAlpha", 151976b6a8c18550ace670e0410453741d11dafa474Ian Lake context.getResources().getInteger(R.integer.cancel_button_image_alpha)); 152976b6a8c18550ace670e0410453741d11dafa474Ian Lake big.setOnClickPendingIntent(R.id.cancel_action, cancelButtonIntent); 153976b6a8c18550ace670e0410453741d11dafa474Ian Lake } else { 154976b6a8c18550ace670e0410453741d11dafa474Ian Lake big.setViewVisibility(R.id.cancel_action, View.GONE); 155976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 156976b6a8c18550ace670e0410453741d11dafa474Ian Lake return big; 157976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 158976b6a8c18550ace670e0410453741d11dafa474Ian Lake 159976b6a8c18550ace670e0410453741d11dafa474Ian Lake private static RemoteViews generateMediaActionButton(Context context, 160976b6a8c18550ace670e0410453741d11dafa474Ian Lake NotificationCompatBase.Action action) { 161976b6a8c18550ace670e0410453741d11dafa474Ian Lake final boolean tombstone = (action.getActionIntent() == null); 162976b6a8c18550ace670e0410453741d11dafa474Ian Lake RemoteViews button = new RemoteViews(context.getPackageName(), 163976b6a8c18550ace670e0410453741d11dafa474Ian Lake R.layout.notification_media_action); 164976b6a8c18550ace670e0410453741d11dafa474Ian Lake button.setImageViewResource(R.id.action0, action.getIcon()); 165976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (!tombstone) { 166976b6a8c18550ace670e0410453741d11dafa474Ian Lake button.setOnClickPendingIntent(R.id.action0, action.getActionIntent()); 167976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 168956192ae5d9dd882c91c9cb607954f0eebcb7976Ian Lake if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { 169956192ae5d9dd882c91c9cb607954f0eebcb7976Ian Lake button.setContentDescription(R.id.action0, action.getTitle()); 170956192ae5d9dd882c91c9cb607954f0eebcb7976Ian Lake } 171976b6a8c18550ace670e0410453741d11dafa474Ian Lake return button; 172976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 173976b6a8c18550ace670e0410453741d11dafa474Ian Lake 1743b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek private static int getBigMediaLayoutResource(boolean decoratedCustomView, int actionCount) { 175976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (actionCount <= 3) { 1763b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek return decoratedCustomView 1773b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek ? R.layout.notification_template_big_media_narrow_custom 1783b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek : R.layout.notification_template_big_media_narrow; 179976b6a8c18550ace670e0410453741d11dafa474Ian Lake } else { 1803b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek return decoratedCustomView 1813b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek ? R.layout.notification_template_big_media_custom 1823b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek : R.layout.notification_template_big_media; 183976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 184976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 185976b6a8c18550ace670e0410453741d11dafa474Ian Lake 1863b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek public static RemoteViews applyStandardTemplateWithActions(Context context, 187976b6a8c18550ace670e0410453741d11dafa474Ian Lake CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo, 1883b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int number, int smallIcon, Bitmap largeIcon, CharSequence subText, 1893b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean useChronometer, long when, int priority, int color, int resId, boolean fitIn1U, 1903b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek ArrayList<NotificationCompat.Action> actions) { 1913b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek RemoteViews remoteViews = applyStandardTemplate(context, contentTitle, contentText, 1923b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentInfo, number, smallIcon, largeIcon, subText, useChronometer, when, priority, 1933b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek color, resId, fitIn1U); 1943b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek remoteViews.removeAllViews(R.id.actions); 1953b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean actionsVisible = false; 1963b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (actions != null) { 1973b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int N = actions.size(); 1983b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (N > 0) { 1993b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek actionsVisible = true; 2003b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (N > MAX_ACTION_BUTTONS) N = MAX_ACTION_BUTTONS; 2013b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek for (int i = 0; i < N; i++) { 2023b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek final RemoteViews button = generateActionButton(context, actions.get(i)); 2033b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek remoteViews.addView(R.id.actions, button); 2043b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2053b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2063b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2073b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int actionVisibility = actionsVisible ? View.VISIBLE : View.GONE; 2083b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek remoteViews.setViewVisibility(R.id.actions, actionVisibility); 2093b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek remoteViews.setViewVisibility(R.id.action_divider, actionVisibility); 2103b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek return remoteViews; 2113b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2123b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 2133b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek private static RemoteViews generateActionButton(Context context, 2143b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek NotificationCompat.Action action) { 2153b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek final boolean tombstone = (action.actionIntent == null); 2163b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek RemoteViews button = new RemoteViews(context.getPackageName(), 2173b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek tombstone ? getActionTombstoneLayoutResource() 2183b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek : getActionLayoutResource()); 2193b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek button.setImageViewBitmap(R.id.action_image, 2203b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek createColoredBitmap(context, action.getIcon(), 2213b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek context.getResources().getColor(R.color.notification_action_color_filter))); 2223b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek button.setTextViewText(R.id.action_text, action.title); 2233b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (!tombstone) { 2243b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek button.setOnClickPendingIntent(R.id.action_container, action.actionIntent); 2253b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2263b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek button.setContentDescription(R.id.action_container, action.title); 2273b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek return button; 2283b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2293b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 2303b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek private static Bitmap createColoredBitmap(Context context, int iconId, int color) { 2313b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek return createColoredBitmap(context, iconId, color, 0); 2323b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2333b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 2343b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek private static Bitmap createColoredBitmap(Context context, int iconId, int color, int size) { 2353b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek Drawable drawable = context.getResources().getDrawable(iconId); 2363b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int width = size == 0 ? drawable.getIntrinsicWidth() : size; 2373b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int height = size == 0 ? drawable.getIntrinsicHeight() : size; 2383b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek Bitmap resultBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 2393b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek drawable.setBounds(0, 0, width, height); 2403b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (color != 0) { 2413b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek drawable.mutate().setColorFilter( 2423b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)); 2433b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2443b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek Canvas canvas = new Canvas(resultBitmap); 2453b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek drawable.draw(canvas); 2463b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek return resultBitmap; 2473b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2483b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 2493b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek private static int getActionLayoutResource() { 2503b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek return R.layout.notification_action; 2513b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2523b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 2533b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek private static int getActionTombstoneLayoutResource() { 2543b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek return R.layout.notification_action_tombstone; 2553b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2563b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 2573b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek public static RemoteViews applyStandardTemplate(Context context, 2583b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo, 2593b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int number, int smallIcon, Bitmap largeIcon, CharSequence subText, 2603b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean useChronometer, long when, int priority, int color, int resId, 2613b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean fitIn1U) { 2623b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek Resources res = context.getResources(); 263976b6a8c18550ace670e0410453741d11dafa474Ian Lake RemoteViews contentView = new RemoteViews(context.getPackageName(), resId); 264976b6a8c18550ace670e0410453741d11dafa474Ian Lake boolean showLine3 = false; 265976b6a8c18550ace670e0410453741d11dafa474Ian Lake boolean showLine2 = false; 266976b6a8c18550ace670e0410453741d11dafa474Ian Lake 2673b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean minPriority = priority < NotificationCompat.PRIORITY_LOW; 2683b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean afterJellyBean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; 2693b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean afterLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; 2703b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (afterJellyBean && !afterLollipop) { 2713b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek // lets color the backgrounds 2723b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (minPriority) { 2733b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setInt(R.id.notification_background, 2743b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek "setBackgroundResource", R.drawable.notification_bg_low); 2753b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setInt(R.id.icon, 2763b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek "setBackgroundResource", R.drawable.notification_template_icon_low_bg); 2773b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } else { 2783b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setInt(R.id.notification_background, 2793b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek "setBackgroundResource", R.drawable.notification_bg); 2803b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setInt(R.id.icon, 2813b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek "setBackgroundResource", R.drawable.notification_template_icon_bg); 2823b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2833b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2843b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 2853b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (largeIcon != null) { 2863b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek // On versions before Jellybean, the large icon was shown by SystemUI, so we need to hide 2873b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek // it here. 2883b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (afterJellyBean) { 2893b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setViewVisibility(R.id.icon, View.VISIBLE); 2903b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setImageViewBitmap(R.id.icon, largeIcon); 2913b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } else { 2923b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setViewVisibility(R.id.icon, View.GONE); 2933b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 2943b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (smallIcon != 0) { 2953b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int backgroundSize = res.getDimensionPixelSize( 2963b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek R.dimen.notification_right_icon_size); 2973b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int iconSize = backgroundSize - res.getDimensionPixelSize( 2983b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek R.dimen.notification_small_icon_background_padding) * 2; 2993b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (afterLollipop) { 3003b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek Bitmap smallBit = createIconWithBackground(context, 3013b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek smallIcon, 3023b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek backgroundSize, 3033b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek iconSize, 3043b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek color); 3053b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setImageViewBitmap(R.id.right_icon, smallBit); 3063b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } else { 3073b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setImageViewBitmap(R.id.right_icon, 3083b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek createColoredBitmap(context, smallIcon, Color.WHITE)); 3093b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 3103b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setViewVisibility(R.id.right_icon, View.VISIBLE); 3113b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 3123b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } else if (smallIcon != 0) { // small icon at left 313b5d323aec7885d728503cc080c6c5e5a20e5850cIan Lake contentView.setViewVisibility(R.id.icon, View.VISIBLE); 3143b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (afterLollipop) { 3153b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int backgroundSize = res.getDimensionPixelSize( 3163b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek R.dimen.notification_large_icon_width) 3173b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek - res.getDimensionPixelSize(R.dimen.notification_big_circle_margin); 3183b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int iconSize = res.getDimensionPixelSize( 3193b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek R.dimen.notification_small_icon_size_as_large); 3203b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek Bitmap smallBit = createIconWithBackground(context, 3213b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek smallIcon, 3223b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek backgroundSize, 3233b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek iconSize, 3243b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek color); 3253b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setImageViewBitmap(R.id.icon, smallBit); 3263b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } else { 3273b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setImageViewBitmap(R.id.icon, 3283b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek createColoredBitmap(context, smallIcon, Color.WHITE)); 3293b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 330976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 331976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (contentTitle != null) { 332976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setTextViewText(R.id.title, contentTitle); 333976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 334976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (contentText != null) { 335976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setTextViewText(R.id.text, contentText); 336976b6a8c18550ace670e0410453741d11dafa474Ian Lake showLine3 = true; 337976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 3383b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek // If there is a large icon we have a right side 3393b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek boolean hasRightSide = !afterLollipop && largeIcon != null; 340976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (contentInfo != null) { 341976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setTextViewText(R.id.info, contentInfo); 342976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setViewVisibility(R.id.info, View.VISIBLE); 343976b6a8c18550ace670e0410453741d11dafa474Ian Lake showLine3 = true; 3443b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek hasRightSide = true; 345976b6a8c18550ace670e0410453741d11dafa474Ian Lake } else if (number > 0) { 3463b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek final int tooBig = res.getInteger( 347976b6a8c18550ace670e0410453741d11dafa474Ian Lake R.integer.status_bar_notification_info_maxnum); 348976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (number > tooBig) { 3493b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setTextViewText(R.id.info, ((Resources) res).getString( 350976b6a8c18550ace670e0410453741d11dafa474Ian Lake R.string.status_bar_notification_info_overflow)); 351976b6a8c18550ace670e0410453741d11dafa474Ian Lake } else { 352976b6a8c18550ace670e0410453741d11dafa474Ian Lake NumberFormat f = NumberFormat.getIntegerInstance(); 353976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setTextViewText(R.id.info, f.format(number)); 354976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 355976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setViewVisibility(R.id.info, View.VISIBLE); 356976b6a8c18550ace670e0410453741d11dafa474Ian Lake showLine3 = true; 3573b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek hasRightSide = true; 358976b6a8c18550ace670e0410453741d11dafa474Ian Lake } else { 359976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setViewVisibility(R.id.info, View.GONE); 360976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 361976b6a8c18550ace670e0410453741d11dafa474Ian Lake 362976b6a8c18550ace670e0410453741d11dafa474Ian Lake // Need to show three lines? Only allow on Jellybean+ 3633b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (subText != null && afterJellyBean) { 364976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setTextViewText(R.id.text, subText); 365976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (contentText != null) { 366976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setTextViewText(R.id.text2, contentText); 367976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setViewVisibility(R.id.text2, View.VISIBLE); 368976b6a8c18550ace670e0410453741d11dafa474Ian Lake showLine2 = true; 369976b6a8c18550ace670e0410453741d11dafa474Ian Lake } else { 370976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setViewVisibility(R.id.text2, View.GONE); 371976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 372976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 373976b6a8c18550ace670e0410453741d11dafa474Ian Lake 374976b6a8c18550ace670e0410453741d11dafa474Ian Lake // RemoteViews.setViewPadding and RemoteViews.setTextViewTextSize is not available on ICS- 3753b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (showLine2 && afterJellyBean) { 376976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (fitIn1U) { 377976b6a8c18550ace670e0410453741d11dafa474Ian Lake // need to shrink all the type to make sure everything fits 378976b6a8c18550ace670e0410453741d11dafa474Ian Lake final float subTextSize = res.getDimensionPixelSize( 379976b6a8c18550ace670e0410453741d11dafa474Ian Lake R.dimen.notification_subtext_size); 380976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX, subTextSize); 381976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 382976b6a8c18550ace670e0410453741d11dafa474Ian Lake // vertical centering 383976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setViewPadding(R.id.line1, 0, 0, 0, 0); 384976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 385976b6a8c18550ace670e0410453741d11dafa474Ian Lake 386976b6a8c18550ace670e0410453741d11dafa474Ian Lake if (when != 0) { 3873b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (useChronometer && afterJellyBean) { 388976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setViewVisibility(R.id.chronometer, View.VISIBLE); 389976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setLong(R.id.chronometer, "setBase", 390976b6a8c18550ace670e0410453741d11dafa474Ian Lake when + (SystemClock.elapsedRealtime() - System.currentTimeMillis())); 391976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setBoolean(R.id.chronometer, "setStarted", true); 392976b6a8c18550ace670e0410453741d11dafa474Ian Lake } else { 393976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setViewVisibility(R.id.time, View.VISIBLE); 394976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setLong(R.id.time, "setTime", when); 395976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 3963b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek hasRightSide = true; 397976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 3983b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek contentView.setViewVisibility(R.id.right_side, hasRightSide ? View.VISIBLE : View.GONE); 399976b6a8c18550ace670e0410453741d11dafa474Ian Lake contentView.setViewVisibility(R.id.line3, showLine3 ? View.VISIBLE : View.GONE); 400976b6a8c18550ace670e0410453741d11dafa474Ian Lake return contentView; 401976b6a8c18550ace670e0410453741d11dafa474Ian Lake } 4023b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 4033b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek public static Bitmap createIconWithBackground(Context ctx, int iconId, int size, int iconSize, 4043b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int color) { 4053b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek Bitmap coloredBitmap = createColoredBitmap(ctx, R.drawable.notification_icon_background, 4063b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek color == NotificationCompat.COLOR_DEFAULT ? 0 : color, size); 4073b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek Canvas canvas = new Canvas(coloredBitmap); 4083b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek Drawable icon = ctx.getResources().getDrawable(iconId).mutate(); 4093b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek icon.setFilterBitmap(true); 4103b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int inset = (size - iconSize) / 2; 4113b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek icon.setBounds(inset, inset, iconSize + inset, iconSize + inset); 4123b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek icon.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP)); 4133b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek icon.draw(canvas); 4143b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek return coloredBitmap; 4153b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 4163b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 4173b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek public static void buildIntoRemoteViews(Context ctx, RemoteViews outerView, 4183b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek RemoteViews innerView) { 4193b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek // this needs to be done fore the other calls, since otherwise we might hide the wrong 4203b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek // things if our ids collide. 4213b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek hideNormalContent(outerView); 4223b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek outerView.removeAllViews(R.id.notification_main_column); 4233b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek outerView.addView(R.id.notification_main_column, innerView.clone()); 4243b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek outerView.setViewVisibility(R.id.notification_main_column, View.VISIBLE); 4253b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 4263b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek // Adjust padding depending on font size. 4273b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek outerView.setViewPadding(R.id.notification_main_column_container, 4283b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 0, calculateTopPadding(ctx), 0, 0); 4293b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 4303b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 4313b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 4323b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek private static void hideNormalContent(RemoteViews outerView) { 4333b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek outerView.setViewVisibility(R.id.title, View.GONE); 4343b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek outerView.setViewVisibility(R.id.text2, View.GONE); 4353b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek outerView.setViewVisibility(R.id.text, View.GONE); 4363b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 4373b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 4383b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek public static int calculateTopPadding(Context ctx) { 4393b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int padding = ctx.getResources().getDimensionPixelSize(R.dimen.notification_top_pad); 4403b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek int largePadding = ctx.getResources().getDimensionPixelSize( 4413b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek R.dimen.notification_top_pad_large_text); 4423b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek float fontScale = ctx.getResources().getConfiguration().fontScale; 4433b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek float largeFactor = (constrain(fontScale, 1.0f, 1.3f) - 1f) / (1.3f - 1f); 4443b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 4453b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek // Linearly interpolate the padding between large and normal with the font scale ranging 4463b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek // from 1f to LARGE_TEXT_SCALE 4473b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek return Math.round((1 - largeFactor) * padding + largeFactor * largePadding); 4483b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 4493b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek 4503b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek public static float constrain(float amount, float low, float high) { 4513b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek return amount < low ? low : (amount > high ? high : amount); 4523b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek } 453976b6a8c18550ace670e0410453741d11dafa474Ian Lake} 454