Professional Documents
Culture Documents
@JeremMartinez
TrustBK
The new traditional bank
TrustBK
Content title
Action
Kitkat (4.4)
Action
Lollipop (5.0)
ACTION
Marshmallow (6.0)
ACTION
Nougat (7.0)
Content title
Content text
ACTION
Android reo
Droidcon SubText 13:37
Content title
Content text
ACTION
Be a good
3 citizen
Letters SMS
Telegrams Emails
A M
P
Telegrams Emails
[ S
Phone calls Batman
1
Disruptions
through the day
Deletion
of information by mistake
Info forgotten
Bad timing
Amount
Priority
1 Category
Metadata
Amount
Priority
1 Category
Metadata
Amount
Priority
1 Category
Metadata
Importance
Channels
Global app view Channel view
4 Categorize
PAIN FUN
URGENT
PAIN FUN
NON-URGENT
URGENT
PAIN FUN
NON-URGENT
URGENT
FUN
VIP of our life
Urgent & Fun
URGENT
PAIN FUN
NON-URGENT
FUN
NON-URGENT
Procrastination
Non-urgent & Fun
URGENT
PAIN FUN
NON-URGENT
URGENT
PAIN
Livelihood
Urgent & Painful
URGENT
PAIN FUN
NON-URGENT
PAIN
NON-URGENT
Nagging
Non-urgent & Painful
2 main principles
to evaluate a notification
Be relevant
Help yourself with context
Be legitimate
Don’t lie about urgency
Use case
Scheduled
Always up to date
Scheduled
Urgent
5 Triggering
Notification notification = new NotificationCompat.Builder(this).
setSmallIcon(R.drawable.ic_notification).
setContentTitle("Title").
setContentText("Text").
build();
NotificationManagerCompat.from(this).notify(12345, notification);
Notification notification = new NotificationCompat.Builder(this).
setSmallIcon(R.drawable.ic_notification).
setContentTitle("Title").
setContentText("Text").
build();
NotificationManagerCompat.from(this).notify(12345, notification);
1. Local events
e.g. downloads, updates, posting a tweet
2. Scheduled
AlarmManager
context.getSystemService( AlarmManager.class);
alarmManager.setExact(type, triggerAtMillis, operation);
alarmManager.setExact(type, triggerAtMillis, operation);
setExact
if (BuildUtils.hasMarshmallow()) {
alarmManager.setExactAndAllowWhileIdle(type, millis, operation);
} else if (BuildUtils.hasKitKat()) {
alarmManager.setExact(type, millis, operation);
} else {
alarmManager.set(type, millis, operation);
}
setExact
if (BuildUtils.hasMarshmallow()) {
alarmManager.setExactAndAllowWhileIdle(type, millis, operation);
} else if (BuildUtils.hasKitKat()) {
alarmManager.setExact(type, millis, operation);
} else {
alarmManager.set(type, millis, operation);
}
setExact
if (BuildUtils.hasMarshmallow()) {
alarmManager.setExactAndAllowWhileIdle(type, millis, operation);
} else if (BuildUtils.hasKitKat()) {
alarmManager.setExact(type, millis, operation);
} else {
alarmManager.set(type, millis, operation);
}
setExact
if (BuildUtils.hasMarshmallow()) {
alarmManager.setExactAndAllowWhileIdle(type, millis, operation);
} else if (BuildUtils.hasKitKat()) {
alarmManager.setExact(type, millis, operation);
} else {
alarmManager.set(type, millis, operation);
}
alarmManager.setExact(type, triggerAtMillis, operation);
alarmManager.setExact (type, triggerAtMillis, operation);
type
System.currentTimeMillis()
time since boot including sleep
AlarmManager.RTC | AlarmManager.RTC_WAKEUP
type
SystemClock.elapsedRealtime()
wall clock time in UTC
AlarmManager.ELAPSED_REALTIME | AlarmManager.ELAPSED_REALTIME_WAKEUP
alarmManager.setExact (type, triggerAtMillis, operation);
alarmManager.setExact (type, triggerAtMillis, operation);
alarmManager.setExact (type, triggerAtMillis, operation);
operation PendingIntent
PendingIntent.getActivity( PendingIntent.getActivity(
context, context,
123, 123,
intent, intent,
FLAG_UPDATE_CURRENT); FLAG_UPDATE_CURRENT);
=?
final Intent intent = new Intent(this, MainActivity.class);
PendingIntent.getActivity( PendingIntent.getActivity(
context, context,
123, 123,
intent, intent,
FLAG_UPDATE_CURRENT); FLAG_UPDATE_CURRENT);
final Intent intent = new Intent(this, MainActivity.class);
PendingIntent.getActivity( PendingIntent.getActivity(
context, context,
1234, 1235,
intent, intent,
FLAG_UPDATE_CURRENT); FLAG_UPDATE_CURRENT);
=?
final Intent intent = new Intent(this, MainActivity.class);
PendingIntent.getActivity( PendingIntent.getActivity(
context, context,
1234, 1235,
intent, intent,
FLAG_UPDATE_CURRENT); FLAG_UPDATE_CURRENT);
final Intent intent1 = new Intent(this, MainActivity.class);
final Intent intent2 = new Intent(this, MainActivity.class);
PendingIntent.getActivity( PendingIntent.getActivity(
context, context,
123, 123,
intent1, intent2,
FLAG_UPDATE_CURRENT); FLAG_UPDATE_CURRENT);
=?
final Intent intent1 = new Intent(this, MainActivity.class);
final Intent intent2 = new Intent(this, MainActivity.class);
PendingIntent.getActivity( PendingIntent.getActivity(
context, context,
123, 123,
intent1, intent2,
FLAG_UPDATE_CURRENT); FLAG_UPDATE_CURRENT);
final Intent intent1 = new Intent(this, MainActivity.class).
putExtra("extra1", "extra1");
final Intent intent2 = new Intent(this, MainActivity.class).
putExtra(“extra2", "extra2");
PendingIntent.getActivity( PendingIntent.getActivity(
context, context,
123, 123,
intent1, intent2,
FLAG_UPDATE_CURRENT); FLAG_UPDATE_CURRENT);
=?
final Intent intent1 = new Intent(this, MainActivity.class).
putExtra("extra1", "extra1");
final Intent intent2 = new Intent(this, MainActivity.class).
putExtra(“extra2", "extra2");
PendingIntent.getActivity( PendingIntent.getActivity(
context, context,
123, 123,
intent1, intent2,
FLAG_UPDATE_CURRENT); FLAG_UPDATE_CURRENT);
final Intent intent1 = new Intent(this, MainActivity.class).
addCategory(Intent.CATEGORY_APP_BROWSER);
final Intent intent2 = new Intent(this, MainActivity.class).
addCategory(Intent.CATEGORY_APP_CALCULATOR);
PendingIntent.getActivity( PendingIntent.getActivity(
context, context,
123, 123,
intent1, intent2,
FLAG_UPDATE_CURRENT); FLAG_UPDATE_CURRENT);
=?
final Intent intent1 = new Intent(this, MainActivity.class).
addCategory(Intent.CATEGORY_APP_BROWSER);
final Intent intent2 = new Intent(this, MainActivity.class).
addCategory(Intent.CATEGORY_APP_CALCULATOR);
PendingIntent.getActivity( PendingIntent.getActivity(
context, context,
123, 123,
intent1, intent2,
FLAG_UPDATE_CURRENT); FLAG_UPDATE_CURRENT);
public boolean filterEquals(Intent other) {
if (other == null) {
return false;
}
if (!Objects.equals(this.mAction, other.mAction)) return false;
if (!Objects.equals(this.mData, other.mData)) return false;
if (!Objects.equals(this.mType, other.mType)) return false;
if (!Objects.equals(this.mPackage, other.mPackage)) return false;
if (!Objects.equals(this.mComponent, other.mComponent)) return false;
if (!Objects.equals(this.mCategories, other.mCategories)) return false;
return true;
}
It can be trickier…
Survive app upgrade
e N
a s
e l e
R
Register
PendingIntent
e N
a s
e l e
R
new Intent(this, MainActivity.class).
putExtra("extra1", "extra1");
Register
PendingIntent
e N
a s
e l e
R
Register
PendingIntent
“extra1" “extra2”
e N
a s Refactoring
e l e
R
Register
PendingIntent
N +1
se e N
l ea a s
e e l e
R R
Register
PendingIntent
N +1
se e N
l ea a s
e e l e
R R
new Intent(this, MainActivity.class).
putExtra("extra1", "extra1");
Register
PendingIntent
N +1
se e N
l ea a s
e e l e
R R
Register
PendingIntent
N +1 E
e N NP
a s se
e l e l ea
R Re
3. Realtime
Push notifications: GCM & Firebase
- Use extensively group
InboxStyle MessagingStyle
Default
BigText
BigPicture
Media
Notification.Style
DecoratedCustomViewStyle
RemoteViews
Run in another process
Avoid RemoteViews
Prefer default styling or span
Spanned everything!
Very powerful API — Available everywhere
SpannableString delayedSpanned = new SpannableString(delayed);
delayedSpanned.setSpan(new StrikethroughSpan(), //
0, delayedSpanned.length(), //
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
delayedSpanned.setSpan(new ForegroundColorSpan(textColor), //
0, delayedSpanned.length(), //
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
SpannableString delayedSpanned = new SpannableString(delayed);
delayedSpanned.setSpan(new StrikethroughSpan(), //
0, delayedSpanned.length(), //
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
delayedSpanned.setSpan(new ForegroundColorSpan(textColor), //
0, delayedSpanned.length(), //
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
SpannableString delayedSpanned = new SpannableString(delayed);
delayedSpanned.setSpan(new StrikethroughSpan(), //
0, delayedSpanned.length(), //
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
delayedSpanned.setSpan(new ForegroundColorSpan(textColor), //
0, delayedSpanned.length(), //
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
SpannableString delayedSpanned = new SpannableString(delayed);
delayedSpanned.setSpan(new StrikethroughSpan(), //
0, delayedSpanned.length(), //
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
delayedSpanned.setSpan(new ForegroundColorSpan(textColor), //
0, delayedSpanned.length(), //
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(delayedSpanned);
7 Other tips
Transient
Be able to find the same info
elsewhere in the app
Be patient
Wait for the content
Clean up
Delete outdated notification
Think VIP
Help Android to order
Think multi-devices
Synchronize notifications
8 Conclusion
www.trustbk.com @JeremMartinez