Compare commits

...

2 Commits

Author SHA1 Message Date
Philipp Crocoll
319d197d79 manifest for 1.12-r5-test2848 2025-04-15 18:20:14 +02:00
Philipp Crocoll
b459e9f9a5 add logging and improve permissions checking for issues with showing the Activate Keyboard screen. 2025-04-15 17:57:51 +02:00
8 changed files with 112 additions and 13 deletions

View File

@@ -56,6 +56,8 @@ using Android.Util;
using AndroidX.Core.Content;
using Google.Android.Material.Dialog;
using keepass2android;
using AndroidX.Core.App;
using Google.Android.Material.Snackbar;
namespace keepass2android
{
@@ -571,13 +573,41 @@ namespace keepass2android
if (permissions.Length == 1 && permissions.First() == Android.Manifest.Permission.PostNotifications &&
grantResults.First() == Permission.Granted)
{
StartNotificationsServiceAfterPermissionsCheck(requestCode == 1 /*requestCode is used to transfer this flag*/);
if (!CopyToClipboardService.HasEntryNotificationPermissions(this, false))
{
Intent intent = new Intent();
if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
intent.SetAction(Android.Provider.Settings.ActionAppNotificationSettings);
intent.PutExtra(Android.Provider.Settings.ExtraAppPackage, PackageName);
}
else if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
intent.SetAction(Android.Provider.Settings.ActionAppNotificationSettings);
intent.PutExtra("app_package", PackageName);
intent.PutExtra("app_uid", ApplicationInfo.Uid);
}
else
{
intent.SetAction(Android.Provider.Settings.ActionApplicationDetailsSettings);
intent.AddCategory(Intent.CategoryDefault);
intent.SetData(Uri.Parse("package:" + PackageName));
}
StartActivity(intent);
}
else
{
Kp2aLog.Log($"StartNotificationsServiceAfterPermissionsCheck(activateKeyboard: requestCode == {requestCode}");
StartNotificationsServiceAfterPermissionsCheck(requestCode == 1 /*requestCode is used to transfer this flag*/);
}
}
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
internal void StartNotificationsService(bool activateKeyboard)
{
Kp2aLog.Log($"StartNotificationsService. ActivateKeyboard={activateKeyboard}");
if (PreferenceManager.GetDefaultSharedPreferences(this).GetBoolean(
GetString(Resource.String.CopyToClipboardNotification_key),
Resources.GetBoolean(Resource.Boolean.CopyToClipboardNotification_default)) == false
@@ -585,13 +615,17 @@ namespace keepass2android
GetString(Resource.String.UseKp2aKeyboard_key),
Resources.GetBoolean(Resource.Boolean.UseKp2aKeyboard_default)) == false)
{
//notifications are disabled
//notifications are disabled
Kp2aLog.Log($"StartNotificationsService. Notifications disabled. Returning.");
return;
}
if ((int)Build.VERSION.SdkInt < 33 || CheckSelfPermission(Android.Manifest.Permission.PostNotifications) ==
Permission.Granted)
{
if ((int)Build.VERSION.SdkInt < 33 || CopyToClipboardService.HasEntryNotificationPermissions(this, activateKeyboard))
{
Kp2aLog.Log($"StartNotificationsService. Permissions ok. activateKeyboard={activateKeyboard}");
StartNotificationsServiceAfterPermissionsCheck(activateKeyboard);
return;
}
@@ -602,16 +636,40 @@ namespace keepass2android
if (!ShouldShowRequestPermissionRationale(Android.Manifest.Permission.PostNotifications) //this menthod returns false if we haven't asked yet or if the user has denied permission too often
&& PreferenceManager.GetDefaultSharedPreferences(this).GetBoolean("RequestedPostNotificationsPermission", false))//use a preference to tell the difference between "haven't asked yet" and "have asked too often"
{
//user has denied permission before. Do not show the dialog. User must give permission in the Android App settings.
Kp2aLog.Log($"StartNotificationsService. Permissions not granted. Showing snackbar.");
//user has denied permission before. Do not show the dialog. User must give permission in the Android App settings.
var snackbar = Snackbar
.Make(SnackbarAnchorView, Resource.String.post_notifications_snackbar,
Snackbar.LengthIndefinite);
snackbar.SetTextMaxLines(10);
if ((int)Build.VERSION.SdkInt >= 23)
{
snackbar.SetBackgroundTint(App.Context.GetColor(Resource.Color.md_theme_inverseSurface));
snackbar.SetTextColor(App.Context.GetColor(Resource.Color.md_theme_inverseOnSurface));
}
snackbar.SetAction(Resource.String.post_notifications_snackbar_config, view => { ShowNotificationPermissionsDialog(activateKeyboard); });
snackbar.Show();
return;
}
ShowNotificationPermissionsDialog(activateKeyboard);
}
private void ShowNotificationPermissionsDialog(bool activateKeyboard)
{
Kp2aLog.Log($"ShowNotificationPermissionsDialog");
new MaterialAlertDialogBuilder(this)
.SetTitle(Resource.String.post_notifications_dialog_title)
.SetMessage(Resource.String.post_notifications_dialog_message)
.SetNegativeButton(Resource.String.post_notifications_dialog_disable, (sender, args) =>
{
//disable this dialog for the future by disabling the notification preferences
//disable this dialog for the future by disabling the notification preferences
var edit= PreferenceManager.GetDefaultSharedPreferences(this).Edit();
edit.PutBoolean(GetString(Resource.String.CopyToClipboardNotification_key), false);
edit.PutBoolean(GetString(Resource.String.UseKp2aKeyboard_key), false);
@@ -632,8 +690,6 @@ namespace keepass2android
})
.SetNeutralButton(Resource.String.post_notifications_dialog_notnow, (sender, args) => { })
.Show();
}
private void StartNotificationsServiceAfterPermissionsCheck(bool activateKeyboard)

View File

@@ -337,6 +337,7 @@ namespace keepass2android
if (PreferenceManager.GetDefaultSharedPreferences(this)
.GetBoolean(GetString(Resource.String.UseKp2aKeyboardInKp2a_key), false))
{
Kp2aLog.Log("Activating keyboard in EntryEditActivity due to UseKp2aKeyboardInKp2a");
CopyToClipboardService.ActivateKeyboard(this);
}
}

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="206"
android:versionName="1.12-r5"
android:versionCode="207"
android:versionName="1.12-r5-test2848"
package="keepass2android.keepass2android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto">

View File

@@ -1578,7 +1578,8 @@ namespace keepass2android
if (PreferenceManager.GetDefaultSharedPreferences(this)
.GetBoolean(GetString(Resource.String.UseKp2aKeyboardInKp2a_key), false))
{
CopyToClipboardService.ActivateKeyboard(this);
Kp2aLog.Log("Activating keyboard in PasswordActivity due to UseKp2aKeyboardInKp2a");
CopyToClipboardService.ActivateKeyboard(this);
}
DonateReminder.ShowDonateReminderIfAppropriate(this);

View File

@@ -1224,6 +1224,9 @@
<string name="enable_fingerprint_hint">Keepass2Android has detected biometric hardware. Do you want to enable Biometric Unlock for this database?</string>
<string name="post_notifications_dialog_title">Allow notifications</string>
<string name="post_notifications_dialog_message">Keepass2Android can show notifications with buttons to copy values like passwords and TOTPs to clipboard, or to bring up the built-in keyboard. This is useful to transfer values into other apps without switching to Keepass2Android repeatedly. Do you want to enable such notifications?</string>
<string name="post_notifications_snackbar">Cannot make entry available through notification. No permission granted.</string>
<string name="post_notifications_snackbar_config">Configure</string>
<string name="post_notifications_dialog_allow">Allow notifications</string>
<string name="post_notifications_dialog_disable">Disable this feature</string>
<string name="post_notifications_dialog_notnow">Not now</string>

View File

@@ -328,6 +328,7 @@ namespace keepass2android
if (prefs.GetBoolean("kp2a_switch_rooted", false))
{
activationCondition = ActivationCondition.Always;
Kp2aLog.Log("Will activate keyboard because SearchUrlTask opened with ActionSend and kp2a_switch_rooted");
}
else
{
@@ -336,6 +337,7 @@ namespace keepass2android
if (prefs.GetBoolean(this.GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), this.Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default)))
{
activationCondition = ActivationCondition.Always;
Kp2aLog.Log("Will activate keyboard because SearchUrlTask opened with ActionSend and OpenKp2aKeyboardAutomatically");
}
}

View File

@@ -355,6 +355,10 @@ namespace keepass2android
activity.GetString(Resource.String
.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key), false);
Kp2aLog.Log($"AppTask.CompleteOnCreateEntryActivity. ActivateKeyboard={activateKeyboard}, kp2a_switch_rooted={prefs.GetBoolean("kp2a_switch_rooted", false)}, OpenKp2aKeyboardAutomaticallyOnlyAfterSearch={prefs.GetBoolean(
activity.GetString(Resource.String
.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key), false)}");
activity.StartNotificationsService(activateKeyboard);
}
@@ -622,6 +626,7 @@ namespace keepass2android
bool isTotpEntry = totpPluginAdapter != null;
bool activateKeyboard = ActivateKeyboard == ActivationCondition.Always || (ActivateKeyboard == ActivationCondition.WhenTotp && isTotpEntry);
Kp2aLog.Log($"activateKeyboard == {activateKeyboard}. Task.Activate=={ActivateKeyboard}, isTotpEntry={isTotpEntry}");
if ((ShowUserNotifications == ActivationCondition.Always)
|| ((ShowUserNotifications == ActivationCondition.WhenTotp) && isTotpEntry)

View File

@@ -878,6 +878,37 @@ namespace keepass2android
{
get { return PackageName + "/keepass2android.softkeyboard.KP2AKeyboard"; }
}
private static bool IsChannelPermissionGranted(Context context, string channelId)
{
if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
if (!string.IsNullOrEmpty(channelId))
{
NotificationManager? manager =
(NotificationManager?)context.GetSystemService(Context.NotificationService)!;
NotificationChannel? channel = manager?.GetNotificationChannel(channelId);
return channel?.Importance != Android.App.NotificationImportance.None;
}
return false;
}
return true;
}
public static bool HasEntryNotificationPermissions(Context context, bool activateKeyboard)
{
if (!NotificationManagerCompat.From(context).AreNotificationsEnabled())
{
return false;
}
return IsChannelPermissionGranted(context, App.NotificationChannelIdEntry);
}
}
[BroadcastReceiver(Permission = "keepass2android." + AppNames.PackagePart + ".permission.CopyToClipboard")]