Loading README.md +9 −3 Original line number Diff line number Diff line Loading @@ -4,13 +4,19 @@ - Vincent (vincent.bourgmayer@eelo.io) - Frank ___ /!\ This is not the current version used in build. /!\ Please check "Settings" branch or "Apps" branch. /!\ ___ #### Actu: This branch has merged the apps branch. ___ /!\ This is not the current version used in build. /!\ Please check "Apps" branch or "Authentification" branch. /!\ ___ #### TODO: This is a list of thing to do: + Prevent failure due to service stopping, or internet connexion lost + Sync settings: only sync needed files + Sync settings + code cleaning and rewriting + Use Eelo Account instead of raw credentials app/build.gradle +5 −2 Original line number Diff line number Diff line Loading @@ -52,11 +52,14 @@ dependencies { implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.0.2' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:rules:1.0.2' androidTestImplementation 'com.android.support:support-annotations:27.1.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' implementation 'com.android.support:recyclerview-v7:26.1.0' compile 'com.github.nextcloud:android-library:1.0.40' compile('com.crashlytics.sdk.android:crashlytics:2.9.2@aar') { transitive = true; } compile 'com.android.support:support-annotations:27.1.1' } No newline at end of file app/src/androidTest/java/io/eelo/drive/ExampleInstrumentedTest.java +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ public class ExampleInstrumentedTest { // Context of the app under test. Context appContext = InstrumentationRegistry.getTargetContext(); assertEquals("io.eelo.drive", appContext.getPackageName()); } } app/src/main/AndroidManifest.xml +10 −14 Original line number Diff line number Diff line <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.eelo.drive" > android:sharedUserId="android.uid.system" > <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <!-- needed for PersistedJob --> <application android:allowBackup="true" Loading @@ -27,27 +25,25 @@ <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <service android:name=".jobs.CloudScannerJob" android:permission="android.permission.BIND_JOB_SERVICE" /> <service android:name=".jobs.LocalScannerJob" <activity android:name=".ui.SettingsActivity" android:label="Settings"> <intent-filter> <action android:name="android.intent.action.APPLICATION_PREFERENCES"/> <category android:name="android.intent.category.PREFERENCE"/> </intent-filter> </activity> <service android:name=".jobs.ScannerJob" android:permission="android.permission.BIND_JOB_SERVICE" /> <service android:name=".services.LocalObserverService" /> <service android:name=".services.RemoteObserverService"/> <service android:name=".services.ObserverService"/> <service android:name=".services.OperationManagerService"></service> <receiver android:name=".receivers.BatteryStateReceiver" android:enabled="true"> <intent-filter> <action android:name="android.intent.action.BATTERY_LOW"/> <action android:name="android.intent.action.BATTERY_OKAY"/> </intent-filter> </receiver> <meta-data android:name="preloaded_fonts" android:resource="@array/preloaded_fonts" /> <meta-data android:name="io.fabric.ApiKey" android:value="63e8fd2ffc15b7b187bd369a9c0535e9fe151e8a" /> Loading app/src/main/java/io/eelo/drive/database/DbHelper.java +81 −52 Original line number Diff line number Diff line package io.eelo.drive.database; import android.content.Context; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; Loading @@ -16,11 +17,13 @@ import io.eelo.drive.models.SyncedFileState; * Created by Vincent on 10/04/2018. * source: https://developer.android.com/training/data-storage/sqlite.html#java * https://vogella.developpez.com/tutoriels/android/utilisation-base-donnees-sqlite/ * * @TODO: rewrite it cleaner */ public class DbHelper extends SQLiteOpenHelper { public final class DbHelper extends SQLiteOpenHelper { final public static String TAG = DbHelper.class.getSimpleName(); //Tag for log public static final int DATABASE_VERSION = 8; public static final int DATABASE_VERSION = 13; public static final String DATABASE_NAME = "eelo_drive.db"; /** Loading @@ -32,11 +35,10 @@ public class DbHelper extends SQLiteOpenHelper { /** * Function to create a new DB. * @param db * @param db SQLiteDatabase object */ @Override public void onCreate(SQLiteDatabase db) { Log.i(TAG, "onCreate()"); db.execSQL(RootFolderContract.SQL_CREATE_TABLE_ROOTFOLDER); db.execSQL(SyncedFileStateContract.SQL_CREATE_TABLE_SYNCEDFILESTATE); } Loading @@ -44,18 +46,40 @@ public class DbHelper extends SQLiteOpenHelper { /** * Function to upgrade a DB. * Delete old Tables * @param db * @param oldVersion * @param newVersion * @param db SQLiteDatabase object * @param oldVersion Version number of the db to delete * @param newVersion Version number of the db to create */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.d(TAG, "onUpgrade()"); db.execSQL(RootFolderContract.SQL_DELETE_TABLE_ROOTFOLDER); db.execSQL(SyncedFileStateContract.SQL_DELETE_TABLE_SYNCEDFILESTATE); this.onCreate(db); } private static SyncedFileStateDAO openSyncedFileStateDAO(Context context, boolean writeMod){ SyncedFileStateDAO dao = new SyncedFileStateDAO(context); try{ dao.open(writeMod); }catch (Exception e){ Log.e(TAG, e.toString()); return null; } return dao; } private static RootFolderDAO openRootFolderDAO(Context context, boolean writeMod){ RootFolderDAO dao = new RootFolderDAO(context); try{ dao.open(writeMod); }catch(Exception e){ Log.e(TAG, e.toString() ); return null; } return dao; } /** * Insert, update or delete a new SyncedFileState in DB. Loading @@ -68,11 +92,9 @@ public class DbHelper extends SQLiteOpenHelper { Log.i(TAG, "manageSyncedFileStateDB()"); int result = -1; SyncedFileStateDAO dao = new SyncedFileStateDAO(context); try{ dao.open(true); }catch (Exception e){ Log.e(TAG, e.toString()); SyncedFileStateDAO dao = openSyncedFileStateDAO(context, true); if(dao == null){ return result; } if(action == "UPDATE") { Loading Loading @@ -101,13 +123,9 @@ public class DbHelper extends SQLiteOpenHelper { * @return instance of SyncedFileState or null if it can't open DB */ public static SyncedFileState loadSyncedFile(Context context, String Path, boolean useLocalPath) { Log.i( TAG, "loadSyncedFile("+Path+")" ); SyncedFileStateDAO dao = openSyncedFileStateDAO(context, false); SyncedFileStateDAO dao = new SyncedFileStateDAO( context ); try{ dao.open( false ); }catch ( Exception e ){ Log.e( TAG, e.toString() ); if(dao == null){ return null; } SyncedFileState syncedFileState = dao.getByPath(Path, useLocalPath); Loading @@ -118,24 +136,17 @@ public class DbHelper extends SQLiteOpenHelper { /** * get many synced file filtered on remote or local path * @param context calling context to get DAO * @param paths path of folder on which to filter syncedFileStates. Use parent path of the file * @param useLocalPath True if path is a local path, if it's false use remote path * @param ids List<String> id of root folders * @return null if DB opening failed, either return thelist of SyncedFileState */ public static List<SyncedFileState> getSyncedFileStatesByFolders(Context context, String[] paths, boolean useLocalPath) { Log.i( TAG, "getSyncedFileStatesByFolders("+paths+")" ); public static List<SyncedFileState> getSyncedFileStatesByFolders(Context context, List<Long> ids) {//Connect to DB SyncedFileStateDAO dao = openSyncedFileStateDAO(context, false); //Connect to DB SyncedFileStateDAO dao = new SyncedFileStateDAO( context ); try{ dao.open( false ); }catch ( Exception e ){ Log.e( TAG, e.toString() ); if(dao == null){ return null; } List<SyncedFileState> result = dao.getByParentPath(paths, useLocalPath); List<SyncedFileState> result = dao.getFilteredByRootFolderID(ids); dao.close(); return result; Loading @@ -143,26 +154,23 @@ public class DbHelper extends SQLiteOpenHelper { /** * Update array of rootFolder's row in DB * @TODO: handle failure of dao.update (...) * @param rootFolders RootFolder array to update * @param context * @return number of affected row. Return -1 if failed */ public static int updateRootFolders(RootFolder[] rootFolders, Context context){ Log.i(TAG, "updateRootFolder"); public static int updateRootFolders(List<RootFolder> rootFolders, Context context){ int result = -1; //Connect to DB RootFolderDAO dao = new RootFolderDAO(context); try{ dao.open(true); }catch(Exception e){ Log.e(TAG, e.toString() ); RootFolderDAO dao = openRootFolderDAO(context, true); if(dao == null){ return result; } //Execute queries for(int i = 0; i < rootFolders.length; ++i ){ result += dao.update( rootFolders[i] ); int rootFoldersSize = rootFolders.size(); for(int i = 0; i < rootFoldersSize; ++i ){ result += dao.update( rootFolders.get(i) ); } dao.close(); return result; Loading @@ -170,24 +178,45 @@ public class DbHelper extends SQLiteOpenHelper { /** * Load root path from DB * @param context * @param filter use either "SCANLOCAL" to get localy scannable folder either "SCANREMOTE" * to get remotly scanable folder or any other value to get "ENABLED" folder * @param filter_val param used in combination with filter. Allow to filter all those which * match the filter (if this is true) or all those which doesn't match the filter * @return List<RootFolder> a list of RootFolder from DB */ public static List<RootFolder> getRootFolders(Context context) { Log.i(TAG, "getRootFolders"); RootFolderDAO dao = new RootFolderDAO(context ); public static List<RootFolder> getRootFolders(Context context, String filter, boolean filter_val) { RootFolderDAO dao = openRootFolderDAO(context, false); List<RootFolder> mRootFolder = new ArrayList<RootFolder>(); try{ dao.open( false ); }catch ( Exception e ){ Log.e( TAG, e.toString() ); if(dao == null){ return mRootFolder; } mRootFolder = dao.getAllRootFolders(); Log.d( TAG, "rootFolder size : "+ mRootFolder.size() ); if( filter.equals("SCANLOCAL") ){ mRootFolder = dao.getAllRootFolders(RootFolderContract.SCANLOCAL, filter_val); } else if(filter.equals("SCANREMOTE")){ mRootFolder = dao.getAllRootFolders(RootFolderContract.SCANREMOTE, filter_val); }else { mRootFolder = dao.getAllRootFolders(RootFolderContract.ENABLED, filter_val); } dao.close(); return mRootFolder; } /** * Save new rootFolder into DB * @param mRootFolder The root Folder to insert * @param context The context of the app * @return the id of the root folder or -1 if it hasn't been inserted */ public static long insertRootFolder(RootFolder mRootFolder, Context context){ RootFolderDAO dao = openRootFolderDAO(context, true); if(dao == null){ return -1; } long id = dao.insert(mRootFolder); dao.close(); return id; } } Loading
README.md +9 −3 Original line number Diff line number Diff line Loading @@ -4,13 +4,19 @@ - Vincent (vincent.bourgmayer@eelo.io) - Frank ___ /!\ This is not the current version used in build. /!\ Please check "Settings" branch or "Apps" branch. /!\ ___ #### Actu: This branch has merged the apps branch. ___ /!\ This is not the current version used in build. /!\ Please check "Apps" branch or "Authentification" branch. /!\ ___ #### TODO: This is a list of thing to do: + Prevent failure due to service stopping, or internet connexion lost + Sync settings: only sync needed files + Sync settings + code cleaning and rewriting + Use Eelo Account instead of raw credentials
app/build.gradle +5 −2 Original line number Diff line number Diff line Loading @@ -52,11 +52,14 @@ dependencies { implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.0.2' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:rules:1.0.2' androidTestImplementation 'com.android.support:support-annotations:27.1.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' implementation 'com.android.support:recyclerview-v7:26.1.0' compile 'com.github.nextcloud:android-library:1.0.40' compile('com.crashlytics.sdk.android:crashlytics:2.9.2@aar') { transitive = true; } compile 'com.android.support:support-annotations:27.1.1' } No newline at end of file
app/src/androidTest/java/io/eelo/drive/ExampleInstrumentedTest.java +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ public class ExampleInstrumentedTest { // Context of the app under test. Context appContext = InstrumentationRegistry.getTargetContext(); assertEquals("io.eelo.drive", appContext.getPackageName()); } }
app/src/main/AndroidManifest.xml +10 −14 Original line number Diff line number Diff line <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.eelo.drive" > android:sharedUserId="android.uid.system" > <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <!-- needed for PersistedJob --> <application android:allowBackup="true" Loading @@ -27,27 +25,25 @@ <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <service android:name=".jobs.CloudScannerJob" android:permission="android.permission.BIND_JOB_SERVICE" /> <service android:name=".jobs.LocalScannerJob" <activity android:name=".ui.SettingsActivity" android:label="Settings"> <intent-filter> <action android:name="android.intent.action.APPLICATION_PREFERENCES"/> <category android:name="android.intent.category.PREFERENCE"/> </intent-filter> </activity> <service android:name=".jobs.ScannerJob" android:permission="android.permission.BIND_JOB_SERVICE" /> <service android:name=".services.LocalObserverService" /> <service android:name=".services.RemoteObserverService"/> <service android:name=".services.ObserverService"/> <service android:name=".services.OperationManagerService"></service> <receiver android:name=".receivers.BatteryStateReceiver" android:enabled="true"> <intent-filter> <action android:name="android.intent.action.BATTERY_LOW"/> <action android:name="android.intent.action.BATTERY_OKAY"/> </intent-filter> </receiver> <meta-data android:name="preloaded_fonts" android:resource="@array/preloaded_fonts" /> <meta-data android:name="io.fabric.ApiKey" android:value="63e8fd2ffc15b7b187bd369a9c0535e9fe151e8a" /> Loading
app/src/main/java/io/eelo/drive/database/DbHelper.java +81 −52 Original line number Diff line number Diff line package io.eelo.drive.database; import android.content.Context; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; Loading @@ -16,11 +17,13 @@ import io.eelo.drive.models.SyncedFileState; * Created by Vincent on 10/04/2018. * source: https://developer.android.com/training/data-storage/sqlite.html#java * https://vogella.developpez.com/tutoriels/android/utilisation-base-donnees-sqlite/ * * @TODO: rewrite it cleaner */ public class DbHelper extends SQLiteOpenHelper { public final class DbHelper extends SQLiteOpenHelper { final public static String TAG = DbHelper.class.getSimpleName(); //Tag for log public static final int DATABASE_VERSION = 8; public static final int DATABASE_VERSION = 13; public static final String DATABASE_NAME = "eelo_drive.db"; /** Loading @@ -32,11 +35,10 @@ public class DbHelper extends SQLiteOpenHelper { /** * Function to create a new DB. * @param db * @param db SQLiteDatabase object */ @Override public void onCreate(SQLiteDatabase db) { Log.i(TAG, "onCreate()"); db.execSQL(RootFolderContract.SQL_CREATE_TABLE_ROOTFOLDER); db.execSQL(SyncedFileStateContract.SQL_CREATE_TABLE_SYNCEDFILESTATE); } Loading @@ -44,18 +46,40 @@ public class DbHelper extends SQLiteOpenHelper { /** * Function to upgrade a DB. * Delete old Tables * @param db * @param oldVersion * @param newVersion * @param db SQLiteDatabase object * @param oldVersion Version number of the db to delete * @param newVersion Version number of the db to create */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.d(TAG, "onUpgrade()"); db.execSQL(RootFolderContract.SQL_DELETE_TABLE_ROOTFOLDER); db.execSQL(SyncedFileStateContract.SQL_DELETE_TABLE_SYNCEDFILESTATE); this.onCreate(db); } private static SyncedFileStateDAO openSyncedFileStateDAO(Context context, boolean writeMod){ SyncedFileStateDAO dao = new SyncedFileStateDAO(context); try{ dao.open(writeMod); }catch (Exception e){ Log.e(TAG, e.toString()); return null; } return dao; } private static RootFolderDAO openRootFolderDAO(Context context, boolean writeMod){ RootFolderDAO dao = new RootFolderDAO(context); try{ dao.open(writeMod); }catch(Exception e){ Log.e(TAG, e.toString() ); return null; } return dao; } /** * Insert, update or delete a new SyncedFileState in DB. Loading @@ -68,11 +92,9 @@ public class DbHelper extends SQLiteOpenHelper { Log.i(TAG, "manageSyncedFileStateDB()"); int result = -1; SyncedFileStateDAO dao = new SyncedFileStateDAO(context); try{ dao.open(true); }catch (Exception e){ Log.e(TAG, e.toString()); SyncedFileStateDAO dao = openSyncedFileStateDAO(context, true); if(dao == null){ return result; } if(action == "UPDATE") { Loading Loading @@ -101,13 +123,9 @@ public class DbHelper extends SQLiteOpenHelper { * @return instance of SyncedFileState or null if it can't open DB */ public static SyncedFileState loadSyncedFile(Context context, String Path, boolean useLocalPath) { Log.i( TAG, "loadSyncedFile("+Path+")" ); SyncedFileStateDAO dao = openSyncedFileStateDAO(context, false); SyncedFileStateDAO dao = new SyncedFileStateDAO( context ); try{ dao.open( false ); }catch ( Exception e ){ Log.e( TAG, e.toString() ); if(dao == null){ return null; } SyncedFileState syncedFileState = dao.getByPath(Path, useLocalPath); Loading @@ -118,24 +136,17 @@ public class DbHelper extends SQLiteOpenHelper { /** * get many synced file filtered on remote or local path * @param context calling context to get DAO * @param paths path of folder on which to filter syncedFileStates. Use parent path of the file * @param useLocalPath True if path is a local path, if it's false use remote path * @param ids List<String> id of root folders * @return null if DB opening failed, either return thelist of SyncedFileState */ public static List<SyncedFileState> getSyncedFileStatesByFolders(Context context, String[] paths, boolean useLocalPath) { Log.i( TAG, "getSyncedFileStatesByFolders("+paths+")" ); public static List<SyncedFileState> getSyncedFileStatesByFolders(Context context, List<Long> ids) {//Connect to DB SyncedFileStateDAO dao = openSyncedFileStateDAO(context, false); //Connect to DB SyncedFileStateDAO dao = new SyncedFileStateDAO( context ); try{ dao.open( false ); }catch ( Exception e ){ Log.e( TAG, e.toString() ); if(dao == null){ return null; } List<SyncedFileState> result = dao.getByParentPath(paths, useLocalPath); List<SyncedFileState> result = dao.getFilteredByRootFolderID(ids); dao.close(); return result; Loading @@ -143,26 +154,23 @@ public class DbHelper extends SQLiteOpenHelper { /** * Update array of rootFolder's row in DB * @TODO: handle failure of dao.update (...) * @param rootFolders RootFolder array to update * @param context * @return number of affected row. Return -1 if failed */ public static int updateRootFolders(RootFolder[] rootFolders, Context context){ Log.i(TAG, "updateRootFolder"); public static int updateRootFolders(List<RootFolder> rootFolders, Context context){ int result = -1; //Connect to DB RootFolderDAO dao = new RootFolderDAO(context); try{ dao.open(true); }catch(Exception e){ Log.e(TAG, e.toString() ); RootFolderDAO dao = openRootFolderDAO(context, true); if(dao == null){ return result; } //Execute queries for(int i = 0; i < rootFolders.length; ++i ){ result += dao.update( rootFolders[i] ); int rootFoldersSize = rootFolders.size(); for(int i = 0; i < rootFoldersSize; ++i ){ result += dao.update( rootFolders.get(i) ); } dao.close(); return result; Loading @@ -170,24 +178,45 @@ public class DbHelper extends SQLiteOpenHelper { /** * Load root path from DB * @param context * @param filter use either "SCANLOCAL" to get localy scannable folder either "SCANREMOTE" * to get remotly scanable folder or any other value to get "ENABLED" folder * @param filter_val param used in combination with filter. Allow to filter all those which * match the filter (if this is true) or all those which doesn't match the filter * @return List<RootFolder> a list of RootFolder from DB */ public static List<RootFolder> getRootFolders(Context context) { Log.i(TAG, "getRootFolders"); RootFolderDAO dao = new RootFolderDAO(context ); public static List<RootFolder> getRootFolders(Context context, String filter, boolean filter_val) { RootFolderDAO dao = openRootFolderDAO(context, false); List<RootFolder> mRootFolder = new ArrayList<RootFolder>(); try{ dao.open( false ); }catch ( Exception e ){ Log.e( TAG, e.toString() ); if(dao == null){ return mRootFolder; } mRootFolder = dao.getAllRootFolders(); Log.d( TAG, "rootFolder size : "+ mRootFolder.size() ); if( filter.equals("SCANLOCAL") ){ mRootFolder = dao.getAllRootFolders(RootFolderContract.SCANLOCAL, filter_val); } else if(filter.equals("SCANREMOTE")){ mRootFolder = dao.getAllRootFolders(RootFolderContract.SCANREMOTE, filter_val); }else { mRootFolder = dao.getAllRootFolders(RootFolderContract.ENABLED, filter_val); } dao.close(); return mRootFolder; } /** * Save new rootFolder into DB * @param mRootFolder The root Folder to insert * @param context The context of the app * @return the id of the root folder or -1 if it hasn't been inserted */ public static long insertRootFolder(RootFolder mRootFolder, Context context){ RootFolderDAO dao = openRootFolderDAO(context, true); if(dao == null){ return -1; } long id = dao.insert(mRootFolder); dao.close(); return id; } }