diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6ba265a284592e3672280c4bdf7c0aa14a25109d..1e1f9bc24082959028072915af7e5891b41b35ef 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: "registry.gitlab.e.foundation:5000/e/apps/docker-android-apps-cicd:latest" +image: "registry.gitlab.e.foundation:5000/e/apps/docker-android-apps-cicd:legacy" stages: - build diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fafd9d3fcf85537caa4988171b05acac3cedff14..6a4e9cd0d040013716ded104771352d2111c7c53 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,6 +24,7 @@ http://www.gnu.org/licenses/gpl.html android:protectionLevel="signature" /> files; + + //private List syncedFileStatesList; + + public FileObserver(List files) { + this.files = files; + + } + + public List getFiles() { + return files; + } + + public void setFiles(List files) { + this.files = files; + } + +// public List getSyncedFileStatesList() { +// return syncedFileStatesList; +// } +// +// public void setSyncedFileStatesList(List syncedFileStatesList) { +// this.syncedFileStatesList = syncedFileStatesList; +// } +} diff --git a/app/src/main/java/foundation/e/drive/models/SyncedFileState.java b/app/src/main/java/foundation/e/drive/models/SyncedFileState.java index 42c76a102482a4681845082e752f1edf57211f3d..3b9255be143e3b637c1686beff0ce6d5b7d4ee8e 100644 --- a/app/src/main/java/foundation/e/drive/models/SyncedFileState.java +++ b/app/src/main/java/foundation/e/drive/models/SyncedFileState.java @@ -11,12 +11,14 @@ package foundation.e.drive.models; import android.os.Parcel; import android.os.Parcelable; +import java.io.Serializable; + /** * @author Vincent Bourgmayer * Describe a file state which will be Synchronized (= Synced) or which has already been synced one times */ -public class SyncedFileState implements Parcelable { +public class SyncedFileState implements Parcelable, Serializable { protected SyncedFileState(){}; //@ToRemove. Test Only. It's to allow to make a mock SyncedFileState Class in test. diff --git a/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java b/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java index 88276a6b9703b773b4bdaf40e115b3b11e4e59e0..0ded25fa7bcceb59710911da088f84dcde6eae60 100644 --- a/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java @@ -25,6 +25,7 @@ import java.io.File; import java.util.ArrayList; import foundation.e.drive.database.DbHelper; import foundation.e.drive.models.SyncedFileState; +import foundation.e.drive.services.InitializerService; import foundation.e.drive.utils.CommonUtils; /** @@ -136,6 +137,17 @@ public class UploadFileOperation extends RemoteOperation implements ComparableOp //if upload is a success if( uploadResult.isSuccess() ){ + Log.e(TAG, "upload is success ........................."+file.getName() + +" "+file.getAbsolutePath()); + + + Log.e(TAG, "files size before remove ........................."+InitializerService.files.size()); + + InitializerService.files.remove(file); + + Log.e(TAG, "files size after remove ........................."+InitializerService.files.size()); + + Object data = uploadResult.getSingleData(); if(data != null){ mSyncedState.setLastETAG((String) data); diff --git a/app/src/main/java/foundation/e/drive/receivers/ConnectivityReceiver.java b/app/src/main/java/foundation/e/drive/receivers/ConnectivityReceiver.java index 066582a49dd363e5d4c5a2b323b8eb64690d9c93..ec0dba30b91f10f141b4adade765b666afa90949 100644 --- a/app/src/main/java/foundation/e/drive/receivers/ConnectivityReceiver.java +++ b/app/src/main/java/foundation/e/drive/receivers/ConnectivityReceiver.java @@ -5,46 +5,76 @@ import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; +import android.os.Bundle; +import android.os.Handler; import android.util.Log; import java.io.IOException; +import foundation.e.drive.services.FileObserverService; +import foundation.e.drive.services.InitializerService; +import foundation.e.drive.services.MyApplication; + public class ConnectivityReceiver extends BroadcastReceiver { public static ConnectivityReceiverListener connectivityReceiverListener; + public boolean isConnected; public ConnectivityReceiver() { super(); } - public boolean isConnected(Context context) { -// String command = "ping -c 1 e.foundation"; -// return (Runtime.getRuntime().exec(command).waitFor() == 0); - try { - ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo netInfo = cm.getActiveNetworkInfo(); - //should check null because in airplane mode it will be null - return (netInfo != null && netInfo.isConnected()); - } catch (NullPointerException e) { - e.printStackTrace(); - return false; - } + public static boolean isConnected() { + ConnectivityManager + cm = (ConnectivityManager) MyApplication.getInstance().getApplicationContext() + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); + return activeNetwork != null + && activeNetwork.isConnectedOrConnecting(); } + @Override - public void onReceive(Context context, Intent arg1) { + public void onReceive(final Context context, Intent arg1) { ConnectivityManager cm = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); + final NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); + + + final Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + isConnected = activeNetwork != null + && activeNetwork.isConnectedOrConnecting(); + + if (connectivityReceiverListener != null) { + Log.e("TAG", "connectivityReceiverListener...." + isConnected); + connectivityReceiverListener.onNetworkConnectionChanged(isConnected); + } + + if (isConnected) { + Intent observersServiceIntent = new Intent(context, foundation.e.drive.services.ObserverService.class); + if (InitializerService.schedulerFlag) { + + context.startService(observersServiceIntent); + + } else if (InitializerService.fileObserverFlag) { + // + Bundle mBundle = new Bundle(); + mBundle.putBoolean("isFileObserverService", true); + observersServiceIntent.putExtras(mBundle); + context.startService(observersServiceIntent); + } + + InitializerService.schedulerFlag = false; + InitializerService.fileObserverFlag = false; + } + } + }, 20000); - boolean isConnected = activeNetwork != null - && activeNetwork.isConnectedOrConnecting(); - //if (connectivityReceiverListener != null) { - Log.e("TAG", "ConnectivityReceiver onNetworkConnectionChanged...." + isConnected); - //connectivityReceiverListener.onNetworkConnectionChanged(isConnected); - //} } public interface ConnectivityReceiverListener { diff --git a/app/src/main/java/foundation/e/drive/services/FileObserverService.java b/app/src/main/java/foundation/e/drive/services/FileObserverService.java index 964fe206b7cd220036261c42b8bd0d8b04887164..f77708f330c057e5d6518cd6d6d18368d8de64ee 100644 --- a/app/src/main/java/foundation/e/drive/services/FileObserverService.java +++ b/app/src/main/java/foundation/e/drive/services/FileObserverService.java @@ -5,6 +5,7 @@ import android.app.Service; import android.content.Intent; import android.os.AsyncTask; import android.os.Build; +import android.os.Bundle; import android.os.Environment; import android.os.FileObserver; @@ -16,14 +17,21 @@ import android.support.annotation.Nullable; import android.util.Log; import java.io.File; +import java.util.ArrayList; +import java.util.List; +import foundation.e.drive.receivers.ConnectivityReceiver; +import foundation.e.drive.utils.CommonUtils; import foundation.e.drive.utils.RecursiveFileObserver; -public class FileObserverService extends Service { +public class FileObserverService extends Service { + + private final static String TAG = FileObserverService.class.getSimpleName(); RecursiveFileObserver mFileObserver = null; private int observerFlag=-1; + //List syncedFileStatesList=new ArrayList<>(); @Override @@ -53,18 +61,30 @@ public class FileObserverService extends Service { //Modify =2, create =256, delete =512, movedTo =128 if(event== FileObserver.CREATE || event==FileObserver.MODIFY || event== FileObserver.DELETE || event ==FileObserver.MOVED_TO){ - Log.d("OnEvent", "...Event ..." + event+"...file ..." + file); + Log.i(TAG, "...Event ..." + event+"...file ..." + file); + + if(!InitializerService.files.contains(file)){ + + InitializerService.files.add(file); + } - try - { - if(observerFlag == -1){ - new AsyncTaskRunner().execute(""); + + if(ConnectivityReceiver.isConnected()){ + try + { + if(observerFlag == -1){ + new AsyncTaskRunner().execute(""); + } + } + catch (Exception e) + { + e.printStackTrace(); } } - catch (Exception e) - { - e.printStackTrace(); + else { + InitializerService.fileObserverFlag=true; } + } } @@ -90,7 +110,7 @@ public class FileObserverService extends Service { @Override public void onTaskRemoved(Intent rootIntent) { - Log.d("TAG", "............onTaskRemoved"); + Log.d(TAG, "............onTaskRemoved"); super.onTaskRemoved(rootIntent); Intent intent = new Intent(this, InitializerService.class); this.startActivity(intent); @@ -108,23 +128,22 @@ public class FileObserverService extends Service { @Override protected void onPostExecute(String s) { super.onPostExecute(s); - // Log.d("onPostExecute", "...ObserverService Intent...post Execute " ); - - final Handler handler = new Handler(); - handler.postDelayed(new Runnable() { - @Override - public void run() { - // Log.e("onPostExecute", "...ObserverService Intent..." ); - // Do something after 20s = 20000ms - Intent observersServiceIntent = new Intent(getApplicationContext(), foundation.e.drive.services.ObserverService.class); - startService(observersServiceIntent); - - observerFlag=-1; - } - }, 20000); + try { + Intent observersServiceIntent = new Intent(getApplicationContext(), foundation.e.drive.services.ObserverService.class); + + Bundle mBundle = new Bundle(); + mBundle.putBoolean("isFileObserverService", true); + // mBundle.putByteArray("fileObserverObject", CommonUtils.convertToBytes(new foundation.e.drive.models.FileObserver(files))); + observersServiceIntent.putExtras(mBundle); + startService(observersServiceIntent); + }catch (Exception exception){ + exception.printStackTrace(); + } + observerFlag=-1; } + } diff --git a/app/src/main/java/foundation/e/drive/services/InitializerService.java b/app/src/main/java/foundation/e/drive/services/InitializerService.java index ad556cea4a7b16a8c9aef74026eba249ed2ae874..b894bc2a7ba79f18941c1658b667cd525b491d0e 100644 --- a/app/src/main/java/foundation/e/drive/services/InitializerService.java +++ b/app/src/main/java/foundation/e/drive/services/InitializerService.java @@ -28,6 +28,7 @@ import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -61,6 +62,10 @@ public class InitializerService extends Service private int restartFolderCreationCounter =0; private ConnectivityReceiver connectivityReceiver; + public static List files=new ArrayList<>(); + public static boolean schedulerFlag=false; + public static boolean fileObserverFlag=false; + @Override public void onCreate() { Log.i(TAG, "onCreate()"); diff --git a/app/src/main/java/foundation/e/drive/services/MyApplication.java b/app/src/main/java/foundation/e/drive/services/MyApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..79ae6d83d3d151f591cdc38464ac92dec0636d5a --- /dev/null +++ b/app/src/main/java/foundation/e/drive/services/MyApplication.java @@ -0,0 +1,25 @@ +package foundation.e.drive.services; + +import android.app.Application; + +import foundation.e.drive.receivers.ConnectivityReceiver; + +public class MyApplication extends Application { + + private static MyApplication mInstance; + + @Override + public void onCreate() { + super.onCreate(); + + mInstance = this; + } + + public static synchronized MyApplication getInstance() { + return mInstance; + } + + public void setConnectivityListener(ConnectivityReceiver.ConnectivityReceiverListener listener) { + ConnectivityReceiver.connectivityReceiverListener = listener; + } +} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/drive/services/ObserverService.java b/app/src/main/java/foundation/e/drive/services/ObserverService.java index dfd2873ebef992f461c2e242e31883bf3dd283f5..c9c37220db976a79395fd706780f4b058f76edd9 100644 --- a/app/src/main/java/foundation/e/drive/services/ObserverService.java +++ b/app/src/main/java/foundation/e/drive/services/ObserverService.java @@ -15,6 +15,7 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; +import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Parcelable; @@ -69,6 +70,8 @@ public class ObserverService extends Service implements OnRemoteOperationListene private int initialFolderCounter; private Account mAccount; private HashMap operationsForIntent; + private Boolean isFileObserverService=false; + // private foundation.e.drive.models.FileObserver fileObserverObject; /* Lifecycle Methods */ @Override @@ -82,6 +85,16 @@ public class ObserverService extends Service implements OnRemoteOperationListene public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand("+startId+")"); + try { + Bundle bundle = intent.getExtras(); + if(null!=bundle){ + isFileObserverService = bundle.getBoolean("isFileObserverService"); + // fileObserverObject = (foundation.e.drive.models.FileObserver)CommonUtils.convertFromBytes(bundle.getByteArray("fileObserverObject")); + } + }catch (Exception ex){ + ex.printStackTrace(); + } + CommonUtils.setServiceUnCaughtExceptionHandler(this); SharedPreferences prefs = this.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); @@ -239,7 +252,24 @@ public class ObserverService extends Service implements OnRemoteOperationListene return; } } else { - scanLocalFiles(); + if(isFileObserverService){ + + // List files = fileObserverObject.getFiles(); + DbHelper.updateSyncedFolders(mSyncedFolders, this); //@ToDo: maybe do this when all contents will be synced. + + List syncedFileStates = DbHelper.getSyncedFileStatesByFolders(this, + getIdsFromFolderToScan()); + + if(!syncedFileStates.isEmpty() || !InitializerService.files.isEmpty() ) { + handleLocalFiles(InitializerService.files, syncedFileStates); + } + + // handleLocalFiles(fileObserverObject.getFiles(), fileObserverObject.getSyncedFileStatesList()); + + }else { + scanLocalFiles(); + } + } } @@ -529,7 +559,7 @@ public class ObserverService extends Service implements OnRemoteOperationListene * Prepare the list of files and SyncedFileState for synchronisation */ private void scanLocalFiles(){ - Log.i( TAG, "scanLocalFiles()" ); + List fileList = new ArrayList<>(); List folderIdList= new ArrayList<>(); boolean contentToSyncFound = false; @@ -619,6 +649,7 @@ public class ObserverService extends Service implements OnRemoteOperationListene if(contentToSyncFound) { DbHelper.updateSyncedFolders(mSyncedFolders, this); //@ToDo: maybe do this when all contents will be synced. + List syncedFileStates = DbHelper.getSyncedFileStatesByFolders(this, folderIdList); @@ -637,7 +668,6 @@ public class ObserverService extends Service implements OnRemoteOperationListene * @param syncedFileStates List of SyncedFileState to scan */ private void handleLocalFiles(List localFileList, List syncedFileStates ){ - Log.i(TAG, "handleLocalFiles()"); Log.d(TAG, "Loop through local file list"); Log.v(TAG, "format: filePath, exist, lastModified) :"); diff --git a/app/src/main/java/foundation/e/drive/utils/CommonUtils.java b/app/src/main/java/foundation/e/drive/utils/CommonUtils.java index 2d1c16e2075583f573ec17e3d5845d66938b3a93..98a9841bc5c894ba87c2e51e23e9297a9ee1a805 100644 --- a/app/src/main/java/foundation/e/drive/utils/CommonUtils.java +++ b/app/src/main/java/foundation/e/drive/utils/CommonUtils.java @@ -30,7 +30,12 @@ import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.resources.files.FileUtils; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import foundation.e.drive.receivers.ScreenOffReceiver; @@ -291,4 +296,26 @@ public abstract class CommonUtils { + "\n File can be read?: " + f.canRead() + "\n File can be written?: " + f.canWrite(); } + + /* + this function convert object to bytes + */ + public static byte[] convertToBytes(Object object) throws IOException { + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bos)) { + out.writeObject(object); + return bos.toByteArray(); + } + } + + /* + this function convert bytes to Object + */ + public static Object convertFromBytes(byte[] bytes) throws IOException, ClassNotFoundException { + try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); + ObjectInputStream in = new ObjectInputStream(bis)) { + return in.readObject(); + } + } + } \ No newline at end of file diff --git a/app/src/main/java/foundation/e/drive/utils/JobUtils.java b/app/src/main/java/foundation/e/drive/utils/JobUtils.java index 213b1e9ff70b78edde1c947021ebc21c79e94211..a33855fab8d86505128ebd34b4273c05cd63d082 100644 --- a/app/src/main/java/foundation/e/drive/utils/JobUtils.java +++ b/app/src/main/java/foundation/e/drive/utils/JobUtils.java @@ -32,23 +32,23 @@ public abstract class JobUtils { */ public static void scheduleScannerJob(Context context){ Log.i(TAG, "scheduleJob"); - Log.i(TAG, "scheduleJob task off"); + /* I. Start periodic checkup */ -// ComponentName jobService = new ComponentName( context, ScannerJob.class ); -// -// JobInfo job = new JobInfo.Builder(ScannerJobId, jobService ) -// .setPeriodic(1860000, 30000) //31git minutes and 30 secondes -// .setPersisted(true) -// .setRequiredNetworkType( JobInfo.NETWORK_TYPE_ANY ) -// .build(); -// -// JobScheduler jobScheduler = context.getSystemService( JobScheduler.class ); -// -// if ( jobScheduler.schedule( job ) == JobScheduler.RESULT_SUCCESS ) { -// Log.d(TAG, "Scheduled job created"); -// } else { -// Log.e(TAG, "Scheduled job not created"); -// } + ComponentName jobService = new ComponentName( context, ScannerJob.class ); + + JobInfo job = new JobInfo.Builder(ScannerJobId, jobService ) + .setPeriodic(7200000 , 30000) //2 hr + .setPersisted(true) + .setRequiredNetworkType( JobInfo.NETWORK_TYPE_ANY ) + .build(); + + JobScheduler jobScheduler = context.getSystemService( JobScheduler.class ); + + if ( jobScheduler.schedule( job ) == JobScheduler.RESULT_SUCCESS ) { + Log.d(TAG, "Scheduled job created"); + } else { + Log.e(TAG, "Scheduled job not created"); + } } /**