Search code examples
androiddropboxdropbox-api

Two-way sync app, Core API or Sync API?


I've never worked with the Dropbox API before and I noticed there's 2 APIs available the Core and Sync, and I don't know which one I should be using. Here's a bit about what I'm trying to do:

A simple two-way sync that mirrors a folder on the users Dropbox to the device, and vice versa. The folder could contain any files there of any type. When making the App on the App Console it asked for permissions and it seems the full dropbox permission is only compatible with the Core API.

Is anyone able to clarify which API I would need to be using? Thanks!

EDIT: I created an app with full dropbox permissions, this failed to work with the Sync API (as stated on the creation page), so instead I made another app allowing text files, then created a .dat file, which resulted in the following error:

DROPBOX_DISALLOWED: sync.hpp:300: app is not allowed to create file p(/c7/r6/t4.dat)

Is there any way around this particularly issue or will I have to use the Core API? Seems a bit limiting that the apps can only work with certain file types only.

EDIT2: My code using to test right now:

public void SyncTest() {
    try {
        DbxFileSystem dbxFs = DbxFileSystem.forAccount(mDbxAcctMgr.getLinkedAccount());

        DbxFile testFile = dbxFs.create(new DbxPath(getString(R.string.remote_path) + "hello.dat"));
        try {
            testFile.writeString("Hello Dropbox!");
        } catch(IOException ioe) {

        } finally {
            testFile.close();
            dbxFs.syncNowAndWait();
        }
    } catch(com.dropbox.sync.android.DbxException.Unauthorized ue) {
        alert(getString(R.string.unauth));
    } catch (com.dropbox.sync.android.DbxException se) {

    }
}

App permission type is "text files". When using an app with "Full dropbox" I get a different error:

DROPBOX_ERROR_USAGE: sync.cpp:244: This app is not allowed to use the Sync API for file access.

Solution

  • I have never worked with the Core API but I am both able to download and receive files.

    It is though worth mentioning, that the intention of the Sync API (likely also the core), is not to keep the local files up-to-date. Rather it is designed to let you retrieve the files available on Dropbox and download on the fly.

    My use case needed the Dropbox files to be retrieve locally, so I run a sync algorithm that run through all the Dropbox files, checks modified and size and downloads all the, either new, or modified files to SD. The downloading is done using IntentServices. Issuing an IntentService for each file that needs to be downloaded.

    So, for one way sync, Sync API works fine. The other way should be possible too, though I assume harder to manage.

    Bottom line being that you should be able to do it but you have to do a lot of lifting yourself.

    The few questions I have seen with the Core API, I have not spotted any huge differences, other than the Sync API lives in a specific Dropbox folder "Dropbox/apps/yourapp", Core API does not.

    If that is the case I would recommend Sync API as it seems to be simpler to work with.

    I am willing to post my code for the one way sync if you choose to go for it :)

    Edit: Added my code for writing to Dropbox

    public class DropboxWriter {
    
    private static final String TAG = "DropboxWriter";
    
    public static boolean writeAssetBinary(Context context, String assetFile,
            DbxFile toFile) {
    
        String tempsdpath = Environment.getExternalStorageDirectory()
                .toString() + "/temp";
    
        AssetManager assetManager = context.getAssets();
    
        OutputStream outputStream = null;
        InputStream inputStream = null;
        try {
            inputStream = assetManager.open(assetFile);
            outputStream = new FileOutputStream(tempsdpath + "/" + assetFile);
            byte buf[] = new byte[1024];
            int len;
            while ((len = inputStream.read(buf)) != -1) {
                outputStream.write(buf, 0, len);
            }
    
        } catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
            if (outputStream != null) {
    
                try {
                    outputStream.flush();
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        try {
            File file = new File(tempsdpath, assetFile);
            toFile.writeFromExistingFile(file, false);
            return true;
        } catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
        } finally {
            toFile.close();
        }
        return false;
    }
    
    public static boolean writeAssetText(Context context, String assetFile,
            DbxFile toFile) {
    
        AssetManager assetManager = context.getAssets();
        ByteArrayOutputStream outputStream = null;
        InputStream inputStream = null;
        try {
            inputStream = assetManager.open(assetFile);
            outputStream = new ByteArrayOutputStream();
            byte buf[] = new byte[1024];
            int len;
            while ((len = inputStream.read(buf)) != -1) {
                outputStream.write(buf, 0, len);
            }
            outputStream.flush();
            outputStream.close();
            inputStream.close();
        } catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
        }
    
        try {
            toFile.writeString(outputStream.toString());
            return true;
        } catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
        } finally {
            toFile.close();
        }
        return false;
    }
    }
    

    Up until this point I have only needed to write files from assets but could easily be rewritten to write from any other file.