package org.witness.informacam.share;
import info.guardianproject.iocipher.File;
import info.guardianproject.iocipher.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringBufferInputStream;
import java.util.LinkedList;
import java.util.Properties;
import org.witness.informacam.R;
import org.witness.informacam.models.media.IMedia;
import org.witness.informacam.utils.Constants.App.Storage;
import android.app.Activity;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.DropboxAPI.DropboxLink;
import com.dropbox.client2.DropboxAPI.Entry;
import com.dropbox.client2.android.AndroidAuthSession;
import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.session.AppKeyPair;
public class DropboxSyncManager {
final static private String APP_KEY = "j0ioje8k7q5o6vc";
final static private String APP_SECRET = "f5s6qyuwzq076yk";
// In the class declaration section:
private DropboxAPI<AndroidAuthSession> mDBApi;
private AndroidAuthSession mSession;
private boolean isAuthenticating = false;
private String mStoredAccessToken;
private LinkedList<IMedia> llMediaQ;
private Context mContext = null;
private NotificationCompat.Builder mBuilder;
private final static int NOTIFY_ID = 7777;
private static DropboxSyncManager mInstance;
private Thread mThread = null;
private DropboxSyncManager (Context context)
{
mContext = context;
}
public static synchronized DropboxSyncManager getInstance (Context context)
{
if (mInstance == null && context != null)
mInstance = new DropboxSyncManager (context);
return mInstance;
}
public boolean isSyncing ()
{
return mDBApi != null;
}
public boolean start (Activity a)
{
if (mDBApi == null)
{
loadCredentials();
if (mStoredAccessToken == null)
{
// And later in some initialization function:
AppKeyPair appKeys = new AppKeyPair(APP_KEY, APP_SECRET);
AndroidAuthSession session = new AndroidAuthSession(appKeys);
mDBApi = new DropboxAPI<AndroidAuthSession>(session);
isAuthenticating = true;
authenticate(a);
return false;
}
else
{
AppKeyPair appKeys = new AppKeyPair(APP_KEY, APP_SECRET);
AndroidAuthSession session = new AndroidAuthSession(appKeys);
session.setOAuth2AccessToken(mStoredAccessToken);
mDBApi = new DropboxAPI<AndroidAuthSession>(session);
return session.isLinked();
}
}
return true;
}
public void stop ()
{
mDBApi = null;
}
public synchronized void uploadMediaAsync (IMedia media)
{
if (mDBApi != null) //if there is no active session, then ignore
{
if (llMediaQ == null)
llMediaQ = new LinkedList<IMedia>();
llMediaQ.add(media);
showNotification();
if (mThread == null || (!mThread.isAlive()))
{
mThread = new Thread ()
{
public void run ()
{
IMedia media = null;
int numUploaded = 0;
while (mDBApi != null && llMediaQ.peek() != null)
{
media = llMediaQ.pop();
try {
Entry result = uploadMedia (media);
if (result != null)
numUploaded++;
uploadMetadata(media,"j3m");
uploadMetadata(media,"csv");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DropboxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
finishNotification(numUploaded);
}
};
mThread.start();
}
}
}
@SuppressWarnings("resource")
private Entry uploadMedia (IMedia media) throws DropboxException, FileNotFoundException
{
InputStream inputStream = null;
long fileLength = -1;
String fileName = null;
java.io.File file = null;
if (media.dcimEntry.fileAsset.source == Storage.Type.IOCIPHER)
{
file = new File (media.dcimEntry.fileAsset.path);
inputStream = new FileInputStream(file.getAbsolutePath());
fileLength = file.length();
fileName = file.getName();
}
else
{
file = new java.io.File (media.dcimEntry.fileAsset.path);
//this is an unencrypted file... let's still use it!
inputStream = new java.io.FileInputStream(file);
fileLength = file.length();
fileName = file.getName();
}
String remotePath = "/" + fileName;
boolean remoteExists = false;
try
{
DropboxLink dl = mDBApi.media(remotePath, true);
if (dl != null)
remoteExists = true;
}
catch (Exception e)
{
remoteExists = false;
}
if (!remoteExists)
{
Entry response = mDBApi.putFile(remotePath, inputStream,
fileLength, null, null);
return response;
// Log.i("DbExampleLog", "The uploaded file's rev is: " + response.rev);
}
return null;
}
@SuppressWarnings("resource")
private Entry uploadMetadata (IMedia media, String type) throws DropboxException, FileNotFoundException
{
String fileName = new File(media.dcimEntry.fileAsset.path).getName();
String remotePath = "/" + fileName + "." + type;
boolean remoteExists = false;
try
{
DropboxLink dl = mDBApi.media(remotePath, true);
if (dl != null)
remoteExists = true;
}
catch (Exception e)
{
remoteExists = false;
}
if (!remoteExists)
{
try {
String metadata = null;
if (type.equals("j3m"))
metadata = media.buildJ3M(mContext, false, null);
else if (type.equals("csv"))
metadata = media.buildCSV(mContext, null);
StringBufferInputStream inputStream = new StringBufferInputStream(metadata);
Entry response = mDBApi.putFile(remotePath, inputStream,
metadata.length(), null, null);
return response;
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Log.i("DbExampleLog", "The uploaded file's rev is: " + response.rev);
}
return null;
}
private void authenticate (Activity a)
{
mSession = mDBApi.getSession();
// MyActivity below should be your activity class name
mSession.startOAuth2Authentication(a);
}
public void finishAuthentication ()
{
if (mDBApi != null && isAuthenticating)
{
mSession = mDBApi.getSession();
if (mSession.authenticationSuccessful()) {
try {
// Required to complete auth, sets the access token on the session
mSession.finishAuthentication();
saveCredentials();
isAuthenticating = false;
} catch (IllegalStateException e) {
Log.e("DbAuthLog", "Error authenticating", e);
}
catch (IOException e) {
Log.e("DbAuthLog", "Error I/O", e);
}
}
}
}
private boolean loadCredentials ()
{
try
{
Properties props = new Properties();
info.guardianproject.iocipher.File fileProps = new info.guardianproject.iocipher.File("/dropbox.properties");
if (fileProps.exists())
{
info.guardianproject.iocipher.FileInputStream fis = new info.guardianproject.iocipher.FileInputStream(fileProps);
props.loadFromXML(fis);
mStoredAccessToken = props.getProperty("dbtoken");
return true;
}
}
catch (IOException ioe)
{
Log.e("DbAuthLog", "Error I/O", ioe);
}
return false;
}
private void saveCredentials () throws IOException
{
if (mSession != null && mSession.isLinked()
&& mSession.getOAuth2AccessToken() != null)
{
mStoredAccessToken = mSession.getOAuth2AccessToken();
Properties props = new Properties();
props.setProperty("dbtoken", mStoredAccessToken);
info.guardianproject.iocipher.File fileProps = new info.guardianproject.iocipher.File("/dropbox.properties");
info.guardianproject.iocipher.FileOutputStream fos = new info.guardianproject.iocipher.FileOutputStream(fileProps);
props.storeToXML(fos,"");
fos.close();
}
else
{
Log.d("Dropbox","no valid dropbox session / not linked");
}
}
private void showNotification ()
{
if (mBuilder == null)
{
Intent intentLaunch = mContext.getPackageManager().getLaunchIntentForPackage(mContext.getPackageName());
PendingIntent pendingIntent=PendingIntent.getActivity(mContext, 0,
intentLaunch, Intent.FLAG_ACTIVITY_NEW_TASK);
mBuilder =new NotificationCompat.Builder(mContext)
.setSmallIcon(R.drawable.ic_action_backup)
.setContentTitle(mContext.getString(R.string.backing_up_camerav_gallery_to_dropbox))
.setContentIntent(pendingIntent);
}
mBuilder.setContentTitle(mContext.getString(R.string.backing_up_camerav_gallery_to_dropbox));
mBuilder.setProgress(0, 100, true);
mBuilder.setContentText(mContext.getString(R.string.camerav_syncing_photos_and_videos_));
NotificationManager mNotificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(NOTIFY_ID,mBuilder.build());
}
private void finishNotification (int numUploaded)
{
NotificationManager mNotificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
String contentText = "CameraV synced " + numUploaded + " new photos and videos.";
mBuilder.setContentTitle(mContext.getString(R.string.dropbox_backup_complete));
mBuilder.setContentText(contentText);
mBuilder.setProgress(100, 100, false);
mNotificationManager.notify(NOTIFY_ID,mBuilder.build());
}
}