* update target-sdk version to 33. update some packages (build currently fails for flavor=Net, but works with NoNet)

* make changes to comply with new target sdk version requirements (mostly Exported-attribute and mutability flags)
* drop samsung fingerprint support (as suggested by Samsung), would require more hacks to keep it with the new target sdk version
* add build-properties.props to allow specifying a flavor in VS builds.
This commit is contained in:
Philipp Crocoll
2023-01-23 10:07:15 +01:00
parent f6e6d0e59c
commit 4b3f6657a8
34 changed files with 127 additions and 331 deletions

View File

@@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 17
VisualStudioVersion = 16.0.29418.71 VisualStudioVersion = 17.4.33205.214
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePassLib2Android", "KeePassLib2Android\KeePassLib2Android.csproj", "{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePassLib2Android", "KeePassLib2Android\KeePassLib2Android.csproj", "{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}"
EndProject EndProject
@@ -25,8 +25,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCloudBindings", "PCloudBin
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "keepass2android-app", "keepass2android\keepass2android-app.csproj", "{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "keepass2android-app", "keepass2android\keepass2android-app.csproj", "{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SamsungPass", "SamsungPass\Xamarin.SamsungPass\SamsungPass\SamsungPass.csproj", "{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -285,30 +283,6 @@ Global
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU {D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|x64.Build.0 = Release|Any CPU {D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|x64.Build.0 = Release|Any CPU
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|x64.Deploy.0 = Release|Any CPU {D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|x64.Deploy.0 = Release|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Win32.ActiveCfg = Debug|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Win32.Build.0 = Debug|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|x64.ActiveCfg = Debug|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|x64.Build.0 = Debug|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Any CPU.Build.0 = Release|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Win32.ActiveCfg = Release|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Win32.Build.0 = Release|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|x64.ActiveCfg = Release|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|x64.Build.0 = Release|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Win32.Build.0 = ReleaseNoNet|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|x64.Build.0 = ReleaseNoNet|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -1,5 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" InitialTargets="showFlavor">
<Target Name="showFlavor" AfterTargets="Build">
<Message Importance="high" Text="building flavor $(Flavor)"></Message>
</Target>
<Import Project="../build-properties.props"/>
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -12,7 +16,7 @@
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile> <AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies> <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<TargetFrameworkVersion>v11.0</TargetFrameworkVersion> <TargetFrameworkVersion>v13.0</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk> <AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<Flavor Condition=" '$(Flavor)' != '' ">$(Flavor)</Flavor> <Flavor Condition=" '$(Flavor)' != '' ">$(Flavor)</Flavor>
<NuGetPackageImportStamp> <NuGetPackageImportStamp>
@@ -66,7 +70,7 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(Flavor)'!='NoNet' "> <ItemGroup Condition=" '$(Flavor)'!='NoNet' ">
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(Flavor)'!='NoNet' "> <ItemGroup Condition=" '$(Flavor)'!='NoNet' ">
<Compile Include="Io\DropboxFileStorage.cs" /> <Compile Include="Io\DropboxFileStorage.cs" />
@@ -181,16 +185,16 @@
<Version>31.3.1</Version> <Version>31.3.1</Version>
</PackageReference> </PackageReference>
<PackageReference Include="MegaApiClient"> <PackageReference Include="MegaApiClient">
<Version>1.10.2</Version> <Version>1.10.3</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Graph"> <PackageReference Include="Microsoft.Graph">
<Version>1.21.0</Version> <Version>1.21.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Graph.Auth"> <PackageReference Include="Microsoft.Graph.Auth">
<Version>1.0.0-preview.1</Version> <Version>1.0.0-preview.7</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Identity.Client"> <PackageReference Include="Microsoft.Identity.Client">
<Version>4.8.2</Version> <Version>4.49.1</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -297,7 +301,7 @@
<Version>28.0.0.3</Version> <Version>28.0.0.3</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.AndroidX.Preference"> <PackageReference Include="Xamarin.AndroidX.Preference">
<Version>1.1.1.11</Version> <Version>1.2.0.3</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />

View File

@@ -0,0 +1,9 @@
<Project>
<PropertyGroup>
<Flavor>NoNet</Flavor>
</PropertyGroup>
</Project>

View File

@@ -39,7 +39,7 @@ dependencies {
implementation 'com.google.api-client:google-api-client:1.30.5' implementation 'com.google.api-client:google-api-client:1.30.5'
implementation 'com.google.api-client:google-api-client-android:1.30.5' implementation 'com.google.api-client:google-api-client-android:1.30.5'
implementation 'com.google.android.gms:play-services-auth:19.2.0' implementation 'com.google.android.gms:play-services-auth:20.4.0'
//onedrive: //onedrive:
compile('com.onedrive.sdk:onedrive-sdk-android:1.2.0') { compile('com.onedrive.sdk:onedrive-sdk-android:1.2.0') {
transitive = false transitive = false

View File

@@ -3,6 +3,8 @@ android {
compileSdkVersion 23 compileSdkVersion 23
buildToolsVersion '28.0.3' buildToolsVersion '28.0.3'
ndkVersion '21.0.6113669'
defaultConfig { defaultConfig {
minSdkVersion 18 minSdkVersion 18
} }

View File

@@ -10,7 +10,8 @@ namespace keepass2android
{ {
[Activity(Label = "@string/app_name", [Activity(Label = "@string/app_name",
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden,
Theme = "@style/MyTheme_ActionBar")] Theme = "@style/MyTheme_ActionBar",
Exported = true)]
[IntentFilter(new[] { "kp2a.action.AboutActivity" }, Categories = new[] { Intent.CategoryDefault })] [IntentFilter(new[] { "kp2a.action.AboutActivity" }, Categories = new[] { Intent.CategoryDefault })]
public class AboutActivity: Activity, IDialogInterfaceOnDismissListener public class AboutActivity: Activity, IDialogInterfaceOnDismissListener
{ {

View File

@@ -28,7 +28,7 @@ using Object = Java.Lang.Object;
namespace keepass2android namespace keepass2android
{ {
[Activity(Label = "@string/child_dbs_title", MainLauncher = false, Theme = "@style/MyTheme_Blue", LaunchMode = LaunchMode.SingleInstance, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden)] [Activity(Label = "@string/child_dbs_title", MainLauncher = false, Theme = "@style/MyTheme_Blue", LaunchMode = LaunchMode.SingleInstance, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden, Exported = true)]
[IntentFilter(new[] { "kp2a.action.ConfigureChildDatabasesActivity" }, Categories = new[] { Intent.CategoryDefault })] [IntentFilter(new[] { "kp2a.action.ConfigureChildDatabasesActivity" }, Categories = new[] { Intent.CategoryDefault })]
public class ConfigureChildDatabasesActivity : LockCloseActivity public class ConfigureChildDatabasesActivity : LockCloseActivity
{ {

View File

@@ -68,6 +68,12 @@ namespace keepass2android
Intent reply = new Intent(); Intent reply = new Intent();
FillResponse.Builder builder = new FillResponse.Builder(); FillResponse.Builder builder = new FillResponse.Builder();
AssistStructure structure = (AssistStructure)Intent.GetParcelableExtra(AutofillManager.ExtraAssistStructure); AssistStructure structure = (AssistStructure)Intent.GetParcelableExtra(AutofillManager.ExtraAssistStructure);
if (structure == null)
{
SetResult(Result.Canceled);
Finish();
return;
}
StructureParser parser = new StructureParser(this, structure); StructureParser parser = new StructureParser(this, structure);
try try
{ {

View File

@@ -41,7 +41,7 @@ namespace keepass2android
[Activity(Label = "@string/app_name", [Activity(Label = "@string/app_name",
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden,
Theme = "@style/MyTheme_ActionBar")] Theme = "@style/MyTheme_ActionBar", Exported = true)]
[IntentFilter(new[] {"kp2a.action.ExportDatabaseActivity"}, Categories = new[] {Intent.CategoryDefault})] [IntentFilter(new[] {"kp2a.action.ExportDatabaseActivity"}, Categories = new[] {Intent.CategoryDefault})]
public class ExportDatabaseActivity : LockCloseActivity public class ExportDatabaseActivity : LockCloseActivity
{ {

View File

@@ -1,157 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.Hardware.Biometrics;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using Com.Samsung.Android.Sdk;
using Com.Samsung.Android.Sdk.Pass;
using Java.Lang;
namespace keepass2android
{
class BiometrySamsungIdentifier: IBiometricIdentifier
{
private readonly Context _context;
SpassFingerprint _spassFingerprint;
Spass _spass;
public BiometrySamsungIdentifier(Context context)
{
_context = context;
_spass = new Spass();
try
{
_spass.Initialize(context);
}
catch (SecurityException)
{
//"Did you add the permission to the AndroidManifest.xml?");
throw;
}
if (_spass.IsFeatureEnabled(Spass.DeviceFingerprint))
{
_spassFingerprint = new SpassFingerprint(context);
}
else
{
throw new RuntimeException("Fingerprint Featue not available.");
}
}
public bool Init()
{
try
{
return _spassFingerprint.HasRegisteredFinger;
}
catch (UnsupportedOperationException)
{
return false;
}
}
class IdentifyListener : Java.Lang.Object, IIdentifyListener
{
private readonly IBiometricAuthCallback _callback;
private readonly Context _context;
private readonly BiometrySamsungIdentifier _id;
public IdentifyListener(IBiometricAuthCallback callback, Context context, BiometrySamsungIdentifier id)
{
_callback = callback;
_context = context;
_id = id;
}
public void OnFinished (int responseCode)
{
_id.Listening = false;
if (responseCode == SpassFingerprint.StatusAuthentificationSuccess)
{
_callback.OnBiometricAuthSucceeded();
}
else if (responseCode == SpassFingerprint.StatusAuthentificationPasswordSuccess)
{
_callback.OnBiometricAuthSucceeded();
}
}
public void OnReady ()
{
}
public void OnCompleted()
{
// TODO
}
public void OnStarted ()
{
}
}
internal bool Listening
{
get; set;
}
public void StartListening(IBiometricAuthCallback callback)
{
if (Listening) return;
try
{
_spassFingerprint.StartIdentifyWithDialog(_context, new IdentifyListener(callback, _context, this), false);
Listening = true;
}
catch (SpassInvalidStateException m)
{
callback.OnBiometricError(m.Message);
}
catch (IllegalStateException ex)
{
callback.OnBiometricError(ex.Message);
}
}
public void StopListening()
{
try
{
_spassFingerprint.CancelIdentify();
Listening = false;
}
catch (IllegalStateException ise)
{
Kp2aLog.Log(ise.ToString());
}
catch (System.Exception e)
{
Kp2aLog.LogUnexpectedError(e);
}
}
public bool HasUserInterface
{
get { return false; }
}
}
}

View File

@@ -22,7 +22,7 @@ namespace keepass2android
{ {
[Activity(Label = "@string/app_name", [Activity(Label = "@string/app_name",
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden,
Theme = "@style/MyTheme_ActionBar", MainLauncher = false)] Theme = "@style/MyTheme_ActionBar", MainLauncher = false, Exported = true)]
[IntentFilter(new[] { "kp2a.action.FingerprintSetupActivity" }, Categories = new[] { Intent.CategoryDefault })] [IntentFilter(new[] { "kp2a.action.FingerprintSetupActivity" }, Categories = new[] { Intent.CategoryDefault })]
public class BiometricSetupActivity : LockCloseActivity, IBiometricAuthCallback public class BiometricSetupActivity : LockCloseActivity, IBiometricAuthCallback
{ {
@@ -142,29 +142,6 @@ namespace keepass2android
FindViewById(Resource.Id.close_database_after_failed).Visibility = _unlockMode == FingerprintUnlockMode.QuickUnlock ? ViewStates.Visible : ViewStates.Gone; FindViewById(Resource.Id.close_database_after_failed).Visibility = _unlockMode == FingerprintUnlockMode.QuickUnlock ? ViewStates.Visible : ViewStates.Gone;
} }
private bool TrySetupSamsung()
{
try
{
//try to create a Samsung ID object
_samsungBiometry = new BiometrySamsungIdentifier(this);
if (!_samsungBiometry.Init())
{
SetError(Resource.String.fingerprint_no_enrolled);
}
ShowRadioButtons();
FindViewById(Resource.Id.container_fingerprint_unlock).Visibility = _samsungBiometry == null
? ViewStates.Visible
: ViewStates.Gone;
return true;
}
catch (Exception)
{
_samsungBiometry = null;
return false;
}
}
string CurrentPreferenceKey string CurrentPreferenceKey
{ {
get { return App.Kp2a.CurrentDb.CurrentFingerprintPrefKey; } get { return App.Kp2a.CurrentDb.CurrentFingerprintPrefKey; }
@@ -246,17 +223,6 @@ namespace keepass2android
return; return;
if (_samsungBiometry != null)
{
_unlockMode = newMode;
UpdateCloseDatabaseAfterFailedBiometricQuickUnlockVisibility();
ISharedPreferencesEditor edit = PreferenceManager.GetDefaultSharedPreferences(this).Edit();
edit.PutString(App.Kp2a.CurrentDb.CurrentFingerprintModePrefKey, _unlockMode.ToString());
edit.Commit();
return;
}
if (newMode == FingerprintUnlockMode.Disabled) if (newMode == FingerprintUnlockMode.Disabled)
{ {
_unlockMode = newMode; _unlockMode = newMode;
@@ -296,8 +262,6 @@ namespace keepass2android
private ImageView _fpIcon; private ImageView _fpIcon;
private TextView _fpTextView; private TextView _fpTextView;
private BiometrySamsungIdentifier _samsungBiometry;
public void OnBiometricAuthSucceeded() public void OnBiometricAuthSucceeded()
{ {
_unlockMode = _desiredUnlockMode; _unlockMode = _desiredUnlockMode;
@@ -353,9 +317,7 @@ namespace keepass2android
HideRadioButtons(); HideRadioButtons();
if (!fpModule.IsHardwareAvailable) if (!fpModule.IsHardwareAvailable)
{ {
//seems like not all Samsung Devices (e.g. Note 4) don't support the Android 6 fingerprint API SetError(Resource.String.fingerprint_hardware_error);
if (!TrySetupSamsung())
SetError(Resource.String.fingerprint_hardware_error);
UpdateCloseDatabaseAfterFailedBiometricQuickUnlockVisibility(); UpdateCloseDatabaseAfterFailedBiometricQuickUnlockVisibility();
return; return;
} }

View File

@@ -42,7 +42,7 @@ using Object = Java.Lang.Object;
namespace keepass2android namespace keepass2android
{ {
[Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden, Theme = "@style/MyTheme_ActionBar")] [Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden, Theme = "@style/MyTheme_ActionBar", Exported = true)]
[MetaData("android.app.default_searchable", Value = "keepass2android.search.SearchResults")] [MetaData("android.app.default_searchable", Value = "keepass2android.search.SearchResults")]
#if NoNet #if NoNet
[MetaData("android.app.searchable", Resource = "@xml/searchable_offline")] [MetaData("android.app.searchable", Resource = "@xml/searchable_offline")]

View File

@@ -68,7 +68,7 @@ namespace keepass2android
/// <summary> /// <summary>
/// Launcher activity of Keepass2Android. This activity usually forwards to SelectCurrentDb but may show the revision dialog after installation or updates. /// Launcher activity of Keepass2Android. This activity usually forwards to SelectCurrentDb but may show the revision dialog after installation or updates.
/// </summary> /// </summary>
[Activity(Label = AppNames.AppName, MainLauncher = false, Theme = "@style/MyTheme_Blue")] [Activity(Label = AppNames.AppName, MainLauncher = false, Theme = "@style/MyTheme_Blue", Exported = true)]
[IntentFilter(new[] { Intent.ActionMain }, Categories = new[] { "android.intent.category.LAUNCHER", "android.intent.category.MULTIWINDOW_LAUNCHER" })] [IntentFilter(new[] { Intent.ActionMain }, Categories = new[] { "android.intent.category.LAUNCHER", "android.intent.category.MULTIWINDOW_LAUNCHER" })]
public class KeePass : LifecycleAwareActivity, IDialogInterfaceOnDismissListener public class KeePass : LifecycleAwareActivity, IDialogInterfaceOnDismissListener
{ {

View File

@@ -17,6 +17,7 @@ namespace keepass2android
ConfigurationChanges = ConfigChanges.Orientation | ConfigurationChanges = ConfigChanges.Orientation |
ConfigChanges.KeyboardHidden, ConfigChanges.KeyboardHidden,
NoHistory = true, NoHistory = true,
Exported = true,
ExcludeFromRecents = true, ExcludeFromRecents = true,
Theme = "@android:style/Theme.Dialog")] Theme = "@android:style/Theme.Dialog")]
[IntentFilter(new[] { "android.nfc.action.NDEF_DISCOVERED" }, [IntentFilter(new[] { "android.nfc.action.NDEF_DISCOVERED" },

View File

@@ -43,7 +43,7 @@
</intent> </intent>
</queries> </queries>
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" /> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
<permission android:description="@string/permission_desc2" android:icon="@drawable/ic_launcher" android:label="KP2A entry search" android:name="keepass2android.keepass2android.permission.KP2aInternalSearch" android:protectionLevel="signature" /> <permission android:description="@string/permission_desc2" android:icon="@drawable/ic_launcher" android:label="KP2A entry search" android:name="keepass2android.keepass2android.permission.KP2aInternalSearch" android:protectionLevel="signature" />
<permission android:description="@string/permission_desc3" android:icon="@drawable/ic_launcher" android:label="KP2A choose autofill dataset" android:name="keepass2android.keepass2android.permission.Kp2aChooseAutofill" android:protectionLevel="signature" /> <permission android:description="@string/permission_desc3" android:icon="@drawable/ic_launcher" android:label="KP2A choose autofill dataset" android:name="keepass2android.keepass2android.permission.Kp2aChooseAutofill" android:protectionLevel="signature" />
@@ -87,13 +87,13 @@
<activity android:name="group.pals.android.lib.ui.filechooser.FileChooserActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:screenOrientation="user" android:theme="@style/Afc.Theme.Light"> <activity android:name="group.pals.android.lib.ui.filechooser.FileChooserActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:screenOrientation="user" android:theme="@style/Afc.Theme.Light">
</activity> </activity>
<service android:name="keepass2android.softkeyboard.KP2AKeyboard" android:permission="android.permission.BIND_INPUT_METHOD"> <service android:name="keepass2android.softkeyboard.KP2AKeyboard" android:permission="android.permission.BIND_INPUT_METHOD" android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.view.InputMethod" /> <action android:name="android.view.InputMethod" />
</intent-filter> </intent-filter>
<meta-data android:name="android.view.im" android:resource="@xml/method" /> <meta-data android:name="android.view.im" android:resource="@xml/method" />
</service> </service>
<activity android:name="keepass2android.softkeyboard.LatinIMESettings" android:label="@string/english_ime_settings"> <activity android:name="keepass2android.softkeyboard.LatinIMESettings" android:label="@string/english_ime_settings" android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
</intent-filter> </intent-filter>
@@ -103,14 +103,15 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="keepass2android.softkeyboard.InputLanguageSelection" <activity android:name="keepass2android.softkeyboard.InputLanguageSelection"
android:label="@string/language_selection_title"> android:label="@string/language_selection_title"
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<action android:name="keepass2android.softkeyboard.INPUT_LANGUAGE_SELECTION"/> <action android:name="keepass2android.softkeyboard.INPUT_LANGUAGE_SELECTION"/>
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.SelectCurrentDbActivity" android:windowSoftInputMode="adjustResize"> <activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.SelectCurrentDbActivity" android:windowSoftInputMode="adjustResize" android:exported="true">
<intent-filter android:label="@string/app_name"> <intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
@@ -272,6 +273,4 @@ The scheme=file is still there for old OS devices. It's also queried by apps lik
<!-- Samsung Pass permission --> <!-- Samsung Pass permission -->
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" /> <uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" />
<!-- READ_PHONE_STATE seems to come from some library or so, not clear where. We don't want to have it, remove it: -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
</manifest> </manifest>

View File

@@ -40,7 +40,7 @@
</intent> </intent>
</queries> </queries>
<uses-sdk android:minSdkVersion="18" android:targetSdkVersion="30" /> <uses-sdk android:minSdkVersion="18" android:targetSdkVersion="33" />
<permission android:description="@string/permission_desc2" android:icon="@drawable/ic_launcher_offline" android:label="KP2A entry search" android:name="keepass2android.keepass2android_nonet.permission.KP2aInternalSearch" android:protectionLevel="signature" /> <permission android:description="@string/permission_desc2" android:icon="@drawable/ic_launcher_offline" android:label="KP2A entry search" android:name="keepass2android.keepass2android_nonet.permission.KP2aInternalSearch" android:protectionLevel="signature" />
<permission android:description="@string/permission_desc3" android:icon="@drawable/ic_launcher_offline" android:label="KP2A choose autofill dataset" android:name="keepass2android.keepass2android_nonet.permission.Kp2aChooseAutofill" android:protectionLevel="signature" /> <permission android:description="@string/permission_desc3" android:icon="@drawable/ic_launcher_offline" android:label="KP2A choose autofill dataset" android:name="keepass2android.keepass2android_nonet.permission.Kp2aChooseAutofill" android:protectionLevel="signature" />
<application <application
@@ -57,13 +57,13 @@
<activity android:name="group.pals.android.lib.ui.filechooser.FileChooserActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:screenOrientation="user" android:theme="@style/Afc.Theme.Light"> <activity android:name="group.pals.android.lib.ui.filechooser.FileChooserActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:screenOrientation="user" android:theme="@style/Afc.Theme.Light">
</activity> </activity>
<service android:name="keepass2android.softkeyboard.KP2AKeyboard" android:permission="android.permission.BIND_INPUT_METHOD"> <service android:name="keepass2android.softkeyboard.KP2AKeyboard" android:permission="android.permission.BIND_INPUT_METHOD" android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.view.InputMethod" /> <action android:name="android.view.InputMethod" />
</intent-filter> </intent-filter>
<meta-data android:name="android.view.im" android:resource="@xml/method" /> <meta-data android:name="android.view.im" android:resource="@xml/method" />
</service> </service>
<activity android:name="keepass2android.softkeyboard.LatinIMESettings" android:label="@string/english_ime_settings"> <activity android:name="keepass2android.softkeyboard.LatinIMESettings" android:label="@string/english_ime_settings" android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
</intent-filter> </intent-filter>
@@ -73,7 +73,8 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="keepass2android.softkeyboard.InputLanguageSelection" <activity android:name="keepass2android.softkeyboard.InputLanguageSelection"
android:label="@string/language_selection_title"> android:label="@string/language_selection_title"
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<action android:name="keepass2android.softkeyboard.INPUT_LANGUAGE_SELECTION"/> <action android:name="keepass2android.softkeyboard.INPUT_LANGUAGE_SELECTION"/>
@@ -81,7 +82,8 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.SelectCurrentDbActivity" android:windowSoftInputMode="adjustResize"> <activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.SelectCurrentDbActivity" android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter android:label="@string/app_name"> <intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
@@ -244,9 +246,5 @@ The scheme=file is still there for old OS devices. It's also queried by apps lik
<uses-permission android:name="keepass2android.keepass2android_nonet.permission.KP2aInternalFileBrowsing" /> <uses-permission android:name="keepass2android.keepass2android_nonet.permission.KP2aInternalFileBrowsing" />
<uses-permission android:name="keepass2android.keepass2android_nonet.permission.KP2aInternalSearch" /> <uses-permission android:name="keepass2android.keepass2android_nonet.permission.KP2aInternalSearch" />
<!-- Samsung Pass permission -->
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" />
<!-- READ_PHONE_STATE seems to come from some library or so, not clear where. We don't want to have it, remove it: -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
</manifest> </manifest>

View File

@@ -46,3 +46,4 @@ using keepass2android;
[assembly: Permission(Name = "keepass2android."+AppNames.PackagePart+".permission.CopyToClipboard", Label = "CopyToClipboard", ProtectionLevel=Protection.Signature)] [assembly: Permission(Name = "keepass2android."+AppNames.PackagePart+".permission.CopyToClipboard", Label = "CopyToClipboard", ProtectionLevel=Protection.Signature)]
[assembly: UsesPermission(Name = "keepass2android." + AppNames.PackagePart + ".permission.CopyToClipboard")] [assembly: UsesPermission(Name = "keepass2android." + AppNames.PackagePart + ".permission.CopyToClipboard")]
[assembly: UsesPermission(Android.Manifest.Permission.ForegroundService)]

View File

@@ -16,6 +16,7 @@ namespace keepass2android
{ {
[Activity(Label = "@string/app_name", [Activity(Label = "@string/app_name",
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden,
Exported = true,
Theme = "@style/MyTheme_ActionBar")] Theme = "@style/MyTheme_ActionBar")]
[IntentFilter(new[] { Strings.ActionQueryCredentials}, [IntentFilter(new[] { Strings.ActionQueryCredentials},
Categories = new[] { Intent.CategoryDefault })] Categories = new[] { Intent.CategoryDefault })]

View File

@@ -270,31 +270,7 @@ namespace keepass2android
_biometryIdentifier = new BiometricDecryption(fpModule, App.Kp2a.GetDbForQuickUnlock().CurrentFingerprintPrefKey, this, _biometryIdentifier = new BiometricDecryption(fpModule, App.Kp2a.GetDbForQuickUnlock().CurrentFingerprintPrefKey, this,
App.Kp2a.GetDbForQuickUnlock().CurrentFingerprintPrefKey); App.Kp2a.GetDbForQuickUnlock().CurrentFingerprintPrefKey);
if ((_biometryIdentifier == null) && (!BiometricDecryption.IsSetUp(this, App.Kp2a.GetDbForQuickUnlock().CurrentFingerprintPrefKey)))
{
try
{
Kp2aLog.Log("trying Samsung Fingerprint API...");
_biometryIdentifier = new BiometrySamsungIdentifier(this);
btn.Click += (sender, args) =>
{
if (_biometryIdentifier.Init())
{
if (numFailedAttempts < maxNumFailedAttempts)
{
_biometryIdentifier.StartListening(this);
}
}
};
Kp2aLog.Log("trying Samsung Fingerprint API...Seems to work!");
}
catch (Exception)
{
Kp2aLog.Log("trying Samsung Fingerprint API...failed.");
_biometryIdentifier = null;
}
}
if (_biometryIdentifier == null) if (_biometryIdentifier == null)
{ {
FindViewById<ImageButton>(Resource.Id.fingerprintbtn).Visibility = ViewStates.Gone; FindViewById<ImageButton>(Resource.Id.fingerprintbtn).Visibility = ViewStates.Gone;

View File

@@ -31,6 +31,7 @@ namespace keepass2android
[Activity(Label = AppNames.AppName, [Activity(Label = AppNames.AppName,
MainLauncher = false, MainLauncher = false,
Theme = "@style/MyTheme_Blue", Theme = "@style/MyTheme_Blue",
Exported = true,
LaunchMode = LaunchMode.SingleInstance)] //caution, see manifest file LaunchMode = LaunchMode.SingleInstance)] //caution, see manifest file
public class SelectCurrentDbActivity : LifecycleAwareActivity public class SelectCurrentDbActivity : LifecycleAwareActivity
{ {

View File

@@ -31,7 +31,7 @@ using KeePassLib.Utility;
namespace keepass2android namespace keepass2android
{ {
[Activity(Label = "@string/kp2a_findUrl", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden, Theme = "@style/MyTheme_ActionBar")] [Activity(Label = "@string/kp2a_findUrl", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden, Theme = "@style/MyTheme_ActionBar", Exported = true)]
#if NoNet #if NoNet
[MetaData("android.app.searchable", Resource = "@xml/searchable_offline")] [MetaData("android.app.searchable", Resource = "@xml/searchable_offline")]
#else #else

View File

@@ -394,7 +394,15 @@ namespace keepass2android
get { return (int)Build.VERSION.SdkInt >= 19; } get { return (int)Build.VERSION.SdkInt >= 19; }
} }
private static void ShowInternalLocalFileChooser(Activity act, int requestCodeBrowse, bool forSaving, string defaultPath)
public static PendingIntentFlags AddMutabilityFlag(PendingIntentFlags flags, PendingIntentFlags mutability)
{
if ((int)Build.VERSION.SdkInt >= 31)
return flags | mutability;
else return flags;
}
private static void ShowInternalLocalFileChooser(Activity act, int requestCodeBrowse, bool forSaving, string defaultPath)
{ {
#if !EXCLUDE_FILECHOOSER #if !EXCLUDE_FILECHOOSER

View File

@@ -1,5 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" InitialTargets="showFlavor">
<Target Name="showFlavor" AfterTargets="Build">
<Message Importance="high" Text="building flavor $(Flavor)">
</Message>
</Target>
<Import Project="../build-properties.props" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -19,7 +24,7 @@
<AndroidResgenClass>Resource</AndroidResgenClass> <AndroidResgenClass>Resource</AndroidResgenClass>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies> <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk> <AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v11.0</TargetFrameworkVersion> <TargetFrameworkVersion>v13.0</TargetFrameworkVersion>
<AndroidManifest>Properties\AndroidManifest_debug.xml</AndroidManifest> <AndroidManifest>Properties\AndroidManifest_debug.xml</AndroidManifest>
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix> <MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix> <MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
@@ -99,6 +104,9 @@
<PackageReference Include="Xamarin.AndroidX.RecyclerView"> <PackageReference Include="Xamarin.AndroidX.RecyclerView">
<Version>1.2.1.3</Version> <Version>1.2.1.3</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.Build.Download">
<Version>0.11.4</Version>
</PackageReference>
<PackageReference Include="ZXing.Net.Mobile"> <PackageReference Include="ZXing.Net.Mobile">
<Version>3.1.0-beta2</Version> <Version>3.1.0-beta2</Version>
</PackageReference> </PackageReference>
@@ -186,7 +194,6 @@
<Compile Include="EntryActivityClasses\WriteBinaryToFilePopupItem.cs" /> <Compile Include="EntryActivityClasses\WriteBinaryToFilePopupItem.cs" />
<Compile Include="FileSelectHelper.cs" /> <Compile Include="FileSelectHelper.cs" />
<Compile Include="BiometricModule.cs" /> <Compile Include="BiometricModule.cs" />
<Compile Include="FingerprintSamsungIdentifier.cs" />
<Compile Include="FingerprintSetupActivity.cs" /> <Compile Include="FingerprintSetupActivity.cs" />
<Compile Include="ExportDatabaseActivity.cs" /> <Compile Include="ExportDatabaseActivity.cs" />
<Compile Include="fileselect\FileChooserFileProvider.cs" /> <Compile Include="fileselect\FileChooserFileProvider.cs" />
@@ -412,7 +419,7 @@
<AndroidResource Include="Resources\drawable-mdpi\ic_arrow_back_white_24dp.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_arrow_back_white_24dp.png" />
<AndroidResource Include="Resources\drawable-mdpi\ic_cross.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_cross.png" />
<AndroidResource Include="Resources\drawable-mdpi\ic_entry_attachments.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_entry_attachments.png" />
<AndroidResource Include="Resources\drawable-mdpi\ic_entry_history.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_entry_history.png" />
<AndroidResource Include="Resources\drawable-mdpi\ic_entry_comments.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_entry_comments.png" />
<AndroidResource Include="Resources\drawable-mdpi\ic_entry_created.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_entry_created.png" />
<AndroidResource Include="Resources\drawable-mdpi\ic_entry_expires.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_entry_expires.png" />
@@ -488,7 +495,7 @@
<AndroidResource Include="Resources\drawable-mdpi\ic_storage_ftp.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_storage_ftp.png" />
<AndroidResource Include="Resources\drawable-mdpi\ic_storage_ftps.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_storage_ftps.png" />
<AndroidResource Include="Resources\drawable-mdpi\ic_storage_gdrive.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_storage_gdrive.png" />
<AndroidResource Include="Resources\drawable-mdpi\ic_storage_gdriveKP2A.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_storage_gdriveKP2A.png" />
<AndroidResource Include="Resources\drawable-mdpi\ic_storage_http.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_storage_http.png" />
<AndroidResource Include="Resources\drawable-mdpi\ic_storage_https.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_storage_https.png" />
<AndroidResource Include="Resources\drawable-mdpi\ic_storage_owncloud.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_storage_owncloud.png" />
@@ -1953,10 +1960,6 @@
<Project>{3da3911e-36de-465e-8f15-f1991b6437e5}</Project> <Project>{3da3911e-36de-465e-8f15-f1991b6437e5}</Project>
<Name>PluginSdkBinding</Name> <Name>PluginSdkBinding</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\SamsungPass\Xamarin.SamsungPass\SamsungPass\SamsungPass.csproj">
<Project>{3a4b8e88-fa9b-4663-bcda-21c12e3af98a}</Project>
<Name>SamsungPass</Name>
</ProjectReference>
<ProjectReference Include="..\TwofishCipher\TwofishCipher.csproj"> <ProjectReference Include="..\TwofishCipher\TwofishCipher.csproj">
<Project>{5cf675a5-9bee-4720-bed9-d5bf14a2ebf9}</Project> <Project>{5cf675a5-9bee-4720-bed9-d5bf14a2ebf9}</Project>
<Name>TwofishCipher</Name> <Name>TwofishCipher</Name>

View File

@@ -19,7 +19,7 @@ using keepass2android.views;
namespace keepass2android namespace keepass2android
{ {
[Activity(Label = AppNames.AppName, Theme = "@style/android:Theme.Material.Light")] [Activity(Label = AppNames.AppName, Theme = "@style/android:Theme.Material.Light", Exported = true)]
[IntentFilter(new[] { Strings.ActionEditPluginSettings }, [IntentFilter(new[] { Strings.ActionEditPluginSettings },
Label = AppNames.AppName, Label = AppNames.AppName,
Categories = new[] { Intent.CategoryDefault })] Categories = new[] { Intent.CategoryDefault })]

View File

@@ -5,6 +5,7 @@ using Android.App;
using Android.Content; using Android.Content;
using Android.Content.PM; using Android.Content.PM;
using Android.Util; using Android.Util;
using Group.Pals.Android.Lib.UI.Filechooser.Utils;
using KeePassLib.Utility; using KeePassLib.Utility;
using Keepass2android.Pluginsdk; using Keepass2android.Pluginsdk;
using Org.Json; using Org.Json;
@@ -14,7 +15,7 @@ namespace keepass2android
/// <summary> /// <summary>
/// Class which manages plugins inside the app /// Class which manages plugins inside the app
/// </summary> /// </summary>
[BroadcastReceiver] [BroadcastReceiver(Exported = true)]
[IntentFilter(new[] { Strings.ActionRequestAccess })] [IntentFilter(new[] { Strings.ActionRequestAccess })]
public class PluginHost : BroadcastReceiver public class PluginHost : BroadcastReceiver
{ {

View File

@@ -9,7 +9,7 @@ using Keepass2android.Pluginsdk;
namespace keepass2android namespace keepass2android
{ {
[Activity(Label = "@string/plugins", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, Theme="@style/android:Theme.Material.Light")] [Activity(Label = "@string/plugins", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, Theme="@style/android:Theme.Material.Light", Exported = true)]
[IntentFilter(new[] { "kp2a.action.PluginListActivity" }, Categories = new[] { Intent.CategoryDefault })] [IntentFilter(new[] { "kp2a.action.PluginListActivity" }, Categories = new[] { Intent.CategoryDefault })]
public class PluginListActivity : ListActivity public class PluginListActivity : ListActivity
{ {

View File

@@ -31,7 +31,7 @@ namespace keepass2android.search
/// <summary> /// <summary>
/// Activity to show search results /// Activity to show search results
/// </summary> /// </summary>
[Activity(Label = "@string/app_name", Theme = "@style/MyTheme_ActionBar", LaunchMode = Android.Content.PM.LaunchMode.SingleTop, Permission="keepass2android."+AppNames.PackagePart+".permission.KP2aInternalSearch", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden)] [Activity(Label = "@string/app_name", Theme = "@style/MyTheme_ActionBar", LaunchMode = Android.Content.PM.LaunchMode.SingleTop, Permission="keepass2android."+AppNames.PackagePart+".permission.KP2aInternalSearch", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden, Exported = true)]
#if NoNet #if NoNet
[MetaData("android.app.searchable", Resource = "@xml/searchable_offline")] [MetaData("android.app.searchable", Resource = "@xml/searchable_offline")]
#else #else

View File

@@ -30,7 +30,8 @@ namespace keepass2android.services.AutofillBase
} }
//make sure we have a pendingIntent always not null //make sure we have a pendingIntent always not null
pendingIntent ??= PendingIntent.GetService(context, 0, new Intent(), pendingIntent ??= PendingIntent.GetService(context, 0, new Intent(),
PendingIntentFlags.OneShot | PendingIntentFlags.UpdateCurrent); Util.AddMutabilityFlag(PendingIntentFlags.OneShot | PendingIntentFlags.UpdateCurrent, PendingIntentFlags.Mutable));
var slice = CreateInlinePresentationSlice( var slice = CreateInlinePresentationSlice(
inlinePresentationSpec, inlinePresentationSpec,
text, text,
@@ -46,6 +47,7 @@ namespace keepass2android.services.AutofillBase
return null; return null;
} }
private static Android.App.Slices.Slice CreateInlinePresentationSlice( private static Android.App.Slices.Slice CreateInlinePresentationSlice(
InlinePresentationSpec inlinePresentationSpec, InlinePresentationSpec inlinePresentationSpec,
string text, string text,
@@ -107,7 +109,7 @@ namespace keepass2android.services.AutofillBase
datasetBuilder.SetId(datasetName); datasetBuilder.SetId(datasetName);
var setValueAtLeastOnce = filledAutofillFieldCollection.ApplyToFields(autofillFields, datasetBuilder); var setValueAtLeastOnce = filledAutofillFieldCollection.ApplyToFields(autofillFields, datasetBuilder);
AddInlinePresentation(context, inlinePresentationSpec, datasetName, datasetBuilder, intentBuilder.AppIconResource); AddInlinePresentation(context, inlinePresentationSpec, datasetName, datasetBuilder, intentBuilder.AppIconResource, null);
if (setValueAtLeastOnce) if (setValueAtLeastOnce)
{ {
@@ -121,12 +123,14 @@ namespace keepass2android.services.AutofillBase
return null; return null;
} }
public static void AddInlinePresentation(Context context, InlinePresentationSpec inlinePresentationSpec, string datasetName, Dataset.Builder datasetBuilder, int iconId) public static void AddInlinePresentation(Context context, InlinePresentationSpec inlinePresentationSpec,
string datasetName, Dataset.Builder datasetBuilder, int iconId, PendingIntent pendingIntent)
{ {
if (inlinePresentationSpec != null) if (inlinePresentationSpec != null)
{ {
var inlinePresentation = BuildInlinePresentation(inlinePresentationSpec, datasetName, "", iconId, null, context); var inlinePresentation = BuildInlinePresentation(inlinePresentationSpec, datasetName, "", iconId, pendingIntent, context);
datasetBuilder.SetInlinePresentation(inlinePresentation); if (inlinePresentation != null)
datasetBuilder.SetInlinePresentation(inlinePresentation);
} }
} }

View File

@@ -25,12 +25,12 @@ namespace keepass2android.services.AutofillBase
{ {
public interface IAutofillIntentBuilder public interface IAutofillIntentBuilder
{ {
IntentSender GetAuthIntentSenderForResponse(Context context, string query, string queryDomain, string queryPackage, PendingIntent GetAuthPendingIntentForResponse(Context context, string query, string queryDomain, string queryPackage,
bool isManualRequest, bool autoReturnFromQuery, AutofillServiceBase.DisplayWarning warning); bool isManualRequest, bool autoReturnFromQuery, AutofillServiceBase.DisplayWarning warning);
IntentSender GetAuthIntentSenderForWarning(Context context, string query, string queryDomain, string queryPackage, AutofillServiceBase.DisplayWarning warning); PendingIntent GetAuthPendingIntentForWarning(Context context, string query, string queryDomain, string queryPackage, AutofillServiceBase.DisplayWarning warning);
IntentSender GetDisableIntentSenderForResponse(Context context, string query, PendingIntent GetDisablePendingIntentForResponse(Context context, string query,
bool isManualRequest, bool isDisable); bool isManualRequest, bool isDisable);
Intent GetRestartAppIntent(Context context); Intent GetRestartAppIntent(Context context);
@@ -266,8 +266,8 @@ namespace keepass2android.services.AutofillBase
else else
{ {
//return an "auth" dataset (actually for just warning the user in case domain/package dont match) //return an "auth" dataset (actually for just warning the user in case domain/package dont match)
IntentSender sender = PendingIntent pendingIntent =
IntentBuilder.GetAuthIntentSenderForWarning(this, query, queryDomain, queryPackage, warning); IntentBuilder.GetAuthPendingIntentForWarning(this, query, queryDomain, queryPackage, warning);
var datasetName = filledAutofillFieldCollection.DatasetName; var datasetName = filledAutofillFieldCollection.DatasetName;
if (datasetName == null) if (datasetName == null)
{ {
@@ -279,9 +279,9 @@ namespace keepass2android.services.AutofillBase
AutofillHelper.NewRemoteViews(PackageName, datasetName, AppNames.LauncherIcon); AutofillHelper.NewRemoteViews(PackageName, datasetName, AppNames.LauncherIcon);
var datasetBuilder = new Dataset.Builder(presentation); var datasetBuilder = new Dataset.Builder(presentation);
datasetBuilder.SetAuthentication(sender); datasetBuilder.SetAuthentication(pendingIntent?.IntentSender);
AutofillHelper.AddInlinePresentation(this, inlinePresentationSpec, datasetName, datasetBuilder, AppNames.LauncherIcon); AutofillHelper.AddInlinePresentation(this, inlinePresentationSpec, datasetName, datasetBuilder, AppNames.LauncherIcon, null);
//need to add placeholders so we can directly fill after ChooseActivity //need to add placeholders so we can directly fill after ChooseActivity
foreach (var autofillId in autofillIds) foreach (var autofillId in autofillIds)
@@ -310,20 +310,20 @@ namespace keepass2android.services.AutofillBase
private void AddQueryDataset(string query, string queryDomain, string queryPackage, bool isManual, AutofillId[] autofillIds, FillResponse.Builder responseBuilder, bool autoReturnFromQuery, DisplayWarning warning, InlinePresentationSpec inlinePresentationSpec) private void AddQueryDataset(string query, string queryDomain, string queryPackage, bool isManual, AutofillId[] autofillIds, FillResponse.Builder responseBuilder, bool autoReturnFromQuery, DisplayWarning warning, InlinePresentationSpec inlinePresentationSpec)
{ {
var sender = IntentBuilder.GetAuthIntentSenderForResponse(this, query, queryDomain, queryPackage, isManual, autoReturnFromQuery, warning); PendingIntent pendingIntent = IntentBuilder.GetAuthPendingIntentForResponse(this, query, queryDomain, queryPackage, isManual, autoReturnFromQuery, warning);
string text = GetString(Resource.String.autofill_sign_in_prompt); string text = GetString(Resource.String.autofill_sign_in_prompt);
RemoteViews presentation = AutofillHelper.NewRemoteViews(base.PackageName, RemoteViews overlayPresentation = AutofillHelper.NewRemoteViews(base.PackageName,
text, AppNames.LauncherIcon); text, AppNames.LauncherIcon);
var datasetBuilder = new Dataset.Builder(presentation); var datasetBuilder = new Dataset.Builder(overlayPresentation);
datasetBuilder.SetAuthentication(sender); datasetBuilder.SetAuthentication(pendingIntent?.IntentSender);
//need to add placeholders so we can directly fill after ChooseActivity //need to add placeholders so we can directly fill after ChooseActivity
foreach (var autofillId in autofillIds) foreach (var autofillId in autofillIds)
{ {
datasetBuilder.SetValue(autofillId, AutofillValue.ForText("PLACEHOLDER")); datasetBuilder.SetValue(autofillId, AutofillValue.ForText("PLACEHOLDER"));
} }
AutofillHelper.AddInlinePresentation(this, inlinePresentationSpec, text, datasetBuilder, AppNames.LauncherIcon); AutofillHelper.AddInlinePresentation(this, inlinePresentationSpec, text, datasetBuilder, AppNames.LauncherIcon, pendingIntent);
responseBuilder.AddDataset(datasetBuilder.Build()); responseBuilder.AddDataset(datasetBuilder.Build());
@@ -364,16 +364,16 @@ namespace keepass2android.services.AutofillBase
if (isQueryDisabled && !isManual) if (isQueryDisabled && !isManual)
return; return;
bool isForDisable = !isQueryDisabled; bool isForDisable = !isQueryDisabled;
var sender = IntentBuilder.GetDisableIntentSenderForResponse(this, query, isManual, isForDisable); var pendingIntent = IntentBuilder.GetDisablePendingIntentForResponse(this, query, isManual, isForDisable);
string text = GetString(isForDisable ? Resource.String.autofill_disable : Resource.String.autofill_enable_for, new Java.Lang.Object[] { GetDisplayNameForQuery(query, this) }); string text = GetString(isForDisable ? Resource.String.autofill_disable : Resource.String.autofill_enable_for, new Java.Lang.Object[] { GetDisplayNameForQuery(query, this) });
RemoteViews presentation = AutofillHelper.NewRemoteViews(base.PackageName, RemoteViews presentation = AutofillHelper.NewRemoteViews(base.PackageName,
text, Resource.Drawable.ic_menu_close_grey); text, Resource.Drawable.ic_menu_close_grey);
var datasetBuilder = new Dataset.Builder(presentation); var datasetBuilder = new Dataset.Builder(presentation);
datasetBuilder.SetAuthentication(sender); datasetBuilder.SetAuthentication(pendingIntent?.IntentSender);
AutofillHelper.AddInlinePresentation(this, inlinePresentationSpec, text, datasetBuilder, Resource.Drawable.ic_menu_close_grey); AutofillHelper.AddInlinePresentation(this, inlinePresentationSpec, text, datasetBuilder, Resource.Drawable.ic_menu_close_grey, null);
foreach (var autofillId in autofillIds) foreach (var autofillId in autofillIds)
{ {

View File

@@ -201,7 +201,7 @@ namespace keepass2android
extra.PutInt("requestCode", requestCode); extra.PutInt("requestCode", requestCode);
intent.PutExtras(extra); intent.PutExtras(extra);
return PendingIntent.GetBroadcast(_ctx, requestCode, intent, PendingIntentFlags.CancelCurrent); return PendingIntent.GetBroadcast(_ctx, requestCode, intent, Util.AddMutabilityFlag(PendingIntentFlags.CancelCurrent, PendingIntentFlags.Immutable));
} }
@@ -223,7 +223,7 @@ namespace keepass2android
PendingIntent pending; PendingIntent pending;
if (intentText == null) if (intentText == null)
{ {
pending = PendingIntent.GetActivity(_ctx.ApplicationContext, 0, new Intent(), 0); pending = PendingIntent.GetActivity(_ctx.ApplicationContext, 0, new Intent(), Util.AddMutabilityFlag(0, PendingIntentFlags.Immutable));
} }
else else
{ {
@@ -248,7 +248,8 @@ namespace keepass2android
PendingIntent pending; PendingIntent pending;
Intent intent = new Intent(_ctx, typeof(CopyToClipboardBroadcastReceiver)); Intent intent = new Intent(_ctx, typeof(CopyToClipboardBroadcastReceiver));
intent.SetAction(intentText); intent.SetAction(intentText);
pending = PendingIntent.GetBroadcast(_ctx, descResId, intent, PendingIntentFlags.CancelCurrent); pending = PendingIntent.GetBroadcast(_ctx, descResId, intent, Util.AddMutabilityFlag(PendingIntentFlags.CancelCurrent, PendingIntentFlags.Immutable));
return pending; return pending;
} }

View File

@@ -17,7 +17,7 @@ using AutofillServiceBase = keepass2android.services.AutofillBase.AutofillServic
namespace keepass2android.services namespace keepass2android.services
{ {
[Service(Label = AppNames.AppName, Permission=Manifest.Permission.BindAutofillService)] [Service(Label = AppNames.AppName, Permission=Manifest.Permission.BindAutofillService, Exported = true)]
[IntentFilter(new [] {"android.service.autofill.AutofillService"})] [IntentFilter(new [] {"android.service.autofill.AutofillService"})]
[MetaData("android.autofill", Resource = "@xml/autofillservice")] [MetaData("android.autofill", Resource = "@xml/autofillservice")]
[Register("keepass2android.services.Kp2aAutofillService")] [Register("keepass2android.services.Kp2aAutofillService")]

View File

@@ -14,8 +14,9 @@ namespace keepass2android.services
{ {
class Kp2aAutofillIntentBuilder: IAutofillIntentBuilder class Kp2aAutofillIntentBuilder: IAutofillIntentBuilder
{ {
private static int _pendingIntentRequestCode = 0;
public IntentSender GetAuthIntentSenderForResponse(Context context, string query, string queryDomain, string queryPackage, public PendingIntent GetAuthPendingIntentForResponse(Context context, string query, string queryDomain, string queryPackage,
bool isManualRequest, bool autoReturnFromQuery, AutofillServiceBase.DisplayWarning warning) bool isManualRequest, bool autoReturnFromQuery, AutofillServiceBase.DisplayWarning warning)
{ {
Intent intent = new Intent(context, typeof(ChooseForAutofillActivity)); Intent intent = new Intent(context, typeof(ChooseForAutofillActivity));
@@ -25,10 +26,10 @@ namespace keepass2android.services
intent.PutExtra(ChooseForAutofillActivityBase.ExtraIsManualRequest, isManualRequest); intent.PutExtra(ChooseForAutofillActivityBase.ExtraIsManualRequest, isManualRequest);
intent.PutExtra(ChooseForAutofillActivityBase.ExtraAutoReturnFromQuery, autoReturnFromQuery); intent.PutExtra(ChooseForAutofillActivityBase.ExtraAutoReturnFromQuery, autoReturnFromQuery);
intent.PutExtra(ChooseForAutofillActivityBase.ExtraDisplayWarning, (int)warning); intent.PutExtra(ChooseForAutofillActivityBase.ExtraDisplayWarning, (int)warning);
return PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.CancelCurrent).IntentSender; return PendingIntent.GetActivity(context, _pendingIntentRequestCode++, intent, Util.AddMutabilityFlag(PendingIntentFlags.CancelCurrent, PendingIntentFlags.Mutable));
} }
public IntentSender GetAuthIntentSenderForWarning(Context context, string query, string queryDomain, string queryPackage, public PendingIntent GetAuthPendingIntentForWarning(Context context, string query, string queryDomain, string queryPackage,
AutofillServiceBase.DisplayWarning warning) AutofillServiceBase.DisplayWarning warning)
{ {
Intent intent = new Intent(context, typeof(ChooseForAutofillActivity)); Intent intent = new Intent(context, typeof(ChooseForAutofillActivity));
@@ -37,10 +38,10 @@ namespace keepass2android.services
intent.PutExtra(ChooseForAutofillActivityBase.ExtraQueryPackageString, queryPackage); intent.PutExtra(ChooseForAutofillActivityBase.ExtraQueryPackageString, queryPackage);
intent.PutExtra(ChooseForAutofillActivityBase.ExtraDisplayWarning, (int)warning); intent.PutExtra(ChooseForAutofillActivityBase.ExtraDisplayWarning, (int)warning);
intent.PutExtra(ChooseForAutofillActivityBase.ExtraUseLastOpenedEntry, true); intent.PutExtra(ChooseForAutofillActivityBase.ExtraUseLastOpenedEntry, true);
return PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.CancelCurrent).IntentSender; return PendingIntent.GetActivity(context, _pendingIntentRequestCode++, intent, Util.AddMutabilityFlag(PendingIntentFlags.CancelCurrent, PendingIntentFlags.Immutable));
} }
public IntentSender GetDisableIntentSenderForResponse(Context context, string query, public PendingIntent GetDisablePendingIntentForResponse(Context context, string query,
bool isManualRequest, bool isDisable) bool isManualRequest, bool isDisable)
{ {
Intent intent = new Intent(context, typeof(DisableAutofillForQueryActivity)); Intent intent = new Intent(context, typeof(DisableAutofillForQueryActivity));
@@ -48,7 +49,7 @@ namespace keepass2android.services
intent.PutExtra(ChooseForAutofillActivityBase.ExtraIsManualRequest, isManualRequest); intent.PutExtra(ChooseForAutofillActivityBase.ExtraIsManualRequest, isManualRequest);
intent.PutExtra(DisableAutofillForQueryActivity.ExtraIsDisable, isDisable); intent.PutExtra(DisableAutofillForQueryActivity.ExtraIsDisable, isDisable);
return PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.CancelCurrent).IntentSender; return PendingIntent.GetActivity(context, _pendingIntentRequestCode++, intent, Util.AddMutabilityFlag(PendingIntentFlags.CancelCurrent, PendingIntentFlags.Immutable));
} }
public Intent GetRestartAppIntent(Context context) public Intent GetRestartAppIntent(Context context)

View File

@@ -173,7 +173,7 @@ namespace keepass2android
builder.SetContentIntent(GetSwitchToAppPendingIntent()); builder.SetContentIntent(GetSwitchToAppPendingIntent());
// Additional action to allow locking the database // Additional action to allow locking the database
builder.AddAction(Android.Resource.Drawable.IcLockLock, GetString(Resource.String.QuickUnlock_lockButton), builder.AddAction(Android.Resource.Drawable.IcLockLock, GetString(Resource.String.QuickUnlock_lockButton),
PendingIntent.GetBroadcast(this, 0, new Intent(this, typeof(ApplicationBroadcastReceiver)).SetAction(Intents.CloseDatabase), PendingIntentFlags.UpdateCurrent)); PendingIntent.GetBroadcast(this, 0, new Intent(this, typeof(ApplicationBroadcastReceiver)).SetAction(Intents.CloseDatabase), Util.AddMutabilityFlag(PendingIntentFlags.UpdateCurrent, PendingIntentFlags.Immutable)));
return builder.Build(); return builder.Build();
@@ -216,7 +216,7 @@ namespace keepass2android
// Default action is to show Kp2A // Default action is to show Kp2A
builder.SetContentIntent(GetSwitchToAppPendingIntent()); builder.SetContentIntent(GetSwitchToAppPendingIntent());
// Additional action to allow locking the database // Additional action to allow locking the database
builder.AddAction(Resource.Drawable.ic_action_lock, GetString(Resource.String.menu_lock), PendingIntent.GetBroadcast(this, 0, new Intent(this, typeof(ApplicationBroadcastReceiver)).SetAction(Intents.LockDatabase), PendingIntentFlags.UpdateCurrent)); builder.AddAction(Resource.Drawable.ic_action_lock, GetString(Resource.String.menu_lock), PendingIntent.GetBroadcast(this, 0, new Intent(this, typeof(ApplicationBroadcastReceiver)).SetAction(Intents.LockDatabase), Util.AddMutabilityFlag(PendingIntentFlags.UpdateCurrent, PendingIntentFlags.Immutable)));
return builder.Build(); return builder.Build();
} }
@@ -227,7 +227,7 @@ namespace keepass2android
startKp2aIntent.SetAction(Intent.ActionMain); startKp2aIntent.SetAction(Intent.ActionMain);
startKp2aIntent.AddCategory(Intent.CategoryLauncher); startKp2aIntent.AddCategory(Intent.CategoryLauncher);
return PendingIntent.GetActivity(this, 0, startKp2aIntent, PendingIntentFlags.UpdateCurrent); return PendingIntent.GetActivity(this, 0, startKp2aIntent, Util.AddMutabilityFlag(PendingIntentFlags.UpdateCurrent, PendingIntentFlags.Immutable));
} }
private static string GetDatabaseName() private static string GetDatabaseName()

View File

@@ -35,7 +35,7 @@ namespace keepass2android
private static PendingIntent BuildPendingBroadcastIntent(Context ctx) private static PendingIntent BuildPendingBroadcastIntent(Context ctx)
{ {
return PendingIntent.GetBroadcast(ctx, 0, BuildBroadcastIntent(ctx), PendingIntentFlags.UpdateCurrent); return PendingIntent.GetBroadcast(ctx, 0, BuildBroadcastIntent(ctx), Util.AddMutabilityFlag(PendingIntentFlags.UpdateCurrent, PendingIntentFlags.Immutable));
} }
private static Intent BuildBroadcastIntent(Context ctx) private static Intent BuildBroadcastIntent(Context ctx)