Android auto support

pull/187/head
M66B 5 years ago
parent a0b3b88cc7
commit 07287df049

@ -121,6 +121,9 @@
<meta-data <meta-data
android:name="android.allow_multiple_resumed_activities" android:name="android.allow_multiple_resumed_activities"
android:value="true" /> android:value="true" />
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/car" />
<meta-data <meta-data
android:name="com.bugsnag.android.API_KEY" android:name="com.bugsnag.android.API_KEY"
android:value="9d2d57476a0614974449a3ec33f2604a" /> android:value="9d2d57476a0614974449a3ec33f2604a" />

@ -38,7 +38,9 @@ import android.util.Pair;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.core.app.Person;
import androidx.core.app.RemoteInput; import androidx.core.app.RemoteInput;
import androidx.core.graphics.drawable.IconCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
@ -3562,6 +3564,7 @@ class Core {
boolean name_email = prefs.getBoolean("name_email", false); boolean name_email = prefs.getBoolean("name_email", false);
boolean prefer_contact = prefs.getBoolean("prefer_contact", false); boolean prefer_contact = prefs.getBoolean("prefer_contact", false);
boolean flags = prefs.getBoolean("flags", true); boolean flags = prefs.getBoolean("flags", true);
boolean notify_messaging = prefs.getBoolean("notify_messaging", false);
boolean notify_preview = prefs.getBoolean("notify_preview", true); boolean notify_preview = prefs.getBoolean("notify_preview", true);
boolean notify_preview_all = prefs.getBoolean("notify_preview_all", false); boolean notify_preview_all = prefs.getBoolean("notify_preview_all", false);
boolean wearable_preview = prefs.getBoolean("wearable_preview", false); boolean wearable_preview = prefs.getBoolean("wearable_preview", false);
@ -3782,6 +3785,17 @@ class Core {
.setOnlyAlertOnce(alert_once) .setOnlyAlertOnce(alert_once)
.setAllowSystemGeneratedContextualActions(false); .setAllowSystemGeneratedContextualActions(false);
NotificationCompat.MessagingStyle messagingStyle = null;
if (notify_messaging) {
// https://developer.android.com/training/cars/messaging
Person.Builder me = new Person.Builder()
.setName(MessageHelper.formatAddresses(message.to, name_email, false));
messagingStyle = new NotificationCompat.MessagingStyle(me.build());
if (!TextUtils.isEmpty(message.subject))
messagingStyle.setConversationTitle(message.subject);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
mbuilder mbuilder
.setGroup(Long.toString(group)) .setGroup(Long.toString(group))
@ -3815,6 +3829,7 @@ class Core {
context.getString(R.string.title_advanced_notify_action_trash), context.getString(R.string.title_advanced_notify_action_trash),
piTrash) piTrash)
.setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_DELETE) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_DELETE)
.setShowsUserInterface(false)
.setAllowGeneratedReplies(false); .setAllowGeneratedReplies(false);
mbuilder.addAction(actionTrash.build()); mbuilder.addAction(actionTrash.build());
@ -3832,6 +3847,7 @@ class Core {
R.drawable.twotone_report_problem_24, R.drawable.twotone_report_problem_24,
context.getString(R.string.title_advanced_notify_action_junk), context.getString(R.string.title_advanced_notify_action_junk),
piJunk) piJunk)
.setShowsUserInterface(false)
.setAllowGeneratedReplies(false); .setAllowGeneratedReplies(false);
mbuilder.addAction(actionJunk.build()); mbuilder.addAction(actionJunk.build());
@ -3850,6 +3866,7 @@ class Core {
context.getString(R.string.title_advanced_notify_action_archive), context.getString(R.string.title_advanced_notify_action_archive),
piArchive) piArchive)
.setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_ARCHIVE) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_ARCHIVE)
.setShowsUserInterface(false)
.setAllowGeneratedReplies(false); .setAllowGeneratedReplies(false);
mbuilder.addAction(actionArchive.build()); mbuilder.addAction(actionArchive.build());
@ -3870,6 +3887,7 @@ class Core {
R.drawable.twotone_folder_24, R.drawable.twotone_folder_24,
folder.getDisplayName(context), folder.getDisplayName(context),
piMove) piMove)
.setShowsUserInterface(false)
.setAllowGeneratedReplies(false); .setAllowGeneratedReplies(false);
mbuilder.addAction(actionMove.build()); mbuilder.addAction(actionMove.build());
@ -3890,7 +3908,7 @@ class Core {
R.drawable.twotone_reply_24, R.drawable.twotone_reply_24,
context.getString(R.string.title_advanced_notify_action_reply), context.getString(R.string.title_advanced_notify_action_reply),
piReply) piReply)
.setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY) .setShowsUserInterface(true)
.setAllowGeneratedReplies(false); .setAllowGeneratedReplies(false);
mbuilder.addAction(actionReply.build()); mbuilder.addAction(actionReply.build());
} }
@ -3909,6 +3927,7 @@ class Core {
context.getString(R.string.title_advanced_notify_action_reply_direct), context.getString(R.string.title_advanced_notify_action_reply_direct),
piReply) piReply)
.setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY)
.setShowsUserInterface(false)
.setAllowGeneratedReplies(false); .setAllowGeneratedReplies(false);
RemoteInput.Builder input = new RemoteInput.Builder("text") RemoteInput.Builder input = new RemoteInput.Builder("text")
.setLabel(context.getString(R.string.title_advanced_notify_action_reply)); .setLabel(context.getString(R.string.title_advanced_notify_action_reply));
@ -3927,6 +3946,7 @@ class Core {
context.getString(R.string.title_advanced_notify_action_flag), context.getString(R.string.title_advanced_notify_action_flag),
piFlag) piFlag)
.setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_THUMBS_UP) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_THUMBS_UP)
.setShowsUserInterface(false)
.setAllowGeneratedReplies(false); .setAllowGeneratedReplies(false);
mbuilder.addAction(actionFlag.build()); mbuilder.addAction(actionFlag.build());
@ -3943,6 +3963,7 @@ class Core {
context.getString(R.string.title_advanced_notify_action_seen), context.getString(R.string.title_advanced_notify_action_seen),
piSeen) piSeen)
.setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ)
.setShowsUserInterface(false)
.setAllowGeneratedReplies(false); .setAllowGeneratedReplies(false);
mbuilder.addAction(actionSeen.build()); mbuilder.addAction(actionSeen.build());
@ -3959,6 +3980,7 @@ class Core {
context.getString(R.string.title_advanced_notify_action_snooze), context.getString(R.string.title_advanced_notify_action_snooze),
piSnooze) piSnooze)
.setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MUTE) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MUTE)
.setShowsUserInterface(false)
.setAllowGeneratedReplies(false); .setAllowGeneratedReplies(false);
mbuilder.addAction(actionSnooze.build()); mbuilder.addAction(actionSnooze.build());
@ -3998,6 +4020,7 @@ class Core {
} }
// Device // Device
if (messagingStyle == null) {
StringBuilder sbm = new StringBuilder(); StringBuilder sbm = new StringBuilder();
if (!TextUtils.isEmpty(message.subject)) if (!TextUtils.isEmpty(message.subject))
sbm.append("<em>").append(message.subject).append("</em>").append("<br>"); sbm.append("<em>").append(message.subject).append("</em>").append("<br>");
@ -4013,6 +4036,20 @@ class Core {
mbuilder.setStyle(bigText); mbuilder.setStyle(bigText);
} }
} else {
Person.Builder you = new Person.Builder()
.setName(MessageHelper.formatAddresses(message.from, name_email, false));
if (info[0].hasPhoto())
you.setIcon(IconCompat.createWithBitmap(info[0].getPhotoBitmap()));
if (info[0].hasLookupUri())
you.setUri(info[0].getLookupUri().toString());
messagingStyle.addMessage(preview == null ? "" : preview, message.received, you.build());
mbuilder.setStyle(messagingStyle);
}
} else { } else {
if (!TextUtils.isEmpty(message.subject)) if (!TextUtils.isEmpty(message.subject))
mbuilder.setContentText(message.subject); mbuilder.setContentText(message.subject);

@ -87,6 +87,7 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared
private SwitchCompat swNotifyPreviewAll; private SwitchCompat swNotifyPreviewAll;
private SwitchCompat swNotifyPreviewOnly; private SwitchCompat swNotifyPreviewOnly;
private SwitchCompat swWearablePreview; private SwitchCompat swWearablePreview;
private SwitchCompat swMessagingStyle;
private SwitchCompat swBiometricsNotify; private SwitchCompat swBiometricsNotify;
private SwitchCompat swAlertOnce; private SwitchCompat swAlertOnce;
private TextView tvNoGrouping; private TextView tvNoGrouping;
@ -105,6 +106,7 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared
"badge", "unseen_ignored", "badge", "unseen_ignored",
"notify_background_only", "notify_known", "notify_summary", "notify_remove", "notify_clear", "notify_background_only", "notify_known", "notify_summary", "notify_remove", "notify_clear",
"notify_preview", "notify_preview_all", "notify_preview_only", "wearable_preview", "notify_preview", "notify_preview_all", "notify_preview_only", "wearable_preview",
"notify_messaging",
"biometrics_notify", "biometrics_notify",
"alert_once" "alert_once"
}; };
@ -153,6 +155,7 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared
swNotifyPreviewAll = view.findViewById(R.id.swNotifyPreviewAll); swNotifyPreviewAll = view.findViewById(R.id.swNotifyPreviewAll);
swNotifyPreviewOnly = view.findViewById(R.id.swNotifyPreviewOnly); swNotifyPreviewOnly = view.findViewById(R.id.swNotifyPreviewOnly);
swWearablePreview = view.findViewById(R.id.swWearablePreview); swWearablePreview = view.findViewById(R.id.swWearablePreview);
swMessagingStyle = view.findViewById(R.id.swMessagingStyle);
swBiometricsNotify = view.findViewById(R.id.swBiometricsNotify); swBiometricsNotify = view.findViewById(R.id.swBiometricsNotify);
swAlertOnce = view.findViewById(R.id.swAlertOnce); swAlertOnce = view.findViewById(R.id.swAlertOnce);
tvNoGrouping = view.findViewById(R.id.tvNoGrouping); tvNoGrouping = view.findViewById(R.id.tvNoGrouping);
@ -400,6 +403,13 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared
} }
}); });
swMessagingStyle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
prefs.edit().putBoolean("notify_messaging", checked).apply();
}
});
swBiometricsNotify.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { swBiometricsNotify.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override @Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
@ -521,6 +531,7 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared
swNotifyPreviewAll.setChecked(prefs.getBoolean("notify_preview_all", false)); swNotifyPreviewAll.setChecked(prefs.getBoolean("notify_preview_all", false));
swNotifyPreviewOnly.setChecked(prefs.getBoolean("notify_preview_only", false)); swNotifyPreviewOnly.setChecked(prefs.getBoolean("notify_preview_only", false));
swWearablePreview.setChecked(prefs.getBoolean("wearable_preview", false)); swWearablePreview.setChecked(prefs.getBoolean("wearable_preview", false));
swMessagingStyle.setChecked(prefs.getBoolean("notify_messaging", false));
swBiometricsNotify.setChecked(prefs.getBoolean("biometrics_notify", false)); swBiometricsNotify.setChecked(prefs.getBoolean("biometrics_notify", false));
swAlertOnce.setChecked(!prefs.getBoolean("alert_once", true)); swAlertOnce.setChecked(!prefs.getBoolean("alert_once", true));

@ -534,6 +534,29 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swWearablePreview" /> app:layout_constraintTop_toBottomOf="@id/swWearablePreview" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swMessagingStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_advanced_notify_messaging"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvWearablePreviewHint"
app:switchPadding="12dp" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvMessagingStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="48dp"
android:text="@string/title_advanced_messaging_hint"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="italic"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swMessagingStyle" />
<androidx.appcompat.widget.SwitchCompat <androidx.appcompat.widget.SwitchCompat
android:id="@+id/swBiometricsNotify" android:id="@+id/swBiometricsNotify"
android:layout_width="0dp" android:layout_width="0dp"
@ -542,7 +565,7 @@
android:text="@string/title_advanced_biometrics_notify" android:text="@string/title_advanced_biometrics_notify"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvWearablePreviewHint" app:layout_constraintTop_toBottomOf="@id/tvMessagingStyle"
app:switchPadding="12dp" /> app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat <androidx.appcompat.widget.SwitchCompat

@ -452,6 +452,7 @@
<string name="title_advanced_notify_remove">Remove new message notification on tapping on notification</string> <string name="title_advanced_notify_remove">Remove new message notification on tapping on notification</string>
<string name="title_advanced_notify_clear">Remove new message notifications on viewing message list</string> <string name="title_advanced_notify_clear">Remove new message notifications on viewing message list</string>
<string name="title_advanced_wearable_preview">Only send notifications with a message preview to wearables</string> <string name="title_advanced_wearable_preview">Only send notifications with a message preview to wearables</string>
<string name="title_advanced_notify_messaging">Use Android messaging style notification format</string>
<string name="title_advanced_biometrics_notify">Show notification content when using biometric authentication</string> <string name="title_advanced_biometrics_notify">Show notification content when using biometric authentication</string>
<string name="title_advanced_light">Use notification light</string> <string name="title_advanced_light">Use notification light</string>
<string name="title_advanced_sound">Select notification sound</string> <string name="title_advanced_sound">Select notification sound</string>
@ -585,6 +586,7 @@
<string name="title_advanced_notify_preview_all_hint">For wearables that can show the full text (up to 5,000 characters)</string> <string name="title_advanced_notify_preview_all_hint">For wearables that can show the full text (up to 5,000 characters)</string>
<string name="title_advanced_notify_preview_only_hint">This delays showing of notifications until the message text has been downloaded</string> <string name="title_advanced_notify_preview_only_hint">This delays showing of notifications until the message text has been downloaded</string>
<string name="title_advanced_wearable_hint">Notifications are only sent to a wearable after the message text has been downloaded</string> <string name="title_advanced_wearable_hint">Notifications are only sent to a wearable after the message text has been downloaded</string>
<string name="title_advanced_messaging_hint">This is required for Android Auto support</string>
<string name="title_advanced_move_hint">The target folder can be configured in the account settings</string> <string name="title_advanced_move_hint">The target folder can be configured in the account settings</string>
<string name="title_advanced_notify_no_grouping">This Android version does not support notification grouping</string> <string name="title_advanced_notify_no_grouping">This Android version does not support notification grouping</string>
<string name="title_advanced_notify_no_channels">This Android version does not support notification channels</string> <string name="title_advanced_notify_no_channels">This Android version does not support notification channels</string>

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<automotiveApp>
<uses name="notification" />
</automotiveApp>
Loading…
Cancel
Save