...
 
Commits (30)
......@@ -16,7 +16,7 @@ android {
applicationId "foundation.e.drive"
minSdkVersion 24
versionCode 1
versionName "alpha-${versionMajor}-build-${buildTime()}"
versionName "beta-${versionMajor}-build-n-${buildTime()}"
setProperty("archivesBaseName", "$applicationId.$versionName")
}
......
......@@ -8,12 +8,15 @@
package foundation.e.drive.models;
import android.os.Parcel;
import android.os.Parcelable;
/**
* @author Vincent Bourgmayer
* Describe a file state which will be Synchronized (= Synced) or which has already been synced one times
*/
public class SyncedFileState {
public class SyncedFileState implements Parcelable {
protected SyncedFileState(){}; //@ToRemove. Test Only. It's to allow to make a mock SyncedFileState Class in test.
private int id;
......@@ -46,6 +49,42 @@ public class SyncedFileState {
this.isMediaType = isMediaType;
}
protected SyncedFileState(Parcel in) {
id = in.readInt();
name = in.readString();
localPath = in.readString();
remotePath = in.readString();
lastETAG = in.readString();
localLastModified = in.readLong();
syncedFolderId = in.readLong();
isMediaType = in.readByte() != 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
dest.writeString(localPath);
dest.writeString(remotePath);
dest.writeString(lastETAG);
dest.writeLong(localLastModified);
dest.writeLong(syncedFolderId);
dest.writeByte((byte) (isMediaType ? 1 : 0));
}
public static final Creator<SyncedFileState> CREATOR = new Creator<SyncedFileState>() {
@Override
public SyncedFileState createFromParcel(Parcel in) {
return new SyncedFileState(in);
}
@Override
public SyncedFileState[] newArray(int size) {
return new SyncedFileState[size];
}
};
public int getId() {
return id;
}
......@@ -125,4 +164,9 @@ public class SyncedFileState {
+"\nSyncedFolderId: "+this.syncedFolderId
+"\nisMediaType: "+this.isMediaType;
}
@Override
public int describeContents() {
return 0;
}
}
......@@ -4,18 +4,6 @@ import com.owncloud.android.lib.common.operations.RemoteOperation;
public interface ComparableOperation {
/**
* Return the path that point on a remote file
* @return String URI of the file
*/
public String getRemotePath();
/**
* Return the path that point on a local file
* @return String URI of the file
*/
public String getLocalPath();
/**
* Say if File affected by operation is a media or a settings
* @return
......
......@@ -9,16 +9,15 @@
package foundation.e.drive.operations;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.resources.files.FileUtils;
import com.owncloud.android.lib.resources.files.model.RemoteFile;
import java.io.File;
import foundation.e.drive.database.DbHelper;
import foundation.e.drive.models.SyncedFileState;
import foundation.e.drive.utils.CommonUtils;
......@@ -28,61 +27,68 @@ import foundation.e.drive.utils.CommonUtils;
* Encapsulate a global download process for a file
*/
public class DownloadFileOperation extends RemoteOperation implements ComparableOperation{
public class DownloadFileOperation extends RemoteOperation implements ComparableOperation, Parcelable {
private final static String TAG = DownloadFileOperation.class.getSimpleName();
private final RemoteFile mRFile;
private final Context mContext;
private Context mContext;
private String mTargetPath;
private int restartCounter =0;
private SyncedFileState mSyncedState;
private String previousEtag;
/**
* Constructor download operation for new file
* @param remoteFile Must not be null. File to download
* @param targetPath Local Path where to download the file Must not be null or empty
* @param context context of the app not service context
* COnstructor of download operation where syncedFileState is already known
* @param remoteFile remote file to Download
* @param syncedFileState SyncedFileState corresponding to remote file
*/
public DownloadFileOperation(RemoteFile remoteFile, String targetPath, Long syncedFolderId,boolean syncedFolderIsMediaType, Context context){
this.mContext = context;
public DownloadFileOperation(RemoteFile remoteFile, SyncedFileState syncedFileState){
this.mRFile = remoteFile;
String remotePath = remoteFile.getRemotePath();
this.mSyncedState = DbHelper.loadSyncedFile(mContext, remotePath, false );
this.mTargetPath = targetPath;
if(this.mSyncedState == null){ //It's the first synchronisation of this file
Log.d(TAG, " no SyncedFileState stored in DB for: "+remoteFile.getRemotePath()
+"\n so it's first synchronisation of this file");
this.mSyncedState = new SyncedFileState(-1,
CommonUtils.getFileNameFromPath( remotePath ), //No need to check if null. It has already be done in ObserverService
this.mTargetPath,
remotePath,
this.mRFile.getEtag(),
0L,
syncedFolderId, syncedFolderIsMediaType);
}
this.mSyncedState = syncedFileState;
this.previousEtag = mSyncedState.getLastETAG();
this.mTargetPath = this.mSyncedState.getLocalPath();
}
protected DownloadFileOperation(Parcel in) {
mRFile = in.readParcelable(RemoteFile.class.getClassLoader());
mTargetPath = in.readString();
restartCounter = in.readInt();
mSyncedState = in.readParcelable(SyncedFileState.class.getClassLoader());
previousEtag = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(mRFile, flags);
dest.writeString(mTargetPath);
dest.writeInt(restartCounter);
dest.writeParcelable(mSyncedState, flags);
dest.writeString(previousEtag);
}
public static final Creator<DownloadFileOperation> CREATOR = new Creator<DownloadFileOperation>() {
@Override
public DownloadFileOperation createFromParcel(Parcel in) {
return new DownloadFileOperation(in);
}
@Override
public DownloadFileOperation[] newArray(int size) {
return new DownloadFileOperation[size];
}
};
/**
* COnstructor of download operation where syncedFileState is already known
* @param remoteFile remote file to Download
* @param targetPath can be null if defined in syncedFileState
* @param context calling context
* @param syncedFileState SyncedFileState corresponding to remote file
* Set the context required to use DB
* @param context
*/
public DownloadFileOperation(RemoteFile remoteFile, String targetPath, Context context, SyncedFileState syncedFileState){
this.mRFile = remoteFile;
public void setContext(Context context){
this.mContext = context;
this.mSyncedState = syncedFileState;
this.previousEtag = mSyncedState.getLastETAG();
this.mTargetPath = (targetPath == null)?this.mSyncedState.getLocalPath(): targetPath;
}
@Override
protected RemoteOperationResult run(OwnCloudClient ownCloudClient) {
Log.i(TAG, "run(ownCloudClient)");
......@@ -181,17 +187,12 @@ public class DownloadFileOperation extends RemoteOperation implements Comparable
}
@Override
public String getRemotePath() {
return mSyncedState.getRemotePath();
}
@Override
public String getLocalPath() {
return mTargetPath;
public RemoteOperation toRemoteOperation() {
return this;
}
@Override
public RemoteOperation toRemoteOperation() {
return this;
public int describeContents() {
return 0;
}
}
......@@ -8,17 +8,18 @@
package foundation.e.drive.operations;
import android.os.Parcel;
import android.os.Parcelable;
import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.resources.files.RemoveFileRemoteOperation;
import foundation.e.drive.models.SyncedFileState;
/**
*
* @author Vincent Bourgmayer
* Created by Vincent on 19/06/2018.
* Class to be able to wrap concerned SyncedFileState in operation, so it can be retrieve at the end
*/
public class RemoveFileOperation extends RemoveFileRemoteOperation implements ComparableOperation{
public class RemoveFileOperation extends RemoveFileRemoteOperation implements ComparableOperation, Parcelable {
private SyncedFileState mSyncedFileState;
......@@ -27,6 +28,29 @@ public class RemoveFileOperation extends RemoveFileRemoteOperation implements Co
this.mSyncedFileState = syncedFileState;
}
protected RemoveFileOperation(Parcel in) {
super(in.readString());
this.mSyncedFileState = in.readParcelable(SyncedFileState.class.getClassLoader());
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mSyncedFileState.getRemotePath());
dest.writeParcelable(this.mSyncedFileState, flags);
}
public static final Creator<RemoveFileOperation> CREATOR = new Creator<RemoveFileOperation>() {
@Override
public RemoveFileOperation createFromParcel(Parcel in) {
return new RemoveFileOperation(in);
}
@Override
public RemoveFileOperation[] newArray(int size) {
return new RemoveFileOperation[size];
}
};
public SyncedFileState getSyncedFileState() {
return mSyncedFileState;
}
......@@ -41,19 +65,12 @@ public class RemoveFileOperation extends RemoveFileRemoteOperation implements Co
}
@Override
public String getRemotePath() {
return this.mSyncedFileState.getRemotePath();
public RemoteOperation toRemoteOperation() {
return this;
}
/**
* @inherited
*/
@Override
public String getLocalPath() {
return getSyncedFileState().getLocalPath();
}
@Override
public RemoteOperation toRemoteOperation() {
return this;
public int describeContents() {
return 0;
}
}
......@@ -22,8 +22,12 @@ public abstract class AppConstants {
public static final String APPLICATIONS_LIST_FILE_NAME = "packages_list.csv";
public static final String APPLICATIONS_LIST_FILE_NAME_TMP = "tmp_packages_list.csv";
public static final String SHARED_PREFERENCE_NAME ="preferences";
public static final String KEY_LAST_SYNC_TIME = "lastSyncTimestamp"; //key for read/write last sync time (in ms) in prefs.
public static final String KEY_OMS_IS_WORKING = "OMS_is_working";
public static final String[] MEDIA_SYNCABLE_CATEGORIES = new String[]{"Images", "Movies", "Music", "Ringtones", "Documents", "Podcasts"};
public static final String[] SETTINGS_SYNCABLE_CATEGORIES = new String[] {"Rom settings"};
}
package foundation.e.drive.utils;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.Context;
import com.owncloud.android.lib.common.OwnCloudBasicCredentials;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
public class DavClientProvider {
private DavClientProvider (){}
private OwnCloudClient clientInstance;
public OwnCloudClient getClientInstance(Account account, Context ctx) {
if(clientInstance == null){
this.clientInstance = CommonUtils.getOwnCloudClient(account, ctx);
}
/*if(clientInstance.getCredentials().getClass().getName().equals(OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials.class.getName())){
clientInstance.setCredentials(
new OwnCloudBasicCredentials(
account.name,
AccountManager.get(ctx).getPassword(account)
)
);
}*/
return clientInstance;
}
/** Holder */
private static class DavClientHolder
{
/** Instance unique non préinitialisée */
private final static DavClientProvider instance = new DavClientProvider();
}
/** Point d'accès pour l'instance unique du singleton */
public static DavClientProvider getInstance()
{
return DavClientHolder.instance;
}
}
package foundation.e.drive.Test;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.util.ArrayDeque;
import java.util.concurrent.ConcurrentLinkedDeque;
import foundation.e.drive.Test.mockObject.mockContext;
import foundation.e.drive.Test.mockObject.mockRemoteFile;
import foundation.e.drive.Test.mockObject.mockSfs;
import foundation.e.drive.operations.ComparableOperation;
import foundation.e.drive.operations.DownloadFileOperation;
import foundation.e.drive.operations.UploadFileOperation;
public class doTest {
public mockContext context;
private UploadFileOperation upload1;
private UploadFileOperation upload2;
private DownloadFileOperation download1;
@Before
public void init(){
context = new mockContext();
upload1 = new UploadFileOperation(new File("toto.txt"), this.context, new mockSfs(), true);
upload2 = new UploadFileOperation(new File("titi.txt"), this.context, new mockSfs(), true);
download1 = new DownloadFileOperation(new mockRemoteFile(), "toto/toto.txt", this.context, new mockSfs());
}
@Test
public void MD5Test(){
System.out.println(System.currentTimeMillis());
String hash = MD5Test.calculateMD5(new File("D:/projet/projet_dnd/mon_livre/GLT-old.odt") );
System.out.println(System.currentTimeMillis());
System.out.println("Hash : "+hash);
}
@Test
public void loopThroughConcurrentLinkedDeque(){
ConcurrentLinkedDeque<ComparableOperation> CLD = new ConcurrentLinkedDeque<>();
CLD.add(upload1);
CLD.add(upload2);
int counter = 0;
for(ComparableOperation o : CLD){
System.out.println(counter);
System.out.println(o.getClass().getSimpleName());
if (counter == 1){
o = download1;
}
System.out.println(o.getClass().getSimpleName());
++counter;
}
}
@Test
public void loopThroughArrayDeque(){
ArrayDeque<ComparableOperation> cO = new ArrayDeque<>();
cO.add(upload1);
cO.add(upload2);
int counter = 0;
for(ComparableOperation o : cO){
++counter;
System.out.println(counter);
System.out.println(o.getClass().getSimpleName());
if(counter == 1) {
o = download1;
}
System.out.println(o.getClass().getSimpleName());
}
}
}