mirror of
https://github.com/moparisthebest/keepass2android
synced 2024-11-12 04:25:09 -05:00
request permissions at runtime
use externalFilesDir when creating a database to make sure we don't need permissions here revert Support Design library to previous version, had issues with 23.x
This commit is contained in:
parent
1690aff45e
commit
a10a92d58d
@ -3,18 +3,25 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Security;
|
|
||||||
using System.Security;
|
using System.Security;
|
||||||
|
using Android;
|
||||||
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
|
using Android.Content.PM;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using Java.Security.Cert;
|
using Java.IO;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
using KeePassLib.Utility;
|
using KeePassLib.Utility;
|
||||||
|
using File = System.IO.File;
|
||||||
|
using FileNotFoundException = System.IO.FileNotFoundException;
|
||||||
|
using IOException = System.IO.IOException;
|
||||||
|
|
||||||
namespace keepass2android.Io
|
namespace keepass2android.Io
|
||||||
{
|
{
|
||||||
public class BuiltInFileStorage: IFileStorage
|
public class BuiltInFileStorage : IFileStorage, IPermissionRequestingFileStorage
|
||||||
{
|
{
|
||||||
|
private const string PermissionGrantedKey = "PermissionGranted";
|
||||||
|
|
||||||
public enum CertificateProblem :long
|
public enum CertificateProblem :long
|
||||||
{
|
{
|
||||||
CertEXPIRED = 0x800B0101,
|
CertEXPIRED = 0x800B0101,
|
||||||
@ -112,7 +119,8 @@ namespace keepass2android.Io
|
|||||||
|
|
||||||
private void ConvertException(IOConnectionInfo ioc, WebException ex)
|
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);
|
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)
|
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();
|
Intent intent = new Intent();
|
||||||
activity.IocToIntent(intent, ioc);
|
activity.IocToIntent(intent, ioc);
|
||||||
activity.OnImmediateResult(requestCode, (int) FileStorageResults.FileUsagePrepared, intent);
|
activity.OnImmediateResult(requestCode, (int) FileStorageResults.FileUsagePrepared, intent);
|
||||||
@ -251,24 +279,42 @@ namespace keepass2android.Io
|
|||||||
//nothing to do, we're ready to go
|
//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)
|
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)
|
public void OnStart(IFileStorageSetupActivity activity)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnActivityResult(IFileStorageSetupActivity activity, int requestCode, int resultCode, Intent data)
|
public void OnActivityResult(IFileStorageSetupActivity activity, int requestCode, int resultCode, Intent data)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetDisplayName(IOConnectionInfo ioc)
|
public string GetDisplayName(IOConnectionInfo ioc)
|
||||||
@ -310,7 +356,7 @@ namespace keepass2android.Io
|
|||||||
{
|
{
|
||||||
//test if we can open
|
//test if we can open
|
||||||
//http://www.doubleencore.com/2014/03/android-external-storage/#comment-1294469517
|
//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();
|
writer.Close();
|
||||||
return false; //we can write
|
return false; //we can write
|
||||||
@ -358,5 +404,11 @@ namespace keepass2android.Io
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnRequestPermissionsResult(IFileStorageSetupActivity fileStorageSetupActivity, int requestCode,
|
||||||
|
string[] permissions, Permission[] grantResults)
|
||||||
|
{
|
||||||
|
fileStorageSetupActivity.State.PutBoolean(PermissionGrantedKey, grantResults[0] == Permission.Granted);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,6 +5,7 @@ using System.Net;
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
|
using Android.Content.PM;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using KeePassLib.Cryptography;
|
using KeePassLib.Cryptography;
|
||||||
using KeePassLib.Serialization;
|
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
|
/// 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.
|
/// files on remote.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CachingFileStorage : IFileStorage, IOfflineSwitchable
|
public class CachingFileStorage : IFileStorage, IOfflineSwitchable, IPermissionRequestingFileStorage
|
||||||
{
|
{
|
||||||
|
|
||||||
protected readonly OfflineSwitchableFileStorage _cachedStorage;
|
protected readonly OfflineSwitchableFileStorage _cachedStorage;
|
||||||
@ -618,5 +619,11 @@ namespace keepass2android.Io
|
|||||||
get { return _cachedStorage.IsOffline; }
|
get { return _cachedStorage.IsOffline; }
|
||||||
set { _cachedStorage.IsOffline = value; }
|
set { _cachedStorage.IsOffline = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnRequestPermissionsResult(IFileStorageSetupActivity fileStorageSetupActivity, int requestCode,
|
||||||
|
string[] permissions, Permission[] grantResults)
|
||||||
|
{
|
||||||
|
_cachedStorage.OnRequestPermissionsResult(fileStorageSetupActivity, requestCode, permissions, grantResults);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
|
using Android.Content.PM;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ namespace keepass2android.Io
|
|||||||
|
|
||||||
public static String ExtraProcessName = "EXTRA_PROCESS_NAME";
|
public static String ExtraProcessName = "EXTRA_PROCESS_NAME";
|
||||||
public static String ExtraAlwaysReturnSuccess = "EXTRA_ALWAYS_RETURN_SUCCESS";
|
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 ExtraIsForSave = "IS_FOR_SAVE";
|
||||||
public static String ExtraErrorMessage = "EXTRA_ERROR_MESSAGE";
|
public static String ExtraErrorMessage = "EXTRA_ERROR_MESSAGE";
|
||||||
|
|
||||||
@ -170,6 +171,11 @@ namespace keepass2android.Io
|
|||||||
bool IsReadOnly(IOConnectionInfo ioc);
|
bool IsReadOnly(IOConnectionInfo ioc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IPermissionRequestingFileStorage
|
||||||
|
{
|
||||||
|
void OnRequestPermissionsResult(IFileStorageSetupActivity fileStorageSetupActivity, int requestCode, string[] permissions, Permission[] grantResults);
|
||||||
|
}
|
||||||
|
|
||||||
public interface IWriteTransaction: IDisposable
|
public interface IWriteTransaction: IDisposable
|
||||||
{
|
{
|
||||||
Stream OpenFile();
|
Stream OpenFile();
|
||||||
|
@ -4,6 +4,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
|
using Android.Content.PM;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
using KeePassLib.Utility;
|
using KeePassLib.Utility;
|
||||||
@ -16,7 +17,7 @@ using FileNotFoundException = Java.IO.FileNotFoundException;
|
|||||||
namespace keepass2android.Io
|
namespace keepass2android.Io
|
||||||
{
|
{
|
||||||
#if !EXCLUDE_JAVAFILESTORAGE
|
#if !EXCLUDE_JAVAFILESTORAGE
|
||||||
public abstract class JavaFileStorage: IFileStorage
|
public abstract class JavaFileStorage: IFileStorage, IPermissionRequestingFileStorage
|
||||||
{
|
{
|
||||||
protected string Protocol { get { return _jfs.ProtocolId; } }
|
protected string Protocol { get { return _jfs.ProtocolId; } }
|
||||||
|
|
||||||
@ -356,6 +357,12 @@ namespace keepass2android.Io
|
|||||||
return ioc.Path;
|
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
|
#endif
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
|
using Android.Content.PM;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
|
|
||||||
@ -16,7 +17,7 @@ namespace keepass2android.Io
|
|||||||
/// Encapsulates another IFileStorage. Allows to switch to offline mode by throwing
|
/// Encapsulates another IFileStorage. Allows to switch to offline mode by throwing
|
||||||
/// an exception when trying to read or write a file.
|
/// an exception when trying to read or write a file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class OfflineSwitchableFileStorage : IFileStorage, IOfflineSwitchable
|
public class OfflineSwitchableFileStorage : IFileStorage, IOfflineSwitchable, IPermissionRequestingFileStorage
|
||||||
{
|
{
|
||||||
private readonly IFileStorage _baseStorage;
|
private readonly IFileStorage _baseStorage;
|
||||||
public bool IsOffline { get; set; }
|
public bool IsOffline { get; set; }
|
||||||
@ -179,6 +180,15 @@ namespace keepass2android.Io
|
|||||||
{
|
{
|
||||||
return _baseStorage.IsReadOnly(ioc);
|
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
|
public class OfflineModeException : Exception
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
<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>v5.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
|
||||||
|
<AndroidUseLatestPlatformSdk>False</AndroidUseLatestPlatformSdk>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
@ -85,7 +85,7 @@
|
|||||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
|
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" exported="" name="httpmime-4.0.3" level="project" />
|
<orderEntry type="library" exported="" name="httpmime-4.0.3" level="project" />
|
||||||
<orderEntry type="library" exported="" name="jsr305-1.3.9" level="project" />
|
<orderEntry type="library" exported="" name="jsr305-1.3.9" level="project" />
|
||||||
@ -104,8 +104,8 @@
|
|||||||
<orderEntry type="library" exported="" name="httpcore-4.0.1" level="project" />
|
<orderEntry type="library" exported="" name="httpcore-4.0.1" level="project" />
|
||||||
<orderEntry type="library" exported="" name="json_simple-1.1" level="project" />
|
<orderEntry type="library" exported="" name="json_simple-1.1" level="project" />
|
||||||
<orderEntry type="library" exported="" name="google-http-client-android-1.16.0-rc" level="project" />
|
<orderEntry type="library" exported="" name="google-http-client-android-1.16.0-rc" level="project" />
|
||||||
<orderEntry type="library" exported="" name="google-http-client-gson-1.20.0" level="project" />
|
|
||||||
<orderEntry type="library" exported="" name="gson-2.1" level="project" />
|
<orderEntry type="library" exported="" name="gson-2.1" level="project" />
|
||||||
|
<orderEntry type="library" exported="" name="google-http-client-gson-1.20.0" level="project" />
|
||||||
<orderEntry type="library" exported="" name="google-http-client-jackson-1.16.0-rc" level="project" />
|
<orderEntry type="library" exported="" name="google-http-client-jackson-1.16.0-rc" level="project" />
|
||||||
<orderEntry type="library" exported="" name="commons-logging-1.1.1" level="project" />
|
<orderEntry type="library" exported="" name="commons-logging-1.1.1" level="project" />
|
||||||
</component>
|
</component>
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 21
|
compileSdkVersion 23
|
||||||
buildToolsVersion "21.1.2"
|
buildToolsVersion '23.0.0'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 21
|
targetSdkVersion 23
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled true
|
minifyEnabled true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
productFlavors {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
Binary file not shown.
@ -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.FileList;
|
||||||
import com.google.api.services.drive.model.ParentReference;
|
import com.google.api.services.drive.model.ParentReference;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
@ -43,7 +46,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
|
|||||||
static final int MAGIC_GDRIVE=2082334;
|
static final int MAGIC_GDRIVE=2082334;
|
||||||
static final int REQUEST_ACCOUNT_PICKER = MAGIC_GDRIVE+1;
|
static final int REQUEST_ACCOUNT_PICKER = MAGIC_GDRIVE+1;
|
||||||
static final int REQUEST_AUTHORIZATION = MAGIC_GDRIVE+2;
|
static final int REQUEST_AUTHORIZATION = MAGIC_GDRIVE+2;
|
||||||
|
private boolean mRequiresRuntimePermissions = false;
|
||||||
|
|
||||||
|
|
||||||
class FileSystemEntryData
|
class FileSystemEntryData
|
||||||
@ -253,7 +256,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
|
|||||||
|
|
||||||
public GoogleDriveFileStorage()
|
public GoogleDriveFileStorage()
|
||||||
{
|
{
|
||||||
logDebug("Creating GDrive FileStorage");
|
logDebug("Creating GDrive FileStorage.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -424,7 +427,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
|
|||||||
throw new FileNotFoundException(parentPath + " is trashed!");
|
throw new FileNotFoundException(parentPath + " is trashed!");
|
||||||
logDebug("listing files in "+parentId);
|
logDebug("listing files in "+parentId);
|
||||||
Files.List request = driveService.files().list()
|
Files.List request = driveService.files().list()
|
||||||
.setQ("trashed=false and '"+parentId+"' in parents");
|
.setQ("trashed=false and '" + parentId + "' in parents");
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
@ -505,7 +508,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
|
|||||||
FileEntry res = convertToFileEntry(
|
FileEntry res = convertToFileEntry(
|
||||||
getFileForPath(gdrivePath, getDriveService(gdrivePath.getAccount())),
|
getFileForPath(gdrivePath, getDriveService(gdrivePath.getAccount())),
|
||||||
filename);
|
filename);
|
||||||
logDebug("getFileEntry res"+res);
|
logDebug("getFileEntry res" + res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@ -551,13 +554,13 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
|
|||||||
{
|
{
|
||||||
logDebug("getDriveService "+accountName);
|
logDebug("getDriveService "+accountName);
|
||||||
AccountData accountData = mAccountData.get(accountName);
|
AccountData accountData = mAccountData.get(accountName);
|
||||||
logDebug("accountData "+accountData);
|
logDebug("accountData " + accountData);
|
||||||
return accountData.drive;
|
return accountData.drive;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(final JavaFileStorage.FileStorageSetupActivity setupAct, int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(final JavaFileStorage.FileStorageSetupActivity setupAct, int requestCode, int resultCode, Intent data) {
|
||||||
logDebug("ActivityResult: "+requestCode+"/"+resultCode);
|
logDebug("ActivityResult: " + requestCode + "/" + resultCode);
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_ACCOUNT_PICKER:
|
case REQUEST_ACCOUNT_PICKER:
|
||||||
logDebug("ActivityResult: REQUEST_ACCOUNT_PICKER");
|
logDebug("ActivityResult: REQUEST_ACCOUNT_PICKER");
|
||||||
@ -773,16 +776,23 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume(JavaFileStorage.FileStorageSetupActivity setupAct) {
|
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."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void initFileStorage(FileStorageSetupActivity setupAct) {
|
||||||
public void onStart(final JavaFileStorage.FileStorageSetupActivity setupAct) {
|
|
||||||
|
|
||||||
logDebug("onStart");
|
|
||||||
Activity activity = (Activity)setupAct;
|
Activity activity = (Activity)setupAct;
|
||||||
|
|
||||||
if (PROCESS_NAME_SELECTFILE.equals(setupAct.getProcessName()))
|
if (PROCESS_NAME_SELECTFILE.equals(setupAct.getProcessName()))
|
||||||
@ -799,6 +809,22 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume(JavaFileStorage.FileStorageSetupActivity setupAct) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart(final JavaFileStorage.FileStorageSetupActivity setupAct) {
|
||||||
|
logDebug("onStart "+mRequiresRuntimePermissions);
|
||||||
|
if (!mRequiresRuntimePermissions)
|
||||||
|
{
|
||||||
|
initFileStorage(setupAct);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private GoogleAccountCredential createCredential(Context appContext) {
|
private GoogleAccountCredential createCredential(Context appContext) {
|
||||||
List<String> scopes = new ArrayList<String>();
|
List<String> scopes = new ArrayList<String>();
|
||||||
scopes.add(DriveScopes.DRIVE);
|
scopes.add(DriveScopes.DRIVE);
|
||||||
@ -816,6 +842,21 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
|
|||||||
public void onCreate(FileStorageSetupActivity activity,
|
public void onCreate(FileStorageSetupActivity activity,
|
||||||
Bundle savedInstanceState) {
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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_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_IS_FOR_SAVE = "IS_FOR_SAVE";
|
||||||
public static final String EXTRA_ERROR_MESSAGE = "EXTRA_ERROR_MESSAGE";
|
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
|
public interface FileStorageSetupInitiatorActivity
|
||||||
@ -155,5 +155,6 @@ public class FileEntry {
|
|||||||
public void onResume(FileStorageSetupActivity activity);
|
public void onResume(FileStorageSetupActivity activity);
|
||||||
public void onStart(FileStorageSetupActivity activity);
|
public void onStart(FileStorageSetupActivity activity);
|
||||||
public void onActivityResult(FileStorageSetupActivity activity, int requestCode, int resultCode, Intent data);
|
public void onActivityResult(FileStorageSetupActivity activity, int requestCode, int resultCode, Intent data);
|
||||||
|
public void onRequestPermissionsResult(FileStorageSetupActivity activity, int requestCode, String[] permissions, int[] grantResults);
|
||||||
|
|
||||||
}
|
}
|
@ -147,5 +147,10 @@ public abstract class JavaFileStorageBase implements JavaFileStorage{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onRequestPermissionsResult(FileStorageSetupActivity activity, int requestCode, String[] permissions, int[] grantResults)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -287,13 +287,20 @@ namespace keepass2android
|
|||||||
|
|
||||||
private void SetDefaultIoc()
|
private void SetDefaultIoc()
|
||||||
{
|
{
|
||||||
var sdDir = SdDir;
|
File directory = GetExternalFilesDir(null);
|
||||||
string filename = sdDir + "keepass.kdbx";
|
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);
|
filename = ConvertFilenameToIocPath(filename);
|
||||||
int count = 2;
|
int count = 2;
|
||||||
while (new File(filename).Exists())
|
while (new File(filename).Exists())
|
||||||
{
|
{
|
||||||
filename = ConvertFilenameToIocPath(sdDir + "keepass" + count + ".kdbx");
|
filename = ConvertFilenameToIocPath(strDir + "keepass" + count + ".kdbx");
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@ namespace keepass2android
|
|||||||
LaunchMode = LaunchMode.SingleInstance,
|
LaunchMode = LaunchMode.SingleInstance,
|
||||||
WindowSoftInputMode = SoftInput.AdjustResize,
|
WindowSoftInputMode = SoftInput.AdjustResize,
|
||||||
Theme = "@style/MyTheme_Blue")] /*caution: also contained in AndroidManifest.xml*/
|
Theme = "@style/MyTheme_Blue")] /*caution: also contained in AndroidManifest.xml*/
|
||||||
|
[IntentFilter(new[] { "kp2a.action.PasswordActivity" }, Categories = new[] { Intent.CategoryDefault })]
|
||||||
public class PasswordActivity : LockingActivity, IFingerprintAuthCallback
|
public class PasswordActivity : LockingActivity, IFingerprintAuthCallback
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="46" android:versionName="0.9.3-release-3" package="keepass2android.keepass2android_debug" android:installLocation="auto">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="46" android:versionName="0.9.3-release-3" package="keepass2android.keepass2android_debug" android:installLocation="auto">
|
||||||
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
|
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="23" />
|
||||||
<permission android:description="@string/permission_desc" android:icon="@drawable/ic_launcher" android:label="KP2A internal file browsing" android:name="keepass2android.keepass2android_debug.permission.KP2aInternalFileBrowsing" android:protectionLevel="signature" />
|
<permission android:description="@string/permission_desc" android:icon="@drawable/ic_launcher" android:label="KP2A internal file browsing" android:name="keepass2android.keepass2android_debug.permission.KP2aInternalFileBrowsing" android:protectionLevel="signature" />
|
||||||
<application android:label="keepass2android" android:icon="@drawable/ic_launcher">
|
<application android:label="keepass2android" android:icon="@drawable/ic_launcher">
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
android:versionName="1.0.0 preview 2"
|
android:versionName="1.0.0 preview 2"
|
||||||
package="keepass2android.keepass2android"
|
package="keepass2android.keepass2android"
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
|
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="23" />
|
||||||
<permission android:description="@string/permission_desc" android:icon="@drawable/ic_launcher_online" android:label="KP2A internal file browsing" android:name="keepass2android.keepass2android.permission.KP2aInternalFileBrowsing" android:protectionLevel="signature" />
|
<permission android:description="@string/permission_desc" android:icon="@drawable/ic_launcher_online" android:label="KP2A internal file browsing" android:name="keepass2android.keepass2android.permission.KP2aInternalFileBrowsing" android:protectionLevel="signature" />
|
||||||
<application android:label="keepass2android" android:icon="@drawable/ic_launcher_online">
|
<application android:label="keepass2android" android:icon="@drawable/ic_launcher_online">
|
||||||
<activity android:name="com.dropbox.client2.android.AuthActivity" android:launchMode="singleTask" android:configChanges="orientation|keyboard">
|
<activity android:name="com.dropbox.client2.android.AuthActivity" android:launchMode="singleTask" android:configChanges="orientation|keyboard">
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
android:versionName="0.9.8b"
|
android:versionName="0.9.8b"
|
||||||
package="keepass2android.keepass2android_nonet"
|
package="keepass2android.keepass2android_nonet"
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
|
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="23" />
|
||||||
<application android:label="keepass2android" android:icon="@drawable/ic_launcher_offline">
|
<application android:label="keepass2android" android:icon="@drawable/ic_launcher_offline">
|
||||||
<provider android:name="group.pals.android.lib.ui.filechooser.providers.localfile.LocalFileProvider" android:authorities="keepass2android.keepass2android_nonet.android-filechooser.localfile" android:exported="false" />
|
<provider android:name="group.pals.android.lib.ui.filechooser.providers.localfile.LocalFileProvider" android:authorities="keepass2android.keepass2android_nonet.android-filechooser.localfile" android:exported="false" />
|
||||||
<provider android:name="group.pals.android.lib.ui.filechooser.providers.history.HistoryProvider" android:authorities="keepass2android.keepass2android_nonet.android-filechooser.history" android:exported="false" />
|
<provider android:name="group.pals.android.lib.ui.filechooser.providers.history.HistoryProvider" android:authorities="keepass2android.keepass2android_nonet.android-filechooser.history" android:exported="false" />
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--Generated by crowdin.com-->
|
|
||||||
<!--Generated by crowdin.net-->
|
|
||||||
<resources/>
|
|
@ -594,11 +594,13 @@
|
|||||||
</string>
|
</string>
|
||||||
|
|
||||||
<string name="ChangeLog_1_0_0">
|
<string name="ChangeLog_1_0_0">
|
||||||
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
|
* Added "work offline" mode\n
|
||||||
* Allow to copy entries\n
|
* Allow to copy entries\n
|
||||||
* Auto-complete mode for field names\n
|
* Auto-complete mode for field names\n
|
||||||
* Allow to remove items from recent files list\n
|
* Allow to remove items from recent files list\n
|
||||||
|
* Request permissions at runtime in Android 6.0\n
|
||||||
* more to come...\n
|
* more to come...\n
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
|
@ -87,6 +87,17 @@ namespace keepass2android.fileselect
|
|||||||
App.Kp2a.GetFileStorage(Ioc).OnActivityResult(this, requestCode, (int) resultCode, data);
|
App.Kp2a.GetFileStorage(Ioc).OnActivityResult(this, requestCode, (int) resultCode, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
protected override void OnSaveInstanceState(Bundle outState)
|
||||||
{
|
{
|
||||||
base.OnSaveInstanceState(outState);
|
base.OnSaveInstanceState(outState);
|
||||||
|
@ -86,17 +86,17 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="Mono.Android" />
|
<Reference Include="Mono.Android" />
|
||||||
|
<Reference Include="Xamarin.Android.Support.v7.MediaRouter">
|
||||||
|
<HintPath>..\packages\Xamarin.Android.Support.v7.MediaRouter.21.0.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.MediaRouter.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Xamarin.Android.Support.v4">
|
<Reference Include="Xamarin.Android.Support.v4">
|
||||||
<HintPath>..\packages\Xamarin.Android.Support.v4.23.1.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll</HintPath>
|
<HintPath>..\packages\Xamarin.Android.Support.v4.22.2.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Xamarin.Android.Support.v7.AppCompat">
|
<Reference Include="Xamarin.Android.Support.v7.AppCompat">
|
||||||
<HintPath>..\packages\Xamarin.Android.Support.v7.AppCompat.23.1.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.AppCompat.dll</HintPath>
|
<HintPath>..\packages\Xamarin.Android.Support.v7.AppCompat.22.2.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.AppCompat.dll</HintPath>
|
||||||
</Reference>
|
|
||||||
<Reference Include="Xamarin.Android.Support.v7.RecyclerView">
|
|
||||||
<HintPath>..\packages\Xamarin.Android.Support.v7.RecyclerView.23.1.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.RecyclerView.dll</HintPath>
|
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Xamarin.Android.Support.Design">
|
<Reference Include="Xamarin.Android.Support.Design">
|
||||||
<HintPath>..\packages\Xamarin.Android.Support.Design.23.1.1.0\lib\MonoAndroid403\Xamarin.Android.Support.Design.dll</HintPath>
|
<HintPath>..\packages\Xamarin.Android.Support.Design.22.2.1.0\lib\MonoAndroid403\Xamarin.Android.Support.Design.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Xamarin.GooglePlayServices.Base">
|
<Reference Include="Xamarin.GooglePlayServices.Base">
|
||||||
<HintPath>..\packages\Xamarin.GooglePlayServices.Base.27.0.0.0\lib\MonoAndroid41\Xamarin.GooglePlayServices.Base.dll</HintPath>
|
<HintPath>..\packages\Xamarin.GooglePlayServices.Base.27.0.0.0\lib\MonoAndroid41\Xamarin.GooglePlayServices.Base.dll</HintPath>
|
||||||
@ -671,7 +671,6 @@
|
|||||||
<AndroidResource Include="Resources\values-el\strings.xml" />
|
<AndroidResource Include="Resources\values-el\strings.xml" />
|
||||||
<AndroidResource Include="Resources\values-fi\strings.xml" />
|
<AndroidResource Include="Resources\values-fi\strings.xml" />
|
||||||
<AndroidResource Include="Resources\values-in\strings.xml" />
|
<AndroidResource Include="Resources\values-in\strings.xml" />
|
||||||
<AndroidResource Include="Resources\values-iw\strings.xml" />
|
|
||||||
<AndroidResource Include="Resources\values-ko\strings.xml" />
|
<AndroidResource Include="Resources\values-ko\strings.xml" />
|
||||||
<AndroidResource Include="Resources\values-no\strings.xml" />
|
<AndroidResource Include="Resources\values-no\strings.xml" />
|
||||||
<AndroidResource Include="Resources\values-pt-rPT\strings.xml" />
|
<AndroidResource Include="Resources\values-pt-rPT\strings.xml" />
|
||||||
@ -729,7 +728,6 @@
|
|||||||
<Folder Include="Resources\drawable-hdpi\" />
|
<Folder Include="Resources\drawable-hdpi\" />
|
||||||
<Folder Include="Resources\drawable-ldpi\" />
|
<Folder Include="Resources\drawable-ldpi\" />
|
||||||
<Folder Include="Resources\drawable-xxhdpi\" />
|
<Folder Include="Resources\drawable-xxhdpi\" />
|
||||||
<Folder Include="Resources\values-iw\" />
|
|
||||||
<Folder Include="SupportLib\" />
|
<Folder Include="SupportLib\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -847,6 +845,12 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</AndroidResource>
|
</AndroidResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<XamarinComponentReference Include="xamandroidsupportdesign">
|
||||||
|
<Version>22.2.0.0</Version>
|
||||||
|
<Visible>False</Visible>
|
||||||
|
</XamarinComponentReference>
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidAsset Include="Assets\LICENSE_SourceCodePro.txt" />
|
<AndroidAsset Include="Assets\LICENSE_SourceCodePro.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -1643,12 +1647,6 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\layout\image_list_preference_row.xml" />
|
<AndroidResource Include="Resources\layout\image_list_preference_row.xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<XamarinComponentReference Include="xamandroidsupportdesign">
|
|
||||||
<Visible>False</Visible>
|
|
||||||
<Version>23.0.1.3</Version>
|
|
||||||
</XamarinComponentReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\drawable\ic_fingerprint_error.xml" />
|
<AndroidResource Include="Resources\drawable\ic_fingerprint_error.xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Xamarin.Android.Support.Design" version="23.1.1.0" targetFramework="MonoAndroid50" />
|
<package id="Xamarin.Android.Support.Design" version="22.2.1.0" targetFramework="MonoAndroid50" />
|
||||||
<package id="Xamarin.Android.Support.v4" version="23.1.1.0" targetFramework="MonoAndroid50" />
|
<package id="Xamarin.Android.Support.v4" version="22.2.1.0" targetFramework="MonoAndroid50" />
|
||||||
<package id="Xamarin.Android.Support.v7.AppCompat" version="23.1.1.0" targetFramework="MonoAndroid50" />
|
<package id="Xamarin.Android.Support.v7.AppCompat" version="22.2.1.0" targetFramework="MonoAndroid50" />
|
||||||
<package id="Xamarin.Android.Support.v7.RecyclerView" version="23.1.1.0" targetFramework="MonoAndroid50" />
|
<package id="Xamarin.Android.Support.v7.MediaRouter" version="21.0.3.0" targetFramework="MonoAndroid50" />
|
||||||
<package id="Xamarin.GooglePlayServices.Base" version="27.0.0.0" targetFramework="MonoAndroid50" />
|
<package id="Xamarin.GooglePlayServices.Base" version="27.0.0.0" targetFramework="MonoAndroid50" />
|
||||||
<package id="Xamarin.GooglePlayServices.Basement" version="27.0.0.0" targetFramework="MonoAndroid50" />
|
<package id="Xamarin.GooglePlayServices.Basement" version="27.0.0.0" targetFramework="MonoAndroid50" />
|
||||||
<package id="Xamarin.GooglePlayServices.Drive" version="27.0.0.0" targetFramework="MonoAndroid50" />
|
<package id="Xamarin.GooglePlayServices.Drive" version="27.0.0.0" targetFramework="MonoAndroid50" />
|
||||||
|
Loading…
Reference in New Issue
Block a user