Last active
April 7, 2024 15:51
-
-
Save thomashagstrom/b0856a383bcdcf905c7a774c8c1b0879 to your computer and use it in GitHub Desktop.
Xamarin.Forms DropboxService API v2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Threading.Tasks; | |
using Dropbox.Api; | |
using Dropbox.Api.Files; | |
using HLI.Forms.Services; | |
using Xamarin.Forms; | |
namespace MyApp | |
{ | |
public class DropBoxService | |
{ | |
#region Constants | |
private const string AppKeyDropboxtoken = "MyDropboxToken"; | |
private const string ClientId = "MyDropboxClientId"; | |
private const string RedirectUri = "https://www.anysite.se/"; | |
#endregion | |
#region Fields | |
/// <summary> | |
/// Occurs when the user was authenticated | |
/// </summary> | |
public Action OnAuthenticated; | |
private string oauth2State; | |
#endregion | |
#region Properties | |
private string AccessToken { get; set; } | |
#endregion | |
#region Public Methods and Operators | |
/// <summary> | |
/// <para>Runs the Dropbox OAuth authorization process if not yet authenticated.</para> | |
/// <para>Upon completion <seealso cref="OnAuthenticated"/> is called</para> | |
/// </summary> | |
/// <returns>An asynchronous task.</returns> | |
public async Task Authorize() | |
{ | |
if (string.IsNullOrWhiteSpace(this.AccessToken) == false) | |
{ | |
// Already authorized | |
this.OnAuthenticated?.Invoke(); | |
return; | |
} | |
if (this.GetAccessTokenFromSettings()) | |
{ | |
// Found token and set AccessToken | |
return; | |
} | |
// Run Dropbox authentication | |
this.oauth2State = Guid.NewGuid().ToString("N"); | |
var authorizeUri = DropboxOAuth2Helper.GetAuthorizeUri(OAuthResponseType.Token, ClientId, new Uri(RedirectUri), this.oauth2State); | |
var webView = new WebView { Source = new UrlWebViewSource { Url = authorizeUri.AbsoluteUri } }; | |
webView.Navigating += this.WebViewOnNavigating; | |
var contentPage = new ContentPage { Content = webView }; | |
await Application.Current.MainPage.Navigation.PushModalAsync(contentPage); | |
} | |
public async Task<IList<Metadata>> ListFiles() | |
{ | |
try | |
{ | |
using (var client = this.GetClient()) | |
{ | |
var list = await client.Files.ListFolderAsync(string.Empty); | |
return list?.Entries; | |
} | |
} | |
catch (Exception ex) | |
{ | |
AppService.WriteDebug(ex); | |
return null; | |
} | |
} | |
public async Task<byte[]> ReadFile(string file) | |
{ | |
try | |
{ | |
using (var client = this.GetClient()) | |
{ | |
var response = await client.Files.DownloadAsync(file); | |
var bytes = response?.GetContentAsByteArrayAsync(); | |
return bytes?.Result; | |
} | |
} | |
catch (Exception ex) | |
{ | |
AppService.WriteDebug(ex); | |
return null; | |
} | |
} | |
public async Task<FileMetadata> WriteFile(byte[] fileContent, string filename) | |
{ | |
try | |
{ | |
var commitInfo = new CommitInfo(filename, WriteMode.Overwrite.Instance, false, DateTime.Now); | |
using (var client = this.GetClient()) | |
{ | |
var metadata = await client.Files.UploadAsync(commitInfo, new MemoryStream(fileContent)); | |
return metadata; | |
} | |
} | |
catch (Exception ex) | |
{ | |
AppService.WriteDebug(ex); | |
return null; | |
} | |
} | |
#endregion | |
#region Methods | |
/// <summary> | |
/// Saves the Dropbox token to app settings | |
/// </summary> | |
/// <param name="token">Token received from Dropbox authentication</param> | |
private static async Task SaveDropboxToken(string token) | |
{ | |
if (token == null) | |
{ | |
return; | |
} | |
try | |
{ | |
Application.Current.Properties.Add(AppKeyDropboxtoken, token); | |
await Application.Current.SavePropertiesAsync(); | |
} | |
catch (Exception ex) | |
{ | |
AppService.WriteDebug(ex); | |
} | |
} | |
private DropboxClient GetClient() | |
{ | |
return new DropboxClient(this.AccessToken); | |
} | |
/// <summary> | |
/// Tries to find the Dropbox token in application settings | |
/// </summary> | |
/// <returns>Token as string or <c>null</c></returns> | |
private bool GetAccessTokenFromSettings() | |
{ | |
try | |
{ | |
if (!Application.Current.Properties.ContainsKey(AppKeyDropboxtoken)) | |
{ | |
return false; | |
} | |
this.AccessToken = Application.Current.Properties[AppKeyDropboxtoken]?.ToString(); | |
if (this.AccessToken != null) | |
{ | |
this.OnAuthenticated.Invoke(); | |
return true; | |
} | |
return false; | |
} | |
catch (Exception ex) | |
{ | |
AppService.WriteDebug(ex); | |
return false; | |
} | |
} | |
private async void WebViewOnNavigating(object sender, WebNavigatingEventArgs e) | |
{ | |
if (!e.Url.StartsWith(RedirectUri, StringComparison.OrdinalIgnoreCase)) | |
{ | |
// we need to ignore all navigation that isn't to the redirect uri. | |
return; | |
} | |
try | |
{ | |
var result = DropboxOAuth2Helper.ParseTokenFragment(new Uri(e.Url)); | |
if (result.State != this.oauth2State) | |
{ | |
return; | |
} | |
this.AccessToken = result.AccessToken; | |
await SaveDropboxToken(this.AccessToken); | |
this.OnAuthenticated?.Invoke(); | |
} | |
catch (ArgumentException) | |
{ | |
// There was an error in the URI passed to ParseTokenFragment | |
} | |
finally | |
{ | |
e.Cancel = true; | |
await Application.Current.MainPage.Navigation.PopModalAsync(); | |
} | |
} | |
#endregion | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Threading.Tasks; | |
using System.Windows.Input; | |
using Xamarin.Forms; | |
namespace HLI.Forms.ViewModels | |
{ | |
/// <summary> | |
/// Implements DropBoxService | |
/// </summary> | |
public class DropBoxViewModel | |
{ | |
#region Fields | |
private readonly DropBoxService dropBoxService = new DropBoxService(); | |
#endregion | |
#region Constructors and Destructors | |
public DropBoxViewModel() | |
{ | |
this.DropBoxGetCommand = new DelegateCommand(this.OnDropboxGet); | |
this.DropBoxSaveCommand = new DelegateCommand(this.OnDropboxSave); | |
} | |
#endregion | |
#region Public Properties | |
public ICommand DropBoxGetCommand { get; } | |
public ICommand DropBoxSaveCommand { get; } | |
public UriImageSource DropboxIcon | |
=> | |
new UriImageSource | |
{ | |
Uri = | |
new Uri( | |
new OnPlatform<string> | |
{ | |
WinPhone = "https://www.dropbox.com/s/affuim5lv2dqcq2/dropbox-windows-8.png?dl=1", | |
iOS = "https://www.dropbox.com/sh/zcxbhhco5x0bwmm/AAD6Nq7vmOBalRfOOe9oIa_va?dl=1", | |
Android = "https://www.dropbox.com/s/0l0fpn9yytzb1t7/dropbox-android.png?dl=1" | |
}) | |
}; | |
#endregion | |
#region Methods | |
private async void LoadDatabase() | |
{ | |
try | |
{ | |
// Read the database from DropBox folder | |
var db = await this.dropBoxService.ReadFile("DropBoxDatabasePath"); | |
// Write the database to storage | |
await this.sqLite.WriteDatabase(db); | |
AppService.WriteDebug("Drobpox", "Loaded database OK!"); | |
// Go back to origin | |
// await this.NavigationService.GoBackAsync(); | |
} | |
catch (Exception ex) | |
{ | |
} | |
} | |
private async void OnDropboxGet() | |
{ | |
// If the user authenticates - loads database to Dropbox | |
this.dropBoxService.OnAuthenticated += this.LoadDatabase; | |
await this.dropBoxService.Authorize(); | |
} | |
private async void OnDropboxSave() | |
{ | |
// If the user authenticates - save database to Dropbox | |
this.dropBoxService.OnAuthenticated += this.SaveDatabase; | |
await this.dropBoxService.Authorize(); | |
} | |
private async void SaveDatabase() | |
{ | |
try | |
{ | |
// Read the database from app storage | |
var db = this.sqLite.ReadDatabase(); | |
// Write the database to DropBox folder | |
await this.dropBoxService.WriteFile(db, "DropBoxDatabasePath"); | |
AppService.WriteDebug("Drobpox", "Saved database OK!"); | |
} | |
catch (Exception ex) | |
{ | |
AppService.WriteDebug(ex); | |
await this.MainPage.DisplayAlert("Dropbox", $"Something went wrong. If the problem persists, please contact us", "OK"); | |
} | |
} | |
#endregion | |
} | |
} |
Hi, Does this code cater to Scoped Develoopment app? I am little confused what to set to AppKeyDropboxtoken and ClientId as I don't see the exact names on creating app on Dropbox portal. Do they respectively mean 'OAuth2 Access Token' and 'App key'?
Hi, Does this code cater to Scoped Develoopment app? I am little confused what to set to AppKeyDropboxtoken and ClientId as I don't see the exact names on creating app on Dropbox portal. Do they respectively mean 'OAuth2 Access Token' and 'App key'?
Can't say it does. It's a 3 years old hack for a platform I don't use any more.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm working through this and am extremely grateful but a bit more explanation on your tutorial on medium.com about things like client ID and the redirect URI to use would be extremely useful. I have no idea what either of these things is and Dropbox don't appear to provide much help. Back to Google, I guess...