diff --git a/src/Kp2aBusinessLogic/Io/BuiltInFileStorage.cs b/src/Kp2aBusinessLogic/Io/BuiltInFileStorage.cs
index edb3477a..45a7e010 100644
--- a/src/Kp2aBusinessLogic/Io/BuiltInFileStorage.cs
+++ b/src/Kp2aBusinessLogic/Io/BuiltInFileStorage.cs
@@ -3,18 +3,25 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
-using System.Net.Security;
using System.Security;
+using Android;
+using Android.App;
using Android.Content;
+using Android.Content.PM;
using Android.OS;
-using Java.Security.Cert;
+using Java.IO;
using KeePassLib.Serialization;
using KeePassLib.Utility;
+using File = System.IO.File;
+using FileNotFoundException = System.IO.FileNotFoundException;
+using IOException = System.IO.IOException;
namespace keepass2android.Io
{
- public class BuiltInFileStorage: IFileStorage
+ public class BuiltInFileStorage : IFileStorage, IPermissionRequestingFileStorage
{
+ private const string PermissionGrantedKey = "PermissionGranted";
+
public enum CertificateProblem :long
{
CertEXPIRED = 0x800B0101,
@@ -112,7 +119,8 @@ namespace keepass2android.Io
private void ConvertException(IOConnectionInfo ioc, WebException ex)
{
- if ((ex.Response is HttpWebResponse) && (((HttpWebResponse) ex.Response).StatusCode == HttpStatusCode.NotFound))
+ var response = ex.Response as HttpWebResponse;
+ if ((response != null) && (response.StatusCode == HttpStatusCode.NotFound))
{
throw new FileNotFoundException(ex.Message, ioc.Path, ex);
}
@@ -241,6 +249,26 @@ namespace keepass2android.Io
public void PrepareFileUsage(IFileStorageSetupInitiatorActivity activity, IOConnectionInfo ioc, int requestCode, bool alwaysReturnSuccess)
{
+ //check if we need to request the external-storage-permission at runtime
+ if (ioc.IsLocalFile())
+ {
+ bool requiresPermission = !ioc.Path.StartsWith(activity.Activity.FilesDir.CanonicalPath);
+
+ var extDirectory = activity.Activity.GetExternalFilesDir(null);
+ if ((extDirectory != null) && (ioc.Path.StartsWith(extDirectory.CanonicalPath)))
+ requiresPermission = false;
+
+ if (requiresPermission && (Build.VERSION.SdkInt >= BuildVersionCodes.M))
+ {
+ if (activity.Activity.CheckSelfPermission(Manifest.Permission.WriteExternalStorage) ==
+ Permission.Denied)
+ {
+ activity.StartFileUsageProcess(ioc, requestCode, alwaysReturnSuccess);
+ return;
+ }
+ }
+
+ }
Intent intent = new Intent();
activity.IocToIntent(intent, ioc);
activity.OnImmediateResult(requestCode, (int) FileStorageResults.FileUsagePrepared, intent);
@@ -251,24 +279,42 @@ namespace keepass2android.Io
//nothing to do, we're ready to go
}
- public void OnCreate(IFileStorageSetupActivity activity, Bundle savedInstanceState)
+ public void OnCreate(IFileStorageSetupActivity fileStorageSetupActivity, Bundle savedInstanceState)
{
- throw new NotImplementedException();
+ ((Activity)fileStorageSetupActivity).RequestPermissions(new[] { Manifest.Permission.WriteExternalStorage }, 0);
}
public void OnResume(IFileStorageSetupActivity activity)
{
- throw new NotImplementedException();
+ if (activity.State.ContainsKey(PermissionGrantedKey))
+ {
+ if (activity.State.GetBoolean(PermissionGrantedKey))
+ {
+ Intent data = new Intent();
+ data.PutExtra(FileStorageSetupDefs.ExtraIsForSave, activity.IsForSave);
+ data.PutExtra(FileStorageSetupDefs.ExtraPath, IocToPath(activity.Ioc));
+ ((Activity) activity).SetResult((Result) FileStorageResults.FileUsagePrepared, data);
+ ((Activity) activity).Finish();
+ }
+ else
+ {
+ Intent data = new Intent();
+ data.PutExtra(FileStorageSetupDefs.ExtraErrorMessage, "Permission denied. Please grant file access permission for this app.");
+ ((Activity)activity).SetResult(Result.Canceled, data);
+ ((Activity)activity).Finish();
+
+ }
+ }
}
public void OnStart(IFileStorageSetupActivity activity)
{
- throw new NotImplementedException();
+
}
public void OnActivityResult(IFileStorageSetupActivity activity, int requestCode, int resultCode, Intent data)
{
- throw new NotImplementedException();
+
}
public string GetDisplayName(IOConnectionInfo ioc)
@@ -310,7 +356,7 @@ namespace keepass2android.Io
{
//test if we can open
//http://www.doubleencore.com/2014/03/android-external-storage/#comment-1294469517
- using (var writer = new Java.IO.FileOutputStream(ioc.Path, true))
+ using (var writer = new FileOutputStream(ioc.Path, true))
{
writer.Close();
return false; //we can write
@@ -358,5 +404,11 @@ namespace keepass2android.Io
return false;
}
}
+
+ public void OnRequestPermissionsResult(IFileStorageSetupActivity fileStorageSetupActivity, int requestCode,
+ string[] permissions, Permission[] grantResults)
+ {
+ fileStorageSetupActivity.State.PutBoolean(PermissionGrantedKey, grantResults[0] == Permission.Granted);
+ }
}
}
\ No newline at end of file
diff --git a/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs b/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs
index 4a0ee35b..890751be 100644
--- a/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs
+++ b/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs
@@ -5,6 +5,7 @@ using System.Net;
using System.Security.Cryptography;
using System.Text;
using Android.Content;
+using Android.Content.PM;
using Android.OS;
using KeePassLib.Cryptography;
using KeePassLib.Serialization;
@@ -59,7 +60,7 @@ namespace keepass2android.Io
/// Implements the IFileStorage interface as a proxy: A base storage is used as a remote storage. Local files are used to cache the
/// files on remote.
///
- public class CachingFileStorage : IFileStorage, IOfflineSwitchable
+ public class CachingFileStorage : IFileStorage, IOfflineSwitchable, IPermissionRequestingFileStorage
{
protected readonly OfflineSwitchableFileStorage _cachedStorage;
@@ -618,5 +619,11 @@ namespace keepass2android.Io
get { return _cachedStorage.IsOffline; }
set { _cachedStorage.IsOffline = value; }
}
+
+ public void OnRequestPermissionsResult(IFileStorageSetupActivity fileStorageSetupActivity, int requestCode,
+ string[] permissions, Permission[] grantResults)
+ {
+ _cachedStorage.OnRequestPermissionsResult(fileStorageSetupActivity, requestCode, permissions, grantResults);
+ }
}
}
diff --git a/src/Kp2aBusinessLogic/Io/IFileStorage.cs b/src/Kp2aBusinessLogic/Io/IFileStorage.cs
index a290acb2..1ffc6ece 100644
--- a/src/Kp2aBusinessLogic/Io/IFileStorage.cs
+++ b/src/Kp2aBusinessLogic/Io/IFileStorage.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using Android.Content;
+using Android.Content.PM;
using Android.OS;
using KeePassLib.Serialization;
@@ -22,7 +23,7 @@ namespace keepass2android.Io
public static String ExtraProcessName = "EXTRA_PROCESS_NAME";
public static String ExtraAlwaysReturnSuccess = "EXTRA_ALWAYS_RETURN_SUCCESS";
- public static String ExtraPath = "PATH";
+ public static String ExtraPath = "fileName"; //match KP2A PasswordActivity Ioc-Path Extra key
public static String ExtraIsForSave = "IS_FOR_SAVE";
public static String ExtraErrorMessage = "EXTRA_ERROR_MESSAGE";
@@ -170,6 +171,11 @@ namespace keepass2android.Io
bool IsReadOnly(IOConnectionInfo ioc);
}
+ public interface IPermissionRequestingFileStorage
+ {
+ void OnRequestPermissionsResult(IFileStorageSetupActivity fileStorageSetupActivity, int requestCode, string[] permissions, Permission[] grantResults);
+ }
+
public interface IWriteTransaction: IDisposable
{
Stream OpenFile();
diff --git a/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs b/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs
index 63e0855d..4ec59226 100644
--- a/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs
+++ b/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using Android.App;
using Android.Content;
+using Android.Content.PM;
using Android.OS;
using KeePassLib.Serialization;
using KeePassLib.Utility;
@@ -16,7 +17,7 @@ using FileNotFoundException = Java.IO.FileNotFoundException;
namespace keepass2android.Io
{
#if !EXCLUDE_JAVAFILESTORAGE
- public abstract class JavaFileStorage: IFileStorage
+ public abstract class JavaFileStorage: IFileStorage, IPermissionRequestingFileStorage
{
protected string Protocol { get { return _jfs.ProtocolId; } }
@@ -356,6 +357,12 @@ namespace keepass2android.Io
return ioc.Path;
}
+ public void OnRequestPermissionsResult(IFileStorageSetupActivity fileStorageSetupActivity, int requestCode,
+ string[] permissions, Permission[] grantResults)
+ {
+ _jfs.OnRequestPermissionsResult(((IJavaFileStorageFileStorageSetupActivity) fileStorageSetupActivity), requestCode,
+ permissions, grantResults.Select(p => (int)p).ToArray());
+ }
}
#endif
}
\ No newline at end of file
diff --git a/src/Kp2aBusinessLogic/Io/OfflineSwitchableFileStorage.cs b/src/Kp2aBusinessLogic/Io/OfflineSwitchableFileStorage.cs
index 8f492da7..70f9529b 100644
--- a/src/Kp2aBusinessLogic/Io/OfflineSwitchableFileStorage.cs
+++ b/src/Kp2aBusinessLogic/Io/OfflineSwitchableFileStorage.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using Android.Content;
+using Android.Content.PM;
using Android.OS;
using KeePassLib.Serialization;
@@ -16,7 +17,7 @@ namespace keepass2android.Io
/// Encapsulates another IFileStorage. Allows to switch to offline mode by throwing
/// an exception when trying to read or write a file.
///
- public class OfflineSwitchableFileStorage : IFileStorage, IOfflineSwitchable
+ public class OfflineSwitchableFileStorage : IFileStorage, IOfflineSwitchable, IPermissionRequestingFileStorage
{
private readonly IFileStorage _baseStorage;
public bool IsOffline { get; set; }
@@ -179,6 +180,15 @@ namespace keepass2android.Io
{
return _baseStorage.IsReadOnly(ioc);
}
+
+ public void OnRequestPermissionsResult(IFileStorageSetupActivity fileStorageSetupActivity, int requestCode,
+ string[] permissions, Permission[] grantResults)
+ {
+ if (_baseStorage is IPermissionRequestingFileStorage)
+ {
+ ((IPermissionRequestingFileStorage)_baseStorage).OnRequestPermissionsResult(fileStorageSetupActivity, requestCode, permissions, grantResults);
+ }
+ }
}
public class OfflineModeException : Exception
diff --git a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj
index 8cfad986..9a82467e 100644
--- a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj
+++ b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj
@@ -12,7 +12,8 @@
512
Resources\Resource.Designer.cs
Off
- v5.0
+ v6.0
+ False
true
diff --git a/src/java/JavaFileStorage/app/app.iml b/src/java/JavaFileStorage/app/app.iml
index 91b64a71..889b621b 100644
--- a/src/java/JavaFileStorage/app/app.iml
+++ b/src/java/JavaFileStorage/app/app.iml
@@ -85,7 +85,7 @@
-
+
@@ -104,8 +104,8 @@
-
+
diff --git a/src/java/JavaFileStorage/app/build.gradle b/src/java/JavaFileStorage/app/build.gradle
index d5dd100f..b6578585 100644
--- a/src/java/JavaFileStorage/app/build.gradle
+++ b/src/java/JavaFileStorage/app/build.gradle
@@ -1,20 +1,20 @@
apply plugin: 'com.android.library'
android {
- compileSdkVersion 21
- buildToolsVersion "21.1.2"
-
+ compileSdkVersion 23
+ buildToolsVersion '23.0.0'
defaultConfig {
minSdkVersion 14
- targetSdkVersion 21
+ targetSdkVersion 23
}
-
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
}
}
+ productFlavors {
+ }
}
dependencies {
diff --git a/src/java/JavaFileStorage/app/build/outputs/aar/app-debug.aar b/src/java/JavaFileStorage/app/build/outputs/aar/app-debug.aar
index 51287905..3ca10e5f 100644
Binary files a/src/java/JavaFileStorage/app/build/outputs/aar/app-debug.aar and b/src/java/JavaFileStorage/app/build/outputs/aar/app-debug.aar differ
diff --git a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveFileStorage.java b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveFileStorage.java
index b8f87a23..bb95c329 100644
--- a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveFileStorage.java
+++ b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveFileStorage.java
@@ -27,11 +27,14 @@ import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
import com.google.api.services.drive.model.ParentReference;
+import android.Manifest;
import android.accounts.AccountManager;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
@@ -43,9 +46,9 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
static final int MAGIC_GDRIVE=2082334;
static final int REQUEST_ACCOUNT_PICKER = MAGIC_GDRIVE+1;
static final int REQUEST_AUTHORIZATION = MAGIC_GDRIVE+2;
+ private boolean mRequiresRuntimePermissions = false;
+
-
-
class FileSystemEntryData
{
String displayName;
@@ -253,7 +256,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
public GoogleDriveFileStorage()
{
- logDebug("Creating GDrive FileStorage");
+ logDebug("Creating GDrive FileStorage.");
}
@Override
@@ -370,7 +373,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
GDrivePath parentGdrivePath = new GDrivePath(parentPath);
body.setParents(
- Arrays.asList(new ParentReference().setId(parentGdrivePath.getGDriveId())));
+ Arrays.asList(new ParentReference().setId(parentGdrivePath.getGDriveId())));
try
{
File file = getDriveService(parentGdrivePath.getAccount()).files().insert(body).execute();
@@ -393,7 +396,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
GDrivePath parentGdrivePath = new GDrivePath(parentPath);
body.setParents(
- Arrays.asList(new ParentReference().setId(parentGdrivePath.getGDriveId())));
+ Arrays.asList(new ParentReference().setId(parentGdrivePath.getGDriveId())));
try
{
File file = getDriveService(parentGdrivePath.getAccount()).files().insert(body).execute();
@@ -424,7 +427,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
throw new FileNotFoundException(parentPath + " is trashed!");
logDebug("listing files in "+parentId);
Files.List request = driveService.files().list()
- .setQ("trashed=false and '"+parentId+"' in parents");
+ .setQ("trashed=false and '" + parentId + "' in parents");
do {
try {
@@ -505,7 +508,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
FileEntry res = convertToFileEntry(
getFileForPath(gdrivePath, getDriveService(gdrivePath.getAccount())),
filename);
- logDebug("getFileEntry res"+res);
+ logDebug("getFileEntry res" + res);
return res;
}
catch (Exception e)
@@ -551,13 +554,13 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
{
logDebug("getDriveService "+accountName);
AccountData accountData = mAccountData.get(accountName);
- logDebug("accountData "+accountData);
+ logDebug("accountData " + accountData);
return accountData.drive;
}
@Override
public void onActivityResult(final JavaFileStorage.FileStorageSetupActivity setupAct, int requestCode, int resultCode, Intent data) {
- logDebug("ActivityResult: "+requestCode+"/"+resultCode);
+ logDebug("ActivityResult: " + requestCode + "/" + resultCode);
switch (requestCode) {
case REQUEST_ACCOUNT_PICKER:
logDebug("ActivityResult: REQUEST_ACCOUNT_PICKER");
@@ -773,6 +776,38 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
}
+ @Override
+ public void onRequestPermissionsResult(FileStorageSetupActivity setupAct, int requestCode, String[] permissions, int[] grantResults)
+ {
+ logDebug("onRequestPermissionsResult");
+ if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
+ {
+ logDebug("granted");
+ initFileStorage(setupAct);
+ }
+ else
+ {
+ logDebug("denied");
+ finishWithError(setupAct, new Exception("You must grant the requested permissions to continue."));
+ }
+ }
+
+ private void initFileStorage(FileStorageSetupActivity setupAct) {
+ Activity activity = (Activity)setupAct;
+
+ if (PROCESS_NAME_SELECTFILE.equals(setupAct.getProcessName()))
+ {
+ GoogleAccountCredential credential = createCredential(activity.getApplicationContext());
+
+ logDebug("starting REQUEST_ACCOUNT_PICKER");
+ activity.startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
+ }
+
+ if (PROCESS_NAME_FILE_USAGE_SETUP.equals(setupAct.getProcessName()))
+ {
+ initializeAccountOrPath(setupAct, setupAct.getPath());
+ }
+ }
@Override
public void onResume(JavaFileStorage.FileStorageSetupActivity setupAct) {
@@ -781,22 +816,13 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
@Override
public void onStart(final JavaFileStorage.FileStorageSetupActivity setupAct) {
-
- logDebug("onStart");
- Activity activity = (Activity)setupAct;
-
- if (PROCESS_NAME_SELECTFILE.equals(setupAct.getProcessName()))
+ logDebug("onStart "+mRequiresRuntimePermissions);
+ if (!mRequiresRuntimePermissions)
{
- GoogleAccountCredential credential = createCredential(activity.getApplicationContext());
-
- logDebug("starting REQUEST_ACCOUNT_PICKER");
- activity.startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
+ initFileStorage(setupAct);
}
- if (PROCESS_NAME_FILE_USAGE_SETUP.equals(setupAct.getProcessName()))
- {
- initializeAccountOrPath(setupAct, setupAct.getPath());
- }
+
}
private GoogleAccountCredential createCredential(Context appContext) {
@@ -816,6 +842,21 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
public void onCreate(FileStorageSetupActivity activity,
Bundle savedInstanceState) {
+ logDebug("onCreate");
+ mRequiresRuntimePermissions = false;
+ if (Build.VERSION.SDK_INT >= 23)
+ {
+ Activity act = (Activity)activity;
+ int permissionRes = act.checkSelfPermission(Manifest.permission.GET_ACCOUNTS);
+ logDebug("permissionRes="+permissionRes);
+ if (permissionRes == PackageManager.PERMISSION_DENIED)
+ {
+ logDebug("requestPermissions");
+ mRequiresRuntimePermissions = true;
+ act.requestPermissions(new String[] {Manifest.permission.GET_ACCOUNTS}, 0);
+ }
+ }
+
}
diff --git a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/JavaFileStorage.java b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/JavaFileStorage.java
index 0bf332fc..0dca7e9d 100644
--- a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/JavaFileStorage.java
+++ b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/JavaFileStorage.java
@@ -18,7 +18,7 @@ public interface JavaFileStorage {
public static final String EXTRA_PATH = "fileName"; //match KP2A PasswordActivity Ioc-Path Extra key
public static final String EXTRA_IS_FOR_SAVE = "IS_FOR_SAVE";
public static final String EXTRA_ERROR_MESSAGE = "EXTRA_ERROR_MESSAGE";
- public static final String EXTRA_ALWAYS_RETURN_SUCCESS = "EXTRA_ALWAYS_RETURN_SUCCESS";;
+ public static final String EXTRA_ALWAYS_RETURN_SUCCESS = "EXTRA_ALWAYS_RETURN_SUCCESS";
public interface FileStorageSetupInitiatorActivity
@@ -155,5 +155,6 @@ public class FileEntry {
public void onResume(FileStorageSetupActivity activity);
public void onStart(FileStorageSetupActivity activity);
public void onActivityResult(FileStorageSetupActivity activity, int requestCode, int resultCode, Intent data);
+ public void onRequestPermissionsResult(FileStorageSetupActivity activity, int requestCode, String[] permissions, int[] grantResults);
}
\ No newline at end of file
diff --git a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/JavaFileStorageBase.java b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/JavaFileStorageBase.java
index b2a8f999..f598fd2b 100644
--- a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/JavaFileStorageBase.java
+++ b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/JavaFileStorageBase.java
@@ -147,5 +147,10 @@ public abstract class JavaFileStorageBase implements JavaFileStorage{
}
+ public void onRequestPermissionsResult(FileStorageSetupActivity activity, int requestCode, String[] permissions, int[] grantResults)
+ {
+
+ }
+
}
diff --git a/src/keepass2android/CreateDatabaseActivity.cs b/src/keepass2android/CreateDatabaseActivity.cs
index 983d6f4c..191da39d 100644
--- a/src/keepass2android/CreateDatabaseActivity.cs
+++ b/src/keepass2android/CreateDatabaseActivity.cs
@@ -287,13 +287,20 @@ namespace keepass2android
private void SetDefaultIoc()
{
- var sdDir = SdDir;
- string filename = sdDir + "keepass.kdbx";
+ File directory = GetExternalFilesDir(null);
+ if (directory == null)
+ directory = FilesDir;
+
+ string strDir = directory.CanonicalPath;
+ if (!strDir.EndsWith(File.Separator))
+ strDir += File.Separator;
+
+ string filename = strDir + "keepass.kdbx";
filename = ConvertFilenameToIocPath(filename);
int count = 2;
while (new File(filename).Exists())
{
- filename = ConvertFilenameToIocPath(sdDir + "keepass" + count + ".kdbx");
+ filename = ConvertFilenameToIocPath(strDir + "keepass" + count + ".kdbx");
count++;
}
diff --git a/src/keepass2android/PasswordActivity.cs b/src/keepass2android/PasswordActivity.cs
index e72b4f40..09707b2f 100644
--- a/src/keepass2android/PasswordActivity.cs
+++ b/src/keepass2android/PasswordActivity.cs
@@ -71,7 +71,8 @@ namespace keepass2android
LaunchMode = LaunchMode.SingleInstance,
WindowSoftInputMode = SoftInput.AdjustResize,
Theme = "@style/MyTheme_Blue")] /*caution: also contained in AndroidManifest.xml*/
- public class PasswordActivity : LockingActivity, IFingerprintAuthCallback
+ [IntentFilter(new[] { "kp2a.action.PasswordActivity" }, Categories = new[] { Intent.CategoryDefault })]
+ public class PasswordActivity : LockingActivity, IFingerprintAuthCallback
{
enum KeyProviders
diff --git a/src/keepass2android/Properties/AndroidManifest_debug.xml b/src/keepass2android/Properties/AndroidManifest_debug.xml
index eb16b722..860c126f 100644
--- a/src/keepass2android/Properties/AndroidManifest_debug.xml
+++ b/src/keepass2android/Properties/AndroidManifest_debug.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/src/keepass2android/Properties/AndroidManifest_net.xml b/src/keepass2android/Properties/AndroidManifest_net.xml
index e3bafa41..881671cb 100644
--- a/src/keepass2android/Properties/AndroidManifest_net.xml
+++ b/src/keepass2android/Properties/AndroidManifest_net.xml
@@ -4,7 +4,7 @@
android:versionName="1.0.0 preview 2"
package="keepass2android.keepass2android"
android:installLocation="auto">
-
+
diff --git a/src/keepass2android/Properties/AndroidManifest_nonet.xml b/src/keepass2android/Properties/AndroidManifest_nonet.xml
index 1508c61a..951fd68e 100644
--- a/src/keepass2android/Properties/AndroidManifest_nonet.xml
+++ b/src/keepass2android/Properties/AndroidManifest_nonet.xml
@@ -4,7 +4,7 @@
android:versionName="0.9.8b"
package="keepass2android.keepass2android_nonet"
android:installLocation="auto">
-
+
diff --git a/src/keepass2android/Resources/values-iw/strings.xml b/src/keepass2android/Resources/values-iw/strings.xml
deleted file mode 100644
index 7ad103b9..00000000
--- a/src/keepass2android/Resources/values-iw/strings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/src/keepass2android/Resources/values/strings.xml b/src/keepass2android/Resources/values/strings.xml
index b6ab7735..961e3a9c 100644
--- a/src/keepass2android/Resources/values/strings.xml
+++ b/src/keepass2android/Resources/values/strings.xml
@@ -594,11 +594,13 @@
- Version 1.0.0 - preview 1\n
+ Version 1.0.0 - preview 2\n
+ * Fingerprint Unlock (requires Android 6.0 or later)\n
* Added "work offline" mode\n
* Allow to copy entries\n
* Auto-complete mode for field names\n
* Allow to remove items from recent files list\n
+ * Request permissions at runtime in Android 6.0\n
* more to come...\n
diff --git a/src/keepass2android/fileselect/FileStorageSetupActivity.cs b/src/keepass2android/fileselect/FileStorageSetupActivity.cs
index ce686e87..25ae1667 100644
--- a/src/keepass2android/fileselect/FileStorageSetupActivity.cs
+++ b/src/keepass2android/fileselect/FileStorageSetupActivity.cs
@@ -87,7 +87,18 @@ namespace keepass2android.fileselect
App.Kp2a.GetFileStorage(Ioc).OnActivityResult(this, requestCode, (int) resultCode, data);
}
- protected override void OnSaveInstanceState(Bundle outState)
+ public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
+ {
+ base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
+ var fileStorage = App.Kp2a.GetFileStorage(Ioc);
+ if (fileStorage is IPermissionRequestingFileStorage)
+ {
+ ((IPermissionRequestingFileStorage)fileStorage).OnRequestPermissionsResult(this, requestCode, permissions, grantResults);
+ }
+
+ }
+
+ protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
diff --git a/src/keepass2android/keepass2android.csproj b/src/keepass2android/keepass2android.csproj
index a482aa3a..d96039f0 100644
--- a/src/keepass2android/keepass2android.csproj
+++ b/src/keepass2android/keepass2android.csproj
@@ -86,17 +86,17 @@
+
+ ..\packages\Xamarin.Android.Support.v7.MediaRouter.21.0.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.MediaRouter.dll
+
- ..\packages\Xamarin.Android.Support.v4.23.1.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll
+ ..\packages\Xamarin.Android.Support.v4.22.2.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll
- ..\packages\Xamarin.Android.Support.v7.AppCompat.23.1.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.AppCompat.dll
-
-
- ..\packages\Xamarin.Android.Support.v7.RecyclerView.23.1.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.RecyclerView.dll
+ ..\packages\Xamarin.Android.Support.v7.AppCompat.22.2.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.AppCompat.dll
- ..\packages\Xamarin.Android.Support.Design.23.1.1.0\lib\MonoAndroid403\Xamarin.Android.Support.Design.dll
+ ..\packages\Xamarin.Android.Support.Design.22.2.1.0\lib\MonoAndroid403\Xamarin.Android.Support.Design.dll
..\packages\Xamarin.GooglePlayServices.Base.27.0.0.0\lib\MonoAndroid41\Xamarin.GooglePlayServices.Base.dll
@@ -671,7 +671,6 @@
-
@@ -729,7 +728,6 @@
-
@@ -847,6 +845,12 @@
Designer
+
+
+ 22.2.0.0
+ False
+
+
@@ -1643,12 +1647,6 @@
-
-
- False
- 23.0.1.3
-
-
diff --git a/src/keepass2android/packages.config b/src/keepass2android/packages.config
index e35326ad..15f24723 100644
--- a/src/keepass2android/packages.config
+++ b/src/keepass2android/packages.config
@@ -1,9 +1,9 @@
-
-
-
-
+
+
+
+