bug fixes and improvements after adding multi-database support

This commit is contained in:
Philipp Crocoll
2018-10-25 06:03:08 +02:00
parent a2dab72b25
commit 4f3f18a0ad
25 changed files with 501 additions and 291 deletions

View File

@@ -88,7 +88,8 @@ namespace keepass2android
EventHandler<DialogClickEventArgs> yesHandler,
EventHandler<DialogClickEventArgs> noHandler,
EventHandler<DialogClickEventArgs> cancelHandler,
Context ctx);
Context ctx,
string messageSuffix = "");
/// <summary>
/// Asks the user the question "messageKey" with the options Yes/No/Cancel, but the yes/no strings can be selected freely, calls the handler corresponding to the answer.
@@ -98,7 +99,8 @@ namespace keepass2android
EventHandler<DialogClickEventArgs> yesHandler,
EventHandler<DialogClickEventArgs> noHandler,
EventHandler<DialogClickEventArgs> cancelHandler,
Context ctx);
Context ctx,
string messageSuffix = "");
/// <summary>
/// Returns a Handler object which can run tasks on the UI thread
@@ -127,6 +129,5 @@ namespace keepass2android
#endif
}
}
}

View File

@@ -211,6 +211,8 @@ namespace keepass2android
}
Entries [e.Uuid] = e;
}
Groups[currentGroup.Uuid] = currentGroup;
foreach (PwGroup g in childGroups)
{
if (checkForDuplicateUuids)
@@ -222,7 +224,6 @@ namespace keepass2android
}
* */
}
Groups[g.Uuid] = g;
PopulateGlobals(g);
}
}
@@ -231,7 +232,13 @@ namespace keepass2android
PopulateGlobals(currentGroup, _app.CheckForDuplicateUuids);
}
public void UpdateGlobals()
{
Entries.Clear();
Groups.Clear();
PopulateGlobals(Root);
}
}
[Serializable]

View File

@@ -88,8 +88,10 @@ namespace keepass2android
save.SetStatusLogger(StatusLogger);
_onFinishToRun = null;
save.Run();
db.UpdateGlobals();
}
}

View File

@@ -21,6 +21,7 @@ namespace keepass2android
//determine once. The property is queried for each delete operation, but might return false
//after one entry/group is deleted (and thus in recycle bin and thus can't be recycled anymore)
_canRecycle = DetermineCanRecycle();
ShowDatabaseIocInStatus = true;
}
private bool DetermineCanRecycle()

View File

@@ -121,25 +121,27 @@ namespace keepass2android
public void Start()
{
if (CanRecycle)
string messageSuffix = ShowDatabaseIocInStatus ? "(" + App.GetFileStorage(Db.Ioc).GetDisplayName(Db.Ioc) + ")" : "";
if (CanRecycle)
{
App.AskYesNoCancel(UiStringKey.AskDeletePermanently_title,
QuestionRecycleResourceId,
(dlgSender, dlgEvt) =>
{
DeletePermanently = true;
ProgressTask pt = new ProgressTask(App, Ctx, this);
pt.Run();
DeletePermanently = true;
ProgressTask pt = new ProgressTask(App, Ctx, this);
pt.Run();
},
(dlgSender, dlgEvt) =>
{
DeletePermanently = false;
ProgressTask pt = new ProgressTask(App, Ctx, this);
pt.Run();
DeletePermanently = false;
ProgressTask pt = new ProgressTask(App, Ctx, this);
pt.Run();
},
(dlgSender, dlgEvt) => { },
Ctx);
Ctx, messageSuffix);
@@ -150,12 +152,12 @@ namespace keepass2android
QuestionNoRecycleResourceId,
(dlgSender, dlgEvt) =>
{
ProgressTask pt = new ProgressTask(App, Ctx, this);
pt.Run();
ProgressTask pt = new ProgressTask(App, Ctx, this);
pt.Run();
},
null,
(dlgSender, dlgEvt) => { },
Ctx);
Ctx, messageSuffix);
}
@@ -234,13 +236,21 @@ namespace keepass2android
// Commit database
SaveDb save = new SaveDb(Ctx, App, Db, OnFinishToRun, false);
save.SetStatusLogger(StatusLogger);
save.ShowDatabaseIocInStatus = ShowDatabaseIocInStatus;
save.SetStatusLogger(StatusLogger);
save.Run();
}
protected abstract void PerformDelete(List<PwGroup> touchedGroups, List<PwGroup> permanentlyDeletedGroups);
public bool ShowDatabaseIocInStatus
{
get;
set;
}
protected abstract void PerformDelete(List<PwGroup> touchedGroups, List<PwGroup> permanentlyDeletedGroups);
public abstract UiStringKey StatusMessage { get; }

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Android.App;
@@ -50,11 +51,20 @@ namespace keepass2android.database.edit
}
HashSet<Database> removeDatabases = new HashSet<Database>();
Database addDatabase = _app.FindDatabaseForGroupId(_targetGroup.Uuid);
if (addDatabase == null)
{
Finish(false, "Did not find target database. Did you lock it?");
return;
}
foreach (var elementToMove in _elementsToMove)
{
_app.DirtyGroups.Add(elementToMove.ParentGroup);
//TODO is this safe when transferring between databases?
PwGroup pgParent = elementToMove.ParentGroup;
if (pgParent != _targetGroup)
{
@@ -63,8 +73,12 @@ namespace keepass2android.database.edit
PwEntry entry = elementToMove as PwEntry;
if (entry != null)
{
var dbRem = _app.FindDatabaseForEntryId(entry.Uuid);
removeDatabases.Add(dbRem);
dbRem.Entries.Remove(entry.Uuid);
pgParent.Entries.Remove(entry);
_targetGroup.AddEntry(entry, true, true);
addDatabase.Entries.Add(entry.Uuid, entry);
}
else
{
@@ -74,30 +88,58 @@ namespace keepass2android.database.edit
Finish(false, _app.GetResourceString(UiStringKey.CannotMoveGroupHere));
return;
}
var dbRem = _app.FindDatabaseForEntryId(@group.Uuid);
if (dbRem == null)
{
Finish(false, "Did not find source database. Did you lock it?");
return;
}
dbRem.Groups.Remove(group.Uuid);
removeDatabases.Add(dbRem);
pgParent.Groups.Remove(group);
_targetGroup.AddGroup(group, true, true);
addDatabase.Groups.Add(group.Uuid, group);
}
}
}
}
_onFinishToRun = new ActionOnFinish(ActiveActivity, (success, message, activity) =>
{
if (!success)
{ // Let's not bother recovering from a failure.
_app.Lock(false);
}
}, OnFinishToRun);
//Unchecked
//TODO save the right database
//first save the database where we added the elements
var allDatabasesToSave = new List<Database> {addDatabase};
//then all databases where we removed elements:
removeDatabases.RemoveWhere(db => db == addDatabase);
allDatabasesToSave.AddRange(removeDatabases);
// Save
SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun, false);
save.SetStatusLogger(StatusLogger);
save.Run();
int indexToSave = 0;
bool allSavesSuccess = true;
void ContinueSave(bool success, string message, Activity activeActivity)
{
allSavesSuccess &= success;
indexToSave++;
if (indexToSave == allDatabasesToSave.Count)
{
OnFinishToRun.SetResult(allSavesSuccess);
OnFinishToRun.Run();
return;
}
SaveDb saveDb = new SaveDb(_ctx, _app, allDatabasesToSave[indexToSave], new ActionOnFinish(activeActivity, ContinueSave), false);
saveDb.SetStatusLogger(StatusLogger);
saveDb.ShowDatabaseIocInStatus = allDatabasesToSave.Count > 1;
saveDb.Run();
}
SaveDb save = new SaveDb(_ctx, _app, allDatabasesToSave[0], new ActionOnFinish(ActiveActivity, ContinueSave), false);
save.SetStatusLogger(StatusLogger);
save.ShowDatabaseIocInStatus = allDatabasesToSave.Count > 1;
save.Run();
}
}
}

View File

@@ -79,9 +79,10 @@ namespace keepass2android
_db = db;
_dontSave = false;
}
public override void Run ()
public bool ShowDatabaseIocInStatus { get; set; }
public override void Run ()
{
if (!_dontSave)
@@ -95,7 +96,13 @@ namespace keepass2android
return;
}
StatusLogger.UpdateMessage(UiStringKey.saving_database);
string message = _app.GetResourceString(UiStringKey.saving_database);
if (ShowDatabaseIocInStatus)
message += " (" + _app.GetFileStorage(_db.Ioc).GetDisplayName(_db.Ioc) + ")";
StatusLogger.UpdateMessage(message);
IOConnectionInfo ioc = _db.Ioc;
IFileStorage fileStorage = _app.GetFileStorage(ioc);

View File

@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace keepass2android
{
public abstract class ActivityLaunchMode
{
public abstract void Launch(Activity act, Intent i);
}
public class ActivityLaunchModeForward : ActivityLaunchMode
{
public override void Launch(Activity act, Intent i)
{
i.AddFlags(ActivityFlags.ForwardResult);
act.StartActivity(i);
}
}
public class ActivityLaunchModeRequestCode : ActivityLaunchMode
{
private readonly int _reqCode;
public ActivityLaunchModeRequestCode(int reqCode)
{
_reqCode = reqCode;
}
public override void Launch(Activity act, Intent i)
{
act.StartActivityForResult(i, _reqCode);
}
}
public class ActivityLaunchModeSimple : ActivityLaunchMode
{
public override void Launch(Activity act, Intent i)
{
act.StartActivity(i);
}
}
}

View File

@@ -497,8 +497,13 @@ namespace keepass2android
dbHelper.CreateFile(_ioc, Filename);
}
GroupActivity.Launch(_activity, _activity._appTask);
_activity.Finish();
Intent data = new Intent();
data.PutExtra("ioc", IOConnectionInfo.SerializeToString(_ioc));
_activity.SetResult(Result.Ok, data);
_activity.Finish();
}
else

View File

@@ -207,7 +207,14 @@ namespace keepass2android
{
Kp2aLog.Log("FP: StopListening ");
_selfCancelled = true;
_cancellationSignal.Cancel();
try
{
_cancellationSignal.Cancel();
}
catch (System.ObjectDisposedException e)
{
Kp2aLog.LogUnexpectedError(e);
}
_cancellationSignal = null;
}
}

View File

@@ -63,11 +63,11 @@ namespace keepass2android
private const String Tag = "Group Activity:";
private const string Askaddtemplates = "AskAddTemplates";
public static void Launch(Activity act, AppTask appTask) {
Launch(act, null, appTask);
public static void Launch(Activity act, AppTask appTask, ActivityLaunchMode launchMode) {
Launch(act, null, appTask, launchMode);
}
public static void Launch (Activity act, PwGroup g, AppTask appTask)
public static void Launch (Activity act, PwGroup g, AppTask appTask, ActivityLaunchMode launchMode)
{
Intent i = new Intent(act, typeof(GroupActivity));
@@ -76,7 +76,7 @@ namespace keepass2android
}
appTask.ToIntent(i);
act.StartActivityForResult(i,0);
launchMode.Launch(act, i);
}
protected PwUuid RetrieveGroupId(Intent i)

View File

@@ -199,6 +199,12 @@ namespace keepass2android
Finish();
}
if (resultCode == KeePass.ExitLoadAnotherDb)
{
AppTask.SetActivityResult(this, KeePass.ExitLoadAnotherDb);
Finish();
}
if (resultCode == KeePass.ExitReloadDb)
{
AppTask.SetActivityResult(this, KeePass.ExitReloadDb);

View File

@@ -67,8 +67,7 @@ namespace keepass2android
ConfigurationChanges = ConfigChanges.Orientation,
LaunchMode = LaunchMode.SingleInstance,
WindowSoftInputMode = SoftInput.AdjustResize,
Theme = "@style/MyTheme_Blue")] /*caution: also contained in AndroidManifest.xml*/
//CAUTION: don't add intent filters here, they must be set in the manifest xml file
Theme = "@style/MyTheme_Blue")]
public class PasswordActivity : LockingActivity, IFingerprintAuthCallback
{
@@ -84,10 +83,9 @@ namespace keepass2android
public const String KeyDefaultFilename = "defaultFileName";
private const String KeyKeyfile = "keyFile";
private const String KeyPassword = "password";
public const String KeyKeyfile = "keyFile";
public const String KeyPassword = "password";
private const String ViewIntent = "android.intent.action.VIEW";
private const string ShowpasswordKey = "ShowPassword";
private const string KeyProviderIdOtp = "KP2A-OTP";
private const string KeyProviderIdOtpRecovery = "KP2A-OTPSecret";
@@ -103,15 +101,16 @@ namespace keepass2android
private const int RequestCodePrepareKeyFile = 1004;
private const int RequestCodeSelectAuxFile = 1005;
public const int ResultSelectOtherFile = (int) Result.FirstUser;
private Task<MemoryStream> _loadDbFileTask;
private Task<MemoryStream> _loadDbFileTask;
private bool _loadDbTaskOffline; //indicate if preloading was started with offline mode
private IOConnectionInfo _ioConnection;
private String _keyFile;
bool _showPassword;
internal AppTask AppTask;
private bool _killOnDestroy;
private string _password = "";
//OTPs which should be entered into the OTP fields as soon as these become visible
@@ -160,52 +159,31 @@ namespace keepass2android
//can be set before launching the Activity. Will be used once to immediately open the database
static CompositeKey compositeKeyForImmediateLoad = null;
public static void Launch(Activity act, IOConnectionInfo ioc, AppTask appTask, CompositeKey compositeKey)
public static void Launch(Activity act, IOConnectionInfo ioc, CompositeKey compositeKey, ActivityLaunchMode launchMode)
{
compositeKeyForImmediateLoad = compositeKey;
Launch(act, ioc, appTask);
Launch(act, ioc, launchMode);
}
public static void Launch(Activity act, String fileName, AppTask appTask)
{
File dbFile = new File(fileName);
if ( ! dbFile.Exists() ) {
throw new FileNotFoundException();
}
Intent i = new Intent(act, typeof(PasswordActivity));
i.SetFlags(ActivityFlags.ForwardResult);
i.PutExtra(Util.KeyFilename, fileName);
appTask.ToIntent(i);
act.StartActivity(i);
}
public static void Launch(Activity act, IOConnectionInfo ioc, AppTask appTask)
public static void Launch(Activity act, IOConnectionInfo ioc, ActivityLaunchMode launchMode)
{
if (ioc.IsLocalFile())
{
Launch(act, ioc.Path, appTask);
return;
}
Intent i = new Intent(act, typeof(PasswordActivity));
Util.PutIoConnectionToIntent(ioc, i);
i.SetFlags(ActivityFlags.ForwardResult);
appTask.ToIntent(i);
act.StartActivity(i);
launchMode.Launch(act, i);
}
public void LaunchNextActivity()
{
//StackBaseActivity will launch the next activity
Intent data = new Intent();
data.PutExtra("ioc", IOConnectionInfo.SerializeToString(_ioConnection));
SetResult(Result.Ok, data);
Finish();
}
@@ -215,8 +193,6 @@ namespace keepass2android
_keepPasswordInOnResume = true;
Kp2aLog.Log("PasswordActivity.OnActivityResult "+resultCode+"/"+requestCode);
AppTask.TryGetFromActivityResult(data, ref AppTask);
switch(resultCode) {
@@ -663,7 +639,7 @@ namespace keepass2android
_activityDesign.ApplyTheme();
base.OnCreate(savedInstanceState);
_intentReceiver = new PasswordActivityBroadcastReceiver(this);
_intentReceiver = new PasswordActivityBroadcastReceiver(this);
IntentFilter filter = new IntentFilter();
filter.AddAction(Intent.ActionScreenOff);
RegisterReceiver(_intentReceiver, filter);
@@ -678,19 +654,6 @@ namespace keepass2android
Intent i = Intent;
//only load the AppTask if this is the "first" OnCreate (not because of kill/resume, i.e. savedInstanceState==null)
// and if the activity is not launched from history (i.e. recent tasks) because this would mean that
// the Activity was closed already (user cancelling the task or task complete) but is restarted due recent tasks.
// Don't re-start the task (especially bad if tak was complete already)
if (Intent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory))
{
AppTask = new NullTask();
}
else
{
AppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
}
String action = i.Action;
@@ -700,11 +663,7 @@ namespace keepass2android
_ioConnection = new IOConnectionInfo();
if (action != null && action.Equals(ViewIntent))
{
if (!GetIocFromViewIntent(i)) return;
}
else if ((action != null) && (action.Equals(Intents.StartWithOtp)))
if ((action != null) && (action.Equals(Intents.StartWithOtp)))
{
if (!GetIocFromOtpIntent(savedInstanceState, i)) return;
_keepPasswordInOnResume = true;
@@ -802,11 +761,10 @@ namespace keepass2android
RequestPermissions(new[] { Manifest.Permission.UseFingerprint }, FingerprintPermissionRequestCode);
var matchingOpenDb = App.Kp2a.OpenDatabases.FirstOrDefault(db => db.Ioc.IsSameFileAs(_ioConnection));
if (matchingOpenDb != null)
{
App.Kp2a.CurrentDb = matchingOpenDb;
Finish();
if (App.Kp2a.TrySelectCurrentDb(_ioConnection))
{
//database already opened. return the ioc and we're good.
LaunchNextActivity();
}
}
@@ -1137,50 +1095,6 @@ namespace keepass2android
return true;
}
private bool GetIocFromViewIntent(Intent i)
{
//started from "view" intent (e.g. from file browser)
_ioConnection.Path = i.DataString;
if (_ioConnection.Path.StartsWith("file://"))
{
_ioConnection.Path = URLDecoder.Decode(_ioConnection.Path.Substring(7));
if (_ioConnection.Path.Length == 0)
{
// No file name
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
Finish();
return false;
}
File dbFile = new File(_ioConnection.Path);
if (!dbFile.Exists())
{
// File does not exist
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
Finish();
return false;
}
}
else
{
if (!_ioConnection.Path.StartsWith("content://"))
{
Toast.MakeText(this, Resource.String.error_can_not_handle_uri, ToastLength.Long).Show();
Finish();
return false;
}
IoUtil.TryTakePersistablePermissions(this.ContentResolver, i.Data);
}
SetKeyProviderFromString(LoadKeyProviderStringForIoc(_ioConnection.Path));
return true;
}
private void InitializeBottomBarButtons()
{
@@ -1607,7 +1521,6 @@ namespace keepass2android
CopyToClipboardService.ActivateKeyboard(this);
}
AppTask.CanActivateSearchViewOnStart = true;
DonateReminder.ShowDonateReminderIfAppropriate(this);
@@ -1635,7 +1548,6 @@ namespace keepass2android
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
AppTask.ToBundle(outState);
outState.PutBoolean(ShowpasswordKey, _showPassword);
outState.PutString(KeyFileOrProviderKey, GetKeyProviderString());
@@ -1751,6 +1663,7 @@ namespace keepass2android
killButton.Click += (sender, args) =>
{
_killOnDestroy = true;
SetResult(Result.Canceled);
Finish();
};
@@ -1856,9 +1769,9 @@ namespace keepass2android
keyboard.HideSoftInputFromWindow(pwd.WindowToken, HideSoftInputFlags.ImplicitOnly);
}, 50);
}
}
}
private bool InitFingerprintUnlock()
private bool InitFingerprintUnlock()
{
var btn = FindViewById<ImageButton>(Resource.Id.fingerprintbtn);
try
@@ -1986,12 +1899,8 @@ namespace keepass2android
private void GoToFileSelectActivity()
{
Intent intent = new Intent(this, typeof (FileSelectActivity));
intent.PutExtra(FileSelectActivity.NoForwardToPasswordActivity, true);
AppTask.ToIntent(intent);
intent.AddFlags(ActivityFlags.ForwardResult);
StartActivity(intent);
Finish();
SetResult((Result) ResultSelectOtherFile);
Finish();
}
private class AfterLoad : OnFinish {
@@ -2014,7 +1923,6 @@ namespace keepass2android
_act.BroadcastOpenDatabase();
_act.InvalidCompositeKeyCount = 0;
_act.LoadingErrorCount = 0;
_act.Finish();
GC.Collect(); // Ensure temporary memory used while loading is collected
@@ -2080,20 +1988,22 @@ namespace keepass2android
(sender, args) =>
{
((Dialog) sender).Dismiss();
_act.LaunchNextActivity();
})
if (Success)
{
_act.LaunchNextActivity();
}
})
.SetCancelable(false)
.Show();
}
else
{
DisplayMessage(_act);
if (Success)
{
_act.LaunchNextActivity();
}
DisplayMessage(_act);
if (Success)
{
_act.LaunchNextActivity();
}
}
@@ -2207,6 +2117,7 @@ namespace keepass2android
}
}

View File

@@ -53,7 +53,7 @@
</intent-filter>
</activity>
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.PasswordActivity" 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">
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
@@ -64,7 +64,7 @@
</intent-filter>
<intent-filter>
<action android:name="kp2a.action.PasswordActivity" />
<action android:name="kp2a.action.SelectCurrentDbActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
@@ -97,13 +97,15 @@
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
</intent-filter>
<intent-filter android:label="@string/kp2a_findUrl">
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:scheme="https"
android:host="my.yubico.com"
android:pathPrefix="/neo"/>
<action android:name="keepass2android.ACTION_START_WITH_TASK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<uses-library required="false" name="com.sec.android.app.multiwindow" />

View File

@@ -58,7 +58,7 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.PasswordActivity" 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">
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
@@ -69,7 +69,7 @@
</intent-filter>
<intent-filter>
<action android:name="kp2a.action.PasswordActivity" />
<action android:name="kp2a.action.SelectCurrentDbActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
@@ -122,14 +122,15 @@
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:scheme="https"
android:host="my.yubico.com"
android:pathPrefix="/neo"/>
</intent-filter>
<intent-filter android:label="@string/kp2a_findUrl">
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="keepass2android.ACTION_START_WITH_TASK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<uses-library required="false" name="com.sec.android.app.multiwindow" />
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />

View File

@@ -41,7 +41,7 @@
</intent-filter>
</activity>
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.PasswordActivity" 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">
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
@@ -52,7 +52,7 @@
</intent-filter>
<intent-filter>
<action android:name="kp2a.action.PasswordActivity" />
<action android:name="kp2a.action.SelectCurrentDbActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
@@ -112,6 +112,16 @@
android:host="my.yubico.com"
android:pathPrefix="/neo"/>
</intent-filter>
<intent-filter android:label="@string/kp2a_findUrl">
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="keepass2android.ACTION_START_WITH_TASK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<uses-library required="false" name="com.sec.android.app.multiwindow" />
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />

View File

@@ -16,6 +16,8 @@ using Android.Text;
using Android.Util;
using Android.Views;
using Android.Widget;
using Java.IO;
using Java.Net;
using keepass2android.Io;
using keepass2android.Utils;
using KeePassLib.Keys;
@@ -24,9 +26,12 @@ using Object = Java.Lang.Object;
namespace keepass2android
{
[Activity(Label = AppNames.AppName, MainLauncher = false, Theme = "@style/MyTheme_Blue", LaunchMode = LaunchMode.SingleInstance)]
[Activity(Label = AppNames.AppName, MainLauncher = false, Theme = "@style/MyTheme_Blue", LaunchMode = LaunchMode.SingleInstance)] //caution, see manifest file
public class SelectCurrentDbActivity : AppCompatActivity
{
private int ReqCodeOpenNewDb = 1;
public class OpenDatabaseAdapter : BaseAdapter
{
@@ -135,12 +140,13 @@ namespace keepass2android
private void OnOpenOther()
{
StartFileSelect();
StartFileSelect(true);
}
private void OnItemSelected(Database selectedDatabase)
{
App.Kp2a.CurrentDb = selectedDatabase;
LaunchingOther = true;
AppTask.LaunchFirstGroupActivity(this);
}
@@ -155,7 +161,12 @@ namespace keepass2android
SupportActionBar.Title = GetString(Resource.String.select_database);
if ((AppTask == null) && (Intent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory)))
//only load the AppTask if this is the "first" OnCreate (not because of kill/resume, i.e. savedInstanceState==null)
// and if the activity is not launched from history (i.e. recent tasks) because this would mean that
// the Activity was closed already (user cancelling the task or task complete) but is restarted due recent tasks.
// Don't re-start the task (especially bad if tak was complete already)
if (Intent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory))
{
AppTask = new NullTask();
}
@@ -168,19 +179,91 @@ namespace keepass2android
var gridView = FindViewById<GridView>(Resource.Id.gridview);
gridView.ItemClick += (sender, args) => OnItemSelected(_adapter._displayedDatabases[args.Position]);
gridView.Adapter = _adapter;
if (!string.IsNullOrEmpty(Intent.GetStringExtra(Util.KeyFilename)))
{
//forward to password activity
Intent i = new Intent(this, typeof(PasswordActivity));
IOConnectionInfo ioc = new IOConnectionInfo();
Util.SetIoConnectionFromIntent(ioc, Intent);
Util.PutIoConnectionToIntent(ioc, i);
i.PutExtra(PasswordActivity.KeyKeyfile, i.GetStringExtra(PasswordActivity.KeyKeyfile));
i.PutExtra(PasswordActivity.KeyPassword, i.GetStringExtra(PasswordActivity.KeyPassword));
LaunchingOther = true;
StartActivityForResult(i, ReqCodeOpenNewDb);
}
else
{
if (Intent.Action == Intent.ActionView)
{
GetIocFromViewIntent(Intent);
}
else if (Intent.Action == Intent.ActionSend)
{
AppTask = new SearchUrlTask { UrlToSearchFor = Intent.GetStringExtra(Intent.ExtraText) };
}
}
_intentReceiver = new MyBroadcastReceiver(this);
IntentFilter filter = new IntentFilter();
filter.AddAction(Intents.DatabaseLocked);
RegisterReceiver(_intentReceiver, filter);
}
IOConnectionInfo LoadIoc(string defaultFileName)
private bool GetIocFromViewIntent(Intent intent)
{
return App.Kp2a.FileDbHelper.CursorToIoc(App.Kp2a.FileDbHelper.FetchFileByName(defaultFileName));
}
IOConnectionInfo ioc = new IOConnectionInfo();
//started from "view" intent (e.g. from file browser)
ioc.Path = intent.DataString;
if (ioc.Path.StartsWith("file://"))
{
ioc.Path = URLDecoder.Decode(ioc.Path.Substring(7));
if (ioc.Path.Length == 0)
{
// No file name
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
return false;
}
File dbFile = new File(ioc.Path);
if (!dbFile.Exists())
{
// File does not exist
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
return false;
}
}
else
{
if (!ioc.Path.StartsWith("content://"))
{
Toast.MakeText(this, Resource.String.error_can_not_handle_uri, ToastLength.Long).Show();
return false;
}
IoUtil.TryTakePersistablePermissions(this.ContentResolver, intent.Data);
}
{
Intent launchIntent = new Intent(this, typeof(PasswordActivity));
Util.PutIoConnectionToIntent(ioc, launchIntent);
LaunchingOther = true;
StartActivityForResult(launchIntent, ReqCodeOpenNewDb);
}
return true;
}
protected override void OnResume()
{
base.OnResume();
if (!IsFinishing && !LaunchingPasswordActivity)
if (!IsFinishing && !LaunchingOther)
{
if (App.Kp2a.OpenDatabases.Any() == false)
{
@@ -188,13 +271,6 @@ namespace keepass2android
return;
}
if (_loadAnotherDatabase)
{
StartFileSelect();
_loadAnotherDatabase = false;
return;
}
//database loaded
if (App.Kp2a.QuickLocked)
{
@@ -208,6 +284,7 @@ namespace keepass2android
//database(s) unlocked
if (App.Kp2a.OpenDatabases.Count() == 1)
{
LaunchingOther = true;
AppTask.LaunchFirstGroupActivity(this);
return;
}
@@ -223,21 +300,23 @@ namespace keepass2android
protected override void OnPause()
{
LaunchingPasswordActivity = false;
LaunchingOther = false;
base.OnPause();
}
private void StartFileSelect()
private void StartFileSelect(bool noForwardToPassword = false)
{
Intent intent = new Intent(this, typeof(FileSelectActivity));
AppTask.ToIntent(intent);
intent.AddFlags(ActivityFlags.ForwardResult);
StartActivity(intent);
intent.PutExtra(FileSelectActivity.NoForwardToPasswordActivity, noForwardToPassword);
LaunchingOther = true;
StartActivityForResult(intent, ReqCodeOpenNewDb);
}
internal AppTask AppTask;
private bool _loadAnotherDatabase;
private OpenDatabaseAdapter _adapter;
private MyBroadcastReceiver _intentReceiver;
public override void OnBackPressed()
{
@@ -261,6 +340,40 @@ namespace keepass2android
AppTask.TryGetFromActivityResult(data, ref AppTask);
if (requestCode == ReqCodeOpenNewDb)
{
switch ((int)resultCode)
{
case (int)Result.Ok:
string iocString = data?.GetStringExtra("ioc");
IOConnectionInfo ioc = IOConnectionInfo.UnserializeFromString(iocString);
if (App.Kp2a.TrySelectCurrentDb(ioc))
{
LaunchingOther = true;
AppTask.CanActivateSearchViewOnStart = true;
AppTask.LaunchFirstGroupActivity(this);
}
break;
case PasswordActivity.ResultSelectOtherFile:
StartFileSelect(true);
break;
case (int)Result.Canceled:
if (App.Kp2a.OpenDatabases.Any() == false)
{
//don't open fileselect/password activity again
OnBackPressed();
}
break;
default:
break;
}
return;
}
switch (resultCode)
{
case KeePass.ExitNormal: // Returned to this screen using the Back key
@@ -297,7 +410,7 @@ namespace keepass2android
break;
case KeePass.ExitLoadAnotherDb:
_loadAnotherDatabase = true;
StartFileSelect(true);
break;
}
@@ -305,10 +418,39 @@ namespace keepass2android
private void LaunchPasswordActivityForReload(IOConnectionInfo ioc, CompositeKey compositeKey)
{
LaunchingPasswordActivity = true;
PasswordActivity.Launch(this, ioc, AppTask, compositeKey);
LaunchingOther = true;
PasswordActivity.Launch(this, ioc, compositeKey, new ActivityLaunchModeRequestCode(ReqCodeOpenNewDb));
}
public bool LaunchingPasswordActivity { get; set; }
public bool LaunchingOther { get; set; }
private class MyBroadcastReceiver : BroadcastReceiver
{
readonly SelectCurrentDbActivity _activity;
public MyBroadcastReceiver(SelectCurrentDbActivity activity)
{
_activity = activity;
}
public override void OnReceive(Context context, Intent intent)
{
switch (intent.Action)
{
case Intents.DatabaseLocked:
_activity.OnLockDatabase();
break;
case Intent.ActionScreenOff:
App.Kp2a.OnScreenOff();
break;
}
}
}
private void OnLockDatabase()
{
//app tasks are assumed to be finished/cancelled when the database is locked
AppTask = new NullTask();
}
}
}

View File

@@ -56,11 +56,11 @@ namespace keepass2android
{
}
public static void Launch(Activity act, SearchUrlTask task)
public static void Launch(Activity act, SearchUrlTask task, ActivityLaunchMode launchMode)
{
Intent i = new Intent(act, typeof(ShareUrlResults));
task.ToIntent(i);
act.StartActivityForResult(i, 0);
launchMode.Launch(act, i);
}
@@ -171,7 +171,8 @@ namespace keepass2android
newTask.ShowUserNotifications = currentSelectTask.ShowUserNotifications;
selectOtherEntry.Click += (sender, e) => {
GroupActivity.Launch (this, newTask);
GroupActivity.Launch (this, newTask, new ActivityLaunchModeRequestCode(0));
};
@@ -182,7 +183,7 @@ namespace keepass2android
createUrlEntry.Visibility = ViewStates.Visible;
createUrlEntry.Click += (sender, e) =>
{
GroupActivity.Launch(this, new CreateEntryThenCloseTask { Url = url, ShowUserNotifications = (AppTask as SelectEntryTask)?.ShowUserNotifications ?? true });
GroupActivity.Launch(this, new CreateEntryThenCloseTask { Url = url, ShowUserNotifications = (AppTask as SelectEntryTask)?.ShowUserNotifications ?? true }, new ActivityLaunchModeRequestCode(0));
Toast.MakeText(this, GetString(Resource.String.select_group_then_add, new Java.Lang.Object[] { GetString(Resource.String.add_entry) }), ToastLength.Long).Show();
};
}

View File

@@ -500,14 +500,10 @@ namespace keepass2android
return Application.Context.Resources.GetDrawable((int)field.GetValue(null));
}
public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
EventHandler<DialogClickEventArgs> yesHandler,
EventHandler<DialogClickEventArgs> noHandler,
EventHandler<DialogClickEventArgs> cancelHandler,
Context ctx)
public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey, EventHandler<DialogClickEventArgs> yesHandler, EventHandler<DialogClickEventArgs> noHandler, EventHandler<DialogClickEventArgs> cancelHandler, Context ctx, string messageSuffix)
{
AskYesNoCancel(titleKey, messageKey, UiStringKey.yes, UiStringKey.no,
yesHandler, noHandler, cancelHandler, ctx);
yesHandler, noHandler, cancelHandler, ctx, messageSuffix);
}
public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
@@ -515,9 +511,9 @@ namespace keepass2android
EventHandler<DialogClickEventArgs> yesHandler,
EventHandler<DialogClickEventArgs> noHandler,
EventHandler<DialogClickEventArgs> cancelHandler,
Context ctx)
Context ctx, string messageSuffix = "")
{
AskYesNoCancel(titleKey, messageKey, yesString, noString, yesHandler, noHandler, cancelHandler, null, ctx);
AskYesNoCancel(titleKey, messageKey, yesString, noString, yesHandler, noHandler, cancelHandler, null, ctx, messageSuffix);
}
public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
@@ -526,7 +522,7 @@ namespace keepass2android
EventHandler<DialogClickEventArgs> noHandler,
EventHandler<DialogClickEventArgs> cancelHandler,
EventHandler dismissHandler,
Context ctx)
Context ctx, string messageSuffix = "")
{
Handler handler = new Handler(Looper.MainLooper);
handler.Post(() =>
@@ -534,7 +530,7 @@ namespace keepass2android
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.SetTitle(GetResourceString(titleKey));
builder.SetMessage(GetResourceString(messageKey));
builder.SetMessage(GetResourceString(messageKey)+(messageSuffix != "" ? " " + messageSuffix: ""));
string yesText = GetResourceString(yesString);
builder.SetPositiveButton(yesText, yesHandler);
@@ -787,6 +783,7 @@ namespace keepass2android
}
public class CertificateErrorHandlerImpl : Java.Lang.Object, Keepass2android.Javafilestorage.ICertificateErrorHandler
{
private readonly Kp2aApp _app;
@@ -1022,9 +1019,9 @@ namespace keepass2android
public PwGroup FindGroup(PwUuid uuid)
{
PwGroup result;
foreach (Database db in OpenDatabases)
{
PwGroup result;
if (db.Groups.TryGetValue(uuid, out result))
return result;
}
@@ -1044,7 +1041,19 @@ namespace keepass2android
}
return null;
}
}
public bool TrySelectCurrentDb(IOConnectionInfo ioConnection)
{
var matchingOpenDb = App.Kp2a.OpenDatabases.FirstOrDefault(db => db.Ioc.IsSameFileAs(ioConnection));
if (matchingOpenDb != null)
{
CurrentDb = matchingOpenDb;
return true;
}
return false;
}
}
///Application class for Keepass2Android: Contains static Database variable to be used by all components.

View File

@@ -187,7 +187,7 @@ namespace keepass2android
public virtual void LaunchFirstGroupActivity(Activity act)
{
GroupActivity.Launch(act, this);
GroupActivity.Launch(act, this, new ActivityLaunchModeRequestCode(0));
}
public virtual void AfterAddNewEntry(EntryEditActivity entryEditActivity, PwEntry newEntry)
@@ -403,11 +403,11 @@ namespace keepass2android
{
if (String.IsNullOrEmpty(UrlToSearchFor))
{
GroupActivity.Launch(act, new SelectEntryTask() { ShowUserNotifications = ShowUserNotifications});
GroupActivity.Launch(act, new SelectEntryTask() { ShowUserNotifications = ShowUserNotifications}, new ActivityLaunchModeRequestCode(0));
}
else
{
ShareUrlResults.Launch(act, this);
ShareUrlResults.Launch(act, this, new ActivityLaunchModeRequestCode(0));
}
@@ -792,7 +792,6 @@ namespace keepass2android
#endif
private LinkedList<string> _groupUuid;
private readonly Database _db;
protected AppTask TaskToBeLaunchedAfterNavigation;
protected String FullGroupName {
@@ -817,8 +816,7 @@ namespace keepass2android
/// <param name="groups">Groups.</param>
/// <param name="taskToBeLaunchedAfterNavigation">Task to be launched after navigation.</param>
/// <param name="toastEnable">If set to <c>true</c>, toast will be displayed after navigation.</param>
protected NavigateAndLaunchTask(Database db, PwGroup groups, AppTask taskToBeLaunchedAfterNavigation, bool toastEnable = false) {
_db = db;
protected NavigateAndLaunchTask(PwGroup groups, AppTask taskToBeLaunchedAfterNavigation, bool toastEnable = false) {
TaskToBeLaunchedAfterNavigation = taskToBeLaunchedAfterNavigation;
PopulateGroups (groups);
ToastEnable = toastEnable;
@@ -935,7 +933,7 @@ namespace keepass2android
groupBaseActivity.StartTask (TaskToBeLaunchedAfterNavigation);
return;
} else if (_groupUuid.Contains(groupBaseActivity.UuidGroup)) { // Need to go up in groups tree
} else if (_groupUuid.Contains(groupBaseActivity.UuidGroup)) { // Need to down up in groups tree
// Get next Group Uuid
var linkedListNode = _groupUuid.Find(groupBaseActivity.UuidGroup);
@@ -947,16 +945,27 @@ namespace keepass2android
PwUuid nextGroupPwUuid = new PwUuid (MemUtil.HexStringToByteArray (nextGroupUuid));
// Create Group Activity
PwGroup nextGroup = _db.Groups[nextGroupPwUuid];
GroupActivity.Launch (groupBaseActivity, nextGroup, this);
PwGroup nextGroup = App.Kp2a.CurrentDb.Groups[nextGroupPwUuid];
GroupActivity.Launch (groupBaseActivity, nextGroup, this, new ActivityLaunchModeRequestCode(0));
}
return;
} else { // Need to go down in groups tree
SetActivityResult(groupBaseActivity, KeePass.ExitNormal);
groupBaseActivity.Finish();
} else { // Need to go up in groups tree
var targetUuid = new PwUuid(MemUtil.HexStringToByteArray(_groupUuid.Last.Value));
var targetDb = App.Kp2a.FindDatabaseForGroupId(targetUuid);
if (App.Kp2a.CurrentDb != targetDb)
{
App.Kp2a.CurrentDb = targetDb;
GroupActivity.Launch(groupBaseActivity,targetDb.Root,this,new ActivityLaunchModeForward());
}
else
{
SetActivityResult(groupBaseActivity, KeePass.ExitNormal);
}
groupBaseActivity.Finish();
}
}
}
public override void SetupGroupBaseActivityButtons(GroupBaseActivity groupBaseActivity)
@@ -972,19 +981,29 @@ namespace keepass2android
public class NavigateToFolder: NavigateAndLaunchTask {
public NavigateToFolder()
{
}
public NavigateToFolder(Database db, PwGroup groups, bool toastEnable = false)
: base(db, groups, new NullTask(), toastEnable)
public NavigateToFolder(Database db, PwGroup groups, bool toastEnable = false)
: base(groups, new NullTask(), toastEnable)
{
}
}
public class NavigateToFolderAndLaunchMoveElementTask: NavigateAndLaunchTask {
public NavigateToFolderAndLaunchMoveElementTask(Database db, PwGroup groups, List<PwUuid> uuids, bool toastEnable = false)
:base(db, groups, new MoveElementsTask() { Uuids = uuids }, toastEnable) {
public NavigateToFolderAndLaunchMoveElementTask()
{
}
public NavigateToFolderAndLaunchMoveElementTask(Database db, PwGroup groups, List<PwUuid> uuids, bool toastEnable = false)
:base(groups, new MoveElementsTask() { Uuids = uuids }, toastEnable) {
}
public override void Setup(Bundle b) {

View File

@@ -44,12 +44,6 @@ namespace keepass2android
ConfigurationChanges=ConfigChanges.Orientation|
ConfigChanges.KeyboardHidden,
Theme = "@style/MyTheme_Blue")]
[IntentFilter(new [] { Intent.ActionSend },
Label = "@string/kp2a_findUrl",
Categories=new[]{Intent.CategoryDefault},
DataMimeType="text/plain")]
[IntentFilter(new[] { Strings.ActionStartWithTask },
Categories = new[] { Intent.CategoryDefault })]
public class FileSelectActivity : AppCompatActivity
{
private readonly ActivityDesign _design;
@@ -72,7 +66,7 @@ namespace keepass2android
private bool _recentMode;
internal AppTask AppTask;
private const int RequestCodeSelectIoc = 456;
private const int RequestCodeEditIoc = 457;
@@ -85,24 +79,7 @@ namespace keepass2android
Kp2aLog.Log("FileSelect.OnCreate");
Kp2aLog.Log("FileSelect:apptask="+Intent.GetStringExtra("KP2A_APPTASK"));
if (Intent.Action == Intent.ActionSend)
{
AppTask = new SearchUrlTask { UrlToSearchFor = Intent.GetStringExtra(Intent.ExtraText) };
}
else
{
//see PasswordActivity for an explanation
if (Intent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory))
{
AppTask = new NullTask();
}
else
{
AppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
}
}
_dbHelper = App.Kp2a.FileDbHelper;
@@ -150,7 +127,7 @@ namespace keepass2android
{
//ShowFilenameDialog(false, true, true, Android.OS.Environment.ExternalStorageDirectory + GetString(Resource.String.default_file_path), "", Intents.RequestCodeFileBrowseForCreate)
Intent i = new Intent(this, typeof (CreateDatabaseActivity));
this.AppTask.ToIntent(i);
i.SetFlags(ActivityFlags.ForwardResult);
StartActivity(i);
Finish();
@@ -177,7 +154,6 @@ namespace keepass2android
if (savedInstanceState != null)
{
AppTask = AppTask.CreateFromBundle(savedInstanceState);
_recentMode = savedInstanceState.GetBoolean(BundleKeyRecentMode, _recentMode);
}
@@ -202,7 +178,7 @@ namespace keepass2android
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
AppTask.ToBundle(outState);
outState.PutBoolean(BundleKeyRecentMode, _recentMode);
}
@@ -366,7 +342,7 @@ namespace keepass2android
{
try
{
PasswordActivity.Launch(this, ioc, AppTask);
PasswordActivity.Launch(this, ioc, new ActivityLaunchModeForward());
Finish();
} catch (Java.IO.FileNotFoundException)
{
@@ -379,7 +355,7 @@ namespace keepass2android
private void AfterQueryCredentials(IOConnectionInfo ioc)
{
PasswordActivity.Launch(this, ioc, AppTask);
PasswordActivity.Launch(this, ioc, new ActivityLaunchModeForward());
Finish();
}
@@ -399,11 +375,6 @@ namespace keepass2android
{
base.OnActivityResult(requestCode, resultCode, data);
//update app task.
//this is important even if we're about to close, because then we should get a NullTask here
//in order not to do the same task next time again!
AppTask.TryGetFromActivityResult(data, ref AppTask);
if (resultCode == KeePass.ExitCloseAfterTaskComplete)
{
//no need to set the result ExitCloseAfterTaskComplete here, there's no parent Activity on the stack

View File

@@ -173,6 +173,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ActivityLaunchMode.cs" />
<Compile Include="ChallengeXCKey.cs" />
<Compile Include="EntryActivityClasses\ViewImagePopupItem.cs" />
<Compile Include="FileSaveProcessManager.cs" />

View File

@@ -952,7 +952,7 @@ namespace keepass2android
{
var key = App.Kp2a.CurrentDb.KpDatabase.MasterKey;
App.Kp2a.CloseDatabase(App.Kp2a.CurrentDb);
PasswordActivity.Launch(Activity, newIoc, new NullTask(), key);
PasswordActivity.Launch(Activity, newIoc, key, new ActivityLaunchModeSimple());
});
builder.Show();
@@ -1021,8 +1021,8 @@ namespace keepass2android
}
/// <summary>
/// Activity to configure the application and database settings. The database must be unlocked, and this activity will close if it becomes locked.
/// </summary>

View File

@@ -15,6 +15,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Linq;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
@@ -165,6 +166,10 @@ namespace keepass2android.view
else {
String groupDetail = pw.ParentGroup.GetFullPath();
if (App.Kp2a.OpenDatabases.Count() > 1)
{
groupDetail += "(" + App.Kp2a.GetFileStorage(db.Ioc).GetDisplayName(db.Ioc) + ")";
}
var strGroupDetail = new SpannableString (groupDetail);

View File

@@ -130,7 +130,7 @@ namespace keepass2android.view
private void LaunchGroup() {
GroupActivity.Launch(_groupBaseActivity, _pwGroup, _groupBaseActivity.AppTask);
GroupActivity.Launch(_groupBaseActivity, _pwGroup, _groupBaseActivity.AppTask, new ActivityLaunchModeRequestCode(0));
//_groupBaseActivity.OverridePendingTransition(Resource.Animation.anim_enter, Resource.Animation.anim_leave);
}