diff --git a/app/build.gradle b/app/build.gradle index 7144efd737c9811c7c56501f24d219475591708b..6f4aaa57a77417379a15172c3dd7c7c8d8c38d32 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,6 +56,10 @@ android { buildFeatures { viewBinding true } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } 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 90f47e0798b2f2c7ed0922b81df7a1f4115903b0..d0c2fdbf52dafa1f6a01612d902b3ef653b0d2c8 100644 --- a/app/src/main/java/foundation/e/drive/activity/AccountsActivity.java +++ b/app/src/main/java/foundation/e/drive/activity/AccountsActivity.java @@ -8,6 +8,12 @@ package foundation.e.drive.activity; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_ALIAS_KEY; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_EMAIL; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_GROUPS; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_NAME; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_TOTAL_QUOTA_KEY; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_USED_QUOTA_KEY; import static foundation.e.drive.widgets.EDriveWidget.buildIntent; import static foundation.e.drive.widgets.EDriveWidget.convertIntoMB; import static foundation.e.drive.widgets.EDriveWidget.dataForWeb; @@ -18,8 +24,6 @@ import android.content.ComponentName; import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; import android.view.View; import androidx.appcompat.app.AppCompatActivity; @@ -27,32 +31,18 @@ import androidx.core.content.ContextCompat; import com.bumptech.glide.Glide; import com.owncloud.android.lib.common.OwnCloudClient; -import com.owncloud.android.lib.common.UserInfo; -import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation; - -import java.util.ArrayList; import foundation.e.drive.R; import foundation.e.drive.databinding.ActivityAccountsBinding; -import foundation.e.drive.operations.GetAliasOperation; import foundation.e.drive.utils.CommonUtils; -import foundation.e.drive.widgets.EDriveNetworkCallback; import foundation.e.drive.widgets.EDriveWidget; public class AccountsActivity extends AppCompatActivity { - private static final String NON_OFFICIAL_AVATAR_PATH = "/index.php/avatar/"; + public static final String NON_OFFICIAL_AVATAR_PATH = "/index.php/avatar/"; private static final String ACCOUNT_SETTINGS = EDriveWidget.ACCOUNT_MANAGER_PACKAGE_NAME + ".ui.AccountsActivity"; - private final GetRemoteUserInfoOperation getRemoteUserInfoOperation = new GetRemoteUserInfoOperation(); - private final GetAliasOperation getAliasOperation = new GetAliasOperation(); - private UserInfo userInfo = null; - private ArrayList aliases; - private OwnCloudClient client; - private Account account; - private ActivityAccountsBinding binding; @Override @@ -63,139 +53,84 @@ public class AccountsActivity extends AppCompatActivity { setContentView(binding.getRoot()); setSupportActionBar(binding.toolbar); - binding.toolbar.setNavigationOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - onBackPressed(); - } - }); + binding.toolbar.setNavigationOnClickListener(v -> onBackPressed()); - binding.settings.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - final Intent settingsIntent = buildIntent(Intent.ACTION_VIEW, "") - .setComponent(new ComponentName( - EDriveWidget.ACCOUNT_MANAGER_PACKAGE_NAME, ACCOUNT_SETTINGS)); - startActivity(settingsIntent); - } + binding.settings.setOnClickListener(v -> { + final Intent settingsIntent = buildIntent(Intent.ACTION_VIEW, "") + .setComponent(new ComponentName( + EDriveWidget.ACCOUNT_MANAGER_PACKAGE_NAME, ACCOUNT_SETTINGS)); + startActivity(settingsIntent); }); + showDetails(); + } + private void showDetails() { final AccountManager accountManager = AccountManager.get(this); - account = CommonUtils.getAccount(getString(R.string.eelo_account_type), + final Account account = CommonUtils.getAccount(getString(R.string.eelo_account_type), accountManager); - client = CommonUtils.getOwnCloudClient(account, this); - - final HandlerThread handlerThread = new HandlerThread("Network Request"); - handlerThread.start(); - final Handler mHandler = new Handler(handlerThread.getLooper()); - - final EDriveNetworkCallback callback = new EDriveNetworkCallback() { - @Override - public void onComplete() { - runOnUiThread(new Runnable() { - @Override - public void run() { - onNetworkRequestCompleted(); - } - }); - } - }; + final OwnCloudClient client = CommonUtils.getOwnCloudClient(account, this); - if (!CommonUtils.haveNetworkConnection(this, true)) { - handleNoInternetConnection(); - return; - } + 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); - binding.loading.setVisibility(View.VISIBLE); - mHandler.post(new Runnable() { - @Override - public void run() { - if (client != null) { - RemoteOperationResult ocsResult = getRemoteUserInfoOperation.execute(client); - if (ocsResult.isSuccess() && ocsResult.getData() != null) { - userInfo = (UserInfo) ocsResult.getData().get(0); - } - RemoteOperationResult aliasResult = getAliasOperation.execute(client); - if (aliasResult.isSuccess() && aliasResult.getData() != null) { - aliases = aliasResult.getData(); - } - } - callback.onComplete(); - } - }); - } + binding.name.setText(accountManager.getUserData(account, ACCOUNT_DATA_NAME)); + binding.email.setText(email); - private void onNetworkRequestCompleted() { - binding.loading.setVisibility(View.GONE); - if (userInfo.displayName == null) { - binding.name.setText(userInfo.alternateDisplayName); - } else { - binding.name.setText(userInfo.displayName); - } - binding.email.setText(userInfo.id); - - final int usedMB = convertIntoMB(userInfo.quota.used); - final int totalMB = convertIntoMB(userInfo.quota.total); - - binding.progress.setMax(totalMB); - binding.progress.setProgress(usedMB); + binding.progress.setMax(convertIntoMB(totalQuota)); + binding.progress.setProgress(convertIntoMB(usedQuota)); binding.progress.setVisibility(View.VISIBLE); binding.plan.setText(getString(R.string.free_plan, - CommonUtils.humanReadableByteCountBin(userInfo.quota.total))); - for (String group : userInfo.groups) { + CommonUtils.humanReadableByteCountBin(Long.parseLong(totalQuota)))); + + String[] groups = accountManager.getUserData(account, ACCOUNT_DATA_GROUPS).split(","); + for (String group : groups) { if (group.contains("premium-")) { - binding.plan.setText(getString(R.string.premium_plan, group.split("-")[1])); + binding.plan.setText(getString(R.string.premium_plan, + group.split("-")[1])); break; } } + binding.myPlan.setVisibility(View.VISIBLE); binding.plan.setVisibility(View.VISIBLE); binding.status.setText(getString(R.string.progress_status, - CommonUtils.humanReadableByteCountBin(userInfo.quota.used), - CommonUtils.humanReadableByteCountBin(userInfo.quota.total))); + CommonUtils.humanReadableByteCountBin(Long.parseLong(usedQuota)), + CommonUtils.humanReadableByteCountBin(Long.parseLong(totalQuota)))); + String aliases = accountManager.getUserData(account, ACCOUNT_DATA_ALIAS_KEY); if (aliases != null && !aliases.isEmpty()) { binding.alias.setVisibility(View.VISIBLE); - binding.alias1.setText(aliases.get(0).toString()); + binding.alias1.setText(aliases.split(",")[0]); binding.aliasDivider.setVisibility(View.VISIBLE); } else { binding.alias.setVisibility(View.GONE); binding.alias1Container.setVisibility(View.GONE); } - binding.alias1Clipboard.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { + binding.alias1Clipboard.setOnClickListener(v -> CommonUtils.copyToClipboard(Uri.parse(binding.alias1.getText().toString()), - v.getContext(), v.getContext().getString(R.string.alias)); - } - }); + v.getContext(), v.getContext().getString(R.string.alias))); binding.upgrade.setVisibility(View.VISIBLE); - binding.upgrade.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - final Intent upgradeIntent = buildIntent(Intent.ACTION_VIEW, - String.format(EDriveWidget.WEBPAGE, userInfo.id, - dataForWeb(userInfo.quota.total))); - startActivity(upgradeIntent); - } + binding.upgrade.setOnClickListener(v -> { + final Intent upgradeIntent = buildIntent(Intent.ACTION_VIEW, + String.format(EDriveWidget.WEBPAGE, email, + dataForWeb(Long.parseLong(totalQuota)))); + startActivity(upgradeIntent); }); - binding.alias.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (binding.alias1Container.getVisibility() == View.VISIBLE) { - binding.alias1Container.setVisibility(View.GONE); - binding.alias.setCompoundDrawablesWithIntrinsicBounds(null, null, - ContextCompat.getDrawable(v.getContext(), R.drawable.ic_expand_more), null); - } else { - binding.alias1Container.setVisibility(View.VISIBLE); - binding.alias.setCompoundDrawablesWithIntrinsicBounds(null, null, - ContextCompat.getDrawable(v.getContext(), R.drawable.ic_expand_less), null); - } + binding.alias.setOnClickListener(v -> { + if (binding.alias1Container.getVisibility() == View.VISIBLE) { + binding.alias1Container.setVisibility(View.GONE); + binding.alias.setCompoundDrawablesWithIntrinsicBounds(null, null, + ContextCompat.getDrawable(v.getContext(), R.drawable.ic_expand_more), null); + } else { + binding.alias1Container.setVisibility(View.VISIBLE); + binding.alias.setCompoundDrawablesWithIntrinsicBounds(null, null, + ContextCompat.getDrawable(v.getContext(), R.drawable.ic_expand_less), null); } }); @@ -206,10 +141,4 @@ public class AccountsActivity extends AppCompatActivity { .into(binding.avatar); binding.avatar.setVisibility(View.VISIBLE); } - - private void handleNoInternetConnection() { - binding.name.setText(account.name); - binding.email.setText(account.type); - binding.avatar.setVisibility(View.VISIBLE); - } } 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 d493028d2be1d477932bdac694748307b467eb0f..fdb73abc13b31e71c6e52a35349d6c60e6038806 100644 --- a/app/src/main/java/foundation/e/drive/services/InitializerService.java +++ b/app/src/main/java/foundation/e/drive/services/InitializerService.java @@ -100,6 +100,8 @@ public class InitializerService extends Service { return; } + CommonUtils.registerPeriodicUserInfoChecking(WorkManager.getInstance(this)); + final List syncCategories = new ArrayList<>(); syncCategories.addAll(Arrays.asList(MEDIA_SYNCABLE_CATEGORIES)); 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 b05476ac3d3793dd58b7345b2060ae580431f692..72cee50c44d164f321e499f76523e008e4695769 100644 --- a/app/src/main/java/foundation/e/drive/services/SynchronizationService.java +++ b/app/src/main/java/foundation/e/drive/services/SynchronizationService.java @@ -158,13 +158,6 @@ public class SynchronizationService extends Service implements OnRemoteOperation if (callerOperation instanceof UploadFileOperation && callerOperationResultData != null && callerOperationResultData.size() > 1) { final Float relativeQuota = (Float) result.getData().get(1); - if (relativeQuota >= 99.0) { - addNotification(getString(R.string.notif_quota_99Plus_title), getString(R.string.notif_quota_99Plus_text)); - } else if (relativeQuota >= 90.0) { - addNotification(getString(R.string.notif_quota_80plus_title), getString(R.string.notif_quota_90Plus_text)); - } else if (relativeQuota >= 80.0) { - addNotification(getString(R.string.notif_quota_80plus_title), getString(R.string.notif_quota_80Plus_text)); - } } switch (result.getCode()) { case OK: @@ -204,7 +197,6 @@ public class SynchronizationService extends Service implements OnRemoteOperation case QUOTA_EXCEEDED: //Case specific to UploadFileOperation Log.w(TAG, "Quota_EXCEEDED"); - addNotification(getString(R.string.notif_quota_99Plus_title), getString(R.string.notif_quota_execeeded_text)); break; case FILE_NOT_FOUND: //Case specific to DownloadFileOperation @@ -237,26 +229,6 @@ public class SynchronizationService extends Service implements OnRemoteOperation return operation; } - /** - * send notification to inform user that he lacks space on ecloud - * Improvement idea: - * - add translatable message & title - * - make message & title to be a parameter of the method, so we could reuse the function somewhere - * - else with different notification. File conflict for example. - **/ - private void addNotification(String title, String text){ - final NotificationCompat.Builder builder = - new NotificationCompat.Builder(this, AppConstants.notificationChannelID) - .setSmallIcon(android.R.drawable.stat_sys_warning) - .setContentTitle(title) - .setContentText(text) - .setStyle(new NotificationCompat.BigTextStyle().bigText(text)); - // Add as notification - final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - manager.notify(0, builder.build()); - } - - /** * Handler for the class diff --git a/app/src/main/java/foundation/e/drive/utils/AppConstants.java b/app/src/main/java/foundation/e/drive/utils/AppConstants.java index d66429479e82651f4aceca379b293975c0f86baa..8f036bab5944ec83914c7bb741bac893a925b4a7 100644 --- a/app/src/main/java/foundation/e/drive/utils/AppConstants.java +++ b/app/src/main/java/foundation/e/drive/utils/AppConstants.java @@ -9,7 +9,6 @@ package foundation.e.drive.utils; import android.os.Build; -import foundation.e.drive.BuildConfig; import java.text.SimpleDateFormat; import java.util.Locale; @@ -24,26 +23,35 @@ public abstract class AppConstants { public static final String MEDIASYNC_PROVIDER_AUTHORITY = "foundation.e.drive.providers.MediasSyncProvider"; public static final String SETTINGSYNC_PROVIDER_AUTHORITY = "foundation.e.drive.providers.SettingsSyncProvider"; public static final String METERED_NETWORK_ALLOWED_AUTHORITY = "foundation.e.drive.providers.MeteredConnectionAllowedProvider"; - public static final String INITIALIZATION_HAS_BEEN_DONE ="initService_has_run"; + public static final String INITIALIZATION_HAS_BEEN_DONE = "initService_has_run"; public static final String INITIALFOLDERS_NUMBER = "initial_folder_number"; public static final String APPLICATIONS_LIST_FILE_NAME = "packages_list.csv"; public static final String APPLICATIONS_LIST_FILE_NAME_TMP = "tmp_packages_list.csv"; - public static final String SHARED_PREFERENCE_NAME ="preferences"; + public static final String SHARED_PREFERENCE_NAME = "preferences"; public static final String KEY_LAST_SYNC_TIME = "lastSyncTimestamp"; + public static final String ACCOUNT_DATA_NAME = "display_name"; + public static final String ACCOUNT_DATA_USED_QUOTA_KEY = "used_quota"; + public static final String ACCOUNT_DATA_TOTAL_QUOTA_KEY = "total_quota"; + public static final String ACCOUNT_DATA_RELATIVE_QUOTA_KEY = "relative_quota"; + public static final String ACCOUNT_DATA_GROUPS = "group"; + public static final String ACCOUNT_DATA_ALIAS_KEY = "alias"; + public static final String ACCOUNT_DATA_EMAIL = "email"; + public static final String[] MEDIA_SYNCABLE_CATEGORIES = new String[]{"Images", "Movies", "Music", "Ringtones", "Documents", "Podcasts"}; - public static final String[] SETTINGS_SYNCABLE_CATEGORIES = new String[] {"Rom settings"}; + public static final String[] SETTINGS_SYNCABLE_CATEGORIES = new String[]{"Rom settings"}; - public static final String notificationChannelID ="foundation.e.drive"; - public static final String WORK_GENERIC_TAG="eDrive"; - public static final String WORK_INITIALIZATION_TAG="eDrive-init"; - public static final String USER_AGENT = "eos("+getBuildTime()+")-eDrive("+ BuildConfig.VERSION_NAME +")"; + public static final String notificationChannelID = "foundation.e.drive"; + public static final String WORK_GENERIC_TAG = "eDrive"; + public static final String WORK_INITIALIZATION_TAG = "eDrive-init"; + public static final String USER_AGENT = "eos(" + getBuildTime() + ")-eDrive(" + BuildConfig.VERSION_NAME + ")"; /** * Get a readable OS's build date String + * * @return Os'build date */ - private static String getBuildTime(){ + private static String getBuildTime() { long ts = Build.TIME; SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.getDefault()); return sdf.format(ts); 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 b93257c4b6cc391a36e838328fced431095c37cc..e3461d2d481166bf62c1ba05d252156dabc8d46e 100644 --- a/app/src/main/java/foundation/e/drive/utils/CommonUtils.java +++ b/app/src/main/java/foundation/e/drive/utils/CommonUtils.java @@ -46,6 +46,7 @@ import java.util.concurrent.TimeUnit; import foundation.e.drive.R; import foundation.e.drive.models.SyncedFolder; +import foundation.e.drive.work.AccountUserInfoWorker; import foundation.e.drive.work.CreateRemoteFolderWorker; import foundation.e.drive.work.FirstStartWorker; import foundation.e.drive.work.FullScanWorker; @@ -69,6 +70,7 @@ import androidx.work.BackoffPolicy; import androidx.work.Constraints; import androidx.work.Data; import androidx.work.ExistingPeriodicWorkPolicy; +import androidx.work.ExistingWorkPolicy; import androidx.work.NetworkType; import androidx.work.OneTimeWorkRequest; import androidx.work.PeriodicWorkRequest; @@ -169,10 +171,11 @@ public abstract class CommonUtils { /** * Read accountManager settings + * * @param account * @return true if usage of metered connection is allowed */ - public static boolean isMeteredNetworkAllowed(Account account){ + public static boolean isMeteredNetworkAllowed(Account account) { return ContentResolver.getSyncAutomatically(account, METERED_NETWORK_ALLOWED_AUTHORITY); } @@ -189,8 +192,8 @@ public abstract class CommonUtils { oc = OwnCloudClientFactory.createOwnCloudClient(serverUri, context, true); oc.setCredentials(new OwnCloudBasicCredentials(account.name, AccountManager.get(context).getPassword(account))); - Log.d(TAG, "user agent: "+AppConstants.USER_AGENT); - if (!AppConstants.USER_AGENT.equals(OwnCloudClientManagerFactory.getUserAgent()) ){ + Log.d(TAG, "user agent: " + AppConstants.USER_AGENT); + if (!AppConstants.USER_AGENT.equals(OwnCloudClientManagerFactory.getUserAgent())) { OwnCloudClientManagerFactory.setUserAgent(AppConstants.USER_AGENT); } @@ -224,7 +227,7 @@ public abstract class CommonUtils { /** * Tell if there is internet connection * - * @param context Activity or service which are calling this method + * @param context Activity or service which are calling this method * @param meteredNetworkAllowed true if service can use metered network / false either * @return True if there is connection, false either */ @@ -238,14 +241,13 @@ public abstract class CommonUtils { && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) && (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) - || meteredNetworkAllowed)) { + || meteredNetworkAllowed)) { return true; } return false; } - /** * Get mimetype of file from the file itself * @@ -343,11 +345,13 @@ public abstract class CommonUtils { value *= Long.signum(bytes); return String.format(Locale.ENGLISH, "%.1f %cB", value / 1024.0, ci.current()); } + /** * Enqueue a unique periodic worker to look for file to be synchronized (remote files + local files + * * @param workManager the instance of workManager */ - public static void registerPeriodicFullScanWorker(WorkManager workManager){ + public static void registerPeriodicFullScanWorker(WorkManager workManager) { final Constraints constraints = new Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .setRequiresBatteryNotLow(true) @@ -367,20 +371,20 @@ public abstract class CommonUtils { /** * This method create a chain of WorkRequests to perform Initialization tasks: - * Firstly, it creates WorkRequest to create remote root folders on ecloud - * Then, once all folders are present on cloud, run the FirstStartWorker. - * - * in details: - * - Create 9 remote folders on ecloud - * - Run a first fullscan (ObserverService) - * - start SynchronizationService - * - Active FileObserver - * - Schedule periodic fullscan. + * Firstly, it creates WorkRequest to create remote root folders on ecloud + * Then, once all folders are present on cloud, run the FirstStartWorker. + *

+ * in details: + * - Create 9 remote folders on ecloud + * - Run a first fullscan (ObserverService) + * - start SynchronizationService + * - Active FileObserver + * - Schedule periodic fullscan. * * @param syncedFolders List of SyncedFolder for which we want to create a remote folder on ecloud - * @param workManager WorkManager instance to register WorkRequest + * @param workManager WorkManager instance to register WorkRequest */ - public static void registerInitializationWorkers(List syncedFolders, WorkManager workManager){ + public static void registerInitializationWorkers(List syncedFolders, WorkManager workManager) { if (syncedFolders == null || syncedFolders.isEmpty()) { Log.e(TAG, "Can't create remote folders. List is empty"); return; @@ -433,7 +437,7 @@ public abstract class CommonUtils { .build(); } - public static void createNotificationChannel(Context context){ + public static void createNotificationChannel(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { final CharSequence name = context.getString(R.string.notif_channel_name); final String description = context.getString(R.string.notif_channel_description); @@ -456,4 +460,24 @@ public abstract class CommonUtils { Toast.LENGTH_SHORT).show(); } + + /** + * Job for Widget & notification about quota + * + * @param workManager + */ + public static void registerPeriodicUserInfoChecking(WorkManager workManager) { + final Constraints constraints = new Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build(); + + final PeriodicWorkRequest periodicUserInfoScanRequest = + new PeriodicWorkRequest.Builder(AccountUserInfoWorker.class, + 30, TimeUnit.MINUTES) + .addTag(AppConstants.WORK_GENERIC_TAG) + .setConstraints(constraints) + .build(); + + workManager.enqueueUniquePeriodicWork(AccountUserInfoWorker.UNIQUE_WORK_NAME, ExistingPeriodicWorkPolicy.REPLACE, periodicUserInfoScanRequest); + } } diff --git a/app/src/main/java/foundation/e/drive/widgets/EDriveNetworkCallback.java b/app/src/main/java/foundation/e/drive/widgets/EDriveNetworkCallback.java deleted file mode 100644 index 3e0706e57f2491e257eb5e19f8f2fcc9af099ad7..0000000000000000000000000000000000000000 --- a/app/src/main/java/foundation/e/drive/widgets/EDriveNetworkCallback.java +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright © ECORP SAS 2022. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v3.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/gpl.html - */ - -package foundation.e.drive.widgets; - -/** - * @author TheScarastic - */ -public interface EDriveNetworkCallback { - void onComplete(); -} 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 9c0480f4e60a16f0dc269ae2743df3ecb4219f09..f2476841f5833d6ef1ac4e40bfdf754762a110f4 100644 --- a/app/src/main/java/foundation/e/drive/widgets/EDriveWidget.java +++ b/app/src/main/java/foundation/e/drive/widgets/EDriveWidget.java @@ -8,6 +8,13 @@ package foundation.e.drive.widgets; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_ALIAS_KEY; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_EMAIL; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_GROUPS; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_NAME; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_TOTAL_QUOTA_KEY; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_USED_QUOTA_KEY; + import android.accounts.Account; import android.accounts.AccountManager; import android.app.PendingIntent; @@ -16,27 +23,16 @@ import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.net.ConnectivityManager; -import android.net.Network; import android.net.Uri; -import android.os.Handler; -import android.os.HandlerThread; import android.provider.Settings; import android.view.View; import android.widget.RemoteViews; -import com.owncloud.android.lib.common.OwnCloudClient; -import com.owncloud.android.lib.common.UserInfo; -import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation; - import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Calendar; import java.util.Locale; import foundation.e.drive.R; -import foundation.e.drive.operations.GetAliasOperation; import foundation.e.drive.utils.CommonUtils; /** @@ -50,27 +46,20 @@ public class EDriveWidget extends AppWidgetProvider { private static final String ADD_ACCOUNT_WEBPAGE = "https://e.foundation/e-email-invite/"; private static final String GET_ACCOUNT_MANAGER_COMPONENT_NAME = ACCOUNT_MANAGER_PACKAGE_NAME + ".ui.setup.LoginActivity"; + private static final String SETUP_ACCOUNT_PROVIDER_TYPE = "setup_account_provider_type"; private static final String ACCOUNT_PROVIDER_EELO = "eelo"; private static final String SHOW_ALIAS = "show_alias"; private static final String HIDE_ALIAS = "hide_alias"; private static final String COPY_ALIAS = "copy_alias"; - private static boolean showAlias = false; - private static boolean isNetworkAvailable = false; - - private static UserInfo userInfo = null; - private static ArrayList aliases = new ArrayList<>(); private final Calendar calender = Calendar.getInstance(); private final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm", Locale.getDefault()); - private final GetRemoteUserInfoOperation getRemoteUserInfoOperation = new GetRemoteUserInfoOperation(); - private final GetAliasOperation getAliasOperation = new GetAliasOperation(); - private OwnCloudClient client = null; private RemoteViews views; - + private Account account = null; public static String dataForWeb(Long bytes) { final String space = CommonUtils.humanReadableByteCountBin(bytes); @@ -88,8 +77,8 @@ public class EDriveWidget extends AppWidgetProvider { return intent; } - public static int convertIntoMB(Long quota) { - return (int) (quota / 1048576); // 1024.0 * 1024.0 = 1048576.0 + public static int convertIntoMB(String quota) { + return (int) (Long.parseLong(quota) / 1048576); // 1024.0 * 1024.0 = 1048576.0 } public void updateAppWidget(final Context context) { @@ -105,64 +94,25 @@ public class EDriveWidget extends AppWidgetProvider { public void updateAppWidget(final Context context, final AppWidgetManager appWidgetManager, final int appWidgetId) { final AccountManager accountManager = AccountManager.get(context); - final Account account = CommonUtils.getAccount(context.getString(R.string.eelo_account_type), - accountManager); - if (account == null || isNetworkAvailable) { - noAccountView(context); - appWidgetManager.updateAppWidget(appWidgetId, views); - return; + // Make Last check to see if account is available + if (account == null) { + account = CommonUtils.getAccount(context.getString(R.string.eelo_account_type), + accountManager); } - client = CommonUtils.getOwnCloudClient(account, context); - final HandlerThread handlerThread = new HandlerThread("Network Request"); - handlerThread.start(); - final Handler mHandler = new Handler(handlerThread.getLooper()); - - final EDriveNetworkCallback callback = new EDriveNetworkCallback() { - @Override - public void onComplete() { - onNetworkRequestCompleted(context); - appWidgetManager.updateAppWidget(appWidgetId, views); - } - }; - - mHandler.post(new Runnable() { - @Override - public void run() { - if (client != null) { - RemoteOperationResult ocsResult = getRemoteUserInfoOperation.execute(client); - if (ocsResult.isSuccess() && ocsResult.getData() != null) { - userInfo = (UserInfo) ocsResult.getData().get(0); - } - RemoteOperationResult aliasResult = getAliasOperation.execute(client); - if (aliasResult.isSuccess() && aliasResult.getData() != null) { - aliases = aliasResult.getData(); - } - } - callback.onComplete(); - } - }); - } - - @Override - public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { - // There may be multiple widgets active, so update all of them - for (int appWidgetId : appWidgetIds) { - updateAppWidget(context, appWidgetManager, appWidgetId); + if (account == null && CommonUtils.haveNetworkConnection(context, true)) { + noAccountView(context); + } else { + onAccountAvailable(context, accountManager); } - super.onUpdate(context, appWidgetManager, appWidgetIds); + appWidgetManager.updateAppWidget(appWidgetId, views); } @Override public void onEnabled(Context context) { - updateAppWidget(context); super.onEnabled(context); - } - - @Override - public void onDisabled(Context context) { - // Enter relevant functionality for when the last widget is disabled + updateAppWidget(context); } @Override @@ -170,8 +120,7 @@ public class EDriveWidget extends AppWidgetProvider { final String action = intent.getAction(); if (action == null) return; switch (action) { - case Intent.ACTION_BOOT_COMPLETED: - registerConnectivityCallback(context); + case AppWidgetManager.ACTION_APPWIDGET_UPDATE: case AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION: updateAppWidget(context); break; @@ -207,8 +156,12 @@ public class EDriveWidget extends AppWidgetProvider { views.setTextViewText(R.id.summary, context.getString(R.string.login_summary)); } - private void onNetworkRequestCompleted(Context context) { - if (!isNetworkAvailable && userInfo == null) { + private void onAccountAvailable(Context context, 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); + + if (email == null || email.trim().isEmpty()) { views = new RemoteViews(context.getPackageName(), R.layout.e_drive_widget_login); views.setViewVisibility(R.id.button_container, View.GONE); views.setTextViewText(R.id.summary, context.getString(R.string.no_internet_widget)); @@ -217,47 +170,42 @@ public class EDriveWidget extends AppWidgetProvider { views = new RemoteViews(context.getPackageName(), R.layout.e_drive_widget); - // Construct the RemoteViews object - final int usedMB = convertIntoMB(userInfo.quota.used); - final int totalMB = convertIntoMB(userInfo.quota.total); - - views.setTextViewText(R.id.email, userInfo.id); - if (!userInfo.alternateDisplayName.isEmpty()) { - views.setTextViewText(R.id.name, userInfo.alternateDisplayName); - } else { - views.setTextViewText(R.id.name, userInfo.displayName); - } + views.setTextViewText(R.id.email, email); + views.setTextViewText(R.id.name, accountManager.getUserData(account, ACCOUNT_DATA_NAME)); - views.setProgressBar(R.id.progress, totalMB, usedMB, false); + views.setProgressBar(R.id.progress, convertIntoMB(totalQuota), convertIntoMB(usedQuota), false); views.setTextViewText(R.id.planName, context.getString(R.string.free_plan, - CommonUtils.humanReadableByteCountBin(userInfo.quota.total))); + CommonUtils.humanReadableByteCountBin(Long.parseLong(totalQuota)))); - for (String group : userInfo.groups) { + String[] groups = accountManager.getUserData(account, ACCOUNT_DATA_GROUPS).split(","); + for (String group : groups) { if (group.contains("premium-")) { views.setTextViewText(R.id.planName, context.getString(R.string.premium_plan, group.split("-")[1])); break; } } + views.setTextViewText(R.id.status, context.getString(R.string.progress_status, - CommonUtils.humanReadableByteCountBin(userInfo.quota.used), - CommonUtils.humanReadableByteCountBin(userInfo.quota.total))); + CommonUtils.humanReadableByteCountBin(Long.parseLong(usedQuota)), + CommonUtils.humanReadableByteCountBin(Long.parseLong(totalQuota)))); views.setTextViewText(R.id.sync, context.getString(R.string.last_synced, sdf.format(calender.getTime()))); + String aliases = accountManager.getUserData(account, ACCOUNT_DATA_ALIAS_KEY); if (aliases.isEmpty()) { views.setViewVisibility(R.id.show_alias, View.GONE); views.setViewVisibility(R.id.alias1_container, View.GONE); views.setViewVisibility(R.id.hide_alias, View.GONE); } else { - views.setTextViewText(R.id.alias1, context.getString(R.string.alias_dot) + aliases.get(0)); + views.setTextViewText(R.id.alias1, context.getString(R.string.alias_dot) + aliases.split(",")[0]); views.setOnClickPendingIntent(R.id.show_alias, getPendingSelfIntent(context, SHOW_ALIAS, null)); views.setOnClickPendingIntent(R.id.hide_alias, getPendingSelfIntent(context, HIDE_ALIAS, null)); views.setOnClickPendingIntent(R.id.alias1_clipboard, getPendingSelfIntent(context, COPY_ALIAS, - String.valueOf(aliases.get(0)))); + String.valueOf(aliases.split(",")[0]))); if (showAlias) { views.setViewVisibility(R.id.show_alias, View.GONE); @@ -275,8 +223,8 @@ public class EDriveWidget extends AppWidgetProvider { views.setOnClickPendingIntent(R.id.settings, pendingIntentSettings); final PendingIntent pendingIntentUpgrade = PendingIntent.getActivity(context, 0, - buildIntent(Intent.ACTION_VIEW, String.format(WEBPAGE, userInfo.id, - dataForWeb(userInfo.quota.total))), + buildIntent(Intent.ACTION_VIEW, String.format(WEBPAGE, email, + dataForWeb(Long.parseLong(totalQuota)))), PendingIntent.FLAG_IMMUTABLE); views.setOnClickPendingIntent(R.id.upgrade, pendingIntentUpgrade); } @@ -289,26 +237,4 @@ public class EDriveWidget extends AppWidgetProvider { } return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE); } - - private void registerConnectivityCallback(final Context context) { - ConnectivityManager cm = (ConnectivityManager) context.getSystemService( - Context.CONNECTIVITY_SERVICE); - cm.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() { - @Override - public void onAvailable(Network network) { - if (!isNetworkAvailable) { - isNetworkAvailable = true; - updateAppWidget(context); - } - } - - @Override - public void onLost(Network network) { - if (isNetworkAvailable) { - isNetworkAvailable = false; - updateAppWidget(context); - } - } - }); - } } \ No newline at end of file diff --git a/app/src/main/java/foundation/e/drive/work/AccountUserInfoWorker.java b/app/src/main/java/foundation/e/drive/work/AccountUserInfoWorker.java new file mode 100644 index 0000000000000000000000000000000000000000..26be1483474b07cab568ffd5383f1280113f5784 --- /dev/null +++ b/app/src/main/java/foundation/e/drive/work/AccountUserInfoWorker.java @@ -0,0 +1,167 @@ +/* + * Copyright © ECORP SAS 2022. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + */ +package foundation.e.drive.work; + +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_ALIAS_KEY; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_EMAIL; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_GROUPS; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_NAME; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_RELATIVE_QUOTA_KEY; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_TOTAL_QUOTA_KEY; +import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_USED_QUOTA_KEY; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.app.NotificationManager; +import android.appwidget.AppWidgetManager; +import android.content.Context; +import android.content.Intent; + +import androidx.annotation.NonNull; +import androidx.core.app.NotificationCompat; +import androidx.work.Worker; +import androidx.work.WorkerParameters; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.UserInfo; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation; + +import java.util.ArrayList; + +import foundation.e.drive.R; +import foundation.e.drive.activity.AccountsActivity; +import foundation.e.drive.operations.GetAliasOperation; +import foundation.e.drive.utils.AppConstants; +import foundation.e.drive.utils.CommonUtils; +import foundation.e.drive.widgets.EDriveWidget; + +/** + * @author vincent Bourgmayer + * @author TheScarastic + */ +public class AccountUserInfoWorker extends Worker { + public static final String UNIQUE_WORK_NAME = "AccountUserInfoWorker"; + final AccountManager accountManager; + final GetRemoteUserInfoOperation getRemoteUserInfoOperation = new GetRemoteUserInfoOperation(); + final GetAliasOperation getAliasOperation = new GetAliasOperation(); + private final Context mContext; + private Account account; + + public AccountUserInfoWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { + super(context, workerParams); + mContext = context; + accountManager = AccountManager.get(context); + } + + @NonNull + @Override + public Result doWork() { + account = CommonUtils.getAccount(mContext.getString(R.string.eelo_account_type), + accountManager); + OwnCloudClient client = CommonUtils.getOwnCloudClient(account, mContext); + + if (account != null && client != null) { + if (fetchUserInfo(client) && fetchAliases(client)) { + Glide.with(mContext) + .load(client.getBaseUri() + AccountsActivity.NON_OFFICIAL_AVATAR_PATH + + client.getCredentials().getUsername() + "/" + 300) + .diskCacheStrategy(DiskCacheStrategy.ALL) + .preload(); + updateWidget(mContext); + return Result.success(); + } else { + return Result.retry(); + } + } + return Result.failure(); + } + + private boolean fetchUserInfo(final OwnCloudClient client) { + final RemoteOperationResult ocsResult = getRemoteUserInfoOperation.execute(client); + + if (ocsResult.isSuccess() && ocsResult.getData() != null && !ocsResult.getData().isEmpty()) { + final UserInfo userInfo = (UserInfo) ocsResult.getData().get(0); + + final String name; + if (userInfo.displayName == null || userInfo.displayName.isEmpty()) { + name = userInfo.alternateDisplayName; + } else { + name = userInfo.displayName; + } + final double relativeQuota = userInfo.getQuota().relative; + final long totalQuota = userInfo.getQuota().total; + final long usedQuota = userInfo.getQuota().used; + final String groups = String.join(",", userInfo.groups); + final String email = userInfo.id; + + accountManager.setUserData(account, ACCOUNT_DATA_NAME, name); + accountManager.setUserData(account, ACCOUNT_DATA_EMAIL, email); + accountManager.setUserData(account, ACCOUNT_DATA_GROUPS, groups); + accountManager.setUserData(account, ACCOUNT_DATA_TOTAL_QUOTA_KEY, "" + totalQuota); + accountManager.setUserData(account, ACCOUNT_DATA_RELATIVE_QUOTA_KEY, "" + relativeQuota); + accountManager.setUserData(account, ACCOUNT_DATA_USED_QUOTA_KEY, "" + usedQuota); + + addNotifAboutQuota(relativeQuota); + return true; + } + return false; + } + + private void addNotifAboutQuota(final double relativeQuota) { + final Context context = getApplicationContext(); + if (relativeQuota >= 99.0) { + addNotification(context.getString(R.string.notif_quota_99Plus_title), context.getString(R.string.notif_quota_99Plus_text)); + } else if (relativeQuota >= 90.0) { + addNotification(context.getString(R.string.notif_quota_80plus_title), context.getString(R.string.notif_quota_90Plus_text)); + } else if (relativeQuota >= 80.0) { + addNotification(context.getString(R.string.notif_quota_80plus_title), context.getString(R.string.notif_quota_80Plus_text)); + } + } + + /** + * send notification to inform user that he lacks space on ecloud + * Improvement idea: + * - add translatable message & title + * - make message & title to be a parameter of the method, so we could reuse the function somewhere + * - else with different notification. File conflict for example. + **/ + private void addNotification(String title, String text) { + final NotificationCompat.Builder builder = + new NotificationCompat.Builder(getApplicationContext(), AppConstants.notificationChannelID) + .setSmallIcon(android.R.drawable.stat_sys_warning) + .setContentTitle(title) + .setContentText(text) + .setStyle(new NotificationCompat.BigTextStyle().bigText(text)); + // Add as notification + final NotificationManager manager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); + manager.notify(0, builder.build()); + } + + private boolean fetchAliases(final OwnCloudClient client) { + final RemoteOperationResult ocsResult = getAliasOperation.execute(client); + String aliases = ""; + if (ocsResult.isSuccess() && ocsResult.getData() != null && !ocsResult.getData().isEmpty()) { + ArrayList alias = new ArrayList<>(ocsResult.getData().size()); + for (Object object : ocsResult.getData()) { + alias.add(object.toString()); + } + aliases = String.join(",", alias); + } + accountManager.setUserData(account, ACCOUNT_DATA_ALIAS_KEY, aliases); + return true; + } + + private void updateWidget(final Context context) { + final Intent updateIntent = new Intent(context, EDriveWidget.class); + updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + context.sendBroadcast(updateIntent); + } +}