0

I have an app written using Xamarin for Android that allows me to store my customers info. I store all the data locally using sqlite and it all works fine. But I need to share this info with my colleague who is using the same app on his phone. So for example, if I add a new customer order from my phone this will be saved into my local db. Now I want to hit a button to trigger the sync of my local db with some backup of this db stores in a shared folder in Dropbox or Google Drive.,

From suggestions below, I am trying to use DropBox Core Api. I got to the point where I authenticate to access my account, now I need to copy my local DB in my app folder in Dropbox. I am using the code below for my second activity. When it launches, I get the authentication page for Dropbox. After that when I click the backup button I am expecting to read the local DB and save it to Dropbox under ./Apps/ClientsApp/. But I only get a generic error (An unhandled exception occured). Where am I making a mistake?

using Dropbox.CoreApi;
using Dropbox.CoreApi.Android;
using Dropbox.CoreApi.Android.Session;

namespace my_app
{
[Activity(Label = "Second Activity")]
class clientsDB : Activity
{
    string AppKey = "myAppKey";
    string AppSecret = "myAppSecret";
    DropboxApi dropboxApi;
    private Button backup;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.clientsDB);

        // dropbox
        AppKeyPair appKeys = new AppKeyPair(AppKey, AppSecret);
        AndroidAuthSession session = new AndroidAuthSession(appKeys);
        dropboxApi = new DropboxApi(session);

        (dropboxApi.Session as AndroidAuthSession).StartOAuth2Authentication(this);

        backup = FindViewById<Button>(Resource.Id.backup);
        backup.Click += Backup_Click;
    }


    private void Backup_Click(object sender, EventArgs e)
    {
        string origin = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "dbClients.db3");

        string dropboxPath = @"./Apps/ClientsApp";
        upload(origin, dropboxPath);

    }

    // use async cause I had Android.OS.NetworkOnMainThreadException 
    async void upload(string origin, string destination)
    {            
        using (var input = File.OpenRead(origin))
        {
            // Gets the local file and upload it to Dropbox
            dropboxApi.PutFile(destination, input, input.Length, null, null);
        }
    }

    protected async override void OnResume()
    {
        base.OnResume();

        // After you allowed to link the app with Dropbox,
        // you need to finish the Authentication process
        var session = dropboxApi.Session as AndroidAuthSession;
        if (!session.AuthenticationSuccessful())
            return;

        try
        {
            // Call this method to finish the authentication process
            session.FinishAuthentication();
        }
        catch (IllegalStateException ex)
        {
            Toast.MakeText(this, ex.LocalizedMessage, ToastLength.Short).Show();
        }
    }


}
}
opt
  • 477
  • 1
  • 10
  • 25
  • You mean you cannot find a db file ? You should have a path to it in your code, used for creating SQLiteConnection (if you're using it). – Dawid Sibiński Mar 25 '17 at 16:57
  • The path is not accessible to me. I have my db store here: dbPath = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "myDB.db3"); – opt Mar 25 '17 at 17:08
  • Why you have no access? I've just tried creating a File variable giving it the path to the DB file and it works. Try: File a = new File(System.IO.Path.Combine(System.Environment.GetFolderPath(Syst‌​em.Environment.Speci‌​alFolder.Personal), "myDB.db3")); Having File variable you can copy the db file/export it to external cloud storage. – Dawid Sibiński Mar 25 '17 at 17:15
  • are you trying to backup the file programatically from within your app, or are you doing it manually from your PC? – Jason Mar 25 '17 at 17:19
  • I need to do this programmatically. For example, a button click will backup all the data I have in mylocal db by creating a backup copy of that db in my Dropbox/GDrive – opt Mar 25 '17 at 17:43

1 Answers1

1

You need to retrieve your database file first. You can do it as follows:

File dbFile = new File(System.IO.Path.Combine(System.Environment.GetFolderPath‌​(Syst‌​em.Environmen‌​t.Speci‌​alFolder.Pe‌​rsonal), "myDB.db3"));

After you have dbFile variable, you can copy it to SD card or export to Dropbox/GDrive. See this answer for more details on exporting it to Dropbox.

EDIT: Dropbox API mentioned in the answer I linked seems to be deprecated, here's the component for Xamarin: https://components.xamarin.com/view/dropboxcoreapiandroid

EDIT:

If you want to copy your database file to external storage (e.g. SD card), you need to add necessary permissions for your Android app.

In order to be able to write a file in such location, you need to add WRITE_EXTERNAL_STORAGE permission to your app. You can do it by going to your Android project -> Properties -> "Android Manifest" tab -> In section "Required permissions" select WRITE_EXTERNAL_STORAGE. You can also select READ_EXTERNAL_STORAGE to be able to read and write to/from external storage.

Community
  • 1
  • 1
Dawid Sibiński
  • 1,657
  • 3
  • 21
  • 40
  • I copied your line to get dbFile but I have an error (Cannot create an instance of the static class 'File'). How can I solve this? – opt Mar 25 '17 at 22:53
  • 1
    @opt You're probably using System.IO.File, whereas you should use Java.IO.File. Make sure you reference the proper one. – Dawid Sibiński Mar 25 '17 at 23:41
  • Yes using Java.IO.File solves that issue. By the way I am trying to use System.IO.File.Copy(origin, destination, true) instead, where origin and destination are strings for the file path. But I get authorization issues, not sure if that is for the origin pr the destination. I am updating my request above with more details in case you can help. Thanks. – opt Mar 26 '17 at 01:04
  • 1
    @opt the problem is that location you're trying to use (/storage/emulated/0/myApp/) is the SD Card location. In order to be able to write a file in this location, you need to add `WRITE_EXTERNAL_STORAGE` permission to your app. You can do it by going to your Android project -> Properties -> "Android Manifest" tab -> In section "Required permissions" select `WRITE_EXTERNAL_STORAGE`. You can also select `READ_EXTERNAL_STORAGE` to be able to read and write to/from external storage. – Dawid Sibiński Mar 26 '17 at 09:58
  • Thank you Dawid. Looking at the Dropbox Core API, I cannot find that in NuGet from Visual Studio. How do you get this working please? – opt Mar 26 '17 at 22:50
  • 1
    This Dropbox Core API is the Xamarin Component, you don't install it from Nuget, but rather from Component Manager. Find more details here: https://developer.xamarin.com/guides/cross-platform/xamarin-studio/components_walkthrough/ – Dawid Sibiński Mar 27 '17 at 13:25
  • Great, I found it and I think I managed to link to Dropbox. What I don't understand is what should I use as Dropbox folder path for the PutFile method. If I open the app folder in Dropbox and then I click share, I have the full link of the folder. If I use this in PutFile and run the code I get a network error. Any idea how can I use that function to save my DB file on it? Thanks. – opt Mar 27 '17 at 23:22
  • 1
    I've never used that API, but I'm quite sure you should use a path relative to your Dropbox main catalogue. So if you pass to this PutFile method a string "/copy.db",it should put the file into your main Dropbox catalogue. Later you can specify your Dropbox' s folders structure and build the path, like "/folderA/copy.db" etc. – Dawid Sibiński Mar 28 '17 at 16:12
  • Hi Dawid, that does not seem to solve the issue. I updated the question with my code, hoping to get your help finding the error. Thanks. – opt Mar 28 '17 at 23:08
  • @opt I don't know this API. Are you sure there should be a dot (.) in your string @"./Apps/ClientsApp"? Have you tried without it? – Dawid Sibiński Mar 30 '17 at 04:41