diff --git a/app/build.gradle b/app/build.gradle index d89a1e5..bee6578 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -27,6 +27,7 @@ android { dependencies { + //implementation "com.android.support:support-compat:28.0.0" implementation 'androidx.recyclerview:recyclerview:1.0.0' implementation fileTree(include: ['*.jar'], dir: 'libs') androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0-beta02', { @@ -34,7 +35,7 @@ dependencies { }) implementation 'androidx.preference:preference:1.0.0' implementation 'com.google.android.material:material:1.0.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2' + implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3' implementation 'com.android.volley:volley:1.1.0' //noinspection GradleDependency implementation 'com.google.android.gms:play-services-auth:15.0.0' diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index 17bbbc1..75ba7f6 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -1,5 +1,6 @@ package de.sebse.fuplanner; +import android.accounts.Account; import android.accounts.AccountManager; import android.content.ContentResolver; import android.content.Intent; @@ -48,6 +49,7 @@ import de.sebse.fuplanner.services.kvv.types.LoginToken; import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.services.news.NewsManager; import de.sebse.fuplanner.tools.CustomAccountManager; +import de.sebse.fuplanner.tools.CustomNotificationManager; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.NewAsyncQueue; import de.sebse.fuplanner.tools.Preferences; @@ -138,12 +140,12 @@ public class MainActivity extends AppCompatActivity changeFragment(getDefaultFragmentAfterLogout()); }); } - ContentResolver.addPeriodicSync( - mAccountManager.getAccountByType(AccountGeneral.ACCOUNT_TYPE), - KVVContentProvider.PROVIDER_NAME, - Bundle.EMPTY, - AccountGeneral.SYNC_INTERVAL); + if (!Preferences.getBoolean(this, R.string.pref_set_auto_sync_on_startup)) { + registerSync(); + Preferences.setBoolean(this, R.string.pref_set_auto_sync_on_startup, true); + } + CustomNotificationManager.createNotificationChannel(this); } @Override @@ -169,6 +171,8 @@ public class MainActivity extends AppCompatActivity getKVV().modules().list().reloadIfOutdated(); } isPaused = false; + //log.d("onResume", "send notification!"); + //CustomNotificationManager.sendNotification(this, "Titel", "Neue Announcements!"); } @Override @@ -357,6 +361,20 @@ public class MainActivity extends AppCompatActivity ((TextView) header.findViewById(R.id.login_mail)).setText(email); changeFragment(newFragment); + registerSync(); + } + + private void registerSync() { + Account accountByType = mAccountManager.getAccountByType(AccountGeneral.ACCOUNT_TYPE); + log.d("registerSync", accountByType); + if (accountByType != null) { + ContentResolver.setSyncAutomatically(accountByType, KVVContentProvider.PROVIDER_NAME, true); + ContentResolver.addPeriodicSync( + accountByType, + KVVContentProvider.PROVIDER_NAME, + Bundle.EMPTY, + AccountGeneral.SYNC_INTERVAL); + } } private void changeFragment(int newFragment) { diff --git a/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVSyncAdapter.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVSyncAdapter.java index cf2d3bf..8ef879e 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVSyncAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVSyncAdapter.java @@ -17,11 +17,13 @@ import de.sebse.fuplanner.services.kvv.KVVListener; import de.sebse.fuplanner.services.kvv.types.LoginToken; import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.CustomAccountManager; +import de.sebse.fuplanner.tools.NewAsyncQueue; import de.sebse.fuplanner.tools.logging.Logger; public class KVVSyncAdapter extends AbstractThreadedSyncAdapter { private KVV mKVV; private Logger log = new Logger(this); + private NewAsyncQueue mQueue = new NewAsyncQueue(); /** * Set up the sync adapter @@ -53,7 +55,12 @@ public class KVVSyncAdapter extends AbstractThreadedSyncAdapter { return accountManager; } }, context); - mKVV.account().restoreOnlineLogin(bool -> {}); + mQueue.add(() -> { + mKVV.account().restoreOnlineLogin(bool -> { + log.d("login restored"); + mQueue.next(); + }); + }); } /* @@ -68,20 +75,29 @@ public class KVVSyncAdapter extends AbstractThreadedSyncAdapter { String authority, ContentProviderClient provider, SyncResult syncResult) { - log.d("start syncing"); - /* - * Put the data transfer code here. - */ - mKVV.modules().list().recv(success -> { - Iterator iterator = success.latestSemesterIterator(); - while (iterator.hasNext()) { - Modules.Module module = iterator.next(); - log.d("sync module", module.title); - mKVV.modules().details().recv(module, success1 -> { - if (success1.second) - log.d("Sync Successful for Module '"+module.title+"'!"); - }, log::e, true); - } - }, log::e, true); + log.d("onPerformSync"); + mQueue.add(() -> { + log.d("start syncing"); + mKVV.modules().list().recv(success -> { + Iterator iterator = success.latestSemesterIterator(); + while (iterator.hasNext()) { + Modules.Module module = iterator.next(); + log.d("sync module", module.title); + mKVV.modules().details().recv(module, success1 -> { + if (success1.second) { + log.d("Sync Successful for Module '"+module.title+"'!"); + mQueue.next(); + } + }, msg -> { + log.e(msg); + mQueue.next(); + }, true); + } + }, msg -> { + log.e(msg); + mQueue.next(); + }, true); + log.d("finished"); + }); } } diff --git a/app/src/main/java/de/sebse/fuplanner/tools/CustomNotificationManager.java b/app/src/main/java/de/sebse/fuplanner/tools/CustomNotificationManager.java new file mode 100644 index 0000000..73e8f46 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/tools/CustomNotificationManager.java @@ -0,0 +1,57 @@ +package de.sebse.fuplanner.tools; + +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.os.Build; + +import org.jetbrains.annotations.NotNull; + +import androidx.core.app.NotificationCompat; +import androidx.core.app.NotificationManagerCompat; +import de.sebse.fuplanner.MainActivity; +import de.sebse.fuplanner.R; + +public class CustomNotificationManager { + private static final String CHANNEL_ID = "fuplanner-default"; + //public static ArrayList passedNotifications = new ArrayList<>(); + + public static void sendNotification(Context context, String textTitle, String textContent) { + Intent intent = new Intent(context, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); + + + NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, CHANNEL_ID) + .setSmallIcon(R.drawable.ic_notification) + .setContentTitle(textTitle) + .setContentText(textContent) + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setContentIntent(pendingIntent) + .setAutoCancel(true); + + NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); + int notificationId = (int) (System.currentTimeMillis() % Integer.MAX_VALUE); + notificationManager.notify(notificationId, mBuilder.build()); + } + + public static void createNotificationChannel(@NotNull Context context) { + // Create the NotificationChannel, but only on API 26+ because + // the NotificationChannel class is new and not in the support library + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + CharSequence name = context.getString(R.string.channel_name); + String description = context.getString(R.string.channel_description); + int importance = NotificationManager.IMPORTANCE_DEFAULT; + NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance); + channel.setDescription(description); + // Register the channel with the system; you can't change the importance + // or other notification behaviors after this + NotificationManager notificationManager = context.getSystemService(NotificationManager.class); + if (notificationManager != null) { + notificationManager.createNotificationChannel(channel); + } + } + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/tools/Preferences.java b/app/src/main/java/de/sebse/fuplanner/tools/Preferences.java index 9c98512..c86eede 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/Preferences.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/Preferences.java @@ -1,6 +1,7 @@ package de.sebse.fuplanner.tools; import android.content.Context; + import androidx.annotation.ArrayRes; import androidx.annotation.StringRes; import androidx.preference.PreferenceManager; @@ -20,4 +21,14 @@ public class Preferences { String string = context.getResources().getString(key); PreferenceManager.getDefaultSharedPreferences(context).edit().putLong(string, value).apply(); } + + public static boolean getBoolean(Context context, @StringRes int key) { + String string = context.getResources().getString(key); + return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(string, false); + } + + public static void setBoolean(Context context, @StringRes int key, boolean value) { + String string = context.getResources().getString(key); + PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(string, value).apply(); + } } diff --git a/app/src/main/res/drawable-hdpi/ic_notification.png b/app/src/main/res/drawable-hdpi/ic_notification.png new file mode 100644 index 0000000..2d7c1b9 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_notification.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_notification.png b/app/src/main/res/drawable-mdpi/ic_notification.png new file mode 100644 index 0000000..279fcdd Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_notification.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_notification.png b/app/src/main/res/drawable-xhdpi/ic_notification.png new file mode 100644 index 0000000..bb5065c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_notification.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_notification.png b/app/src/main/res/drawable-xxhdpi/ic_notification.png new file mode 100644 index 0000000..29dc666 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_notification.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_notification.png b/app/src/main/res/drawable-xxxhdpi/ic_notification.png new file mode 100644 index 0000000..128789a Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_notification.png differ diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 2e1e37d..de49298 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -92,4 +92,5 @@ Das Passwort ist nicht korrekt. Pflichtfeld KVV-Synchronisation + Neue Daten verfügbar \ No newline at end of file diff --git a/app/src/main/res/values/preferences.xml b/app/src/main/res/values/preferences.xml index 63926cc..d1535fd 100644 --- a/app/src/main/res/values/preferences.xml +++ b/app/src/main/res/values/preferences.xml @@ -8,4 +8,6 @@ all pref_last_visited_news + + pref_set_auto_sync_on_startup \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 47efe37..33af0dc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -100,4 +100,6 @@ This password is incorrect This field is required KVV Synchronization + New data available + Notify when new announcements, assignments, grades or resources are available