diff --git a/app/build.gradle b/app/build.gradle index 8a721d8e..df417d05 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -162,6 +162,8 @@ dependencies { implementation "org.redundent:kotlin-xml-builder:1.5.3" implementation "io.github.wulkanowy:signer-android:0.1.1" + + implementation "androidx.work:work-runtime-ktx:${versions.work}" } repositories { mavenCentral() diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9ffe0db4..2d1ad42c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -222,10 +222,6 @@ - diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/App.java b/app/src/main/java/pl/szczodrzynski/edziennik/App.java index 9da8ca74..230bce79 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/App.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/App.java @@ -20,10 +20,13 @@ import android.util.Base64; import android.util.Log; import android.util.Pair; +import androidx.annotation.RequiresApi; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.work.Configuration; + import com.chuckerteam.chucker.api.ChuckerCollector; import com.chuckerteam.chucker.api.ChuckerInterceptor; import com.chuckerteam.chucker.api.RetentionManager; -import com.evernote.android.job.JobManager; import com.google.android.gms.security.ProviderInstaller; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; @@ -55,8 +58,6 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; -import androidx.annotation.RequiresApi; -import androidx.appcompat.app.AppCompatDelegate; import cat.ereza.customactivityoncrash.config.CaocConfig; import im.wangchao.mhttp.MHttp; import im.wangchao.mhttp.internal.cookie.PersistentCookieJar; @@ -66,7 +67,6 @@ import me.leolin.shortcutbadger.ShortcutBadger; import okhttp3.ConnectionSpec; import okhttp3.OkHttpClient; import okhttp3.TlsVersion; -import pl.szczodrzynski.edziennik.ui.modules.base.CrashActivity; import pl.szczodrzynski.edziennik.data.api.Edziennik; import pl.szczodrzynski.edziennik.data.api.Iuczniowie; import pl.szczodrzynski.edziennik.data.api.Librus; @@ -77,24 +77,32 @@ import pl.szczodrzynski.edziennik.data.db.modules.debuglog.DebugLog; import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore; import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull; -import pl.szczodrzynski.edziennik.utils.models.AppConfig; import pl.szczodrzynski.edziennik.network.NetworkUtils; import pl.szczodrzynski.edziennik.network.TLSSocketFactory; -import pl.szczodrzynski.edziennik.receivers.JobsCreator; -import pl.szczodrzynski.edziennik.sync.SyncJob; +import pl.szczodrzynski.edziennik.sync.SyncWorker; +import pl.szczodrzynski.edziennik.ui.modules.base.CrashActivity; import pl.szczodrzynski.edziennik.utils.PermissionChecker; import pl.szczodrzynski.edziennik.utils.Themes; import pl.szczodrzynski.edziennik.utils.Utils; +import pl.szczodrzynski.edziennik.utils.models.AppConfig; import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_LIBRUS; import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_MOBIDZIENNIK; import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_VULCAN; -public class App extends androidx.multidex.MultiDexApplication { +public class App extends androidx.multidex.MultiDexApplication implements Configuration.Provider { private static final String TAG = "App"; public static int profileId = -1; private Context mContext; + @Override + public Configuration getWorkManagerConfiguration() { + return new Configuration.Builder() + .setMinimumLoggingLevel(Log.VERBOSE) + .build(); + } + + public static final int REQUEST_TIMEOUT = 10 * 1000; // notifications @@ -301,12 +309,11 @@ public class App extends androidx.multidex.MultiDexApplication { //profileLoadById(appSharedPrefs.getInt("current_profile_id", 1)); - JobManager.create(this).addJobCreator(new JobsCreator()); if (appConfig.registerSyncEnabled) { - SyncJob.schedule(this); + SyncWorker.Companion.scheduleNext(this); } else { - SyncJob.clear(); + SyncWorker.Companion.cancelNext(this); } db.metadataDao().countUnseen().observeForever(count -> { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt index c03db59c..7ea38470 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt @@ -324,4 +324,6 @@ fun String.crc32(): Long { val crc = CRC32() crc.update(toByteArray()) return crc.value -} \ No newline at end of file +} + +fun Long.formatDate(format: String = "yyyy-MM-dd HH:mm:ss"): String = SimpleDateFormat(format).format(this) \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt index 41de1a6e..cc04e8d0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt @@ -2,10 +2,7 @@ package pl.szczodrzynski.edziennik import android.app.Activity import android.app.ActivityManager -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter +import android.content.* import android.graphics.BitmapFactory import android.graphics.drawable.BitmapDrawable import android.os.* @@ -19,6 +16,7 @@ import androidx.core.graphics.ColorUtils import androidx.lifecycle.Observer import androidx.navigation.NavOptions import com.danimahardhika.cafebar.CafeBar +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.mikepenz.iconics.IconicsColor import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.IconicsSize @@ -37,11 +35,12 @@ import pl.szczodrzynski.edziennik.App.APP_URL import pl.szczodrzynski.edziennik.api.v2.ApiService import pl.szczodrzynski.edziennik.api.v2.events.* import pl.szczodrzynski.edziennik.api.v2.events.requests.SyncProfileRequest +import pl.szczodrzynski.edziennik.api.v2.events.requests.SyncRequest import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface.* import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.* import pl.szczodrzynski.edziennik.databinding.ActivitySzkolnyBinding import pl.szczodrzynski.edziennik.network.ServerRequest -import pl.szczodrzynski.edziennik.sync.SyncJob +import pl.szczodrzynski.edziennik.sync.AppManagerDetectedEvent import pl.szczodrzynski.edziennik.ui.dialogs.changelog.ChangelogDialog import pl.szczodrzynski.edziennik.ui.modules.agenda.AgendaFragment import pl.szczodrzynski.edziennik.ui.modules.announcements.AnnouncementsFragment @@ -370,7 +369,7 @@ class MainActivity : AppCompatActivity() { isStoragePermissionGranted() - SyncJob.schedule(app) + //SyncWorker.scheduleNext(app) // APP BACKGROUND if (app.appConfig.appBackground != null) { @@ -499,7 +498,7 @@ class MainActivity : AppCompatActivity() { profileListEmptyListener() } DRAWER_PROFILE_SYNC_ALL -> { - SyncJob.run(app) + ApiService.startAndRequest(this, SyncRequest()) } else -> { loadTarget(id) @@ -569,6 +568,47 @@ class MainActivity : AppCompatActivity() { @Subscribe(threadMode = ThreadMode.MAIN) fun onSyncErrorEvent(event: SyncErrorEvent) { + } + @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) + fun onAppManagerDetectedEvent(event: AppManagerDetectedEvent) { + if (app.appConfig.dontShowAppManagerDialog) + return + MaterialAlertDialogBuilder(this) + .setTitle(R.string.app_manager_dialog_title) + .setMessage(R.string.app_manager_dialog_text) + .setPositiveButton(R.string.ok) { dialog, which -> + try { + val intent = Intent() + intent.component = ComponentName( + "com.huawei.systemmanager", + "com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity" + ) + startActivity(intent) + } catch (e: Exception) { + e.printStackTrace() + try { + val intent = Intent() + intent.component = ComponentName( + "com.asus.mobilemanager", + "com.asus.mobilemanager.MainActivity" + ) + startActivity(intent) + } catch (e: Exception) { + try { + startActivity(Intent(android.provider.Settings.ACTION_SETTINGS)) + } catch (e: Exception) { + e.printStackTrace() + Toast.makeText(this, R.string.app_manager_open_failed, Toast.LENGTH_SHORT).show() + } + } + } + } + .setNeutralButton(R.string.dont_ask_again) { dialog, which -> + app.appConfig.dontShowAppManagerDialog = true + app.saveConfig("dontShowAppManagerDialog") + } + .setCancelable(false) + .show() } private fun fragmentToFeature(currentFragment: Int): Int { return when (currentFragment) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/Notifier.java b/app/src/main/java/pl/szczodrzynski/edziennik/Notifier.java index 7b316ed8..660647b9 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/Notifier.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/Notifier.java @@ -19,14 +19,11 @@ import java.util.List; import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull; import pl.szczodrzynski.edziennik.receivers.BootReceiver; -import pl.szczodrzynski.edziennik.sync.SyncJob; -import pl.szczodrzynski.edziennik.sync.SyncService; import pl.szczodrzynski.edziennik.utils.models.Date; import pl.szczodrzynski.edziennik.utils.models.Time; import static androidx.core.app.NotificationCompat.PRIORITY_DEFAULT; import static androidx.core.app.NotificationCompat.PRIORITY_MAX; -import static pl.szczodrzynski.edziennik.sync.SyncService.ACTION_CANCEL; public class Notifier { @@ -127,17 +124,17 @@ public class Notifier { | |__| | (_| | || (_| | | |__| | __/ |_ |_____/ \__,_|\__\__,_| \_____|\___|\_*/ public Notification notificationGetDataShow(int maxProgress) { - Intent notificationIntent = new Intent(app.getContext(), SyncService.class); + /*Intent notificationIntent = new Intent(app.getContext(), SyncService.class); notificationIntent.setAction(ACTION_CANCEL); PendingIntent pendingIntent = PendingIntent.getService(app.getContext(), 0, - notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT); + notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);*/ getDataNotificationBuilder = new NotificationCompat.Builder(app, GROUP_KEY_GET_DATA) .setSmallIcon(android.R.drawable.stat_sys_download) .setColor(notificationColor) .setContentTitle(app.getString(R.string.notification_get_data_title)) .setContentText(app.getString(R.string.notification_get_data_text)) - .addAction(R.drawable.ic_notification, app.getString(R.string.notification_get_data_cancel), pendingIntent) + //.addAction(R.drawable.ic_notification, app.getString(R.string.notification_get_data_cancel), pendingIntent) //.setGroup(GROUP_KEY_GET_DATA) .setOngoing(true) .setProgress(maxProgress, 0, false) @@ -209,10 +206,8 @@ public class Notifier { @Override protected void onHandleIntent(Intent intent) { - SyncJob.run((App) getApplication(), intent.getExtras().getInt("failedProfileId", -1), -1); - NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - assert notificationManager != null; - notificationManager.cancel(ID_GET_DATA_ERROR); + + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.java b/app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.java index 21496078..7a6875d8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.java @@ -28,6 +28,8 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; +import pl.szczodrzynski.edziennik.api.v2.ApiService; +import pl.szczodrzynski.edziennik.api.v2.events.requests.SyncRequest; import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull; import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange; import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonFull; @@ -38,7 +40,6 @@ import pl.szczodrzynski.edziennik.utils.models.ItemWidgetTimetableModel; import pl.szczodrzynski.edziennik.utils.models.Time; import pl.szczodrzynski.edziennik.utils.models.Week; import pl.szczodrzynski.edziennik.widgets.WidgetConfig; -import pl.szczodrzynski.edziennik.sync.SyncJob; import pl.szczodrzynski.edziennik.widgets.timetable.LessonDetailsActivity; import pl.szczodrzynski.edziennik.widgets.timetable.WidgetTimetableService; @@ -65,8 +66,8 @@ public class WidgetTimetable extends AppWidgetProvider { @Override public void onReceive(Context context, Intent intent) { - if (ACTION_SYNC_DATA.equals(intent.getAction())){ - SyncJob.run((App) context.getApplicationContext()); + if (ACTION_SYNC_DATA.equals(intent.getAction())) { + ApiService.Companion.startAndRequest(context, new SyncRequest()); } super.onReceive(context, intent); } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/ApiService.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/ApiService.kt index 0f8c0d35..d2d39796 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/ApiService.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/ApiService.kt @@ -39,6 +39,10 @@ class ApiService : Service() { fun start(context: Context) { context.startService(Intent(context, ApiService::class.java)) } + fun startAndRequest(context: Context, request: Any) { + context.startService(Intent(context, ApiService::class.java)) + EventBus.getDefault().postSticky(request) + } } private val app by lazy { applicationContext as App } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Edziennik.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Edziennik.java index 7b9997ca..c73ccd80 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Edziennik.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Edziennik.java @@ -63,7 +63,6 @@ import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull; import pl.szczodrzynski.edziennik.data.db.modules.teams.Team; import pl.szczodrzynski.edziennik.network.ServerRequest; -import pl.szczodrzynski.edziennik.sync.SyncJob; import pl.szczodrzynski.edziennik.utils.Themes; import pl.szczodrzynski.edziennik.utils.models.Date; import pl.szczodrzynski.edziennik.utils.models.Notification; @@ -116,7 +115,6 @@ import static pl.szczodrzynski.edziennik.data.db.modules.notification.Notificati import static pl.szczodrzynski.edziennik.data.db.modules.notification.Notification.TYPE_SERVER_MESSAGE; import static pl.szczodrzynski.edziennik.data.db.modules.notification.Notification.TYPE_TIMETABLE_LESSON_CHANGE; import static pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile.REGISTRATION_ENABLED; -import static pl.szczodrzynski.edziennik.sync.SyncService.PROFILE_MAX_PROGRESS; import static pl.szczodrzynski.edziennik.utils.Utils.d; import static pl.szczodrzynski.edziennik.utils.Utils.ns; @@ -592,12 +590,7 @@ public class Edziennik { } public void notifyAndReload() { - app.notifier.postAll(null); - app.saveConfig(); - SyncJob.schedule(app); - Intent i = new Intent(Intent.ACTION_MAIN) - .putExtra("reloadProfileId", -1); - app.sendBroadcast(i); + // TODO \/ Intent intent = new Intent(app.getContext(), WidgetTimetable.class); intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); @@ -751,7 +744,7 @@ public class Edziennik { MaterialDialog progressDialog = new MaterialDialog.Builder(activity) .title(dialogTitle) .content(dialogText) - .progress(false, PROFILE_MAX_PROGRESS, false) + .progress(false, 110, false) .canceledOnTouchOutside(false) .show(); SyncCallback guiSyncCallback = new SyncCallback() { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/receivers/BootReceiver.java b/app/src/main/java/pl/szczodrzynski/edziennik/receivers/BootReceiver.java index 694bead6..b1524237 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/receivers/BootReceiver.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/receivers/BootReceiver.java @@ -11,16 +11,17 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Build; -import androidx.core.content.FileProvider; import android.widget.Toast; +import androidx.core.content.FileProvider; + import java.io.File; import java.util.List; import pl.szczodrzynski.edziennik.App; import pl.szczodrzynski.edziennik.R; import pl.szczodrzynski.edziennik.network.ServerRequest; -import pl.szczodrzynski.edziennik.sync.SyncJob; +import pl.szczodrzynski.edziennik.sync.SyncWorker; import pl.szczodrzynski.edziennik.utils.Utils; import static android.content.Context.DOWNLOAD_SERVICE; @@ -81,7 +82,7 @@ public class BootReceiver extends BroadcastReceiver { } else { - SyncJob.schedule(app); + SyncWorker.Companion.scheduleNext(app); if (app.networkUtils.isOnline()) { checkUpdate(context, intent); diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/receivers/JobsCreator.java b/app/src/main/java/pl/szczodrzynski/edziennik/receivers/JobsCreator.java deleted file mode 100644 index 0c96d14e..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/receivers/JobsCreator.java +++ /dev/null @@ -1,22 +0,0 @@ -package pl.szczodrzynski.edziennik.receivers; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.evernote.android.job.Job; -import com.evernote.android.job.JobCreator; - -import pl.szczodrzynski.edziennik.sync.SyncJob; - -public class JobsCreator implements JobCreator { - @Override - @Nullable - public Job create(@NonNull String tag) { - switch (tag) { - case SyncJob.TAG: - return new SyncJob(); - default: - return null; - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/receivers/SzkolnyReceiver.kt b/app/src/main/java/pl/szczodrzynski/edziennik/receivers/SzkolnyReceiver.kt index 292b3875..f3a6ad36 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/receivers/SzkolnyReceiver.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/receivers/SzkolnyReceiver.kt @@ -7,19 +7,20 @@ package pl.szczodrzynski.edziennik.receivers import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import org.greenrobot.eventbus.EventBus import pl.szczodrzynski.edziennik.api.v2.ApiService -import pl.szczodrzynski.edziennik.api.v2.events.requests.* +import pl.szczodrzynski.edziennik.api.v2.events.requests.ServiceCloseRequest +import pl.szczodrzynski.edziennik.api.v2.events.requests.SyncProfileRequest +import pl.szczodrzynski.edziennik.api.v2.events.requests.SyncRequest +import pl.szczodrzynski.edziennik.api.v2.events.requests.TaskCancelRequest class SzkolnyReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { - context?.startService(Intent(context, ApiService::class.java)) + context ?: return when (intent?.extras?.getString("task", null)) { - "ServiceCloseRequest" -> EventBus.getDefault().post(ServiceCloseRequest()) - "TaskCancelRequest" -> EventBus.getDefault().post(TaskCancelRequest(intent.extras?.getInt("taskId", -1) ?: return)) - "SyncRequest" -> EventBus.getDefault().post(SyncRequest()) - "SyncProfileRequest" -> EventBus.getDefault().post(SyncProfileRequest(intent.extras?.getInt("profileId", -1) ?: return)) - "AnnouncementsReadRequest" -> EventBus.getDefault().post(AnnouncementsReadRequest(intent.extras?.getInt("profileId", -1) ?: return)) + "ServiceCloseRequest" -> ApiService.startAndRequest(context, ServiceCloseRequest()) + "TaskCancelRequest" -> ApiService.startAndRequest(context, TaskCancelRequest(intent.extras?.getInt("taskId", -1) ?: return)) + "SyncRequest" -> ApiService.startAndRequest(context, SyncRequest()) + "SyncProfileRequest" -> ApiService.startAndRequest(context, SyncProfileRequest(intent.extras?.getInt("profileId", -1) ?: return)) } } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/sync/AppManagerDetectedEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/sync/AppManagerDetectedEvent.kt new file mode 100644 index 00000000..10d93dfc --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/sync/AppManagerDetectedEvent.kt @@ -0,0 +1,3 @@ +package pl.szczodrzynski.edziennik.sync + +class AppManagerDetectedEvent(val failedWorkTimestamps: List) \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/sync/MyFirebaseMessagingService.java b/app/src/main/java/pl/szczodrzynski/edziennik/sync/MyFirebaseMessagingService.java index 312724b7..17102d23 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/sync/MyFirebaseMessagingService.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/sync/MyFirebaseMessagingService.java @@ -17,6 +17,9 @@ import pl.szczodrzynski.edziennik.App; import pl.szczodrzynski.edziennik.BuildConfig; import pl.szczodrzynski.edziennik.MainActivity; import pl.szczodrzynski.edziennik.R; +import pl.szczodrzynski.edziennik.api.v2.ApiService; +import pl.szczodrzynski.edziennik.api.v2.events.requests.SyncProfileRequest; +import pl.szczodrzynski.edziennik.api.v2.events.requests.SyncRequest; import pl.szczodrzynski.edziennik.data.db.modules.events.Event; import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull; import pl.szczodrzynski.edziennik.data.db.modules.events.EventType; @@ -111,7 +114,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService { app.notifier.postAll(profile); app.saveConfig("notifications");*/ d(TAG, "Syncing profile " + profile.getId()); - SyncJob.run(app, -1, profile.getId()); + ApiService.Companion.startAndRequest(app, new SyncProfileRequest(profile.getId(), null)); } else { /*app.notifier.add(new Notification(app.getContext(), remoteMessage.getData().get("message")) .withProfileData(profile.id, profile.name) @@ -122,7 +125,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService { app.notifier.postAll(profile); app.saveConfig("notifications");*/ d(TAG, "Syncing profile " + profile.getId()); - SyncJob.run(app, -1, profile.getId()); + ApiService.Companion.startAndRequest(app, new SyncProfileRequest(profile.getId(), null)); } } }); diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/sync/SyncJob.java b/app/src/main/java/pl/szczodrzynski/edziennik/sync/SyncJob.java deleted file mode 100644 index 3deddb25..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/sync/SyncJob.java +++ /dev/null @@ -1,153 +0,0 @@ -package pl.szczodrzynski.edziennik.sync; - -import android.content.Context; - -import androidx.annotation.NonNull; - -import android.net.ConnectivityManager; -import android.net.NetworkInfo; - -import com.evernote.android.job.Job; -import com.evernote.android.job.JobManager; -import com.evernote.android.job.JobRequest; - -import java.util.Set; - -import pl.szczodrzynski.edziennik.App; - -import static pl.szczodrzynski.edziennik.utils.Utils.d; - -public class SyncJob extends Job { - - public static final String TAG = "SyncJob"; - private static int retryCount = 0; - - public static void schedule(App app) { - schedule(app, false); - } - - /** - * Forces a SyncJob to be scheduled. Does nothing if it's already scheduled. - */ - public static void schedule(App app, boolean internetError) { - int count = count(); - if (count > 0) { - d(TAG, "Job is already scheduled"); - return; - } - if (app.appConfig.registerSyncEnabled) { - //Toast.makeText(app, "Scheduling an alarm", Toast.LENGTH_SHORT).show(); - long timeout = 1000 * app.appConfig.registerSyncInterval; - if (internetError) { - retryCount++; - timeout = 1000 * (30*retryCount*retryCount); // 30sec, 2min, 4min 30sec, 8min, 12min 30sec, ... - timeout = Math.min(timeout, 30 * 60 * 1000); // max 30min between retries - if (timeout > 1000 * app.appConfig.registerSyncInterval) { - timeout = 1000 * app.appConfig.registerSyncInterval; - } - } - - new JobRequest.Builder(SyncJob.TAG) - .setExecutionWindow((long) (timeout - (0.1 * timeout)), (long) (timeout + (0.1 * timeout))) - //.setRequiredNetworkType(JobRequest.NetworkType.CONNECTED) - .build() - .schedule(); - if (!internetError) { - retryCount = 0; - } - } - else { - clear(); - } - } - public static int count() { - Set jobRequests = JobManager.instance().getAllJobRequestsForTag(SyncJob.TAG); - if (App.devMode) { - for (JobRequest jobRequest: jobRequests) { - d(TAG, "JOBLIST: Found at "+jobRequest.getStartMs()+" - "+jobRequest.getEndMs()); - } - } - return jobRequests.size(); - } - public static void clear() { - JobManager.instance().cancelAllForTag(SyncJob.TAG); - } - - /** - * Deletes every scheduled SyncJob and then reschedules it. - */ - public static void update(App app) { - update(app, false); - } - public static void update(App app, boolean internetError) { - app.debugLogAsync("SyncJob update internetError="+internetError); - clear(); - schedule(app, internetError); - } - public static void run(App app) { - app.debugLogAsync("SyncJob run with no IDs"); - clear(); - runService(app, app.getContext(), -1, -1); - /*new JobRequest.Builder(SyncJob.TAG) - .startNow() - .build() - .schedule();*/ - } - - public static void run(App app, int firstProfileId, int targetProfileId) { - app.debugLogAsync("SyncJob run with firstProfileId="+firstProfileId+", targetProfileId="+targetProfileId); - clear(); - runService(app, app.getContext(), firstProfileId, targetProfileId); - /* PersistableBundleCompat extras = new PersistableBundleCompat(); - extras.putInt("firstProfileId", firstProfileId); - extras.putInt("targetProfileId", targetProfileId); - new JobRequest.Builder(SyncJob.TAG) - .startNow() - .setExtras(extras) - .build() - .schedule();*/ - } - - @Override - @NonNull - protected Result onRunJob(@NonNull Params params) { - //Log.d(TAG, "Job is running!"); - - App app = (App) getContext().getApplicationContext(); - - int firstProfileId = params.getExtras().getInt("firstProfileId", -1); - int targetProfileId = params.getExtras().getInt("targetProfileId", -1); - - runService(app, getContext(), firstProfileId, targetProfileId); - - return Result.SUCCESS; - } - - private static void runService(App app, Context context, int firstProfileId, int targetProfileId) { - - SyncService.firstProfileId = firstProfileId; - SyncService.targetProfileId = targetProfileId; - - app.debugLog("SyncJob runService with firstProfileId="+firstProfileId+", targetProfileId="+targetProfileId); - - boolean connected; - - ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (app.appConfig.registerSyncOnlyWifi) { - NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); - connected = mWifi != null && mWifi.isConnected(); - } - else { - NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo(); - connected = netInfo != null && netInfo.isConnected(); - } - - if (!connected) { - app.debugLog("SyncJob cancelling: no internet"); - update(app, true); - } - else { - SyncService.start(context); - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/sync/SyncService.java b/app/src/main/java/pl/szczodrzynski/edziennik/sync/SyncService.java deleted file mode 100644 index e3eddf3d..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/sync/SyncService.java +++ /dev/null @@ -1,258 +0,0 @@ -package pl.szczodrzynski.edziennik.sync; - -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.os.Build; -import android.os.Handler; -import android.os.IBinder; -import androidx.annotation.Nullable; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.data.api.AppError; -import pl.szczodrzynski.edziennik.data.api.interfaces.SyncCallback; -import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore; -import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; -import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull; - -import static pl.szczodrzynski.edziennik.Notifier.ID_GET_DATA; -import static pl.szczodrzynski.edziennik.Notifier.ID_GET_DATA_ERROR; -import static pl.szczodrzynski.edziennik.utils.Utils.d; - -public class SyncService extends Service { - public static final String TAG = "SyncService"; - private App app; - public static boolean running = false; - private List profiles; - public static final int PROFILE_MAX_PROGRESS = 110; - private Profile profile = null; - private int profileId = -1; - public static int progress = 0; - private int profileProgress = 0; - public static int maxProgress; - public static int firstProfileId = -1; - public static int targetProfileId = -1; - public static final String ACTION_CANCEL = "SyncService.ACTION_CANCEL"; - public static SyncCallback customCallback = null; - private static final int PROFILE_TIMEOUT = 40000; - - private Handler timeoutHandler = new Handler(); - private Runnable timeoutRunnable = new Runnable() { - public void run() { - if (!running) - return; - error(AppError.stringErrorCode(app, AppError.CODE_TIMEOUT, ""), profile); - finishDownload(); - } - }; - - public static void start(Context context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - context.startForegroundService(new Intent(context, SyncService.class)); - } else { - context.startService(new Intent(context, SyncService.class)); - } - } - - @Override - public void onCreate() { - super.onCreate(); - app = (App) getApplicationContext(); - app.debugLog("SyncService created"); - startForeground(ID_GET_DATA, app.notifier.notificationGetDataShow(0)); - } - - private void reNotify() { - //app.notifier.notificationCancel(ID_GET_DATA_ERROR); - app.notifier.notificationPost(ID_GET_DATA, app.notifier.notificationGetDataProgress(progress, maxProgress)); - } - private void error(String error, Profile profile) { - app.notifier.notificationPost(ID_GET_DATA_ERROR, app.notifier.notificationGetDataError(profile == null ? "" : profile.getName(), error, profile == null ? -1 : profile.getId())); - } - - long millisStart; - - private void downloadData() { - if (profiles.size() > 0) { - profile = profiles.get(0); - profileId = profile.getId(); - app.debugLog("SyncService downloading profileId="+profileId); - profiles.remove(0); - // mamy profileID wiec nie trzeba nic ładować. DAO musi używać profileId - millisStart = System.currentTimeMillis(); - app.notifier.notificationPost(ID_GET_DATA, app.notifier.notificationGetDataProfile(profile.getName())); - app.apiEdziennik.sync(app, SyncService.this, new SyncCallback() { - @Override - public void onLoginFirst(List profileList, LoginStore loginStore) { - if (customCallback != null) - customCallback.onLoginFirst(profileList, loginStore); - } - - @Override - public void onSuccess(Context activityContext, ProfileFull profile) { - profileProgress++; - progress = profileProgress*PROFILE_MAX_PROGRESS; - updateTimeoutHandler(); - reNotify(); - app.debugLog("SyncService profileId="+profileId+" done in "+(System.currentTimeMillis() - millisStart)+"ms"); - if (customCallback != null) - customCallback.onSuccess(activityContext, profile); - downloadData(); - } - - @Override - public void onError(Context activityContext, AppError error) { - error(error.asReadableString(activityContext), profile); - if (customCallback != null) - customCallback.onError(activityContext, error); - if (error.errorCode == AppError.CODE_NO_INTERNET) { - finishDownload(CODE_NO_INTERNET); // use finishDownload instead of scheduleNext so it always changes the profile back to previousProfile - } else { - finishDownload(CODE_ERROR); - } - } - - @Override - public void onProgress(int progressStep) { - if (customCallback != null) - customCallback.onProgress(Math.min(progressStep, PROFILE_MAX_PROGRESS)); - progress = Math.min(progress+progressStep, (profileProgress+1)*PROFILE_MAX_PROGRESS); - reNotify(); - } - - @Override - public void onActionStarted(int stringResId) { - if (customCallback != null) - customCallback.onActionStarted(stringResId); - app.notifier.notificationPost(ID_GET_DATA, app.notifier.notificationGetDataAction(stringResId)); - } - }, profileId); - } - else { - finishDownload(); - } - } - - private void updateTimeoutHandler() { - timeoutHandler.removeCallbacks(timeoutRunnable); - timeoutHandler.postDelayed(timeoutRunnable, PROFILE_TIMEOUT); - } - - private static final int CODE_OK = 0; - private static final int CODE_ERROR = 1; - private static final int CODE_NO_INTERNET = 2; - private void finishDownload() { - finishDownload(CODE_OK); - } - private void finishDownload(int errorCode) { - timeoutHandler.removeCallbacks(timeoutRunnable); - - app.apiEdziennik.notifyAndReload(); - - app.debugLog("SyncService finishing with profileId="+profileId); - if (errorCode == CODE_OK) { - app.notifier.notificationCancel(ID_GET_DATA_ERROR); - } - SyncJob.update((App) getApplication(), errorCode == CODE_NO_INTERNET); - stopSelf(); - if (customCallback != null && errorCode == CODE_OK) { - customCallback.onSuccess(null, null); - } - customCallback = null; - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - d(TAG, "Got an intent. Service is running "+running); - if (intent != null && intent.getAction() != null && intent.getAction().equals(ACTION_CANCEL)) { - d(TAG, "ACTION_CANCEL intent"); - finishDownload(); - running = true; - } - - if (running) { - app.debugLog("SyncService already running; return"); - return Service.START_STICKY; - } - running = true; - - timeoutHandler.postDelayed(timeoutRunnable, PROFILE_TIMEOUT); - - profiles = app.db.profileDao().getProfilesForSyncNow(); - - app.debugLog("SyncService source profileList="+ Arrays.toString(profiles.toArray())+". firstProfileId="+firstProfileId+", targetProfileId="+targetProfileId); - - if (profiles.size() == 0) { - stopSelf(); - return Service.START_STICKY; - } - - if (firstProfileId != -1) { - d(TAG, "Profile list from first "+firstProfileId); - Collection toRemove = new ArrayList<>(); - for (Profile profile: profiles) { - if (firstProfileId == profile.getId()) { - break; - } - toRemove.add(profile); - } - profiles.removeAll(toRemove); - firstProfileId = -1; - } - if (targetProfileId != -1) { - d(TAG, "Profile list only target "+targetProfileId); - Profile targetProfile = null; - for (Profile profile: profiles) { - if (targetProfileId == profile.getId()) { - targetProfile = profile; - break; - } - } - profiles.clear(); - if (targetProfile != null) - profiles.add(targetProfile); - targetProfileId = -1; - } - - app.debugLog("SyncService target profileList="+ Arrays.toString(profiles.toArray())); - - progress = 0; - profileProgress = 0; - maxProgress = profiles.size()*PROFILE_MAX_PROGRESS; - - app.notifier.notificationPost(ID_GET_DATA, app.notifier.notificationGetDataShow(maxProgress)); - - if (!app.networkUtils.isOnline()) { - app.debugLog("SyncService no internet; update,stop"); - error(AppError.stringErrorCode(app, AppError.CODE_NO_INTERNET, ""), profiles.size() >= 1 ? profiles.get(0) : null); - SyncJob.update((App) getApplication(), true); - if (customCallback != null) { - customCallback.onError(getApplicationContext(), new AppError(TAG, 241, AppError.CODE_NO_INTERNET, null, (Throwable) null)); - } - stopSelf(); - return Service.START_STICKY; - } - - downloadData(); - - return Service.START_STICKY; - } - - @Override - public void onDestroy() { - super.onDestroy(); - app.debugLog("SyncService destroyed"); - running = false; - } - - @Nullable - @Override - public IBinder onBind(Intent intent) { - return null; - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/sync/SyncWorker.kt b/app/src/main/java/pl/szczodrzynski/edziennik/sync/SyncWorker.kt new file mode 100644 index 00000000..3c0e032e --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/sync/SyncWorker.kt @@ -0,0 +1,99 @@ +package pl.szczodrzynski.edziennik.sync + +import android.annotation.SuppressLint +import android.content.Context +import android.os.AsyncTask +import androidx.work.* +import androidx.work.impl.WorkManagerImpl +import org.greenrobot.eventbus.EventBus +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.MINUTE +import pl.szczodrzynski.edziennik.api.v2.ApiService +import pl.szczodrzynski.edziennik.api.v2.events.requests.SyncRequest +import pl.szczodrzynski.edziennik.formatDate +import pl.szczodrzynski.edziennik.utils.Utils.d +import java.util.concurrent.TimeUnit + +class SyncWorker(val context: Context, val params: WorkerParameters) : Worker(context, params) { + companion object { + const val TAG = "SyncWorker" + + /** + * Schedule the sync job only if it's not already scheduled. + */ + @SuppressLint("RestrictedApi") + fun scheduleNext(app: App) { + AsyncTask.execute { + val workManager = WorkManager.getInstance(app) as WorkManagerImpl + val scheduledWork = workManager.workDatabase.workSpecDao().scheduledWork + scheduledWork.forEach { + d(TAG, "Work: ${it.id} at ${(it.periodStartTime+it.initialDelay).formatDate()}. State = ${it.state} (finished = ${it.state.isFinished})") + } + // remove finished work and other than SyncWorker + scheduledWork.removeAll { it.workerClassName != SyncWorker::class.java.canonicalName || it.isPeriodic || it.state.isFinished } + d(TAG, "Found ${scheduledWork.size} unfinished work") + // remove all enqueued work that had to (but didn't) run at some point in the past (at least 1min ago) + val failedWork = scheduledWork.filter { it.state == WorkInfo.State.ENQUEUED && it.periodStartTime+it.initialDelay < System.currentTimeMillis() - 1*MINUTE*1000 } + d(TAG, "${failedWork.size} work requests failed to start (out of ${scheduledWork.size} requests)") + if (failedWork.isNotEmpty()) { + d(TAG, "App Manager detected!") + EventBus.getDefault().postSticky(AppManagerDetectedEvent(failedWork.map { it.periodStartTime+it.initialDelay })) + } + if (scheduledWork.size-failedWork.size < 1) { + d(TAG, "No pending work found, scheduling next:") + rescheduleNext(app) + } + } + } + + /** + * Cancel any existing sync jobs and schedule a new one. + * + * If [registerSyncEnabled] is not true, just cancel every job. + */ + fun rescheduleNext(app: App) { + cancelNext(app) + val enableSync = app.appConfig.registerSyncEnabled + if (!enableSync) { + return + } + val onlyWifi = app.appConfig.registerSyncOnlyWifi + val syncInterval = app.appConfig.registerSyncInterval.toLong() + + val syncAt = System.currentTimeMillis() + syncInterval*1000 + d(TAG, "Scheduling work at ${syncAt.formatDate()}") + + val constraints = Constraints.Builder() + .setRequiredNetworkType( + if (onlyWifi) + NetworkType.UNMETERED + else + NetworkType.CONNECTED) + .build() + + val syncWorkRequest = OneTimeWorkRequestBuilder() + .setInitialDelay(syncInterval, TimeUnit.SECONDS) + .setConstraints(constraints) + .addTag(TAG) + .build() + + WorkManager.getInstance(app).enqueue(syncWorkRequest) + } + + /** + * Cancel any scheduled sync job. + */ + fun cancelNext(app: App) { + d(TAG, "Cancelling work by tag $TAG") + WorkManager.getInstance(app).cancelAllWorkByTag(TAG) + //WorkManager.getInstance(app).pruneWork() // do not prune the work in order to look for failed tasks + } + } + + override fun doWork(): Result { + d(TAG, "Running worker ID ${params.id}") + ApiService.startAndRequest(context, SyncRequest()) + rescheduleNext(context as App) + return Result.success() + } +} \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.java index 265c12fa..d5aca94b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.java @@ -27,6 +27,7 @@ import androidx.annotation.PluralsRes; import androidx.core.graphics.ColorUtils; import androidx.databinding.DataBindingUtil; import androidx.fragment.app.Fragment; +import androidx.work.WorkManager; import com.afollestad.materialdialogs.MaterialDialog; import com.mikepenz.iconics.IconicsColor; @@ -34,19 +35,13 @@ import com.mikepenz.iconics.IconicsDrawable; import com.mikepenz.iconics.IconicsSize; import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial; -import org.greenrobot.eventbus.EventBus; - import java.util.ArrayList; import java.util.List; -import kotlin.Pair; import pl.szczodrzynski.edziennik.App; import pl.szczodrzynski.edziennik.BuildConfig; import pl.szczodrzynski.edziennik.MainActivity; import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.api.v2.ApiService; -import pl.szczodrzynski.edziennik.api.v2.events.requests.AnnouncementsReadRequest; -import pl.szczodrzynski.edziennik.api.v2.events.requests.SyncProfileRequest; import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeFull; import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonFull; import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; @@ -67,8 +62,6 @@ import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem; import static pl.szczodrzynski.edziennik.App.UPDATES_ON_PLAY_STORE; import static pl.szczodrzynski.edziennik.MainActivity.DRAWER_ITEM_GRADES; -import static pl.szczodrzynski.edziennik.MainActivity.DRAWER_ITEM_HOME; -import static pl.szczodrzynski.edziennik.MainActivity.DRAWER_ITEM_MESSAGES; import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER1_FINAL; import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER1_PROPOSED; import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER2_FINAL; @@ -76,7 +69,6 @@ import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMES import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_YEAR_FINAL; import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_YEAR_PROPOSED; import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_MOBIDZIENNIK; -import static pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT; public class HomeFragment extends Fragment { private static final String TAG = "HomeFragment"; @@ -104,55 +96,13 @@ public class HomeFragment extends Fragment { if (app == null || app.profile == null || activity == null || b == null || !isAdded()) return; - /*b.refreshLayout.setOnRefreshListener(() -> { - activity.syncCurrentFeature(MainActivity.DRAWER_ITEM_HOME, b.refreshLayout); - });*/ - /*b.refreshLayout.setOnTouchListener((v, event) -> { - d(TAG, "event "+event); - event.setSource(0x10000000); // set a unique source - activity.swipeRefreshLayout.onTouchEvent(event); - return true; - });*/ - /*b.refreshLayout.setOnDragListener((v, event) -> { - activity.swipeRefreshLayout.onDragEvent(event); - return true; - });*/ + b.devMode.setVisibility(App.devMode ? View.VISIBLE : View.GONE); - b.composeButton.setVisibility(BuildConfig.DEBUG ? View.VISIBLE : View.GONE); b.composeButton.setOnClickListener((v -> { startActivity(new Intent(activity, MessagesComposeActivity.class)); })); - b.testButton.setVisibility(BuildConfig.DEBUG ? View.VISIBLE : View.GONE); - b.testButton.setOnClickListener((v -> { - app.startService(new Intent(app, ApiService.class)); - })); - - b.test2.setVisibility(BuildConfig.DEBUG ? View.VISIBLE : View.GONE); - b.test2.setOnClickListener((v -> { - List> list = new ArrayList<>(); - list.add(new Pair<>(DRAWER_ITEM_HOME, 0)); - EventBus.getDefault().postSticky(new SyncProfileRequest(app.profile.getId(), list)); - })); - - b.test3.setVisibility(BuildConfig.DEBUG ? View.VISIBLE : View.GONE); - b.test3.setOnClickListener((v -> { - List> list = new ArrayList<>(); - list.add(new Pair<>(DRAWER_ITEM_MESSAGES, TYPE_SENT)); - EventBus.getDefault().postSticky(new SyncProfileRequest(app.profile.getId(), list)); - })); - - b.test4.setVisibility(BuildConfig.DEBUG ? View.VISIBLE : View.GONE); - b.test4.setOnClickListener((v -> { - List> list = new ArrayList<>(); - list.add(new Pair<>(DRAWER_ITEM_GRADES, 0)); - EventBus.getDefault().postSticky(new SyncProfileRequest(app.profile.getId(), list)); - })); - - b.test5.setVisibility(BuildConfig.DEBUG ? View.VISIBLE : View.GONE); - b.test5.setOnClickListener((v -> { - EventBus.getDefault().postSticky(new AnnouncementsReadRequest(app.profile.getId())); - })); + b.pruneWorkButton.setOnClickListener((v -> WorkManager.getInstance(app).pruneWork())); //((TextView)v.findViewById(R.id.nextSync)).setText(getString(R.string.next_sync_format,Time.fromMillis(app.appJobs.syncJobTime).getStringHMS())); diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java index 76fb23c1..c442bdc6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java @@ -48,7 +48,7 @@ import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore; import pl.szczodrzynski.edziennik.network.NetworkUtils; import pl.szczodrzynski.edziennik.network.ServerRequest; import pl.szczodrzynski.edziennik.receivers.BootReceiver; -import pl.szczodrzynski.edziennik.sync.SyncJob; +import pl.szczodrzynski.edziennik.sync.SyncWorker; import pl.szczodrzynski.edziennik.ui.dialogs.changelog.ChangelogDialog; import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment; import pl.szczodrzynski.edziennik.ui.modules.webpush.WebPushConfigActivity; @@ -511,6 +511,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { .setOnChangeAction((isChecked, tag) -> { app.appConfig.registerSyncOnlyWifi = isChecked; app.saveConfig("registerSyncOnlyWifi"); + SyncWorker.Companion.rescheduleNext(app); return true; }); } @@ -532,6 +533,10 @@ public class SettingsNewFragment extends MaterialAboutFragment { syncCardIntervalItem.setChecked(app.appConfig.registerSyncEnabled); syncCardIntervalItem.setOnClickAction(() -> { List intervalNames = new ArrayList<>(); + if (App.devMode) { + intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_seconds, 30)); + intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_minutes, 5)); + } intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_minutes, 30)); intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_minutes, 45)); intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_hours, 1)); @@ -540,6 +545,10 @@ public class SettingsNewFragment extends MaterialAboutFragment { intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_hours, 3)); intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_hours, 4)); List intervals = new ArrayList<>(); + if (App.devMode) { + intervals.add(30); + intervals.add(5 * 60); + } intervals.add(30 * 60); intervals.add(45 * 60); intervals.add(60 * 60); @@ -564,20 +573,12 @@ public class SettingsNewFragment extends MaterialAboutFragment { app.appConfig.registerSyncEnabled = true; // app.appConfig modifications have to surround syncCardIntervalItem and those ifs app.saveConfig("registerSyncInterval", "registerSyncEnabled"); - SyncJob.clear(); - SyncJob.schedule(app); + SyncWorker.Companion.rescheduleNext(app); return true; }) .show(); }); syncCardIntervalItem.setOnChangeAction((isChecked, tag) -> { - if (isChecked) { - SyncJob.update(app); - } - else { - SyncJob.clear(); - } - if (isChecked && !app.appConfig.registerSyncEnabled) { addCardItem(CARD_SYNC, 1, getSyncCardWifiItem()); } @@ -586,6 +587,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { } app.appConfig.registerSyncEnabled = isChecked; app.saveConfig("registerSyncEnabled"); + SyncWorker.Companion.rescheduleNext(app); return true; }); items.add(syncCardIntervalItem); diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/Utils.java b/app/src/main/java/pl/szczodrzynski/edziennik/utils/Utils.java index f7bd5c0f..1dadf492 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/Utils.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/Utils.java @@ -14,16 +14,18 @@ import android.net.Uri; import android.os.Build; import android.os.Environment; import android.provider.MediaStore; -import androidx.annotation.AttrRes; -import androidx.annotation.ColorInt; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import android.util.Base64; import android.util.Log; import android.util.TypedValue; import android.webkit.MimeTypeMap; import android.widget.Toast; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.FileProvider; + import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; @@ -64,8 +66,6 @@ import javax.crypto.ShortBufferException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; -import androidx.core.content.FileProvider; - import pl.szczodrzynski.edziennik.App; public class Utils { @@ -106,7 +106,7 @@ public class Utils { public static void d(String TAG, String message) { if (App.devMode) { - Log.d(TAG, message); + Log.d("Szkolny/"+TAG, message); //debugLog.add(TAG+": "+message); } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/AppConfig.java b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/AppConfig.java index b2d104e2..d9310ccb 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/AppConfig.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/AppConfig.java @@ -2,6 +2,7 @@ package pl.szczodrzynski.edziennik.utils.models; import android.util.Pair; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.util.ArrayList; @@ -115,4 +116,7 @@ public class AppConfig { @Nullable public String language = null; + + @NonNull + public boolean dontShowAppManagerDialog = false; } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/widgets/luckynumber/WidgetLuckyNumber.java b/app/src/main/java/pl/szczodrzynski/edziennik/widgets/luckynumber/WidgetLuckyNumber.java index 60f4dce1..051657c0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/widgets/luckynumber/WidgetLuckyNumber.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/widgets/luckynumber/WidgetLuckyNumber.java @@ -22,11 +22,12 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; import pl.szczodrzynski.edziennik.MainActivity; +import pl.szczodrzynski.edziennik.R; +import pl.szczodrzynski.edziennik.api.v2.ApiService; +import pl.szczodrzynski.edziennik.api.v2.events.requests.SyncRequest; import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; import pl.szczodrzynski.edziennik.utils.models.Date; -import pl.szczodrzynski.edziennik.sync.SyncJob; import pl.szczodrzynski.edziennik.widgets.WidgetConfig; import static pl.szczodrzynski.edziennik.utils.Utils.getCellsForSize; @@ -39,7 +40,7 @@ public class WidgetLuckyNumber extends AppWidgetProvider { @Override public void onReceive(Context context, Intent intent) { if (ACTION_SYNC_DATA.equals(intent.getAction())){ - SyncJob.run((App) context.getApplicationContext()); + ApiService.Companion.startAndRequest(context, new SyncRequest()); } super.onReceive(context, intent); } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/widgets/notifications/WidgetNotifications.java b/app/src/main/java/pl/szczodrzynski/edziennik/widgets/notifications/WidgetNotifications.java index 2cd238a1..05b37adb 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/widgets/notifications/WidgetNotifications.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/widgets/notifications/WidgetNotifications.java @@ -22,9 +22,10 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; import pl.szczodrzynski.edziennik.MainActivity; -import pl.szczodrzynski.edziennik.sync.SyncJob; +import pl.szczodrzynski.edziennik.R; +import pl.szczodrzynski.edziennik.api.v2.ApiService; +import pl.szczodrzynski.edziennik.api.v2.events.requests.SyncRequest; import pl.szczodrzynski.edziennik.widgets.WidgetConfig; public class WidgetNotifications extends AppWidgetProvider { @@ -35,7 +36,7 @@ public class WidgetNotifications extends AppWidgetProvider { @Override public void onReceive(Context context, Intent intent) { if (ACTION_SYNC_DATA.equals(intent.getAction())){ - SyncJob.run((App) context.getApplicationContext()); + ApiService.Companion.startAndRequest(context, new SyncRequest()); } super.onReceive(context, intent); } diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index e0fedecb..cedad80b 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -1,6 +1,5 @@ @@ -31,69 +30,41 @@ android:layout_margin="8dp" tools:text="TextView" /> - - - + android:orientation="vertical" + tools:visibility="visible"> + + - - - - - - - - - + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6cb98a7d..ae409e30 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -978,4 +978,8 @@ Pobieranie planu lekcji... Pobieranie ocen proponowanych... Pobieranie listy sprawdzianów... + Wykryto problem z synchronizacją + Na urządzeniu prawdopodobnie zainstalowany jest menedżer aplikacji, który może powodować problemy z synchronizacją automatyczną.\n\nNależy wyłączyć w ustawieniach telefonu optymalizację baterii dla aplikacji Szkolny.eu.\n\nKliknij OK, aby przejść do ustawień telefonu. + Nie pytaj ponownie + Nie udało się otworzyć ustawień diff --git a/build.gradle b/build.gradle index 5e08c012..4c67499d 100644 --- a/build.gradle +++ b/build.gradle @@ -34,6 +34,7 @@ buildscript { room : "2.2.0-beta01", lifecycle : "2.2.0-alpha04", + work : "2.2.0", firebase : '17.2.0', firebasemessaging: "20.0.0",