mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-01-31 05:48:19 +01:00
[Sync] Implement APIv2 auto sync using WorkManager.
This commit is contained in:
parent
dcd355851d
commit
07863fed6f
@ -162,6 +162,8 @@ dependencies {
|
|||||||
implementation "org.redundent:kotlin-xml-builder:1.5.3"
|
implementation "org.redundent:kotlin-xml-builder:1.5.3"
|
||||||
|
|
||||||
implementation "io.github.wulkanowy:signer-android:0.1.1"
|
implementation "io.github.wulkanowy:signer-android:0.1.1"
|
||||||
|
|
||||||
|
implementation "androidx.work:work-runtime-ktx:${versions.work}"
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -222,10 +222,6 @@
|
|||||||
|
|
||||||
<service android:name=".Notifier$GetDataRetryService" />
|
<service android:name=".Notifier$GetDataRetryService" />
|
||||||
|
|
||||||
<service
|
|
||||||
android:name=".sync.SyncService"
|
|
||||||
android:icon="@mipmap/ic_launcher"
|
|
||||||
android:label="@string/sync_service" />
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".receivers.SzkolnyReceiver"
|
android:name=".receivers.SzkolnyReceiver"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
|
@ -20,10 +20,13 @@ import android.util.Base64;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
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.ChuckerCollector;
|
||||||
import com.chuckerteam.chucker.api.ChuckerInterceptor;
|
import com.chuckerteam.chucker.api.ChuckerInterceptor;
|
||||||
import com.chuckerteam.chucker.api.RetentionManager;
|
import com.chuckerteam.chucker.api.RetentionManager;
|
||||||
import com.evernote.android.job.JobManager;
|
|
||||||
import com.google.android.gms.security.ProviderInstaller;
|
import com.google.android.gms.security.ProviderInstaller;
|
||||||
import com.google.firebase.FirebaseApp;
|
import com.google.firebase.FirebaseApp;
|
||||||
import com.google.firebase.FirebaseOptions;
|
import com.google.firebase.FirebaseOptions;
|
||||||
@ -55,8 +58,6 @@ import javax.net.ssl.TrustManager;
|
|||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate;
|
|
||||||
import cat.ereza.customactivityoncrash.config.CaocConfig;
|
import cat.ereza.customactivityoncrash.config.CaocConfig;
|
||||||
import im.wangchao.mhttp.MHttp;
|
import im.wangchao.mhttp.MHttp;
|
||||||
import im.wangchao.mhttp.internal.cookie.PersistentCookieJar;
|
import im.wangchao.mhttp.internal.cookie.PersistentCookieJar;
|
||||||
@ -66,7 +67,6 @@ import me.leolin.shortcutbadger.ShortcutBadger;
|
|||||||
import okhttp3.ConnectionSpec;
|
import okhttp3.ConnectionSpec;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.TlsVersion;
|
import okhttp3.TlsVersion;
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.base.CrashActivity;
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.Edziennik;
|
import pl.szczodrzynski.edziennik.data.api.Edziennik;
|
||||||
import pl.szczodrzynski.edziennik.data.api.Iuczniowie;
|
import pl.szczodrzynski.edziennik.data.api.Iuczniowie;
|
||||||
import pl.szczodrzynski.edziennik.data.api.Librus;
|
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.login.LoginStore;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile;
|
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.profiles.ProfileFull;
|
||||||
import pl.szczodrzynski.edziennik.utils.models.AppConfig;
|
|
||||||
import pl.szczodrzynski.edziennik.network.NetworkUtils;
|
import pl.szczodrzynski.edziennik.network.NetworkUtils;
|
||||||
import pl.szczodrzynski.edziennik.network.TLSSocketFactory;
|
import pl.szczodrzynski.edziennik.network.TLSSocketFactory;
|
||||||
import pl.szczodrzynski.edziennik.receivers.JobsCreator;
|
import pl.szczodrzynski.edziennik.sync.SyncWorker;
|
||||||
import pl.szczodrzynski.edziennik.sync.SyncJob;
|
import pl.szczodrzynski.edziennik.ui.modules.base.CrashActivity;
|
||||||
import pl.szczodrzynski.edziennik.utils.PermissionChecker;
|
import pl.szczodrzynski.edziennik.utils.PermissionChecker;
|
||||||
import pl.szczodrzynski.edziennik.utils.Themes;
|
import pl.szczodrzynski.edziennik.utils.Themes;
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils;
|
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_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_MOBIDZIENNIK;
|
||||||
import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_VULCAN;
|
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";
|
private static final String TAG = "App";
|
||||||
public static int profileId = -1;
|
public static int profileId = -1;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Configuration getWorkManagerConfiguration() {
|
||||||
|
return new Configuration.Builder()
|
||||||
|
.setMinimumLoggingLevel(Log.VERBOSE)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static final int REQUEST_TIMEOUT = 10 * 1000;
|
public static final int REQUEST_TIMEOUT = 10 * 1000;
|
||||||
|
|
||||||
// notifications
|
// notifications
|
||||||
@ -301,12 +309,11 @@ public class App extends androidx.multidex.MultiDexApplication {
|
|||||||
|
|
||||||
//profileLoadById(appSharedPrefs.getInt("current_profile_id", 1));
|
//profileLoadById(appSharedPrefs.getInt("current_profile_id", 1));
|
||||||
|
|
||||||
JobManager.create(this).addJobCreator(new JobsCreator());
|
|
||||||
if (appConfig.registerSyncEnabled) {
|
if (appConfig.registerSyncEnabled) {
|
||||||
SyncJob.schedule(this);
|
SyncWorker.Companion.scheduleNext(this);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SyncJob.clear();
|
SyncWorker.Companion.cancelNext(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
db.metadataDao().countUnseen().observeForever(count -> {
|
db.metadataDao().countUnseen().observeForever(count -> {
|
||||||
|
@ -325,3 +325,5 @@ fun String.crc32(): Long {
|
|||||||
crc.update(toByteArray())
|
crc.update(toByteArray())
|
||||||
return crc.value
|
return crc.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Long.formatDate(format: String = "yyyy-MM-dd HH:mm:ss"): String = SimpleDateFormat(format).format(this)
|
@ -2,10 +2,7 @@ package pl.szczodrzynski.edziennik
|
|||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.ActivityManager
|
import android.app.ActivityManager
|
||||||
import android.content.BroadcastReceiver
|
import android.content.*
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.IntentFilter
|
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.graphics.drawable.BitmapDrawable
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.os.*
|
import android.os.*
|
||||||
@ -19,6 +16,7 @@ import androidx.core.graphics.ColorUtils
|
|||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.navigation.NavOptions
|
import androidx.navigation.NavOptions
|
||||||
import com.danimahardhika.cafebar.CafeBar
|
import com.danimahardhika.cafebar.CafeBar
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.mikepenz.iconics.IconicsColor
|
import com.mikepenz.iconics.IconicsColor
|
||||||
import com.mikepenz.iconics.IconicsDrawable
|
import com.mikepenz.iconics.IconicsDrawable
|
||||||
import com.mikepenz.iconics.IconicsSize
|
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.ApiService
|
||||||
import pl.szczodrzynski.edziennik.api.v2.events.*
|
import pl.szczodrzynski.edziennik.api.v2.events.*
|
||||||
import pl.szczodrzynski.edziennik.api.v2.events.requests.SyncProfileRequest
|
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.api.interfaces.EdziennikInterface.*
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.*
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.*
|
||||||
import pl.szczodrzynski.edziennik.databinding.ActivitySzkolnyBinding
|
import pl.szczodrzynski.edziennik.databinding.ActivitySzkolnyBinding
|
||||||
import pl.szczodrzynski.edziennik.network.ServerRequest
|
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.dialogs.changelog.ChangelogDialog
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.agenda.AgendaFragment
|
import pl.szczodrzynski.edziennik.ui.modules.agenda.AgendaFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.announcements.AnnouncementsFragment
|
import pl.szczodrzynski.edziennik.ui.modules.announcements.AnnouncementsFragment
|
||||||
@ -370,7 +369,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
isStoragePermissionGranted()
|
isStoragePermissionGranted()
|
||||||
|
|
||||||
SyncJob.schedule(app)
|
//SyncWorker.scheduleNext(app)
|
||||||
|
|
||||||
// APP BACKGROUND
|
// APP BACKGROUND
|
||||||
if (app.appConfig.appBackground != null) {
|
if (app.appConfig.appBackground != null) {
|
||||||
@ -499,7 +498,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
profileListEmptyListener()
|
profileListEmptyListener()
|
||||||
}
|
}
|
||||||
DRAWER_PROFILE_SYNC_ALL -> {
|
DRAWER_PROFILE_SYNC_ALL -> {
|
||||||
SyncJob.run(app)
|
ApiService.startAndRequest(this, SyncRequest())
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
loadTarget(id)
|
loadTarget(id)
|
||||||
@ -569,6 +568,47 @@ class MainActivity : AppCompatActivity() {
|
|||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onSyncErrorEvent(event: SyncErrorEvent) {
|
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 {
|
private fun fragmentToFeature(currentFragment: Int): Int {
|
||||||
return when (currentFragment) {
|
return when (currentFragment) {
|
||||||
|
@ -19,14 +19,11 @@ import java.util.List;
|
|||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
|
||||||
import pl.szczodrzynski.edziennik.receivers.BootReceiver;
|
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.Date;
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time;
|
import pl.szczodrzynski.edziennik.utils.models.Time;
|
||||||
|
|
||||||
import static androidx.core.app.NotificationCompat.PRIORITY_DEFAULT;
|
import static androidx.core.app.NotificationCompat.PRIORITY_DEFAULT;
|
||||||
import static androidx.core.app.NotificationCompat.PRIORITY_MAX;
|
import static androidx.core.app.NotificationCompat.PRIORITY_MAX;
|
||||||
import static pl.szczodrzynski.edziennik.sync.SyncService.ACTION_CANCEL;
|
|
||||||
|
|
||||||
public class Notifier {
|
public class Notifier {
|
||||||
|
|
||||||
@ -127,17 +124,17 @@ public class Notifier {
|
|||||||
| |__| | (_| | || (_| | | |__| | __/ |_
|
| |__| | (_| | || (_| | | |__| | __/ |_
|
||||||
|_____/ \__,_|\__\__,_| \_____|\___|\_*/
|
|_____/ \__,_|\__\__,_| \_____|\___|\_*/
|
||||||
public Notification notificationGetDataShow(int maxProgress) {
|
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);
|
notificationIntent.setAction(ACTION_CANCEL);
|
||||||
PendingIntent pendingIntent = PendingIntent.getService(app.getContext(), 0,
|
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)
|
getDataNotificationBuilder = new NotificationCompat.Builder(app, GROUP_KEY_GET_DATA)
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||||
.setColor(notificationColor)
|
.setColor(notificationColor)
|
||||||
.setContentTitle(app.getString(R.string.notification_get_data_title))
|
.setContentTitle(app.getString(R.string.notification_get_data_title))
|
||||||
.setContentText(app.getString(R.string.notification_get_data_text))
|
.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)
|
//.setGroup(GROUP_KEY_GET_DATA)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.setProgress(maxProgress, 0, false)
|
.setProgress(maxProgress, 0, false)
|
||||||
@ -209,10 +206,8 @@ public class Notifier {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onHandleIntent(Intent intent) {
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ import java.lang.reflect.Method;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
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.events.EventFull;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange;
|
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonFull;
|
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.Time;
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Week;
|
import pl.szczodrzynski.edziennik.utils.models.Week;
|
||||||
import pl.szczodrzynski.edziennik.widgets.WidgetConfig;
|
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.LessonDetailsActivity;
|
||||||
import pl.szczodrzynski.edziennik.widgets.timetable.WidgetTimetableService;
|
import pl.szczodrzynski.edziennik.widgets.timetable.WidgetTimetableService;
|
||||||
|
|
||||||
@ -65,8 +66,8 @@ public class WidgetTimetable extends AppWidgetProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (ACTION_SYNC_DATA.equals(intent.getAction())){
|
if (ACTION_SYNC_DATA.equals(intent.getAction())) {
|
||||||
SyncJob.run((App) context.getApplicationContext());
|
ApiService.Companion.startAndRequest(context, new SyncRequest());
|
||||||
}
|
}
|
||||||
super.onReceive(context, intent);
|
super.onReceive(context, intent);
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,10 @@ class ApiService : Service() {
|
|||||||
fun start(context: Context) {
|
fun start(context: Context) {
|
||||||
context.startService(Intent(context, ApiService::class.java))
|
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 }
|
private val app by lazy { applicationContext as App }
|
||||||
|
@ -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.profiles.ProfileFull;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team;
|
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team;
|
||||||
import pl.szczodrzynski.edziennik.network.ServerRequest;
|
import pl.szczodrzynski.edziennik.network.ServerRequest;
|
||||||
import pl.szczodrzynski.edziennik.sync.SyncJob;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Themes;
|
import pl.szczodrzynski.edziennik.utils.Themes;
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Notification;
|
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_SERVER_MESSAGE;
|
||||||
import static pl.szczodrzynski.edziennik.data.db.modules.notification.Notification.TYPE_TIMETABLE_LESSON_CHANGE;
|
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.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.d;
|
||||||
import static pl.szczodrzynski.edziennik.utils.Utils.ns;
|
import static pl.szczodrzynski.edziennik.utils.Utils.ns;
|
||||||
|
|
||||||
@ -592,12 +590,7 @@ public class Edziennik {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void notifyAndReload() {
|
public void notifyAndReload() {
|
||||||
app.notifier.postAll(null);
|
// TODO \/
|
||||||
app.saveConfig();
|
|
||||||
SyncJob.schedule(app);
|
|
||||||
Intent i = new Intent(Intent.ACTION_MAIN)
|
|
||||||
.putExtra("reloadProfileId", -1);
|
|
||||||
app.sendBroadcast(i);
|
|
||||||
|
|
||||||
Intent intent = new Intent(app.getContext(), WidgetTimetable.class);
|
Intent intent = new Intent(app.getContext(), WidgetTimetable.class);
|
||||||
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
|
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
|
||||||
@ -751,7 +744,7 @@ public class Edziennik {
|
|||||||
MaterialDialog progressDialog = new MaterialDialog.Builder(activity)
|
MaterialDialog progressDialog = new MaterialDialog.Builder(activity)
|
||||||
.title(dialogTitle)
|
.title(dialogTitle)
|
||||||
.content(dialogText)
|
.content(dialogText)
|
||||||
.progress(false, PROFILE_MAX_PROGRESS, false)
|
.progress(false, 110, false)
|
||||||
.canceledOnTouchOutside(false)
|
.canceledOnTouchOutside(false)
|
||||||
.show();
|
.show();
|
||||||
SyncCallback guiSyncCallback = new SyncCallback() {
|
SyncCallback guiSyncCallback = new SyncCallback() {
|
||||||
|
@ -11,16 +11,17 @@ import android.content.pm.PackageManager;
|
|||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import androidx.core.content.FileProvider;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.core.content.FileProvider;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.App;
|
import pl.szczodrzynski.edziennik.App;
|
||||||
import pl.szczodrzynski.edziennik.R;
|
import pl.szczodrzynski.edziennik.R;
|
||||||
import pl.szczodrzynski.edziennik.network.ServerRequest;
|
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 pl.szczodrzynski.edziennik.utils.Utils;
|
||||||
|
|
||||||
import static android.content.Context.DOWNLOAD_SERVICE;
|
import static android.content.Context.DOWNLOAD_SERVICE;
|
||||||
@ -81,7 +82,7 @@ public class BootReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SyncJob.schedule(app);
|
SyncWorker.Companion.scheduleNext(app);
|
||||||
if (app.networkUtils.isOnline())
|
if (app.networkUtils.isOnline())
|
||||||
{
|
{
|
||||||
checkUpdate(context, intent);
|
checkUpdate(context, intent);
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,19 +7,20 @@ package pl.szczodrzynski.edziennik.receivers
|
|||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.ApiService
|
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() {
|
class SzkolnyReceiver : BroadcastReceiver() {
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
context?.startService(Intent(context, ApiService::class.java))
|
context ?: return
|
||||||
when (intent?.extras?.getString("task", null)) {
|
when (intent?.extras?.getString("task", null)) {
|
||||||
"ServiceCloseRequest" -> EventBus.getDefault().post(ServiceCloseRequest())
|
"ServiceCloseRequest" -> ApiService.startAndRequest(context, ServiceCloseRequest())
|
||||||
"TaskCancelRequest" -> EventBus.getDefault().post(TaskCancelRequest(intent.extras?.getInt("taskId", -1) ?: return))
|
"TaskCancelRequest" -> ApiService.startAndRequest(context, TaskCancelRequest(intent.extras?.getInt("taskId", -1) ?: return))
|
||||||
"SyncRequest" -> EventBus.getDefault().post(SyncRequest())
|
"SyncRequest" -> ApiService.startAndRequest(context, SyncRequest())
|
||||||
"SyncProfileRequest" -> EventBus.getDefault().post(SyncProfileRequest(intent.extras?.getInt("profileId", -1) ?: return))
|
"SyncProfileRequest" -> ApiService.startAndRequest(context, SyncProfileRequest(intent.extras?.getInt("profileId", -1) ?: return))
|
||||||
"AnnouncementsReadRequest" -> EventBus.getDefault().post(AnnouncementsReadRequest(intent.extras?.getInt("profileId", -1) ?: return))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
package pl.szczodrzynski.edziennik.sync
|
||||||
|
|
||||||
|
class AppManagerDetectedEvent(val failedWorkTimestamps: List<Long>)
|
@ -17,6 +17,9 @@ import pl.szczodrzynski.edziennik.App;
|
|||||||
import pl.szczodrzynski.edziennik.BuildConfig;
|
import pl.szczodrzynski.edziennik.BuildConfig;
|
||||||
import pl.szczodrzynski.edziennik.MainActivity;
|
import pl.szczodrzynski.edziennik.MainActivity;
|
||||||
import pl.szczodrzynski.edziennik.R;
|
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.Event;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull;
|
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.EventType;
|
import pl.szczodrzynski.edziennik.data.db.modules.events.EventType;
|
||||||
@ -111,7 +114,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
|
|||||||
app.notifier.postAll(profile);
|
app.notifier.postAll(profile);
|
||||||
app.saveConfig("notifications");*/
|
app.saveConfig("notifications");*/
|
||||||
d(TAG, "Syncing profile " + profile.getId());
|
d(TAG, "Syncing profile " + profile.getId());
|
||||||
SyncJob.run(app, -1, profile.getId());
|
ApiService.Companion.startAndRequest(app, new SyncProfileRequest(profile.getId(), null));
|
||||||
} else {
|
} else {
|
||||||
/*app.notifier.add(new Notification(app.getContext(), remoteMessage.getData().get("message"))
|
/*app.notifier.add(new Notification(app.getContext(), remoteMessage.getData().get("message"))
|
||||||
.withProfileData(profile.id, profile.name)
|
.withProfileData(profile.id, profile.name)
|
||||||
@ -122,7 +125,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
|
|||||||
app.notifier.postAll(profile);
|
app.notifier.postAll(profile);
|
||||||
app.saveConfig("notifications");*/
|
app.saveConfig("notifications");*/
|
||||||
d(TAG, "Syncing profile " + profile.getId());
|
d(TAG, "Syncing profile " + profile.getId());
|
||||||
SyncJob.run(app, -1, profile.getId());
|
ApiService.Companion.startAndRequest(app, new SyncProfileRequest(profile.getId(), 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<JobRequest> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<Profile> 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<Profile> 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<Profile> 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<SyncWorker>()
|
||||||
|
.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()
|
||||||
|
}
|
||||||
|
}
|
@ -27,6 +27,7 @@ import androidx.annotation.PluralsRes;
|
|||||||
import androidx.core.graphics.ColorUtils;
|
import androidx.core.graphics.ColorUtils;
|
||||||
import androidx.databinding.DataBindingUtil;
|
import androidx.databinding.DataBindingUtil;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.work.WorkManager;
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
import com.mikepenz.iconics.IconicsColor;
|
import com.mikepenz.iconics.IconicsColor;
|
||||||
@ -34,19 +35,13 @@ import com.mikepenz.iconics.IconicsDrawable;
|
|||||||
import com.mikepenz.iconics.IconicsSize;
|
import com.mikepenz.iconics.IconicsSize;
|
||||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial;
|
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial;
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import kotlin.Pair;
|
|
||||||
import pl.szczodrzynski.edziennik.App;
|
import pl.szczodrzynski.edziennik.App;
|
||||||
import pl.szczodrzynski.edziennik.BuildConfig;
|
import pl.szczodrzynski.edziennik.BuildConfig;
|
||||||
import pl.szczodrzynski.edziennik.MainActivity;
|
import pl.szczodrzynski.edziennik.MainActivity;
|
||||||
import pl.szczodrzynski.edziennik.R;
|
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.grades.GradeFull;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonFull;
|
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonFull;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile;
|
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.App.UPDATES_ON_PLAY_STORE;
|
||||||
import static pl.szczodrzynski.edziennik.MainActivity.DRAWER_ITEM_GRADES;
|
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_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_SEMESTER1_PROPOSED;
|
||||||
import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER2_FINAL;
|
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_FINAL;
|
||||||
import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_YEAR_PROPOSED;
|
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.login.LoginStore.LOGIN_TYPE_MOBIDZIENNIK;
|
||||||
import static pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT;
|
|
||||||
|
|
||||||
public class HomeFragment extends Fragment {
|
public class HomeFragment extends Fragment {
|
||||||
private static final String TAG = "HomeFragment";
|
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())
|
if (app == null || app.profile == null || activity == null || b == null || !isAdded())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*b.refreshLayout.setOnRefreshListener(() -> {
|
b.devMode.setVisibility(App.devMode ? View.VISIBLE : View.GONE);
|
||||||
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.composeButton.setVisibility(BuildConfig.DEBUG ? View.VISIBLE : View.GONE);
|
|
||||||
b.composeButton.setOnClickListener((v -> {
|
b.composeButton.setOnClickListener((v -> {
|
||||||
startActivity(new Intent(activity, MessagesComposeActivity.class));
|
startActivity(new Intent(activity, MessagesComposeActivity.class));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
b.testButton.setVisibility(BuildConfig.DEBUG ? View.VISIBLE : View.GONE);
|
b.pruneWorkButton.setOnClickListener((v -> WorkManager.getInstance(app).pruneWork()));
|
||||||
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<Pair<Integer, Integer>> 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<Pair<Integer, Integer>> 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<Pair<Integer, Integer>> 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()));
|
|
||||||
}));
|
|
||||||
|
|
||||||
//((TextView)v.findViewById(R.id.nextSync)).setText(getString(R.string.next_sync_format,Time.fromMillis(app.appJobs.syncJobTime).getStringHMS()));
|
//((TextView)v.findViewById(R.id.nextSync)).setText(getString(R.string.next_sync_format,Time.fromMillis(app.appJobs.syncJobTime).getStringHMS()));
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore;
|
|||||||
import pl.szczodrzynski.edziennik.network.NetworkUtils;
|
import pl.szczodrzynski.edziennik.network.NetworkUtils;
|
||||||
import pl.szczodrzynski.edziennik.network.ServerRequest;
|
import pl.szczodrzynski.edziennik.network.ServerRequest;
|
||||||
import pl.szczodrzynski.edziennik.receivers.BootReceiver;
|
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.dialogs.changelog.ChangelogDialog;
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment;
|
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment;
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.webpush.WebPushConfigActivity;
|
import pl.szczodrzynski.edziennik.ui.modules.webpush.WebPushConfigActivity;
|
||||||
@ -511,6 +511,7 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
|||||||
.setOnChangeAction((isChecked, tag) -> {
|
.setOnChangeAction((isChecked, tag) -> {
|
||||||
app.appConfig.registerSyncOnlyWifi = isChecked;
|
app.appConfig.registerSyncOnlyWifi = isChecked;
|
||||||
app.saveConfig("registerSyncOnlyWifi");
|
app.saveConfig("registerSyncOnlyWifi");
|
||||||
|
SyncWorker.Companion.rescheduleNext(app);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -532,6 +533,10 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
|||||||
syncCardIntervalItem.setChecked(app.appConfig.registerSyncEnabled);
|
syncCardIntervalItem.setChecked(app.appConfig.registerSyncEnabled);
|
||||||
syncCardIntervalItem.setOnClickAction(() -> {
|
syncCardIntervalItem.setOnClickAction(() -> {
|
||||||
List<CharSequence> intervalNames = new ArrayList<>();
|
List<CharSequence> 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, 30));
|
||||||
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_minutes, 45));
|
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_minutes, 45));
|
||||||
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_hours, 1));
|
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, 3));
|
||||||
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_hours, 4));
|
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_hours, 4));
|
||||||
List<Integer> intervals = new ArrayList<>();
|
List<Integer> intervals = new ArrayList<>();
|
||||||
|
if (App.devMode) {
|
||||||
|
intervals.add(30);
|
||||||
|
intervals.add(5 * 60);
|
||||||
|
}
|
||||||
intervals.add(30 * 60);
|
intervals.add(30 * 60);
|
||||||
intervals.add(45 * 60);
|
intervals.add(45 * 60);
|
||||||
intervals.add(60 * 60);
|
intervals.add(60 * 60);
|
||||||
@ -564,20 +573,12 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
|||||||
app.appConfig.registerSyncEnabled = true;
|
app.appConfig.registerSyncEnabled = true;
|
||||||
// app.appConfig modifications have to surround syncCardIntervalItem and those ifs
|
// app.appConfig modifications have to surround syncCardIntervalItem and those ifs
|
||||||
app.saveConfig("registerSyncInterval", "registerSyncEnabled");
|
app.saveConfig("registerSyncInterval", "registerSyncEnabled");
|
||||||
SyncJob.clear();
|
SyncWorker.Companion.rescheduleNext(app);
|
||||||
SyncJob.schedule(app);
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.show();
|
.show();
|
||||||
});
|
});
|
||||||
syncCardIntervalItem.setOnChangeAction((isChecked, tag) -> {
|
syncCardIntervalItem.setOnChangeAction((isChecked, tag) -> {
|
||||||
if (isChecked) {
|
|
||||||
SyncJob.update(app);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SyncJob.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isChecked && !app.appConfig.registerSyncEnabled) {
|
if (isChecked && !app.appConfig.registerSyncEnabled) {
|
||||||
addCardItem(CARD_SYNC, 1, getSyncCardWifiItem());
|
addCardItem(CARD_SYNC, 1, getSyncCardWifiItem());
|
||||||
}
|
}
|
||||||
@ -586,6 +587,7 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
|||||||
}
|
}
|
||||||
app.appConfig.registerSyncEnabled = isChecked;
|
app.appConfig.registerSyncEnabled = isChecked;
|
||||||
app.saveConfig("registerSyncEnabled");
|
app.saveConfig("registerSyncEnabled");
|
||||||
|
SyncWorker.Companion.rescheduleNext(app);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
items.add(syncCardIntervalItem);
|
items.add(syncCardIntervalItem);
|
||||||
|
@ -14,16 +14,18 @@ import android.net.Uri;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.provider.MediaStore;
|
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.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
import android.widget.Toast;
|
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.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@ -64,8 +66,6 @@ import javax.crypto.ShortBufferException;
|
|||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
import androidx.core.content.FileProvider;
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.App;
|
import pl.szczodrzynski.edziennik.App;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
@ -106,7 +106,7 @@ public class Utils {
|
|||||||
|
|
||||||
public static void d(String TAG, String message) {
|
public static void d(String TAG, String message) {
|
||||||
if (App.devMode) {
|
if (App.devMode) {
|
||||||
Log.d(TAG, message);
|
Log.d("Szkolny/"+TAG, message);
|
||||||
//debugLog.add(TAG+": "+message);
|
//debugLog.add(TAG+": "+message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package pl.szczodrzynski.edziennik.utils.models;
|
|||||||
|
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -115,4 +116,7 @@ public class AppConfig {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String language = null;
|
public String language = null;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public boolean dontShowAppManagerDialog = false;
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,12 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.App;
|
import pl.szczodrzynski.edziennik.App;
|
||||||
import pl.szczodrzynski.edziennik.R;
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity;
|
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.data.db.modules.profiles.Profile;
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||||
import pl.szczodrzynski.edziennik.sync.SyncJob;
|
|
||||||
import pl.szczodrzynski.edziennik.widgets.WidgetConfig;
|
import pl.szczodrzynski.edziennik.widgets.WidgetConfig;
|
||||||
|
|
||||||
import static pl.szczodrzynski.edziennik.utils.Utils.getCellsForSize;
|
import static pl.szczodrzynski.edziennik.utils.Utils.getCellsForSize;
|
||||||
@ -39,7 +40,7 @@ public class WidgetLuckyNumber extends AppWidgetProvider {
|
|||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (ACTION_SYNC_DATA.equals(intent.getAction())){
|
if (ACTION_SYNC_DATA.equals(intent.getAction())){
|
||||||
SyncJob.run((App) context.getApplicationContext());
|
ApiService.Companion.startAndRequest(context, new SyncRequest());
|
||||||
}
|
}
|
||||||
super.onReceive(context, intent);
|
super.onReceive(context, intent);
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,10 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.App;
|
import pl.szczodrzynski.edziennik.App;
|
||||||
import pl.szczodrzynski.edziennik.R;
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity;
|
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;
|
import pl.szczodrzynski.edziennik.widgets.WidgetConfig;
|
||||||
|
|
||||||
public class WidgetNotifications extends AppWidgetProvider {
|
public class WidgetNotifications extends AppWidgetProvider {
|
||||||
@ -35,7 +36,7 @@ public class WidgetNotifications extends AppWidgetProvider {
|
|||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (ACTION_SYNC_DATA.equals(intent.getAction())){
|
if (ACTION_SYNC_DATA.equals(intent.getAction())){
|
||||||
SyncJob.run((App) context.getApplicationContext());
|
ApiService.Companion.startAndRequest(context, new SyncRequest());
|
||||||
}
|
}
|
||||||
super.onReceive(context, intent);
|
super.onReceive(context, intent);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:context=".HomeFragment">
|
tools:context=".HomeFragment">
|
||||||
|
|
||||||
@ -31,14 +30,23 @@
|
|||||||
android:layout_margin="8dp"
|
android:layout_margin="8dp"
|
||||||
tools:text="TextView" />
|
tools:text="TextView" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/devMode"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:visibility="visible">
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/mobidziennikMessagesSwitch"
|
android:id="@+id/mobidziennikMessagesSwitch"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_margin="8dp"
|
android:layout_margin="8dp"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
android:text="Zmień moduł wiadomości" />
|
||||||
android:text="Zmień moduł wiadomości"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/composeButton"
|
android:id="@+id/composeButton"
|
||||||
@ -46,54 +54,17 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
android:layout_margin="8dp"
|
||||||
android:visibility="gone"
|
|
||||||
android:text="Compose" />
|
android:text="Compose" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/testButton"
|
android:id="@+id/pruneWorkButton"
|
||||||
style="@style/Widget.MaterialComponents.Button"
|
style="@style/Widget.MaterialComponents.Button"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
android:layout_margin="8dp"
|
||||||
android:text="Start Service"
|
android:text="Prune finished work" />
|
||||||
android:visibility="gone"/>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/test2"
|
|
||||||
style="@style/Widget.MaterialComponents.Button"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="8dp"
|
|
||||||
android:text="Sync profile - view home"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/test3"
|
|
||||||
style="@style/Widget.MaterialComponents.Button"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="8dp"
|
|
||||||
android:text="Sync profile - view messages sent"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/test4"
|
|
||||||
style="@style/Widget.MaterialComponents.Button"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="8dp"
|
|
||||||
android:text="Sync profile - view grades"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/test5"
|
|
||||||
style="@style/Widget.MaterialComponents.Button"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="8dp"
|
|
||||||
android:text="Mark all announcements as read"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator>
|
</pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator>
|
||||||
|
@ -978,4 +978,8 @@
|
|||||||
<string name="edziennik_progress_endpoint_timetable">Pobieranie planu lekcji...</string>
|
<string name="edziennik_progress_endpoint_timetable">Pobieranie planu lekcji...</string>
|
||||||
<string name="edziennik_progress_endpoint_proposed_grades">Pobieranie ocen proponowanych...</string>
|
<string name="edziennik_progress_endpoint_proposed_grades">Pobieranie ocen proponowanych...</string>
|
||||||
<string name="edziennik_progress_endpoint_exams">Pobieranie listy sprawdzianów...</string>
|
<string name="edziennik_progress_endpoint_exams">Pobieranie listy sprawdzianów...</string>
|
||||||
|
<string name="app_manager_dialog_title">Wykryto problem z synchronizacją</string>
|
||||||
|
<string name="app_manager_dialog_text">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.</string>
|
||||||
|
<string name="dont_ask_again">Nie pytaj ponownie</string>
|
||||||
|
<string name="app_manager_open_failed">Nie udało się otworzyć ustawień</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -34,6 +34,7 @@ buildscript {
|
|||||||
|
|
||||||
room : "2.2.0-beta01",
|
room : "2.2.0-beta01",
|
||||||
lifecycle : "2.2.0-alpha04",
|
lifecycle : "2.2.0-alpha04",
|
||||||
|
work : "2.2.0",
|
||||||
|
|
||||||
firebase : '17.2.0',
|
firebase : '17.2.0',
|
||||||
firebasemessaging: "20.0.0",
|
firebasemessaging: "20.0.0",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user