diff --git a/app/src/main/java/foundation/e/drive/FileObservers/FileEventListener.java b/app/src/main/java/foundation/e/drive/FileObservers/FileEventListener.java index 57c342c86c4eb6c08a1538774b2632be49a11b78..383f0d113c87e26fa3d445244bbbd84a63b6d781 100644 --- a/app/src/main/java/foundation/e/drive/FileObservers/FileEventListener.java +++ b/app/src/main/java/foundation/e/drive/FileObservers/FileEventListener.java @@ -15,6 +15,8 @@ import android.content.Context; import android.content.Intent; import android.os.FileObserver; +import androidx.annotation.NonNull; + import com.owncloud.android.lib.resources.files.FileUtils; import java.io.File; @@ -37,12 +39,12 @@ public class FileEventListener { private final Context appContext; private final SynchronizationServiceConnection serviceConnection = new SynchronizationServiceConnection(); - public FileEventListener(Context applicationContext) { + public FileEventListener(@NonNull Context applicationContext) { Timber.tag(FileEventListener.class.getSimpleName()); this.appContext = applicationContext; } - public void onEvent(int event, File file) { + public void onEvent(int event, @NonNull File file) { if (file.isHidden()) return; if (file.isDirectory()) { @@ -57,7 +59,7 @@ public class FileEventListener { * @param event the event mask. CLOSE_WRITE, DELETE & MOVE_SELF are handled * @param file the file concerned by the event */ - private void handleFileEvent(int event, File file) { + private void handleFileEvent(int event, @NonNull File file) { switch(event) { case FileObserver.CLOSE_WRITE: //todo it is called two times per file except if screenshot by example or take a picture handleFileCloseWrite(file); @@ -78,7 +80,7 @@ public class FileEventListener { * @param event FileEvent mask. CREATE, CLOSE_WRITE, DELETE, MOVE_SELF * @param dir directory concerned by file event */ - private void handleDirectoryEvent(int event, File dir) { + private void handleDirectoryEvent(int event, @NonNull File dir) { switch(event) { case FileObserver.CREATE: handleDirectoryCreate(dir); @@ -101,7 +103,7 @@ public class FileEventListener { * Send syncRequest to SynchronizationService * @param request */ - private void sendSyncRequestToSynchronizationService(SyncRequest request) { + private void sendSyncRequestToSynchronizationService(@NonNull SyncRequest request) { Timber.d("Sending a SyncRequest for %s", request.getSyncedFileState().getName()); if (serviceConnection.isBound()) { serviceConnection.getSynchronizationService().queueSyncRequest(request); @@ -116,7 +118,7 @@ public class FileEventListener { * if it's parent directory is already in the database * @param directory */ - private void handleDirectoryCreate(File directory) { + private void handleDirectoryCreate(@NonNull File directory) { Timber.d("handleDirectoryCreate( %s )",directory.getAbsolutePath()); final String parentPath = CommonUtils.getLocalPath(directory.getParentFile()); final SyncedFolder parentFolder = DbHelper.getSyncedFolderByLocalPath(parentPath, appContext); @@ -131,7 +133,7 @@ public class FileEventListener { * todo: check in which condition a directory can generate a close_write * @param directory */ - private void handleDirectoryCloseWrite(File directory) { + private void handleDirectoryCloseWrite(@NonNull File directory) { final String fileLocalPath = CommonUtils.getLocalPath(directory); Timber.d("handleDirectoryCloseWrite( %s )",fileLocalPath ); final SyncedFolder folder = DbHelper.getSyncedFolderByLocalPath(fileLocalPath, appContext); @@ -147,7 +149,7 @@ public class FileEventListener { * Handle a file deletion event for a directory * @param directory */ - private void handleDirectoryDelete(File directory) { + private void handleDirectoryDelete(@NonNull File directory) { final String fileLocalPath = CommonUtils.getLocalPath(directory); Timber.d("handleDirectoryDelete( %s )", fileLocalPath); SyncedFolder folder = DbHelper.getSyncedFolderByLocalPath(fileLocalPath, appContext); @@ -174,7 +176,7 @@ public class FileEventListener { * handle a file close_write event for a file which is not a directory * @param file */ - private void handleFileCloseWrite(File file) { + private void handleFileCloseWrite(@NonNull File file) { final String fileLocalPath = CommonUtils.getLocalPath(file); Timber.d("handleFileCloseWrite( %s )", fileLocalPath); SyncRequest request = null; @@ -217,7 +219,7 @@ public class FileEventListener { * Handle a file deletion event for a file which is not a directory * @param file */ - private void handleFileDelete(File file) { + private void handleFileDelete(@NonNull File file) { final String fileLocalPath = CommonUtils.getLocalPath(file); Timber.d("handleFileDelete( %s )",fileLocalPath); final SyncedFileState fileState = DbHelper.loadSyncedFile( appContext, fileLocalPath, true); diff --git a/app/src/main/java/foundation/e/drive/FileObservers/RecursiveFileObserver.java b/app/src/main/java/foundation/e/drive/FileObservers/RecursiveFileObserver.java index 612554c5d55f031655cfc396ec51fc3bcc220711..3095537c766e4f8ad4280296a45231be09ebfbc7 100644 --- a/app/src/main/java/foundation/e/drive/FileObservers/RecursiveFileObserver.java +++ b/app/src/main/java/foundation/e/drive/FileObservers/RecursiveFileObserver.java @@ -11,6 +11,9 @@ package foundation.e.drive.FileObservers; import android.content.Context; import android.os.FileObserver; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import java.io.File; import java.io.FileFilter; import java.util.HashMap; @@ -40,11 +43,11 @@ public class RecursiveFileObserver extends FileObserver { private int mask; private FileEventListener listener; - public RecursiveFileObserver(Context applicationContext, String path, FileEventListener listener) { + public RecursiveFileObserver(@NonNull Context applicationContext, @NonNull String path, @Nullable FileEventListener listener) { this(applicationContext, path, ALL_EVENTS, listener); } - public RecursiveFileObserver(Context applicationContext, String path, int mask, FileEventListener listener) { + public RecursiveFileObserver(@NonNull Context applicationContext, @NonNull String path, int mask, @Nullable FileEventListener listener) { super(path, mask); this.path = path; this.mask = mask | FileObserver.CREATE | FileObserver.DELETE_SELF; @@ -54,7 +57,7 @@ public class RecursiveFileObserver extends FileObserver { @Override - public void onEvent(int event, String path) { + public void onEvent(int event, @Nullable String path) { File file; if (path == null) { file = new File(this.path); @@ -66,7 +69,7 @@ public class RecursiveFileObserver extends FileObserver { } // protected to avoid SyntheticAccessor - protected void notify(int event, File file) { + protected void notify(int event, @NonNull File file) { if (listener != null) { listener.onEvent(event & FileObserver.ALL_EVENTS, file); } @@ -104,7 +107,7 @@ public class RecursiveFileObserver extends FileObserver { * Start watching a single file * @param path */ - protected void startWatching(String path) { + protected void startWatching(@NonNull String path) { synchronized (observers) { FileObserver observer = observers.remove(path); if (observer != null) { @@ -129,7 +132,7 @@ public class RecursiveFileObserver extends FileObserver { * Stop watching a single file * @param path */ - protected void stopWatching(String path) { + protected void stopWatching(@NonNull String path) { synchronized (observers) { FileObserver observer = observers.remove(path); if (observer != null) { @@ -151,7 +154,7 @@ public class RecursiveFileObserver extends FileObserver { } @Override - public void onEvent(int event, String path) { + public void onEvent(int event, @Nullable String path) { File file; if (path == null) { file = new File(filePath); diff --git a/app/src/main/java/foundation/e/drive/activity/AccountsActivity.java b/app/src/main/java/foundation/e/drive/activity/AccountsActivity.java index 2bbe883981e8e8c1ca85673f79527fad0ff41f85..9882a11d7728e0b5a40cf885c1361bb76c621b03 100644 --- a/app/src/main/java/foundation/e/drive/activity/AccountsActivity.java +++ b/app/src/main/java/foundation/e/drive/activity/AccountsActivity.java @@ -25,6 +25,7 @@ import android.net.Uri; import android.os.Bundle; import android.view.View; +import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; @@ -48,7 +49,7 @@ public class AccountsActivity extends AppCompatActivity { private ActivityAccountsBinding binding; @Override - protected void onCreate(Bundle savedInstanceState) { + protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Timber.tag(AccountsActivity.class.getSimpleName()); binding = ActivityAccountsBinding.inflate(getLayoutInflater()); diff --git a/app/src/main/java/foundation/e/drive/contentScanner/AbstractContentScanner.java b/app/src/main/java/foundation/e/drive/contentScanner/AbstractContentScanner.java index a84584dbf521259df2412863c5f2e9327f02359b..f2cce7457822f3b3b193a23c3fb10daf42e5ecf2 100644 --- a/app/src/main/java/foundation/e/drive/contentScanner/AbstractContentScanner.java +++ b/app/src/main/java/foundation/e/drive/contentScanner/AbstractContentScanner.java @@ -10,6 +10,7 @@ package foundation.e.drive.contentScanner; import android.content.Context; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.owncloud.android.lib.resources.files.FileUtils; @@ -35,7 +36,7 @@ public abstract class AbstractContentScanner { * @param context Context used to access Database, etc. * @param syncedFolders List of SyncedFolders */ - protected AbstractContentScanner(Context context, List syncedFolders) { + protected AbstractContentScanner(@NonNull Context context, @NonNull List syncedFolders) { syncRequests = new HashMap<>(); this.context = context; this.syncedFolders = syncedFolders; @@ -78,7 +79,8 @@ public abstract class AbstractContentScanner { * @param filePath path of the file for which we want a syncFolder * @return SyncedFolder instance if found or null */ - protected SyncedFolder getParentSyncedFolder(String filePath) { + @Nullable + protected SyncedFolder getParentSyncedFolder(@NonNull String filePath) { final String dirPath = filePath.substring(0, filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1); for (SyncedFolder syncedFolder : syncedFolders) { @@ -93,7 +95,7 @@ public abstract class AbstractContentScanner { * When a file doesn't exist anymore we remove it from device/cloud (depending of implementation) & from Database * @param fileState SyncedFileState for which we lack remote file */ - protected abstract void onMissingFile(SyncedFileState fileState); + protected abstract void onMissingFile(@NonNull SyncedFileState fileState); /** * A new file has been found @@ -101,7 +103,7 @@ public abstract class AbstractContentScanner { * - Create a syncRequest for it * @param file The new remote file */ - protected abstract void onNewFileFound(T file); + protected abstract void onNewFileFound(@NonNull T file); /** * A known file has been found @@ -109,7 +111,7 @@ public abstract class AbstractContentScanner { * @param file The remote file * @param fileState file's latest known state */ - protected abstract void onKnownFileFound(T file, SyncedFileState fileState); - protected abstract boolean isFileMatchingSyncedFileState(T file, SyncedFileState fileState); - protected abstract boolean isSyncedFolderParentOfFile(SyncedFolder syncedFolder, String dirPath); + protected abstract void onKnownFileFound(@NonNull T file, @NonNull SyncedFileState fileState); + protected abstract boolean isFileMatchingSyncedFileState(@NonNull T file, @NonNull SyncedFileState fileState); + protected abstract boolean isSyncedFolderParentOfFile(@NonNull SyncedFolder syncedFolder, @NonNull String dirPath); } diff --git a/app/src/main/java/foundation/e/drive/contentScanner/AbstractFileLister.java b/app/src/main/java/foundation/e/drive/contentScanner/AbstractFileLister.java index 1f4284cdc80a89c53f59f7aefdee4e1a523d5c59..0e45cdcdc6ea30967fd96977c05db5212487d9cb 100644 --- a/app/src/main/java/foundation/e/drive/contentScanner/AbstractFileLister.java +++ b/app/src/main/java/foundation/e/drive/contentScanner/AbstractFileLister.java @@ -10,6 +10,7 @@ package foundation.e.drive.contentScanner; import android.content.Context; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.owncloud.android.lib.resources.files.FileUtils; @@ -52,7 +53,11 @@ public abstract class AbstractFileLister { */ protected abstract boolean skipDirectory(@NonNull T currentDirectory, @NonNull SyncedFolder syncedFolder, @NonNull Context context); protected abstract boolean isDirectory(@NonNull T file); + + @Nullable protected abstract String getFileName(@NonNull T file); + + @NonNull protected abstract FolderLoader createFolderLoader(); protected abstract void updateSyncedFolder(@NonNull SyncedFolder syncedFolder,@NonNull T folder); @@ -62,6 +67,8 @@ public abstract class AbstractFileLister { * @param RemoteFile or File */ /* package */ interface FolderLoader { + + @NonNull FolderWrapper getFolderWrapper(); boolean load(@NonNull SyncedFolder folder); } @@ -176,6 +183,7 @@ public abstract class AbstractFileLister { * @param dirContent Content to sort * @return List of subfiles to scan or empty list if nothing */ + @NonNull private List sortContent(@NonNull ListIterator iterator, @NonNull SyncedFolder folder, List dirContent) { final List result = new ArrayList<>(); if (dirContent == null) return result; @@ -203,6 +211,7 @@ public abstract class AbstractFileLister { * List of file to scan * @return List or List is expected based on implementations */ + @NonNull public List getContentToScan() { return contentToScan; } @@ -211,6 +220,7 @@ public abstract class AbstractFileLister { * Share the list of syncedFolder's ID for syncedFolder which has content to scan * @return List of syncedFolder ids */ + @NonNull public List getSyncedFoldersId() { final List result = new ArrayList<>(); for (SyncedFolder folder : folders) { diff --git a/app/src/main/java/foundation/e/drive/contentScanner/FolderWrapper.java b/app/src/main/java/foundation/e/drive/contentScanner/FolderWrapper.java index a1a03caf3838a96df8d02f28229259f24c81bb1b..49a5ee37b32a3e2b59d5ef92f5b187847b348c75 100644 --- a/app/src/main/java/foundation/e/drive/contentScanner/FolderWrapper.java +++ b/app/src/main/java/foundation/e/drive/contentScanner/FolderWrapper.java @@ -48,6 +48,7 @@ public class FolderWrapper { * Get subfiles (including sub folder) of the current folder * @return Null if the directory is missing */ + @NonNull public List getContent() { return content; } diff --git a/app/src/main/java/foundation/e/drive/contentScanner/LocalContentScanner.java b/app/src/main/java/foundation/e/drive/contentScanner/LocalContentScanner.java index 65ad9d4e9c75fd6bc26c8288aa20810929bf3dd9..dbc5864c5bce4c3e17c7754ac2eb40865fdacf6f 100644 --- a/app/src/main/java/foundation/e/drive/contentScanner/LocalContentScanner.java +++ b/app/src/main/java/foundation/e/drive/contentScanner/LocalContentScanner.java @@ -9,6 +9,8 @@ package foundation.e.drive.contentScanner; import android.content.Context; +import androidx.annotation.NonNull; + import java.io.File; import java.util.List; @@ -27,13 +29,13 @@ import timber.log.Timber; */ public class LocalContentScanner extends AbstractContentScanner{ - public LocalContentScanner(Context context, List syncedFolders) { + public LocalContentScanner(@NonNull Context context, @NonNull List syncedFolders) { super(context, syncedFolders); Timber.tag(LocalContentScanner.class.getSimpleName()); } @Override - protected void onMissingFile(SyncedFileState fileState) { + protected void onMissingFile(@NonNull SyncedFileState fileState) { if (!fileState.hasBeenSynchronizedOnce()) return; final File file = new File(fileState.getLocalPath()); @@ -48,7 +50,7 @@ public class LocalContentScanner extends AbstractContentScanner{ } @Override - protected void onNewFileFound(File file) { + protected void onNewFileFound(@NonNull File file) { final String filePath = file.getAbsolutePath(); final SyncedFolder parentDir = getParentSyncedFolder(filePath); if (parentDir == null) return; @@ -70,7 +72,7 @@ public class LocalContentScanner extends AbstractContentScanner{ } @Override - protected void onKnownFileFound(File file, SyncedFileState fileState) { + protected void onKnownFileFound(@NonNull File file, @NonNull SyncedFileState fileState) { if (FileDiffUtils.getActionForFileDiff(file, fileState) == FileDiffUtils.Action.Upload) { Timber.d("Add upload SyncRequest for %s", file.getAbsolutePath()); syncRequests.put(fileState.getId(), new SyncRequest(fileState, SyncRequest.Type.UPLOAD)); @@ -78,12 +80,12 @@ public class LocalContentScanner extends AbstractContentScanner{ } @Override - protected boolean isSyncedFolderParentOfFile(SyncedFolder syncedFolder, String dirPath) { + protected boolean isSyncedFolderParentOfFile(@NonNull SyncedFolder syncedFolder, @NonNull String dirPath) { return syncedFolder.getLocalFolder().equals(dirPath); } @Override - protected boolean isFileMatchingSyncedFileState(File file, SyncedFileState fileState) { + protected boolean isFileMatchingSyncedFileState(@NonNull File file, @NonNull SyncedFileState fileState) { final String filePath = CommonUtils.getLocalPath(file); return fileState.getLocalPath().equals(filePath); } diff --git a/app/src/main/java/foundation/e/drive/contentScanner/LocalFileLister.java b/app/src/main/java/foundation/e/drive/contentScanner/LocalFileLister.java index 934718ac7b080f74c8071f780d9b40832df7fc59..36679f1b74a823c9e1bcdd583f61dcf5787b0fe5 100644 --- a/app/src/main/java/foundation/e/drive/contentScanner/LocalFileLister.java +++ b/app/src/main/java/foundation/e/drive/contentScanner/LocalFileLister.java @@ -10,6 +10,7 @@ package foundation.e.drive.contentScanner; import android.content.Context; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import java.io.File; @@ -56,11 +57,13 @@ public class LocalFileLister extends AbstractFileLister { } @Override + @Nullable protected String getFileName(@NonNull File file) { return file.getName(); } @Override + @NonNull protected LocalFolderLoader createFolderLoader() { return new LocalFolderLoader(); } @@ -75,6 +78,7 @@ public class LocalFileLister extends AbstractFileLister { private FolderWrapper folder; @Override + @NonNull public FolderWrapper getFolderWrapper() { return folder; } diff --git a/app/src/main/java/foundation/e/drive/contentScanner/RemoteContentScanner.java b/app/src/main/java/foundation/e/drive/contentScanner/RemoteContentScanner.java index 9ff7c18c5c58bacadae5b383a9e5c02a487c4b74..37b1ffc5883a8e58a6a7aadcc73938116238400e 100644 --- a/app/src/main/java/foundation/e/drive/contentScanner/RemoteContentScanner.java +++ b/app/src/main/java/foundation/e/drive/contentScanner/RemoteContentScanner.java @@ -12,6 +12,8 @@ import static foundation.e.drive.utils.FileDiffUtils.getActionForFileDiff; import android.content.Context; +import androidx.annotation.NonNull; + import com.owncloud.android.lib.resources.files.model.RemoteFile; import java.util.List; @@ -34,13 +36,13 @@ public class RemoteContentScanner extends AbstractContentScanner { /** * @param context Context used to access Database, etc. */ - public RemoteContentScanner(Context context, List syncedFolders) { + public RemoteContentScanner(@NonNull Context context, @NonNull List syncedFolders) { super(context, syncedFolders); Timber.tag(RemoteContentScanner.class.getSimpleName()); } @Override - protected void onKnownFileFound(RemoteFile file, SyncedFileState fileState) { + protected void onKnownFileFound(@NonNull RemoteFile file, @NonNull SyncedFileState fileState) { final FileDiffUtils.Action action = getActionForFileDiff(file, fileState); if (action == FileDiffUtils.Action.Download) { @@ -57,7 +59,7 @@ public class RemoteContentScanner extends AbstractContentScanner { } @Override - protected void onNewFileFound(RemoteFile file) { + protected void onNewFileFound(@NonNull RemoteFile file) { final String remoteFilePath = file.getRemotePath(); final SyncedFolder parentDir = getParentSyncedFolder(remoteFilePath); if (parentDir == null) return; @@ -81,7 +83,7 @@ public class RemoteContentScanner extends AbstractContentScanner { } @Override - protected void onMissingFile(SyncedFileState fileState) { + protected void onMissingFile(@NonNull SyncedFileState fileState) { if (!fileState.hasBeenSynchronizedOnce()) { return; } @@ -91,12 +93,12 @@ public class RemoteContentScanner extends AbstractContentScanner { } @Override - protected boolean isFileMatchingSyncedFileState(RemoteFile file, SyncedFileState fileState) { + protected boolean isFileMatchingSyncedFileState(@NonNull RemoteFile file, @NonNull SyncedFileState fileState) { return fileState.getRemotePath().equals(file.getRemotePath()); } @Override - protected boolean isSyncedFolderParentOfFile(SyncedFolder syncedFolder, String dirPath) { + protected boolean isSyncedFolderParentOfFile(@NonNull SyncedFolder syncedFolder, @NonNull String dirPath) { return syncedFolder.getRemoteFolder().equals(dirPath); } } diff --git a/app/src/main/java/foundation/e/drive/contentScanner/RemoteFileLister.java b/app/src/main/java/foundation/e/drive/contentScanner/RemoteFileLister.java index 960737dc65dd83bae8f8c50e4e0c6fee96671578..11b18281840d8fe8adfe688f83dd7b986c344148 100644 --- a/app/src/main/java/foundation/e/drive/contentScanner/RemoteFileLister.java +++ b/app/src/main/java/foundation/e/drive/contentScanner/RemoteFileLister.java @@ -10,6 +10,7 @@ package foundation.e.drive.contentScanner; import android.content.Context; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.owncloud.android.lib.common.OwnCloudClient; @@ -31,6 +32,7 @@ import foundation.e.drive.utils.CommonUtils; */ public class RemoteFileLister extends AbstractFileLister { // protected to avoid SyntheticAccessor + @NonNull protected OwnCloudClient client; public RemoteFileLister(@NonNull List directories, @NonNull OwnCloudClient client) { @@ -63,11 +65,13 @@ public class RemoteFileLister extends AbstractFileLister { } @Override + @Nullable protected String getFileName(@NonNull RemoteFile file) { return CommonUtils.getFileNameFromPath(file.getRemotePath()); } @Override + @NonNull protected RemoteFolderLoader createFolderLoader() { return new RemoteFolderLoader(); } @@ -122,12 +126,14 @@ public class RemoteFileLister extends AbstractFileLister { * @return RemoteOperationResult */ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + @NonNull public RemoteOperationResult readRemoteFolder(@NonNull String remotePath, @NonNull OwnCloudClient client) { final ReadFolderRemoteOperation operation = new ReadFolderRemoteOperation(remotePath); return operation.execute(client); } @Override + @NonNull public FolderWrapper getFolderWrapper() { return directory; } diff --git a/app/src/main/java/foundation/e/drive/database/DbHelper.java b/app/src/main/java/foundation/e/drive/database/DbHelper.java index edc336bbec9145de6a99f0787fb98a7c5afd5988..ae0b3033e59967516c2d6fc445f2a7fd95b29b78 100644 --- a/app/src/main/java/foundation/e/drive/database/DbHelper.java +++ b/app/src/main/java/foundation/e/drive/database/DbHelper.java @@ -14,6 +14,8 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import java.io.File; @@ -43,7 +45,7 @@ public final class DbHelper extends SQLiteOpenHelper { /** * Constructor of the helper */ - public DbHelper(Context context){ + public DbHelper(@NonNull Context context){ super(context, DATABASE_NAME, null, DATABASE_VERSION); Timber.tag(DbHelper.class.getSimpleName()); } @@ -53,7 +55,7 @@ public final class DbHelper extends SQLiteOpenHelper { * @param db SQLiteDatabase object */ @Override - public void onCreate(SQLiteDatabase db) { + public void onCreate(@NonNull SQLiteDatabase db) { db.execSQL(SyncedFolderContract.SQL_CREATE_TABLE_SYNCEDFOLDER); db.execSQL(SyncedFileStateContract.SQL_CREATE_TABLE_SYNCEDFILESTATE); } @@ -65,7 +67,7 @@ public final class DbHelper extends SQLiteOpenHelper { * @param newVersion Version number of the db to create */ @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + public void onUpgrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) { Timber.i("onUpgrade(db, %s, %s)",oldVersion, newVersion); try { if (oldVersion < 19) { @@ -87,7 +89,8 @@ public final class DbHelper extends SQLiteOpenHelper { } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - public static SyncedFileStateDAO openSyncedFileStateDAO(Context context, boolean writeMod) { + @Nullable + public static SyncedFileStateDAO openSyncedFileStateDAO(@NonNull Context context, boolean writeMod) { final SyncedFileStateDAO dao = new SyncedFileStateDAO(context); try { dao.open(writeMod); @@ -98,7 +101,8 @@ public final class DbHelper extends SQLiteOpenHelper { return dao; } - private static SyncedFolderDAO openSyncedFolderDAO(Context context, boolean writeMod){ + @Nullable + private static SyncedFolderDAO openSyncedFolderDAO(@NonNull Context context, boolean writeMod){ final SyncedFolderDAO dao = new SyncedFolderDAO(context); try { dao.open(writeMod); @@ -116,7 +120,7 @@ public final class DbHelper extends SQLiteOpenHelper { * @return int If it is an update or a delete then the function return the number of row affected * but if it is an insert then it return the id of the inserted data. */ - public static int manageSyncedFileStateDB(SyncedFileState syncedFileState, String action, Context context){ + public static int manageSyncedFileStateDB(@NonNull SyncedFileState syncedFileState, @NonNull String action, @NonNull Context context){ Timber.d("manageSyncedFileStateDB( %s, %s )", syncedFileState.getName(), action); int result = -1; final SyncedFileStateDAO dao = openSyncedFileStateDAO(context, true); @@ -141,7 +145,8 @@ public final class DbHelper extends SQLiteOpenHelper { * @param useLocalPath True if path is a local path, if it's false use remote path * @return instance of SyncedFileState or null if it can't open DB */ - public static SyncedFileState loadSyncedFile(Context context, String Path, boolean useLocalPath) { + @Nullable + public static SyncedFileState loadSyncedFile(@NonNull Context context, @NonNull String Path, boolean useLocalPath) { final SyncedFileStateDAO dao = openSyncedFileStateDAO(context, false); if (dao == null) { @@ -159,7 +164,8 @@ public final class DbHelper extends SQLiteOpenHelper { * @return empty list if DB opening failed, either return the list of SyncedFileState */ - public static List getSyncedFileStatesByFolders(Context context, List ids) {//Connect to DB + @NonNull + public static List getSyncedFileStatesByFolders(@NonNull Context context, @NonNull List ids) {//Connect to DB final SyncedFileStateDAO dao = openSyncedFileStateDAO(context, false); if (dao == null) { return new ArrayList<>(); @@ -175,7 +181,7 @@ public final class DbHelper extends SQLiteOpenHelper { * @param context appContext * @return number of affected row. Return -1 if failed */ - public static int updateSyncedFolders(List syncedFolders, Context context){ + public static int updateSyncedFolders(@NonNull List syncedFolders, @NonNull Context context){ int result = -1; @@ -193,7 +199,7 @@ public final class DbHelper extends SQLiteOpenHelper { } - public static int updateSyncedFolder(SyncedFolder syncedFolder, Context context) { + public static int updateSyncedFolder(@NonNull SyncedFolder syncedFolder, @NonNull Context context) { int result = -1; final SyncedFolderDAO dao = openSyncedFolderDAO(context, true); @@ -210,7 +216,8 @@ public final class DbHelper extends SQLiteOpenHelper { * @param context app or service activity * @return List a list of SyncedFolder from DB */ - public static List getAllSyncedFolders(Context context) { + @NonNull + public static List getAllSyncedFolders(@NonNull Context context) { final SyncedFolderDAO dao = openSyncedFolderDAO(context, false); List mSyncedFolder = new ArrayList(); if (dao == null) { @@ -222,7 +229,8 @@ public final class DbHelper extends SQLiteOpenHelper { } } - public static List getSyncedFolderList(Context context, boolean isMediaType) { + @NonNull + public static List getSyncedFolderList(@NonNull Context context, boolean isMediaType) { final SyncedFolderDAO dao = openSyncedFolderDAO(context, false); List mSyncedFolder = new ArrayList<>(); if (dao == null) { @@ -241,7 +249,7 @@ public final class DbHelper extends SQLiteOpenHelper { * @param context The context of the app * @return the id of the Synced folder or -1 if it hasn't been inserted */ - public static long insertSyncedFolder(SyncedFolder mSyncedFolder, Context context){ + public static long insertSyncedFolder(@NonNull SyncedFolder mSyncedFolder, @NonNull Context context){ final SyncedFolderDAO dao = openSyncedFolderDAO(context, true); if (dao == null) { return -2; @@ -257,7 +265,7 @@ public final class DbHelper extends SQLiteOpenHelper { * @param context Context of the app * @return int number of row affected */ - public static int deleteSyncedFolder(long id, Context context){ + public static int deleteSyncedFolder(long id, @NonNull Context context){ final SyncedFolderDAO dao = openSyncedFolderDAO(context, true); if (dao == null) { return -1; @@ -267,7 +275,8 @@ public final class DbHelper extends SQLiteOpenHelper { return result; } - public static SyncedFolder getSyncedFolderByLocalPath(String localPath, Context context){ + @Nullable + public static SyncedFolder getSyncedFolderByLocalPath(@NonNull String localPath, @NonNull Context context){ final SyncedFolderDAO dao = openSyncedFolderDAO(context, true); if (dao == null) { return null; @@ -284,7 +293,7 @@ public final class DbHelper extends SQLiteOpenHelper { * @param context context of the app * @return number of row affected */ - public static int forceFoldertoBeRescan(int syncedFolderId, Context context){ + public static int forceFoldertoBeRescan(int syncedFolderId, @NonNull Context context){ final SyncedFolderDAO dao = openSyncedFolderDAO(context, true); if (dao == null) { return -1; @@ -301,7 +310,7 @@ public final class DbHelper extends SQLiteOpenHelper { * @param context context * @return true if there is at least one file that need to be uploaded */ - public static boolean syncedFolderHasContentToUpload(long syncedFolderID, Context context) { + public static boolean syncedFolderHasContentToUpload(long syncedFolderID, @NonNull Context context) { boolean result = false; try { final SyncedFileStateDAO dao = openSyncedFileStateDAO(context, false); @@ -319,7 +328,7 @@ public final class DbHelper extends SQLiteOpenHelper { * @param context context * @return true if there is at least one file to download */ - public static boolean syncedFolderHasContentToDownload(int syncedFolderId, Context context) { + public static boolean syncedFolderHasContentToDownload(int syncedFolderId, @NonNull Context context) { boolean result = false; try { final SyncedFileStateDAO dao = openSyncedFileStateDAO(context, false); @@ -335,7 +344,7 @@ public final class DbHelper extends SQLiteOpenHelper { * Copy database file into user accessible directory for debuging purpose * @return path to the dump or null if failure */ - public static void dumpDatabase(Context context) { + public static void dumpDatabase(@NonNull Context context) { final File database = context.getDatabasePath(DbHelper.DATABASE_NAME); final File dstDir = context.getExternalFilesDir("DataBaseDump"); if (!dstDir.exists()) dstDir.mkdir(); @@ -362,7 +371,7 @@ public final class DbHelper extends SQLiteOpenHelper { * @param context * @throws SQLiteException if database can't be open */ - public static void cleanSyncedFileStateTableAfterUpdate(Context context) throws SQLiteException { + public static void cleanSyncedFileStateTableAfterUpdate(@NonNull Context context) throws SQLiteException { final SyncedFileStateDAO dao = openSyncedFileStateDAO(context, true); dao.deleteHiddenFileStates(); dao.updateUnscannableMediaFiles(); diff --git a/app/src/main/java/foundation/e/drive/database/FailedSyncPrefsManager.java b/app/src/main/java/foundation/e/drive/database/FailedSyncPrefsManager.java index b2d54e828dd224711dcd439cb6d60b53bd4e7d79..b16ac54618746c6429cb594122f255510743fb1e 100644 --- a/app/src/main/java/foundation/e/drive/database/FailedSyncPrefsManager.java +++ b/app/src/main/java/foundation/e/drive/database/FailedSyncPrefsManager.java @@ -11,6 +11,8 @@ package foundation.e.drive.database; import android.content.Context; import android.content.SharedPreferences; +import androidx.annotation.NonNull; + /** * @author vincent Bourgmayer */ @@ -24,7 +26,8 @@ public class FailedSyncPrefsManager { private SharedPreferences preferences; private FailedSyncPrefsManager() {}; - public static FailedSyncPrefsManager getInstance(Context context) { + @NonNull + public static FailedSyncPrefsManager getInstance(@NonNull Context context) { if (instance == null) { instance = new FailedSyncPrefsManager(); instance.preferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); @@ -62,10 +65,13 @@ public class FailedSyncPrefsManager { .remove(getFailureTimeKey(fileStateId)) .apply(); } + + @NonNull private String getFailureCounterKey(int fileStateId) { return fileStateId + FAILURE_COUNTER_KEY; } + @NonNull private String getFailureTimeKey(int fileStateId) { return fileStateId + FAILURE_TIME_KEY; } diff --git a/app/src/main/java/foundation/e/drive/database/SyncedFileStateDAO.java b/app/src/main/java/foundation/e/drive/database/SyncedFileStateDAO.java index 7f14da6521f9a8d10ab2498b310c2aaeec5aea06..9716201fae600d9baf4ae8d6af956b936a7d679a 100644 --- a/app/src/main/java/foundation/e/drive/database/SyncedFileStateDAO.java +++ b/app/src/main/java/foundation/e/drive/database/SyncedFileStateDAO.java @@ -9,32 +9,32 @@ package foundation.e.drive.database; +import static foundation.e.drive.database.SyncedFileStateContract.FILE_NAME; +import static foundation.e.drive.database.SyncedFileStateContract.IS_MEDIA_TYPE; +import static foundation.e.drive.database.SyncedFileStateContract.LAST_ETAG; +import static foundation.e.drive.database.SyncedFileStateContract.LOCAL_LAST_MODIFIED; +import static foundation.e.drive.database.SyncedFileStateContract.LOCAL_PATH; +import static foundation.e.drive.database.SyncedFileStateContract.REMOTE_PATH; +import static foundation.e.drive.database.SyncedFileStateContract.SCANNABLE; +import static foundation.e.drive.database.SyncedFileStateContract.SYNCEDFOLDER_ID; +import static foundation.e.drive.database.SyncedFileStateContract.TABLE_NAME; + import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; - import android.database.sqlite.SQLiteDoneException; import android.database.sqlite.SQLiteStatement; +import androidx.annotation.NonNull; + import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import foundation.e.drive.models.SyncedFileState; import timber.log.Timber; -import static foundation.e.drive.database.SyncedFileStateContract.SCANNABLE; -import static foundation.e.drive.database.SyncedFileStateContract.TABLE_NAME; -import static foundation.e.drive.database.SyncedFileStateContract.FILE_NAME; -import static foundation.e.drive.database.SyncedFileStateContract.IS_MEDIA_TYPE; -import static foundation.e.drive.database.SyncedFileStateContract.LAST_ETAG; -import static foundation.e.drive.database.SyncedFileStateContract.LOCAL_LAST_MODIFIED; -import static foundation.e.drive.database.SyncedFileStateContract.LOCAL_PATH; -import static foundation.e.drive.database.SyncedFileStateContract.REMOTE_PATH; -import static foundation.e.drive.database.SyncedFileStateContract.SYNCEDFOLDER_ID; - /** * @author Vincent Bourgmayer * Offers Query to CRUD operation for SyncedFIleState Object @@ -54,7 +54,7 @@ import static foundation.e.drive.database.SyncedFileStateContract.SYNCEDFOLDER_I }; - /* package */ SyncedFileStateDAO(Context context){ + /* package */ SyncedFileStateDAO(@NonNull Context context){ mHelper = new DbHelper(context); Timber.tag(SyncedFileStateDAO.class.getSimpleName()); } diff --git a/app/src/main/java/foundation/e/drive/database/SyncedFolderDAO.java b/app/src/main/java/foundation/e/drive/database/SyncedFolderDAO.java index c026ade58d13c7e355ae07bb0d6099a6985571e0..48b571ba25210dbf7dc335448a4b9abdf5a615ab 100644 --- a/app/src/main/java/foundation/e/drive/database/SyncedFolderDAO.java +++ b/app/src/main/java/foundation/e/drive/database/SyncedFolderDAO.java @@ -9,30 +9,33 @@ package foundation.e.drive.database; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.SQLException; -import android.database.sqlite.SQLiteDatabase; -import java.util.ArrayList; -import java.util.List; - -import foundation.e.drive.models.SyncedFolder; -import timber.log.Timber; - import static foundation.e.drive.database.SyncedFolderContract.CATEGORIE_LABEL; import static foundation.e.drive.database.SyncedFolderContract.ENABLED; +import static foundation.e.drive.database.SyncedFolderContract.IS_MEDIA_TYPE; import static foundation.e.drive.database.SyncedFolderContract.LAST_ETAG; import static foundation.e.drive.database.SyncedFolderContract.LOCAL_LAST_MODIFIED; import static foundation.e.drive.database.SyncedFolderContract.LOCAL_PATH; import static foundation.e.drive.database.SyncedFolderContract.REMOTE_PATH; import static foundation.e.drive.database.SyncedFolderContract.SCANLOCAL; import static foundation.e.drive.database.SyncedFolderContract.SCANREMOTE; -import static foundation.e.drive.database.SyncedFolderContract.IS_MEDIA_TYPE; import static foundation.e.drive.database.SyncedFolderContract.TABLE_NAME; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.SQLException; +import android.database.sqlite.SQLiteDatabase; + +import androidx.annotation.NonNull; + import com.owncloud.android.lib.resources.files.FileUtils; +import java.util.ArrayList; +import java.util.List; + +import foundation.e.drive.models.SyncedFolder; +import timber.log.Timber; + /** * @author Vincent Bourgmayer * Source: https://vogella.developpez.com/tutoriels/android/utilisation-base-donnees-sqlite/ @@ -52,7 +55,7 @@ import com.owncloud.android.lib.resources.files.FileUtils; IS_MEDIA_TYPE }; - /* package */ SyncedFolderDAO(Context context){ + /* package */ SyncedFolderDAO(@NonNull Context context){ Timber.tag(SyncedFolderDAO.class.getSimpleName()); this.mHelper = new DbHelper(context); } diff --git a/app/src/main/java/foundation/e/drive/fileFilters/CrashlogsFileFilter.java b/app/src/main/java/foundation/e/drive/fileFilters/CrashlogsFileFilter.java index 28d310797312feb122868f59fe19a184396a2778..6f28fddc676678d23811123d12a6ec5d26875f82 100644 --- a/app/src/main/java/foundation/e/drive/fileFilters/CrashlogsFileFilter.java +++ b/app/src/main/java/foundation/e/drive/fileFilters/CrashlogsFileFilter.java @@ -9,6 +9,8 @@ package foundation.e.drive.fileFilters; +import androidx.annotation.NonNull; + import java.io.File; import java.io.FileFilter; @@ -21,7 +23,7 @@ public class CrashlogsFileFilter implements FileFilter { private final static long max_timestamp_delta = 864000000; //10 days in ms (240*3600*1000) @Override - public boolean accept(File pathname) { + public boolean accept(@NonNull File pathname) { String fileTimestamp = extractTimestamp(pathname.getName(), ServiceExceptionHandler.LOG_FILE_NAME_PREFIX, ServiceExceptionHandler.LOG_FILE_EXTENSION); @@ -47,7 +49,7 @@ public class CrashlogsFileFilter implements FileFilter { * @param extension extension to ignore * @return the timestamp extracted from the name */ - private String extractTimestamp(String fileName, String prefix, String extension){ + private String extractTimestamp(String fileName, @NonNull String prefix, @NonNull String extension){ return fileName.substring(prefix.length(), (fileName.length() - extension.length())); } diff --git a/app/src/main/java/foundation/e/drive/fileFilters/FileFilterFactory.java b/app/src/main/java/foundation/e/drive/fileFilters/FileFilterFactory.java index b62ffd6d9fab3886f82575e5f224fa04e588ed51..f015396523da9e6119345778fdab92d2a7cf50e2 100644 --- a/app/src/main/java/foundation/e/drive/fileFilters/FileFilterFactory.java +++ b/app/src/main/java/foundation/e/drive/fileFilters/FileFilterFactory.java @@ -9,15 +9,19 @@ package foundation.e.drive.fileFilters; +import androidx.annotation.NonNull; + import java.io.FileFilter; /** * @author Vincent Bourgmayer */ public class FileFilterFactory { - public static FileFilter getFileFilter(String categorie){ + + @NonNull + public static FileFilter getFileFilter(@NonNull String category){ FileFilter filter; - switch (categorie){ + switch (category){ case "Rom settings": filter = new SettingsFileFilter(); break; diff --git a/app/src/main/java/foundation/e/drive/fileFilters/OnlyFileFilter.java b/app/src/main/java/foundation/e/drive/fileFilters/OnlyFileFilter.java index e5102f361afc43d75b9c3da60e8ef1e55075f4b9..a5b4b32dedeebcc9d15c22c4e4da059dfac54d99 100644 --- a/app/src/main/java/foundation/e/drive/fileFilters/OnlyFileFilter.java +++ b/app/src/main/java/foundation/e/drive/fileFilters/OnlyFileFilter.java @@ -9,6 +9,8 @@ package foundation.e.drive.fileFilters; +import androidx.annotation.NonNull; + import java.io.File; import java.io.FileFilter; @@ -17,7 +19,7 @@ import java.io.FileFilter; */ public class OnlyFileFilter implements FileFilter { @Override - public boolean accept(File pathname) { + public boolean accept(@NonNull File pathname) { return (!pathname.isDirectory()); } } diff --git a/app/src/main/java/foundation/e/drive/models/DownloadRequest.java b/app/src/main/java/foundation/e/drive/models/DownloadRequest.java index 612882ae59c5eecffb60ccc137a2836e18073e60..5cfa450512bccd87d04e7e78723297576f438cf1 100644 --- a/app/src/main/java/foundation/e/drive/models/DownloadRequest.java +++ b/app/src/main/java/foundation/e/drive/models/DownloadRequest.java @@ -7,6 +7,8 @@ */ package foundation.e.drive.models; +import androidx.annotation.NonNull; + import com.owncloud.android.lib.resources.files.model.RemoteFile; /** @@ -15,11 +17,12 @@ import com.owncloud.android.lib.resources.files.model.RemoteFile; public class DownloadRequest extends SyncRequest { private final RemoteFile remoteFile; - public DownloadRequest (RemoteFile remoteFile, SyncedFileState syncedFileState) { + public DownloadRequest (@NonNull RemoteFile remoteFile, @NonNull SyncedFileState syncedFileState) { super(syncedFileState, Type.DOWNLOAD); this.remoteFile = remoteFile; } + @NonNull public RemoteFile getRemoteFile() { return remoteFile; } diff --git a/app/src/main/java/foundation/e/drive/models/SyncRequest.java b/app/src/main/java/foundation/e/drive/models/SyncRequest.java index 29bab6b9f2c52f20b2edf7eec51ec9fb2c7c60fe..239217d17c2639ec51ae3b2f05a434886f1aa3e5 100644 --- a/app/src/main/java/foundation/e/drive/models/SyncRequest.java +++ b/app/src/main/java/foundation/e/drive/models/SyncRequest.java @@ -7,6 +7,7 @@ */ package foundation.e.drive.models; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; public class SyncRequest { @@ -16,15 +17,17 @@ public class SyncRequest { private final Type operationType; - public SyncRequest(SyncedFileState syncedFileState, Type operationType) { + public SyncRequest(@NonNull SyncedFileState syncedFileState, @NonNull Type operationType) { this.syncedFileState = syncedFileState; this.operationType = operationType; } + @NonNull public Type getOperationType() { return operationType; } + @NonNull public SyncedFileState getSyncedFileState() { return syncedFileState; } diff --git a/app/src/main/java/foundation/e/drive/models/SyncWrapper.java b/app/src/main/java/foundation/e/drive/models/SyncWrapper.java index 6cae2050bc3e510bc12cadbdf9d5e357ef6d8c41..da3c2da533031b9d3b905b992ccecb69a2d7fb0c 100644 --- a/app/src/main/java/foundation/e/drive/models/SyncWrapper.java +++ b/app/src/main/java/foundation/e/drive/models/SyncWrapper.java @@ -10,6 +10,9 @@ package foundation.e.drive.models; import android.accounts.Account; import android.content.Context; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.owncloud.android.lib.common.operations.RemoteOperation; @@ -32,12 +35,13 @@ public class SyncWrapper { * @param request SyncRequest at origin of the file transfer * @param context Application context, used to create RemoteOperation to run */ - public SyncWrapper(final SyncRequest request, final Account account, final Context context) { + public SyncWrapper(@NonNull final SyncRequest request, @Nullable final Account account, @NonNull final Context context) { this.request = request; remoteOperation = createRemoteOperation(request, account, context); isRunning = true; } + @Nullable public RemoteOperation getRemoteOperation() { return remoteOperation; } @@ -80,7 +84,7 @@ public class SyncWrapper { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj instanceof SyncRequest) { final SyncRequest objRequest = (SyncRequest) obj; return (objRequest.equals(this.request)); @@ -88,6 +92,7 @@ public class SyncWrapper { return super.equals(obj); } + @NonNull public SyncRequest getRequest() { return request; } 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 952fafbe3956a313aaf09711f2cbe9dc603046a9..0c07ddc9b629ed5827de49edcbaa2efaca2ddd25 100644 --- a/app/src/main/java/foundation/e/drive/models/SyncedFileState.java +++ b/app/src/main/java/foundation/e/drive/models/SyncedFileState.java @@ -12,6 +12,9 @@ package foundation.e.drive.models; import android.os.Parcel; import android.os.Parcelable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + /** * @author Vincent Bourgmayer * Describe a file state which will be Synchronized (= Synced) or which has already been synced one times @@ -49,7 +52,7 @@ public class SyncedFileState implements Parcelable { * @param lastModified Last modified time where local file has changed * @param isMediaType true if its sync as medias or as device/app' settings. */ - public SyncedFileState(int id, String name, String localPath, String remotePath, String etag, long lastModified, long syncedFolderId, boolean isMediaType, int scannable){ + public SyncedFileState(int id, @Nullable String name, @Nullable String localPath, @Nullable String remotePath, @Nullable String etag, long lastModified, long syncedFolderId, boolean isMediaType, int scannable){ this.id = id; this.name = name; this.localPath = localPath; @@ -61,7 +64,7 @@ public class SyncedFileState implements Parcelable { this.scannable = scannable; } - protected SyncedFileState(Parcel in) { + protected SyncedFileState(@NonNull Parcel in) { id = in.readInt(); name = in.readString(); localPath = in.readString(); @@ -74,7 +77,7 @@ public class SyncedFileState implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(id); dest.writeString(name); dest.writeString(localPath); @@ -102,28 +105,34 @@ public class SyncedFileState implements Parcelable { return id; } + @NonNull public SyncedFileState setId(int id) { this.id = id; return this; } + @Nullable public String getName() { return name; } + @Nullable public String getLocalPath() { return localPath; } + @Nullable public String getRemotePath() { return remotePath; } + @Nullable public String getLastETAG() { return lastETAG; } - public SyncedFileState setLastETAG(String lastETAG) { + @NonNull + public SyncedFileState setLastETAG(@Nullable String lastETAG) { this.lastETAG = lastETAG; return this; } @@ -136,6 +145,7 @@ public class SyncedFileState implements Parcelable { return localLastModified; } + @NonNull public SyncedFileState setLocalLastModified(long localLastModified) { this.localLastModified = localLastModified; return this; diff --git a/app/src/main/java/foundation/e/drive/models/SyncedFolder.java b/app/src/main/java/foundation/e/drive/models/SyncedFolder.java index 21cebb9a9c80634e2f920a93f1770f8e0347a12b..ff99e91d6a45a989e2da59e4be9e5b224c58ba3e 100644 --- a/app/src/main/java/foundation/e/drive/models/SyncedFolder.java +++ b/app/src/main/java/foundation/e/drive/models/SyncedFolder.java @@ -12,6 +12,9 @@ package foundation.e.drive.models; import android.os.Parcel; import android.os.Parcelable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + /** * @author Vincent Bourgmayer * This class encapsulates the representation of a synced or syncable folder. @@ -38,7 +41,7 @@ public class SyncedFolder implements Parcelable { * @param remoteFolder path of the folder on server * @param isMediaType If this folder is a media's folder (true) or a settings's folder (false) */ - public SyncedFolder(String libelle, String localFolder, String remoteFolder, boolean isMediaType){ + public SyncedFolder(@Nullable String libelle, @NonNull String localFolder, @NonNull String remoteFolder, boolean isMediaType){ this.enabled = true; this.scanLocal = true; this.scanRemote = true; @@ -58,7 +61,7 @@ public class SyncedFolder implements Parcelable { * @param enabled If this folder is available for synchronisation * @param isMediaType If this folder is a media's folder (true) or a settings's folder (false) */ - public SyncedFolder(String libelle, String localFolder, String remoteFolder, boolean scanLocal, boolean scanRemote, boolean enabled, boolean isMediaType){ + public SyncedFolder(@Nullable String libelle, @NonNull String localFolder, @NonNull String remoteFolder, boolean scanLocal, boolean scanRemote, boolean enabled, boolean isMediaType){ this.libelle = libelle; this.localFolder = localFolder; this.remoteFolder = remoteFolder; @@ -73,7 +76,7 @@ public class SyncedFolder implements Parcelable { * @param in The parcel containing data to build the object */ // protected to avoid SyntheticAccessor - protected SyncedFolder(Parcel in){ + protected SyncedFolder(@NonNull Parcel in){ this.id = in.readInt(); this.libelle = in.readString(); this.localFolder = in.readString(); @@ -94,7 +97,7 @@ public class SyncedFolder implements Parcelable { * @param lastModified LastModified value of the current local folder (must be 0L if not known) * @param lastEtag Last etag of remote folder (must be empty string if not known) */ - public SyncedFolder(SyncedFolder parent, String suffixPath, long lastModified, String lastEtag){ + public SyncedFolder(@NonNull SyncedFolder parent, @NonNull String suffixPath, long lastModified, @Nullable String lastEtag){ this.id = -1; this.libelle = parent.libelle; this.localFolder = parent.localFolder+suffixPath; @@ -121,14 +124,17 @@ public class SyncedFolder implements Parcelable { } }; + @Nullable public String getLibelle() { return libelle; } + @NonNull public String getLocalFolder() { return localFolder; } + @NonNull public String getRemoteFolder() { return remoteFolder; } @@ -137,6 +143,7 @@ public class SyncedFolder implements Parcelable { return enabled; } + @NonNull public SyncedFolder setEnabled(boolean enabled) { this.enabled = enabled; return this; @@ -146,16 +153,19 @@ public class SyncedFolder implements Parcelable { return id; } + @NonNull public SyncedFolder setId(int id) { this.id = id; return this; } + @Nullable public String getLastEtag() { return lastEtag; } - public SyncedFolder setLastEtag(String lastEtag) { + @NonNull + public SyncedFolder setLastEtag(@Nullable String lastEtag) { this.lastEtag = lastEtag; return this; } @@ -164,6 +174,7 @@ public class SyncedFolder implements Parcelable { return lastModified; } + @NonNull public SyncedFolder setLastModified(long lastModified) { this.lastModified = lastModified; return this; @@ -184,6 +195,7 @@ public class SyncedFolder implements Parcelable { * @param toSync True to sync files in this syncedFolder * @return calling instance */ + @NonNull public SyncedFolder setToSync(boolean toSync) { this.toSync = toSync; return this; @@ -211,7 +223,7 @@ public class SyncedFolder implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(this.id); dest.writeString(this.libelle); dest.writeString(this.localFolder); diff --git a/app/src/main/java/foundation/e/drive/operations/DownloadFileOperation.java b/app/src/main/java/foundation/e/drive/operations/DownloadFileOperation.java index 654fde1d8bd4d60fd5d4f090dee4a4ba89420f9c..8e14753622bd0c50761fa3c50d1a555f3650db91 100644 --- a/app/src/main/java/foundation/e/drive/operations/DownloadFileOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/DownloadFileOperation.java @@ -17,6 +17,9 @@ import static com.owncloud.android.lib.common.operations.RemoteOperationResult.R import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import android.content.Context; + +import androidx.annotation.NonNull; + import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -51,7 +54,7 @@ public class DownloadFileOperation extends RemoteOperation { * @param remoteFile remote file to Download * @param syncedFileState SyncedFileState corresponding to remote file */ - public DownloadFileOperation(RemoteFile remoteFile, SyncedFileState syncedFileState, Context context) { + public DownloadFileOperation(@NonNull RemoteFile remoteFile, @NonNull SyncedFileState syncedFileState, @NonNull Context context) { Timber.tag(DownloadFileOperation.class.getSimpleName()); this.remoteFile = remoteFile; this.syncedFileState = syncedFileState; @@ -61,7 +64,8 @@ public class DownloadFileOperation extends RemoteOperation { } @Override - protected RemoteOperationResult run(OwnCloudClient ownCloudClient) { + @NonNull + protected RemoteOperationResult run(@NonNull OwnCloudClient ownCloudClient) { Timber.v( "run() for %s", remoteFile.getRemotePath()); if (syncedFileState.getId() == -1) { this.syncedFileState.setId(DbHelper.manageSyncedFileStateDB(this.syncedFileState, "INSERT", context)); diff --git a/app/src/main/java/foundation/e/drive/operations/GetAliasOperation.java b/app/src/main/java/foundation/e/drive/operations/GetAliasOperation.java index 0602b6e27ccf9f521aa1b0ab75c29b297fb018a8..e1de65d557ce65206645d21e0d29fbd8bd1cbfba 100644 --- a/app/src/main/java/foundation/e/drive/operations/GetAliasOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/GetAliasOperation.java @@ -8,6 +8,9 @@ package foundation.e.drive.operations; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -42,12 +45,13 @@ public class GetAliasOperation extends RemoteOperation> { return (status == HttpStatus.SC_OK); } - public GetAliasOperation(String id) { + public GetAliasOperation(@NonNull String id) { mID = id; } @Override - protected RemoteOperationResult> run(OwnCloudClient client) { + @NonNull + protected RemoteOperationResult> run(@NonNull OwnCloudClient client) { RemoteOperationResult> result; GetMethod get = null; final String uri = client.getBaseUri() + ALIAS_PATH + mID; @@ -87,8 +91,8 @@ public class GetAliasOperation extends RemoteOperation> { return result; } - - public JSONArray parseResponse(String response) { + @Nullable + public JSONArray parseResponse(@NonNull String response) { JSONArray result = null; try { final JSONObject jsonResponse= new JSONObject(response).optJSONObject(NODE_OCS); diff --git a/app/src/main/java/foundation/e/drive/operations/ListFileRemoteOperation.java b/app/src/main/java/foundation/e/drive/operations/ListFileRemoteOperation.java index 627f31ff87de57fbdd3644fb695310d25ff7a0fb..c5aa5ec6f617a00d2fe3292224672590eda41e18 100644 --- a/app/src/main/java/foundation/e/drive/operations/ListFileRemoteOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/ListFileRemoteOperation.java @@ -11,6 +11,7 @@ package foundation.e.drive.operations; import android.content.Context; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.owncloud.android.lib.common.OwnCloudClient; @@ -41,7 +42,7 @@ public class ListFileRemoteOperation extends RemoteOperation updatedSyncedFoldersId; - public ListFileRemoteOperation(List syncedFolders, Context context) { + public ListFileRemoteOperation(@NonNull List syncedFolders, @NonNull Context context) { Timber.tag(ListFileRemoteOperation.class.getSimpleName()); this.syncedFolders = syncedFolders; this.context = context; @@ -54,7 +55,8 @@ public class ListFileRemoteOperation extends RemoteOperation> run(OwnCloudClient ownCloudClient) { + @NonNull + protected RemoteOperationResult> run(@NonNull OwnCloudClient ownCloudClient) { final RemoteFileLister fileLister = new RemoteFileLister(syncedFolders, ownCloudClient); final boolean isContentToScan = fileLister.listContentToScan(context); @@ -70,8 +72,9 @@ public class ListFileRemoteOperation extends RemoteOperation getSyncedFoldersId(){ + */ + @NonNull + public List getSyncedFoldersId(){ return this.updatedSyncedFoldersId; } } diff --git a/app/src/main/java/foundation/e/drive/operations/RemoveFileOperation.java b/app/src/main/java/foundation/e/drive/operations/RemoveFileOperation.java index 29b0d0a9df3b4f0d41772f615c18464ed17e8556..b20a048cc318923d94f4af46384605d565effddf 100644 --- a/app/src/main/java/foundation/e/drive/operations/RemoveFileOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/RemoveFileOperation.java @@ -9,6 +9,8 @@ package foundation.e.drive.operations; +import androidx.annotation.NonNull; + import com.owncloud.android.lib.resources.files.RemoveFileRemoteOperation; import foundation.e.drive.models.SyncedFileState; @@ -20,13 +22,14 @@ import foundation.e.drive.models.SyncedFileState; */ public class RemoveFileOperation extends RemoveFileRemoteOperation { - private SyncedFileState syncedFileState; + private final SyncedFileState syncedFileState; - public RemoveFileOperation(SyncedFileState syncedFileState) { + public RemoveFileOperation(@NonNull SyncedFileState syncedFileState) { super(syncedFileState.getRemotePath()); this.syncedFileState = syncedFileState; } + @NonNull public SyncedFileState getSyncedFileState() { return syncedFileState; } 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 caa1874b3373270ff86de13b87958f88b8496f1b..321df21a1afc1994eec641939d0cd671ab5eaaee 100644 --- a/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java @@ -12,6 +12,8 @@ package foundation.e.drive.operations; import android.accounts.Account; import android.content.Context; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.nextcloud.common.NextcloudClient; @@ -51,7 +53,7 @@ public class UploadFileOperation extends RemoteOperation { * Construct an upload operation with an already known syncedFileState * @param syncedFileState syncedFileState corresponding to file. */ - public UploadFileOperation (final SyncedFileState syncedFileState, final Account account, final Context context) { + public UploadFileOperation (@NonNull final SyncedFileState syncedFileState, @Nullable final Account account, @NonNull final Context context) { Timber.tag(UploadFileOperation.class.getSimpleName()); this.syncedState = syncedFileState; this.context = context; @@ -70,7 +72,8 @@ public class UploadFileOperation extends RemoteOperation { * hasn't change since last update or "forbidden" if no remote path can be fetch. */ @Override - protected RemoteOperationResult run(OwnCloudClient client ) { + @NonNull + protected RemoteOperationResult run(@NonNull OwnCloudClient client ) { final File file = new File(syncedState.getLocalPath()); final ResultCode conditionCheckResult = checkCondition(file, client); @@ -185,7 +188,8 @@ public class UploadFileOperation extends RemoteOperation { * @return RemoteOperationResult */ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - public RemoteOperationResult checkAvailableSpace(NextcloudClient client, long fileSize) { + @NonNull + public RemoteOperationResult checkAvailableSpace(@NonNull NextcloudClient client, long fileSize) { final RemoteOperationResult ocsResult = readUserInfo(client); final ResultCode resultCode; if (ocsResult.isSuccess() && ocsResult.getResultData().getQuota().getFree() < fileSize) { @@ -204,7 +208,8 @@ public class UploadFileOperation extends RemoteOperation { * @return RemoteOperationResult */ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - public RemoteOperationResult readUserInfo(NextcloudClient client) { + @NonNull + public RemoteOperationResult readUserInfo(@NonNull NextcloudClient client) { final GetUserInfoRemoteOperation GetUserInfoRemoteOperation = new GetUserInfoRemoteOperation(); return GetUserInfoRemoteOperation.execute(client); } @@ -216,7 +221,8 @@ public class UploadFileOperation extends RemoteOperation { * @return RemoteOperationResult instance containing failure details or RemoteFile instance */ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - public RemoteOperationResult readRemoteFile(final String remotePath, final OwnCloudClient client) { + @NonNull + public RemoteOperationResult readRemoteFile(@NonNull final String remotePath, @NonNull final OwnCloudClient client) { final ReadFileRemoteOperation readRemoteFile = new ReadFileRemoteOperation(remotePath); return readRemoteFile.execute(client); } @@ -229,7 +235,8 @@ public class UploadFileOperation extends RemoteOperation { * @return RemoteOperationResult instance containing success or failure status with details */ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - public RemoteOperationResult uploadChunkedFile(final File file, final OwnCloudClient client) { + @NonNull + public RemoteOperationResult uploadChunkedFile(@NonNull final File file, @NonNull final OwnCloudClient client) { final String mimeType = CommonUtils.getMimeType(file); final ChunkedFileUploadRemoteOperation uploadOperation = new ChunkedFileUploadRemoteOperation(syncedState.getLocalPath(), syncedState.getRemotePath(), @@ -247,7 +254,8 @@ public class UploadFileOperation extends RemoteOperation { * @return RemoteOperationResult the instance must contains etag in resultData if successful. */ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - public RemoteOperationResult uploadFile(final File file, final OwnCloudClient client) { + @NonNull + public RemoteOperationResult uploadFile(@NonNull final File file, @NonNull final OwnCloudClient client) { final String timeStamp = ((Long) (file.lastModified() / 1000) ).toString() ; final UploadFileRemoteOperation uploadOperation = new UploadFileRemoteOperation(syncedState.getLocalPath(), syncedState.getRemotePath(), @@ -264,13 +272,14 @@ public class UploadFileOperation extends RemoteOperation { * @return true if the parent directory has been created, false either */ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - public boolean createRemoteFolder(String targetPath, OwnCloudClient client) { + public boolean createRemoteFolder(@NonNull String targetPath, @NonNull OwnCloudClient client) { final String remoteFolderPath = targetPath.substring(0, targetPath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1); final CreateFolderRemoteOperation createFolderOperation = new CreateFolderRemoteOperation(remoteFolderPath, true); final RemoteOperationResult createFolderResult = createFolderOperation.execute(client); return createFolderResult.isSuccess() || createFolderResult.getCode() == ResultCode.FOLDER_ALREADY_EXISTS; } + @NonNull public SyncedFileState getSyncedState() { return syncedState; } diff --git a/app/src/main/java/foundation/e/drive/receivers/BootCompletedReceiver.java b/app/src/main/java/foundation/e/drive/receivers/BootCompletedReceiver.java index 094cfeef9692c5f84aadfa9a1e5a409f68ce440c..0ffe6529a666568febca870b386b8d4258e9d9cf 100644 --- a/app/src/main/java/foundation/e/drive/receivers/BootCompletedReceiver.java +++ b/app/src/main/java/foundation/e/drive/receivers/BootCompletedReceiver.java @@ -14,6 +14,8 @@ import android.content.Intent; import android.content.SharedPreferences; import android.database.sqlite.SQLiteException; +import androidx.annotation.NonNull; + import foundation.e.drive.BuildConfig; import foundation.e.drive.database.DbHelper; import foundation.e.drive.services.InitializerService; @@ -28,7 +30,7 @@ public class BootCompletedReceiver extends BroadcastReceiver { private static final String DATE_SYSTEM_PROPERTY = "ro.build.date"; private static final String PREF_VERSION_CODE = "VERSION_CODE"; @Override - public void onReceive(Context context, Intent intent) { + public void onReceive(@NonNull Context context, @NonNull Intent intent) { final String action = intent.getAction(); Timber.tag(BootCompletedReceiver.class.getSimpleName()).v("onReceive(...)"); final SharedPreferences pref = context.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); diff --git a/app/src/main/java/foundation/e/drive/receivers/DebugCmdReceiver.java b/app/src/main/java/foundation/e/drive/receivers/DebugCmdReceiver.java index 9e0e10b4cefa179122314a468db9202218aa8e2b..b5abb15948e84790e1fac10c2db5d3eadd44fd69 100644 --- a/app/src/main/java/foundation/e/drive/receivers/DebugCmdReceiver.java +++ b/app/src/main/java/foundation/e/drive/receivers/DebugCmdReceiver.java @@ -12,6 +12,8 @@ import android.content.Context; import android.content.Intent; import android.util.Log; +import androidx.annotation.NonNull; + import foundation.e.drive.database.DbHelper; import foundation.e.drive.services.ObserverService; import foundation.e.drive.utils.ReleaseTree; @@ -28,7 +30,7 @@ public class DebugCmdReceiver extends BroadcastReceiver { public static final String ACTION_FULL_LOG_ON_PROD = "foundation.e.drive.action.FULL_LOG_ON_PROD"; private static final String FULL_LOG_ENABLE_KEY = "full_log_enable"; @Override - public void onReceive(Context context, Intent intent) { + public void onReceive(@NonNull Context context, @NonNull Intent intent) { Timber.tag(DebugCmdReceiver.class.getSimpleName()).v("onReceive"); switch (intent.getAction()) { case ACTION_FORCE_SYNC: 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 16c8ce4db48c8e6b8ec9e5081a4a27975168c71f..f07ea10c0cb5635622fb8b48d1564058028bb091 100644 --- a/app/src/main/java/foundation/e/drive/services/InitializerService.java +++ b/app/src/main/java/foundation/e/drive/services/InitializerService.java @@ -36,6 +36,7 @@ import static com.owncloud.android.lib.resources.files.FileUtils.PATH_SEPARATOR; import static foundation.e.drive.utils.AppConstants.MEDIA_SYNCABLE_CATEGORIES; import static foundation.e.drive.utils.AppConstants.SETTINGS_SYNCABLE_CATEGORIES; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.work.WorkManager; @@ -56,7 +57,7 @@ public class InitializerService extends Service { } @Override - public int onStartCommand(Intent intent, int flags, int startId) { + public int onStartCommand(@NonNull Intent intent, int flags, int startId) { Timber.i("onStartCommand()"); CommonUtils.setServiceUnCaughtExceptionHandler(this); @@ -118,7 +119,7 @@ public class InitializerService extends Service { * Return a list of SyncedFolder * @param categories categories indicating which syncedFolder to create */ - private void getInitialSyncedFolders(List categories) { + private void getInitialSyncedFolders(@NonNull List categories) { Timber.d("getInitialSyncedFolders"); this.syncedFolders = new ArrayList<>(); @@ -174,7 +175,8 @@ public class InitializerService extends Service { } } - private String getExternalFolder(String directory) { + @NonNull + private String getExternalFolder(@NonNull String directory) { return CommonUtils.getLocalPath(Environment.getExternalStoragePublicDirectory(directory))+ PATH_SEPARATOR; } @@ -189,7 +191,7 @@ public class InitializerService extends Service { @Nullable @Override - public IBinder onBind(Intent intent) { + public IBinder onBind(@Nullable Intent intent) { return null; } } \ 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 d8d4dce703e687ef3a8c6148f073dcdae93b4172..897f77ca49b9d77ad0f0b179223694b9ca430459 100644 --- a/app/src/main/java/foundation/e/drive/services/ObserverService.java +++ b/app/src/main/java/foundation/e/drive/services/ObserverService.java @@ -22,6 +22,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.owncloud.android.lib.common.OwnCloudClient; @@ -68,7 +69,7 @@ public class ObserverService extends Service implements OnRemoteOperationListene private HashMap syncRequests; //integer is SyncedFileState id; Parcelable is the operation private SynchronizationServiceConnection synchronizationServiceConnection = new SynchronizationServiceConnection() { @Override - public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + public void onServiceConnected(@Nullable ComponentName componentName, @NonNull IBinder iBinder) { super.onServiceConnected(componentName, iBinder); final SharedPreferences prefs = getApplicationContext().getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); @@ -103,7 +104,7 @@ public class ObserverService extends Service implements OnRemoteOperationListene } @Override - public int onStartCommand(Intent intent, int flags, int startId) { + public int onStartCommand(@Nullable Intent intent, int flags, int startId) { Timber.i("onStartCommand(%s)", startId); CommonUtils.setServiceUnCaughtExceptionHandler(this); @@ -135,7 +136,7 @@ public class ObserverService extends Service implements OnRemoteOperationListene * @return false if at least one condition is false */ // protected to avoid SyntheticAccessor - protected boolean checkStartCondition(final SharedPreferences prefs, final boolean forcedSync) { + protected boolean checkStartCondition(@NonNull final SharedPreferences prefs, final boolean forcedSync) { Timber.d("checkStartCondition()"); if (mAccount == null) { @@ -303,7 +304,7 @@ public class ObserverService extends Service implements OnRemoteOperationListene * @param result The result of the remote Operation */ @Override - public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) { + public void onRemoteOperationFinish(@Nullable RemoteOperation operation, @NonNull RemoteOperationResult result) { Timber.d("onRemoteOperationFinish()"); if (!(operation instanceof ListFileRemoteOperation)) return; @@ -387,7 +388,7 @@ public class ObserverService extends Service implements OnRemoteOperationListene @Nullable @Override - public IBinder onBind(Intent intent) { + public IBinder onBind(@Nullable Intent intent) { throw new UnsupportedOperationException(); } } diff --git a/app/src/main/java/foundation/e/drive/services/ResetService.java b/app/src/main/java/foundation/e/drive/services/ResetService.java index a5cfb928dc4ba2d160dcb7fc64d9dc11a55093e8..58114e750fefef7e80fa80d6f9684b336afe062a 100644 --- a/app/src/main/java/foundation/e/drive/services/ResetService.java +++ b/app/src/main/java/foundation/e/drive/services/ResetService.java @@ -27,6 +27,7 @@ import timber.log.Timber; import static foundation.e.drive.utils.AppConstants.INITIALFOLDERS_NUMBER; import static foundation.e.drive.utils.AppConstants.INITIALIZATION_HAS_BEEN_DONE; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.work.WorkManager; @@ -37,7 +38,7 @@ import androidx.work.WorkManager; public class ResetService extends Service { @Override - public int onStartCommand(Intent intent, int flags, int startId) { + public int onStartCommand(@NonNull Intent intent, int flags, int startId) { Timber.tag(ResetService.class.getSimpleName()).i("onStartCommand()"); if ( intent.getExtras() != null ) { final String intent_accountName = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME, ""); @@ -110,7 +111,7 @@ public class ResetService extends Service { @Nullable @Override - public IBinder onBind(Intent intent) { + public IBinder onBind(@Nullable Intent intent) { return null; } } \ No newline at end of file diff --git a/app/src/main/java/foundation/e/drive/services/SynchronizationService.java b/app/src/main/java/foundation/e/drive/services/SynchronizationService.java index 0eaa40ffa49487a86f45b50551470589d8647b8d..b71f089fc650c59906bc5650397689fe3be2be36 100644 --- a/app/src/main/java/foundation/e/drive/services/SynchronizationService.java +++ b/app/src/main/java/foundation/e/drive/services/SynchronizationService.java @@ -20,6 +20,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.nextcloud.common.NextcloudClient; import com.owncloud.android.lib.common.OwnCloudClient; @@ -73,7 +74,7 @@ public class SynchronizationService extends Service implements OnRemoteOperation } @Override - public int onStartCommand(Intent intent, int flags, int startId) { + public int onStartCommand(@NonNull Intent intent, int flags, int startId) { Timber.i("onStartCommand()"); final SharedPreferences prefs = this.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); @@ -109,7 +110,7 @@ public class SynchronizationService extends Service implements OnRemoteOperation @Nullable @Override - public IBinder onBind(Intent intent) { + public IBinder onBind(@Nullable Intent intent) { return binder; } @@ -156,7 +157,7 @@ public class SynchronizationService extends Service implements OnRemoteOperation * It also remove already existing request for the same file from the waiting queue * @param request request to add to waiting queue */ - public void queueSyncRequest(SyncRequest request) { + public void queueSyncRequest(@NonNull SyncRequest request) { for (SyncWrapper syncWrapper : startedSync.values()) { //noinspection EqualsBetweenInconvertibleTypes if (syncWrapper.isRunning() && syncWrapper.equals(request)) { @@ -177,7 +178,7 @@ public class SynchronizationService extends Service implements OnRemoteOperation * It also remove already existing request for the same file from the waiting queue * @param requests collections of requests to add */ - public void queueSyncRequests(Collection requests) { + public void queueSyncRequests(@NonNull Collection requests) { for (SyncWrapper syncWrapper : startedSync.values()) { if (syncWrapper.isRunning()) { //noinspection EqualsBetweenInconvertibleTypes @@ -279,7 +280,7 @@ public class SynchronizationService extends Service implements OnRemoteOperation } @Override - public void onRemoteOperationFinish(RemoteOperation callerOperation, RemoteOperationResult result) { + public void onRemoteOperationFinish(@NonNull RemoteOperation callerOperation, @NonNull RemoteOperationResult result) { Timber.i("onRemoteOperationFinish()"); if (callerOperation instanceof RemoveFileOperation && result.isSuccess()) { DbHelper @@ -372,7 +373,9 @@ public class SynchronizationService extends Service implements OnRemoteOperation startWorker(threadId); } - public class SynchronizationBinder extends Binder{ + public class SynchronizationBinder extends Binder { + + @NonNull public SynchronizationService getService(){ return SynchronizationService.this; } diff --git a/app/src/main/java/foundation/e/drive/utils/AccountUtils.java b/app/src/main/java/foundation/e/drive/utils/AccountUtils.java index b121c4f78b361c4fc60bec3e756e6634902645c5..d9b944d9b5dbfac22173abc143225701539df762 100644 --- a/app/src/main/java/foundation/e/drive/utils/AccountUtils.java +++ b/app/src/main/java/foundation/e/drive/utils/AccountUtils.java @@ -30,6 +30,7 @@ import java.util.Optional; public class AccountUtils { + @NonNull public static Optional getPremiumGroup(@NonNull AccountManager accountManager, @Nullable Account account) { if (account == null) { return Optional.empty(); 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 d5fbd01322ac80f3897806afd095ca37bc9641c3..86e67971a8bc6efe2a4d13d6361d09d07ff82b8d 100644 --- a/app/src/main/java/foundation/e/drive/utils/CommonUtils.java +++ b/app/src/main/java/foundation/e/drive/utils/CommonUtils.java @@ -50,6 +50,7 @@ import static foundation.e.drive.utils.AppConstants.METERED_NETWORK_ALLOWED_AUTH import static foundation.e.drive.utils.AppConstants.SETTINGSYNC_PROVIDER_AUTHORITY; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.work.ExistingPeriodicWorkPolicy; import androidx.work.OneTimeWorkRequest; import androidx.work.PeriodicWorkRequest; @@ -71,7 +72,7 @@ public abstract class CommonUtils { * todo: check if the ServiceExceptionHandler could be remove * @param service current service */ - public static void setServiceUnCaughtExceptionHandler(Service service) { + public static void setServiceUnCaughtExceptionHandler(@NonNull Service service) { Thread.UncaughtExceptionHandler defaultUEH = Thread.getDefaultUncaughtExceptionHandler(); if (defaultUEH != null && ServiceExceptionHandler.class.getSimpleName().equals(defaultUEH.getClass().getSimpleName())) { ((ServiceExceptionHandler) defaultUEH).setService(service); @@ -89,7 +90,8 @@ public abstract class CommonUtils { * @param am Account Manager * @return Account or null if not found */ - public static Account getAccount(@NonNull String accountName, String accountType, @NonNull AccountManager am) { + @Nullable + public static Account getAccount(@NonNull String accountName, @NonNull String accountType, @NonNull AccountManager am) { Account[] accounts = am.getAccountsByType(accountType); for (int i = -1, size = accounts.length; ++i < size; ) { if (accounts[i].name.equals(accountName)) { @@ -106,7 +108,8 @@ public abstract class CommonUtils { * @param am Account Manager * @return Account or null if not found */ - public static Account getAccount(String accountType, @NonNull AccountManager am) { + @Nullable + public static Account getAccount(@Nullable String accountType, @NonNull AccountManager am) { Account[] accounts = am.getAccounts(); for (int i = -1, size = accounts.length; ++i < size; ) { if (accounts[i].type.equals(accountType)) { @@ -123,7 +126,7 @@ public abstract class CommonUtils { * @param syncedFileStateIsMedia true if the concerned syncedFileState is a media's type element, false if it is a settings's type element * @return */ - public static boolean isThisSyncAllowed(Account account, boolean syncedFileStateIsMedia) { + public static boolean isThisSyncAllowed(@NonNull Account account, boolean syncedFileStateIsMedia) { return (syncedFileStateIsMedia && isMediaSyncEnabled(account)) || (!syncedFileStateIsMedia && isSettingsSyncEnabled(account)); } @@ -134,7 +137,7 @@ public abstract class CommonUtils { * @param account Concerned account * @return true if media sync enabled */ - public static boolean isMediaSyncEnabled(Account account) { + public static boolean isMediaSyncEnabled(@NonNull Account account) { return ContentResolver.getSyncAutomatically(account, MEDIASYNC_PROVIDER_AUTHORITY); } @@ -144,7 +147,7 @@ public abstract class CommonUtils { * @param account Concerned account * @return true if enabled */ - public static boolean isSettingsSyncEnabled(Account account) { + public static boolean isSettingsSyncEnabled(@NonNull Account account) { return ContentResolver.getSyncAutomatically(account, SETTINGSYNC_PROVIDER_AUTHORITY); } @@ -154,7 +157,7 @@ public abstract class CommonUtils { * @param account * @return true if usage of metered connection is allowed */ - public static boolean isMeteredNetworkAllowed(Account account) { + public static boolean isMeteredNetworkAllowed(@NonNull Account account) { return ContentResolver.getSyncAutomatically(account, METERED_NETWORK_ALLOWED_AUTHORITY); } @@ -166,7 +169,8 @@ public abstract class CommonUtils { * @param path File name will be extracted from this path. Do not provide directory path * @return String, the last part after separator of path or null if invalid path has been provided */ - public static String getFileNameFromPath(String path) { + @Nullable + public static String getFileNameFromPath(@NonNull String path) { final String[] splittedString = path.split(FileUtils.PATH_SEPARATOR); if (splittedString.length <= 0) return null; return splittedString[splittedString.length - 1]; @@ -179,7 +183,7 @@ public abstract class CommonUtils { * @param meteredNetworkAllowed true if service can use metered network / false either * @return True if there is connection, false either */ - public static boolean haveNetworkConnection(Context context, boolean meteredNetworkAllowed) { + public static boolean haveNetworkConnection(@NonNull Context context, boolean meteredNetworkAllowed) { Timber.tag(TAG).v("haveNetworkConnection()"); final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class); @@ -202,7 +206,8 @@ public abstract class CommonUtils { * @param file the file for whom we want Mime type * @return String containing mimeType of the file */ - public static String getMimeType(File file) { + @NonNull + public static String getMimeType(@NonNull File file) { final String mimetype = MimeTypeMap.getSingleton() .getMimeTypeFromExtension( MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString()).toLowerCase(Locale.ROOT)); @@ -218,7 +223,7 @@ public abstract class CommonUtils { * @param context Calling service context * @param filePath String containing path the file to update by mediaScanner */ - public static void doActionMediaScannerConnexionScanFile(Context context, final String filePath) { + public static void doActionMediaScannerConnexionScanFile(@NonNull Context context, @NonNull final String filePath) { Timber.v("doActionMediaScannerConnexionScanFile( %s )", filePath); final String[] filePathArray = new String[] { filePath }; final String[] mimeType = new String[] {getMimeType(new File(filePath))}; @@ -240,7 +245,8 @@ public abstract class CommonUtils { * @param file file from which we want the path * @return canonical path if available */ - public static String getLocalPath(File file) { + @NonNull + public static String getLocalPath(@NonNull File file) { String result; try { result = file.getCanonicalPath(); @@ -258,6 +264,7 @@ public abstract class CommonUtils { * @param bytes file/data size in bytes * @return String in human readable format */ + @NonNull public static String humanReadableByteCountBin(long bytes) { long absB = bytes == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(bytes); if (absB < 1024) { @@ -288,7 +295,7 @@ public abstract class CommonUtils { * @param syncedFolders List of SyncedFolder for which we want to create a remote folder on ecloud * @param workManager WorkManager instance to register WorkRequest */ - public static void registerInitializationWorkers(List syncedFolders, WorkManager workManager) { + public static void registerInitializationWorkers(@Nullable List syncedFolders, @NonNull WorkManager workManager) { if (syncedFolders == null || syncedFolders.isEmpty()) { Timber.tag(TAG).d("registerInitializationWorkers: Can't create remote folders. List is empty"); return; @@ -311,7 +318,7 @@ public abstract class CommonUtils { } - public static void createNotificationChannel(Context context) { + public static void createNotificationChannel(@NonNull Context context) { final CharSequence name = context.getString(R.string.notif_channel_name); final String description = context.getString(R.string.notif_channel_description); int importance = NotificationManager.IMPORTANCE_DEFAULT; @@ -323,7 +330,7 @@ public abstract class CommonUtils { notificationManager.createNotificationChannel(channel); } - public static void copyToClipboard(Uri data, Context context, String label) { + public static void copyToClipboard(@NonNull Uri data, @NonNull Context context, @NonNull String label) { final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); final ClipData clip = ClipData.newPlainText(label, String.valueOf(data)); @@ -338,7 +345,7 @@ public abstract class CommonUtils { * * @param workManager */ - public static void registerPeriodicUserInfoChecking(WorkManager workManager) { + public static void registerPeriodicUserInfoChecking(@NonNull WorkManager workManager) { final PeriodicWorkRequest workRequest = WorkRequestFactory.getPeriodicWorkRequest(WorkRequestFactory.WorkType.PERIODIC_USER_INFO); workManager.enqueueUniquePeriodicWork(AccountUserInfoWorker.UNIQUE_WORK_NAME, ExistingPeriodicWorkPolicy.REPLACE, workRequest); } @@ -350,7 +357,8 @@ public abstract class CommonUtils { * @return value of the prop, returns empty if not found */ @SuppressLint("PrivateApi") - public static String getProp(String prop) { + @NonNull + public static String getProp(@NonNull String prop) { String value = ""; try { Class c = Class.forName("android.os.SystemProperties"); @@ -359,6 +367,6 @@ public abstract class CommonUtils { } catch (Exception e) { e.printStackTrace(); } - return value; + return value == null ? "" : value; } } diff --git a/app/src/main/java/foundation/e/drive/utils/DavClientProvider.java b/app/src/main/java/foundation/e/drive/utils/DavClientProvider.java index 8e27d88a22c27e7bbb4dce09e62eb0c8dfb692d5..70514ae3c240557b464c589f24cf32decf98a4c8 100644 --- a/app/src/main/java/foundation/e/drive/utils/DavClientProvider.java +++ b/app/src/main/java/foundation/e/drive/utils/DavClientProvider.java @@ -14,6 +14,9 @@ import android.accounts.AccountManager; import android.content.Context; import android.net.Uri; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.nextcloud.common.NextcloudClient; import com.nextcloud.common.OkHttpCredentialsUtil; import com.owncloud.android.lib.common.OwnCloudBasicCredentials; @@ -39,7 +42,8 @@ public class DavClientProvider { private OwnCloudClient ocClientInstance; private NextcloudClient ncClientInstance; - public OwnCloudClient getClientInstance(final Account account, final Context ctx) { + @Nullable + public OwnCloudClient getClientInstance(@Nullable final Account account, @NonNull final Context ctx) { if (ocClientInstance == null) { try { //Not sure below if code is used... @@ -68,7 +72,8 @@ public class DavClientProvider { } - public NextcloudClient getNcClientInstance(final Account account, final Context ctx) { + @Nullable + public NextcloudClient getNcClientInstance(@Nullable final Account account, @NonNull final Context ctx) { Timber.v("getNcClientInstance()"); if (ncClientInstance == null) { try { @@ -85,12 +90,13 @@ public class DavClientProvider { return ncClientInstance; } - + @Nullable private static String getAcountPwd(Account account, Context ctx) throws AccountUtils.AccountNotFoundException { return AccountManager.get(ctx).getPassword(account); } /** Point d'accès pour l'instance unique du singleton */ + @NonNull public static DavClientProvider getInstance() { return instance; diff --git a/app/src/main/java/foundation/e/drive/utils/FileDiffUtils.java b/app/src/main/java/foundation/e/drive/utils/FileDiffUtils.java index 7b5c1814bc6727fe66ba0a35620b43b384895ea3..59bc0d9e215dc98adba7d80592bd2e8b705c6104 100644 --- a/app/src/main/java/foundation/e/drive/utils/FileDiffUtils.java +++ b/app/src/main/java/foundation/e/drive/utils/FileDiffUtils.java @@ -7,6 +7,8 @@ */ package foundation.e.drive.utils; +import androidx.annotation.NonNull; + import com.owncloud.android.lib.resources.files.model.RemoteFile; import java.io.File; @@ -33,7 +35,8 @@ public class FileDiffUtils { * @param fileState SyncedFileState instance * @return Action from Enum */ - public static Action getActionForFileDiff(RemoteFile remoteFile, SyncedFileState fileState) { + @NonNull + public static Action getActionForFileDiff(@NonNull RemoteFile remoteFile, @NonNull SyncedFileState fileState) { if (hasAlreadyBeenDownloaded(fileState) && !hasEtagChanged(remoteFile, fileState)) { return Action.skip; } @@ -53,7 +56,8 @@ public class FileDiffUtils { * @param fileState SyncedFileState instance. Containing data from Database * @return Action from Enum */ - public static Action getActionForFileDiff(File localFile, SyncedFileState fileState) { + @NonNull + public static Action getActionForFileDiff(@NonNull File localFile, @NonNull SyncedFileState fileState) { //If no etag is stored in sfs, the file hasn't been sync up to server. then do upload if (fileState.getLocalLastModified() < localFile.lastModified() || !fileState.isLastEtagStored()) { return Action.Upload; @@ -67,7 +71,7 @@ public class FileDiffUtils { * @param fileState last store file's state * @return true if ETag */ - private static boolean hasEtagChanged(RemoteFile file, SyncedFileState fileState) { + private static boolean hasEtagChanged(@NonNull RemoteFile file, @NonNull SyncedFileState fileState) { //if SyncedFileState has no Etag then it hasn't been uploaded and so must not exist on server return fileState.isLastEtagStored() && !file.getEtag().equals(fileState.getLastETAG()); } @@ -78,7 +82,7 @@ public class FileDiffUtils { * @param fileState SyncedFileState containing data from Database * @return true if localLastModified store in Database == 0 */ - private static boolean hasAlreadyBeenDownloaded(SyncedFileState fileState) { + private static boolean hasAlreadyBeenDownloaded(@NonNull SyncedFileState fileState) { return fileState.getLocalLastModified() > 0L; } @@ -88,7 +92,7 @@ public class FileDiffUtils { * @param localFile File instance * @return true if remote file size is same as local file size */ - private static boolean isRemoteSizeSameAsLocalSize(RemoteFile remoteFile, File localFile) { + private static boolean isRemoteSizeSameAsLocalSize(@NonNull RemoteFile remoteFile, @NonNull File localFile) { // if local file doesn't exist its size will be 0 // remoteFile.getSize() : getSize() is equal to getLength() except that for folder is also sum the content of the folder! return remoteFile.getSize() == localFile.length(); diff --git a/app/src/main/java/foundation/e/drive/utils/ServiceExceptionHandler.java b/app/src/main/java/foundation/e/drive/utils/ServiceExceptionHandler.java index 545c8526100e5c3ef20476c9d6cb93c121728aee..699b12ffe7ef31dd374efa7e40345d1a6341d560 100644 --- a/app/src/main/java/foundation/e/drive/utils/ServiceExceptionHandler.java +++ b/app/src/main/java/foundation/e/drive/utils/ServiceExceptionHandler.java @@ -11,6 +11,8 @@ import android.annotation.SuppressLint; import android.app.Service; import android.os.Environment; +import androidx.annotation.NonNull; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -34,18 +36,18 @@ public class ServiceExceptionHandler implements UncaughtExceptionHandler{ * Update the service which use this handler * @param service current running service */ - public void setService(Service service) { + public void setService(@NonNull Service service) { this.service = service; } - public ServiceExceptionHandler(Service service) { + public ServiceExceptionHandler(@NonNull Service service) { this.service = service; defaultUEH = Thread.getDefaultUncaughtExceptionHandler(); } @SuppressLint("SetWorldReadable") @Override - public void uncaughtException(Thread t, Throwable exception) { + public void uncaughtException(@NonNull Thread t, @NonNull Throwable exception) { if(isExternalStorageAvailable() && !isExternalStorageReadOnly()){ diff --git a/app/src/main/java/foundation/e/drive/utils/SynchronizationServiceConnection.java b/app/src/main/java/foundation/e/drive/utils/SynchronizationServiceConnection.java index 370ed76e25f423e4ba7e2e772a38fc0677ea024a..7640135a8fe6d54e1b56949c9c8195501f93b788 100644 --- a/app/src/main/java/foundation/e/drive/utils/SynchronizationServiceConnection.java +++ b/app/src/main/java/foundation/e/drive/utils/SynchronizationServiceConnection.java @@ -15,6 +15,7 @@ import android.content.ServiceConnection; import android.os.IBinder; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import foundation.e.drive.services.SynchronizationService; import timber.log.Timber; @@ -29,7 +30,7 @@ public class SynchronizationServiceConnection implements ServiceConnection { private boolean attemptingToBind = false; @Override - public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + public void onServiceConnected(@Nullable ComponentName componentName, @NonNull IBinder iBinder) { Timber.tag(SynchronizationServiceConnection.class.getSimpleName()) .v("binding to SynchronizationService"); attemptingToBind = false; @@ -39,7 +40,7 @@ public class SynchronizationServiceConnection implements ServiceConnection { } @Override - public void onServiceDisconnected(ComponentName componentName) { + public void onServiceDisconnected(@Nullable ComponentName componentName) { Timber.tag(SynchronizationServiceConnection.class.getSimpleName()) .v("onServiceDisconnected()"); isBound = false; @@ -53,6 +54,7 @@ public class SynchronizationServiceConnection implements ServiceConnection { * Get SynchronizationService. Might be null! * @return */ + @Nullable public SynchronizationService getSynchronizationService() { return synchronizationService; } @@ -61,7 +63,7 @@ public class SynchronizationServiceConnection implements ServiceConnection { * Sources: https://stackoverflow.com/questions/8614335/android-how-to-safely-unbind-a-service * @param context */ - public void unBind(@NonNull Context context) { + public void unBind(@NonNull Context context) { attemptingToBind = false; if (isBound) { context.unbindService(this); diff --git a/app/src/main/java/foundation/e/drive/widgets/EDriveWidget.java b/app/src/main/java/foundation/e/drive/widgets/EDriveWidget.java index 4e44d5a01423f8906f7b9a362352b7548d72a787..837bec2748ad633df41a6704cb1fc6f410129fb3 100644 --- a/app/src/main/java/foundation/e/drive/widgets/EDriveWidget.java +++ b/app/src/main/java/foundation/e/drive/widgets/EDriveWidget.java @@ -30,6 +30,9 @@ import android.provider.Settings; import android.view.View; import android.widget.RemoteViews; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Locale; @@ -64,7 +67,8 @@ public class EDriveWidget extends AppWidgetProvider { private RemoteViews views; private Account account = null; - public static String dataForWeb(String bytes) { + @NonNull + public static String dataForWeb(@NonNull String bytes) { long convertedBytes = 0; try { convertedBytes = Long.parseLong(bytes); @@ -76,7 +80,8 @@ public class EDriveWidget extends AppWidgetProvider { return Math.round(Double.parseDouble(split[0])) + split[1]; } - public static Intent buildIntent(String name, String extra) { + @NonNull + public static Intent buildIntent(@NonNull String name, @NonNull String extra) { final Intent intent = new Intent(name); if (!extra.isEmpty()) { intent.setData(Uri.parse(extra)); @@ -86,7 +91,7 @@ public class EDriveWidget extends AppWidgetProvider { return intent; } - public static int convertIntoMB(String quota) { + public static int convertIntoMB(@NonNull String quota) { int convertedData = 0; try { convertedData = (int) (Long.parseLong(quota) / (1024 * 1024)); @@ -95,7 +100,7 @@ public class EDriveWidget extends AppWidgetProvider { return convertedData; } - public void updateAppWidget(final Context context) { + public void updateAppWidget(@NonNull final Context context) { AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); final ComponentName provider = new ComponentName(context, getClass()); int[] appWidgetIds = appWidgetManager.getAppWidgetIds(provider); @@ -105,7 +110,7 @@ public class EDriveWidget extends AppWidgetProvider { } } - public void updateAppWidget(final Context context, final AppWidgetManager appWidgetManager, + public void updateAppWidget(@NonNull final Context context, @NonNull final AppWidgetManager appWidgetManager, final int appWidgetId) { final AccountManager accountManager = AccountManager.get(context); @@ -124,14 +129,14 @@ public class EDriveWidget extends AppWidgetProvider { } @Override - public void onEnabled(Context context) { + public void onEnabled(@NonNull Context context) { super.onEnabled(context); registerConnectivityCallback(context); updateAppWidget(context); } @Override - public void onReceive(final Context context, Intent intent) { + public void onReceive(@NonNull final Context context, @NonNull Intent intent) { final String action = intent.getAction(); if (action == null) return; switch (action) { @@ -155,7 +160,7 @@ public class EDriveWidget extends AppWidgetProvider { super.onReceive(context, intent); } - private void noAccountView(Context context) { + private void noAccountView(@NonNull Context context) { if (!isNetworkAvailable) { noInternetView(context); return; @@ -179,7 +184,7 @@ public class EDriveWidget extends AppWidgetProvider { views.setTextViewText(R.id.summary, context.getString(R.string.login_summary)); } - private void noInternetView(Context context) { + private void noInternetView(@NonNull Context context) { if (!isNetworkAvailable) { if (isDarkText) { views = new RemoteViews(context.getPackageName(), R.layout.e_drive_widget_login_light); @@ -191,7 +196,7 @@ public class EDriveWidget extends AppWidgetProvider { } } - private void onAccountAvailable(Context context, AccountManager accountManager) { + private void onAccountAvailable(@NonNull Context context, @NonNull AccountManager accountManager) { final String usedQuota = accountManager.getUserData(account, ACCOUNT_DATA_USED_QUOTA_KEY); final String totalQuota = accountManager.getUserData(account, ACCOUNT_DATA_TOTAL_QUOTA_KEY); final String email = accountManager.getUserData(account, ACCOUNT_DATA_EMAIL); @@ -287,7 +292,8 @@ public class EDriveWidget extends AppWidgetProvider { views.setOnClickPendingIntent(R.id.upgrade, pendingIntentUpgrade); } - private PendingIntent getPendingSelfIntent(Context context, String action, String data) { + @NonNull + private PendingIntent getPendingSelfIntent(@NonNull Context context, @NonNull String action, @Nullable String data) { final Intent intent = new Intent(context, getClass()); intent.setAction(action); if (data != null) { @@ -296,12 +302,12 @@ public class EDriveWidget extends AppWidgetProvider { return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE); } - private void registerConnectivityCallback(final Context context) { + private void registerConnectivityCallback(@NonNull final Context context) { final ConnectivityManager cm = (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE); cm.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() { @Override - public void onAvailable(Network network) { + public void onAvailable(@NonNull Network network) { if (!isNetworkAvailable) { isNetworkAvailable = true; updateAppWidget(context); @@ -309,7 +315,7 @@ public class EDriveWidget extends AppWidgetProvider { } @Override - public void onLost(Network network) { + public void onLost(@NonNull Network network) { if (isNetworkAvailable) { isNetworkAvailable = false; updateAppWidget(context); @@ -319,7 +325,7 @@ public class EDriveWidget extends AppWidgetProvider { } @Override - public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) { + public void onAppWidgetOptionsChanged(@NonNull Context context, @NonNull AppWidgetManager appWidgetManager, int appWidgetId, @NonNull Bundle newOptions) { super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions); isDarkText = newOptions.getBoolean(DARK_TEXT_KEY); updateAppWidget(context); diff --git a/app/src/main/java/foundation/e/drive/work/LocalFileDeleter.java b/app/src/main/java/foundation/e/drive/work/LocalFileDeleter.java index f617855185af86fe939b22f5975b8080f5fbb2c1..ecd127896a7fac80d9441e278b26d19dd94518fc 100644 --- a/app/src/main/java/foundation/e/drive/work/LocalFileDeleter.java +++ b/app/src/main/java/foundation/e/drive/work/LocalFileDeleter.java @@ -11,6 +11,8 @@ import android.content.Context; import android.os.Handler; import android.provider.MediaStore; +import androidx.annotation.NonNull; + import java.io.File; import foundation.e.drive.database.DbHelper; @@ -31,18 +33,19 @@ public class LocalFileDeleter { private final SyncedFileState fileState; - public LocalFileDeleter(SyncedFileState syncedFileState) { + public LocalFileDeleter(@NonNull SyncedFileState syncedFileState) { fileState = syncedFileState; } - public Runnable getRunnable(final Handler handler, final int threadId, final Context context, final LocalFileDeletionListener listener) { + @NonNull + public Runnable getRunnable(@NonNull final Handler handler, final int threadId, @NonNull final Context context, @NonNull final LocalFileDeletionListener listener) { return () -> { final boolean succeed = deleteFile(fileState, context); notifyCompletion(threadId, listener, succeed, handler); }; } - private boolean deleteFile(SyncedFileState fileState, Context context) { + private boolean deleteFile(@NonNull SyncedFileState fileState, @NonNull Context context) { final File file = new File(fileState.getLocalPath()); if (file.exists()) { try { @@ -67,7 +70,7 @@ public class LocalFileDeleter { return true; } - private void notifyCompletion(final int threadId, final LocalFileDeletionListener listener, final boolean success, final Handler handler) { + private void notifyCompletion(final int threadId, final @NonNull LocalFileDeletionListener listener, final boolean success, @NonNull final Handler handler) { handler.post(() -> listener.onDeletionComplete(threadId, success)); } } diff --git a/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java b/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java index 52084c10f3d664bd87838ee2c64c474f0d4a8532..e88c43b24ae44698530afd41159c8d69a0080e17 100644 --- a/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java +++ b/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java @@ -52,6 +52,7 @@ public class WorkRequestFactory { * If not, it will throw an InvalidParameterException * @return Periodic WorkRequest */ + @NonNull public static PeriodicWorkRequest getPeriodicWorkRequest(@NonNull WorkType type) { switch (type) { case PERIODIC_SCAN: @@ -105,6 +106,7 @@ public class WorkRequestFactory { * @param syncedFolder this parameter is required for CREATE_REMOTE_DIR work type. If null it will throw an NPE. * @return OneTimeWorkRequest's instance. */ + @NonNull public static OneTimeWorkRequest getOneTimeWorkRequest(@NonNull WorkType type, @Nullable SyncedFolder syncedFolder) { switch (type) { case ONE_TIME_APP_LIST: diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index d05ac80eaf4afd62677c3be06fc47908adfa19d7..98102cb65a5e3c91ef88f63491e17889161f76d4 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -1,5 +1,5 @@ - + /e/ Speicher Mein Cloud-Konto %1$s gratis Abo @@ -20,7 +20,7 @@ \n Videos sicher mit der Cloud eDrive Benachrichtigungskanal 99 %% der Höchstquote des Cloud-Speichers erreicht. Bitte unternimm etwas. - Alias + Alias Ihr Cloud-Speicher ist voll. Ihr Cloud-Speicher ist fast voll. Alias diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 62a95717855a8745f2a89e0e2ff1a1b364aa00bc..a7701e0844e0d7f1240597e96c0375b94288391a 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1,5 +1,5 @@ - + /e/ Disco Configuración adicional de la cuenta Ajustes @@ -11,7 +11,7 @@ Tu almacenamiento en la nube está lleno. Canal de notificaciones de eDrive Si no se detecta conexión a Internet, el widget se actualizará automáticamente cuando se active la conexión - Alias + Alias Alias Ocultar alias Copiar diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 97fe8d8bb7b8338d46dbff3ccd3b9ca6e93fa5b8..9427b1f597c43c8138c604efce50b48a6acc68aa 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1,5 +1,5 @@ - + /e/ Drive Paramètres additionnels du compte Paramètres @@ -11,7 +11,7 @@ Votre stockage cloud est plein. Canal de notification eDrive Aucune connexion internet détectée, le widget se mettra à jour dès qu\'il détectera une connexion - Alias + Alias alias Masquer les alias copier diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 694929965e03c52eae59a1ab8dabbefc7198a5c6..5df904df4691710e394ac5c92ef6870ff5503cf4 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -1,5 +1,5 @@ - + /e/ Drive Impostazioni aggiuntive per l\'account Impostazioni @@ -11,7 +11,7 @@ Il tuo cloud storage è pieno. canale notifiche di eDrive Connessione Internet non attiva, il widget si aggiornerà automaticamente quando verrà attivata - Alias + Alias alias Nascondi alias copia diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 12a2f5554245aca50c35ca4694b3a5c4f0f0eb7c..166c85eb4e36a2f03d5d2966b2e8f8dd43bf47d4 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1,5 +1,5 @@ - + /e/ Drive Разрешить синхронизацию файлов через тарифицируемую сеть Дополнительные настройки для учётной записи @@ -12,7 +12,7 @@ Ваше облачное хранилище переполнено. Канал доставки eDrive уведомлений Не обнаружено подключение к Интернету, виджет автоматически обновится при активном подключении к Интернету - Псевдонимы + Псевдонимы псевдонимы Скрыть псевдонимы копировать diff --git a/lint.xml b/lint.xml index dd1b8927cf27d245e10f4ed68ddc031de8d5e080..8f925319c1e5c16829785e3824f6742fa5acb434 100644 --- a/lint.xml +++ b/lint.xml @@ -5,7 +5,6 @@ -