2017-07-13 06:09:44 +03:00
|
|
|
|
using System;
|
|
|
|
|
using Android.Content;
|
|
|
|
|
using Bit.App.Abstractions;
|
|
|
|
|
using Xamarin.Forms;
|
|
|
|
|
using Android.Webkit;
|
|
|
|
|
using Plugin.CurrentActivity;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using Android.Support.V4.Content;
|
2017-07-22 22:38:08 +03:00
|
|
|
|
using Bit.App;
|
2017-07-23 04:06:53 +03:00
|
|
|
|
using Bit.App.Resources;
|
|
|
|
|
using Android.Provider;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Android.OS;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using Android;
|
|
|
|
|
using Android.Content.PM;
|
|
|
|
|
using Android.Support.V4.App;
|
2017-07-13 06:09:44 +03:00
|
|
|
|
|
|
|
|
|
namespace Bit.Android.Services
|
|
|
|
|
{
|
|
|
|
|
public class DeviceActionService : IDeviceActionService
|
|
|
|
|
{
|
2017-07-13 18:11:04 +03:00
|
|
|
|
private readonly IAppSettingsService _appSettingsService;
|
2017-07-23 04:06:53 +03:00
|
|
|
|
private bool _cameraPermissionsDenied;
|
2017-07-13 18:11:04 +03:00
|
|
|
|
|
2017-07-23 04:06:53 +03:00
|
|
|
|
public DeviceActionService(
|
|
|
|
|
IAppSettingsService appSettingsService)
|
2017-07-13 18:11:04 +03:00
|
|
|
|
{
|
|
|
|
|
_appSettingsService = appSettingsService;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-13 06:09:44 +03:00
|
|
|
|
public void CopyToClipboard(string text)
|
|
|
|
|
{
|
|
|
|
|
var clipboardManager = (ClipboardManager)Forms.Context.GetSystemService(Context.ClipboardService);
|
|
|
|
|
clipboardManager.Text = text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool OpenFile(byte[] fileData, string id, string fileName)
|
|
|
|
|
{
|
2017-07-13 16:01:00 +03:00
|
|
|
|
if(!CanOpenFile(fileName))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-13 19:08:48 +03:00
|
|
|
|
var extension = MimeTypeMap.GetFileExtensionFromUrl(fileName.Replace(' ', '_').ToLower());
|
2017-07-13 06:09:44 +03:00
|
|
|
|
if(extension == null)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-13 19:08:48 +03:00
|
|
|
|
var mimeType = MimeTypeMap.Singleton.GetMimeTypeFromExtension(extension);
|
2017-07-13 06:09:44 +03:00
|
|
|
|
if(mimeType == null)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var cachePath = CrossCurrentActivity.Current.Activity.CacheDir;
|
|
|
|
|
var filePath = Path.Combine(cachePath.Path, fileName);
|
2017-07-13 16:01:00 +03:00
|
|
|
|
File.WriteAllBytes(filePath, fileData);
|
2017-07-13 06:09:44 +03:00
|
|
|
|
var file = new Java.IO.File(cachePath, fileName);
|
2017-07-13 16:01:00 +03:00
|
|
|
|
if(!file.IsFile)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-13 06:09:44 +03:00
|
|
|
|
try
|
|
|
|
|
{
|
2017-07-13 16:01:00 +03:00
|
|
|
|
var intent = new Intent(Intent.ActionView);
|
|
|
|
|
var uri = FileProvider.GetUriForFile(CrossCurrentActivity.Current.Activity.ApplicationContext,
|
|
|
|
|
"com.x8bit.bitwarden.fileprovider", file);
|
|
|
|
|
intent.SetDataAndType(uri, mimeType);
|
|
|
|
|
intent.SetFlags(ActivityFlags.GrantReadUriPermission);
|
|
|
|
|
CrossCurrentActivity.Current.Activity.StartActivity(intent);
|
|
|
|
|
return true;
|
2017-07-13 06:09:44 +03:00
|
|
|
|
}
|
|
|
|
|
catch { }
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2017-07-13 16:01:00 +03:00
|
|
|
|
|
|
|
|
|
public bool CanOpenFile(string fileName)
|
|
|
|
|
{
|
2017-07-13 19:08:48 +03:00
|
|
|
|
var extension = MimeTypeMap.GetFileExtensionFromUrl(fileName.Replace(' ', '_').ToLower());
|
2017-07-13 16:01:00 +03:00
|
|
|
|
if(extension == null)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-13 19:08:48 +03:00
|
|
|
|
var mimeType = MimeTypeMap.Singleton.GetMimeTypeFromExtension(extension);
|
2017-07-13 16:01:00 +03:00
|
|
|
|
if(mimeType == null)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var pm = CrossCurrentActivity.Current.Activity.PackageManager;
|
|
|
|
|
var intent = new Intent(Intent.ActionView);
|
|
|
|
|
intent.SetType(mimeType);
|
|
|
|
|
var activities = pm.QueryIntentActivities(intent, global::Android.Content.PM.PackageInfoFlags.MatchDefaultOnly);
|
|
|
|
|
return (activities?.Count ?? 0) > 0;
|
|
|
|
|
}
|
2017-07-13 17:51:45 +03:00
|
|
|
|
|
|
|
|
|
public void ClearCache()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
DeleteDir(CrossCurrentActivity.Current.Activity.CacheDir);
|
2017-07-13 18:11:04 +03:00
|
|
|
|
_appSettingsService.LastCacheClear = DateTime.UtcNow;
|
2017-07-13 17:51:45 +03:00
|
|
|
|
}
|
|
|
|
|
catch(Exception) { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool DeleteDir(Java.IO.File dir)
|
|
|
|
|
{
|
|
|
|
|
if(dir != null && dir.IsDirectory)
|
|
|
|
|
{
|
|
|
|
|
var children = dir.List();
|
|
|
|
|
for(int i = 0; i < children.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var success = DeleteDir(new Java.IO.File(dir, children[i]));
|
|
|
|
|
if(!success)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return dir.Delete();
|
|
|
|
|
}
|
|
|
|
|
else if(dir != null && dir.IsFile)
|
|
|
|
|
{
|
|
|
|
|
return dir.Delete();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-07-15 08:09:06 +03:00
|
|
|
|
|
2017-07-23 04:06:53 +03:00
|
|
|
|
public Task SelectFileAsync()
|
2017-07-15 08:09:06 +03:00
|
|
|
|
{
|
2017-07-23 04:06:53 +03:00
|
|
|
|
MessagingCenter.Unsubscribe<Application>(Application.Current, "SelectFileCameraPermissionDenied");
|
|
|
|
|
|
|
|
|
|
var hasStorageWritePermission = !_cameraPermissionsDenied && HasPermission(Manifest.Permission.WriteExternalStorage);
|
|
|
|
|
var hasCameraPermission = !_cameraPermissionsDenied && HasPermission(Manifest.Permission.Camera);
|
|
|
|
|
|
|
|
|
|
if(!_cameraPermissionsDenied && !hasStorageWritePermission)
|
|
|
|
|
{
|
|
|
|
|
AskCameraPermission(Manifest.Permission.WriteExternalStorage);
|
|
|
|
|
return Task.FromResult(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!_cameraPermissionsDenied && !hasCameraPermission)
|
|
|
|
|
{
|
|
|
|
|
AskCameraPermission(Manifest.Permission.Camera);
|
|
|
|
|
return Task.FromResult(0);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-25 15:51:55 +03:00
|
|
|
|
var additionalIntents = new List<IParcelable>();
|
|
|
|
|
|
2017-07-23 04:06:53 +03:00
|
|
|
|
var docIntent = new Intent(Intent.ActionOpenDocument);
|
|
|
|
|
docIntent.AddCategory(Intent.CategoryOpenable);
|
|
|
|
|
docIntent.SetType("*/*");
|
|
|
|
|
|
|
|
|
|
var chooserIntent = Intent.CreateChooser(docIntent, AppResources.FileSource);
|
|
|
|
|
|
|
|
|
|
if(!_cameraPermissionsDenied && hasCameraPermission && hasStorageWritePermission)
|
|
|
|
|
{
|
|
|
|
|
var root = new Java.IO.File(global::Android.OS.Environment.ExternalStorageDirectory, "bitwarden");
|
|
|
|
|
var file = new Java.IO.File(root, "temp_camera_photo.jpg");
|
|
|
|
|
if(!file.Exists())
|
|
|
|
|
{
|
2017-07-25 15:51:55 +03:00
|
|
|
|
file.ParentFile.Mkdirs();
|
|
|
|
|
file.CreateNewFile();
|
2017-07-23 04:06:53 +03:00
|
|
|
|
}
|
|
|
|
|
var outputFileUri = global::Android.Net.Uri.FromFile(file);
|
2017-07-25 15:51:55 +03:00
|
|
|
|
additionalIntents.AddRange(GetCameraIntents(outputFileUri));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(additionalIntents.Count > 0)
|
|
|
|
|
{
|
2017-07-23 04:06:53 +03:00
|
|
|
|
chooserIntent.PutExtra(Intent.ExtraInitialIntents, additionalIntents.ToArray());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CrossCurrentActivity.Current.Activity.StartActivityForResult(chooserIntent, Constants.SelectFileRequestCode);
|
|
|
|
|
return Task.FromResult(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<IParcelable> GetCameraIntents(global::Android.Net.Uri outputUri)
|
|
|
|
|
{
|
|
|
|
|
var intents = new List<IParcelable>();
|
|
|
|
|
var pm = CrossCurrentActivity.Current.Activity.PackageManager;
|
|
|
|
|
var captureIntent = new Intent(MediaStore.ActionImageCapture);
|
|
|
|
|
var listCam = pm.QueryIntentActivities(captureIntent, 0);
|
|
|
|
|
foreach(var res in listCam)
|
|
|
|
|
{
|
|
|
|
|
var packageName = res.ActivityInfo.PackageName;
|
|
|
|
|
var intent = new Intent(captureIntent);
|
|
|
|
|
intent.SetComponent(new ComponentName(packageName, res.ActivityInfo.Name));
|
|
|
|
|
intent.SetPackage(packageName);
|
|
|
|
|
intent.PutExtra(MediaStore.ExtraOutput, outputUri);
|
|
|
|
|
intents.Add(intent);
|
|
|
|
|
}
|
|
|
|
|
return intents;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool HasPermission(string permission)
|
|
|
|
|
{
|
|
|
|
|
return ContextCompat.CheckSelfPermission(CrossCurrentActivity.Current.Activity, permission) == Permission.Granted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AskCameraPermission(string permission)
|
|
|
|
|
{
|
|
|
|
|
MessagingCenter.Subscribe<Application>(Application.Current, "SelectFileCameraPermissionDenied", (sender) =>
|
|
|
|
|
{
|
|
|
|
|
_cameraPermissionsDenied = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AskPermission(permission);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AskPermission(string permission)
|
|
|
|
|
{
|
|
|
|
|
ActivityCompat.RequestPermissions(CrossCurrentActivity.Current.Activity, new string[] { permission },
|
|
|
|
|
Constants.SelectFilePermissionRequestCode);
|
2017-07-15 08:09:06 +03:00
|
|
|
|
}
|
2017-07-13 06:09:44 +03:00
|
|
|
|
}
|
|
|
|
|
}
|