diff --git a/app/build.gradle b/app/build.gradle index e39afc1..39de4ac 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,7 +34,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/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ca1fede..a07063c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,6 +5,9 @@ + - + + + + + - + + + + + + + + diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index 21043a4..75ba7f6 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -1,6 +1,8 @@ package de.sebse.fuplanner; +import android.accounts.Account; import android.accounts.AccountManager; +import android.content.ContentResolver; import android.content.Intent; import android.os.Bundle; import android.view.Menu; @@ -36,27 +38,24 @@ import de.sebse.fuplanner.fragments.ScheduleFragment; import de.sebse.fuplanner.fragments.StartupFragment; import de.sebse.fuplanner.fragments.canteen.DaySwitcherFragment; import de.sebse.fuplanner.fragments.moddetails.ModDetailFragment; -import de.sebse.fuplanner.services.Canteen.CanteenBrowser; -import de.sebse.fuplanner.services.Canteen.types.Canteen; -import de.sebse.fuplanner.services.Canteen.types.CanteenListener; -import de.sebse.fuplanner.services.GoogleAuth.Credentials; -import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth; -import de.sebse.fuplanner.services.KVV.KVV; -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.services.News.NewsManager; -import de.sebse.fuplanner.services.newkvv.AccountGeneral; +import de.sebse.fuplanner.services.canteen.CanteenBrowser; +import de.sebse.fuplanner.services.canteen.types.Canteen; +import de.sebse.fuplanner.services.canteen.types.CanteenListener; +import de.sebse.fuplanner.services.fulogin.AccountGeneral; +import de.sebse.fuplanner.services.kvv.KVV; +import de.sebse.fuplanner.services.kvv.KVVListener; +import de.sebse.fuplanner.services.kvv.sync.KVVContentProvider; +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; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.RequestPermissionsResultListener; import de.sebse.fuplanner.tools.logging.Logger; -import de.sebse.fuplanner.tools.network.NetworkCallback; -import de.sebse.fuplanner.tools.network.NetworkError; -import de.sebse.fuplanner.tools.network.NetworkErrorCallback; import de.sebse.fuplanner.tools.types.News; public class MainActivity extends AppCompatActivity @@ -80,7 +79,6 @@ public class MainActivity extends AppCompatActivity private static final int DOUBLE_CLICK_TO_EXIT_MILLIS = 2000; private FragmentManager mFragmentManager; - private GoogleAuth mGoogleAuth; private KVV mKVV; private NewsManager mNewsManager; private CanteenBrowser mCanteenBrowser; @@ -91,7 +89,6 @@ public class MainActivity extends AppCompatActivity @NotNull private String mFragmentData = ""; private final HashMap permissionListeners = new HashMap<>(); - private boolean mOfflineBanner; private final NewAsyncQueue mQueue = new NewAsyncQueue(); private long mDoubleBackToExitPressedOnce = 0; private CustomAccountManager mAccountManager; @@ -143,6 +140,12 @@ public class MainActivity extends AppCompatActivity changeFragment(getDefaultFragmentAfterLogout()); }); } + + 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 @@ -150,16 +153,13 @@ public class MainActivity extends AppCompatActivity super.onPause(); isPaused = true; isLoggedInBeforePause = getKVV().account().isLoggedIn(); - log.d("onPause", isPaused, isLoggedInBeforePause); } @Override protected void onResume() { super.onResume(); - log.d("onResume", isPaused, isLoggedInBeforePause); if (isPaused) { getKVV().account().restoreOnlineLogin(isRestored -> { - log.d("onResume", isRestored); updateNavigation(); if (isRestored && !isLoggedInBeforePause) changeFragment(getDefaultFragmentAfterLogin()); @@ -168,8 +168,11 @@ public class MainActivity extends AppCompatActivity changeFragment(getDefaultFragmentAfterLogout()); } }); + getKVV().modules().list().reloadIfOutdated(); } isPaused = false; + //log.d("onResume", "send notification!"); + //CustomNotificationManager.sendNotification(this, "Titel", "Neue Announcements!"); } @Override @@ -272,11 +275,6 @@ public class MainActivity extends AppCompatActivity case R.id.nav_logout: getKVV().account().logout(true); getKVV().modules().list().delete(); - this.getGoogleAuth().getLoginState(credentials -> { - if (credentials != null) { - this.getGoogleAuth().deleteLoginState(credentials.getUsername(), credentials.getPassword()); - } - }); break; } @@ -292,12 +290,6 @@ public class MainActivity extends AppCompatActivity return true; } - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - this.getGoogleAuth().onActivityResult(requestCode, resultCode, data); - } - @Override protected void onSaveInstanceState(Bundle savedInstanceState) { if (mFragmentPage != FRAGMENT_STARTUP && mFragmentPage != FRAGMENT_NONE) { @@ -325,13 +317,6 @@ public class MainActivity extends AppCompatActivity /* --------------------------------------------*/ /* --------------------------------------------*/ - public GoogleAuth getGoogleAuth() { - if (this.mGoogleAuth == null) { - this.mGoogleAuth = new GoogleAuth(this); - } - return this.mGoogleAuth; - } - public NewsManager getNewsManager() { if (this.mNewsManager == null) { this.mNewsManager = new NewsManager(this); @@ -362,15 +347,13 @@ public class MainActivity extends AppCompatActivity } private void toLogoutState() { - setOfflineBanner(false); setRefreshFailedBanner(false); updateNavigation(); changeFragment(getDefaultFragmentAfterLogout()); mAccountManager.getTokenByType(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV, null); } - private void toLoginState(String fullName, String email, int newFragment, boolean onlineMode) { - setOfflineBanner(!onlineMode); + private void toLoginState(String fullName, String email, int newFragment) { updateNavigation(); View header = mNavigationView.getHeaderView(0); @@ -378,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) { @@ -442,15 +439,9 @@ public class MainActivity extends AppCompatActivity invalidateOptionsMenu(); } - private void setOfflineBanner(boolean visible) { - View offline_header = findViewById(R.id.offline_msg); - offline_header.setVisibility(visible ? View.VISIBLE : View.GONE); - mOfflineBanner = visible; - } - private void setRefreshFailedBanner(boolean refreshFailed) { View viewNoConnection = findViewById(R.id.no_connection_msg); - if (!mOfflineBanner && refreshFailed) + if (refreshFailed) viewNoConnection.setVisibility(View.VISIBLE); else viewNoConnection.setVisibility(View.GONE); @@ -669,20 +660,10 @@ public class MainActivity extends AppCompatActivity - @Override - public void getCredentials(NetworkCallback callback, NetworkErrorCallback error) { - getGoogleAuth().getLoginState(credentials -> { - if (credentials == null || credentials.getUsername() == null || credentials.getPassword() == null) { - error.onError(new NetworkError(200100, 403, "No Google Login available!")); - } else { - callback.onResponse(credentials); - } - }); - } @Override - public void onLogin(LoginToken token, boolean enteringOnlineMode) { - toLoginState(token.getFullName(), token.getEmail(), getDefaultFragmentAfterLogin(), enteringOnlineMode); + public void onLogin(LoginToken token) { + toLoginState(token.getFullName(), token.getEmail(), getDefaultFragmentAfterLogin()); } @Override diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java index db8acb2..3b99e5d 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java @@ -8,8 +8,8 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; import de.sebse.fuplanner.fragments.CanteensFragment.OnCanteensFragmentInteractionListener; -import de.sebse.fuplanner.services.Canteen.types.Canteen; -import de.sebse.fuplanner.services.Canteen.types.Canteens; +import de.sebse.fuplanner.services.canteen.types.Canteen; +import de.sebse.fuplanner.services.canteen.types.Canteens; import de.sebse.fuplanner.tools.ui.ItemViewHolder; /** diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java index 99d838d..6612471 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java @@ -13,7 +13,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.Canteen.CanteenBrowser; +import de.sebse.fuplanner.services.canteen.CanteenBrowser; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java index 3d770ea..01b5916 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java @@ -11,9 +11,9 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; import de.sebse.fuplanner.fragments.ModulesFragment.OnModulesFragmentInteractionListener; -import de.sebse.fuplanner.services.KVV.types.Lecturer; -import de.sebse.fuplanner.services.KVV.types.Modules; -import de.sebse.fuplanner.services.KVV.types.Semester; +import de.sebse.fuplanner.services.kvv.types.Lecturer; +import de.sebse.fuplanner.services.kvv.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Semester; import de.sebse.fuplanner.tools.ui.CustomViewHolder; import de.sebse.fuplanner.tools.ui.ItemViewHolder; import de.sebse.fuplanner.tools.ui.StringViewHolder; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/NewsAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/NewsAdapter.java index a454958..cdebef9 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/NewsAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/NewsAdapter.java @@ -8,7 +8,7 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; import de.sebse.fuplanner.fragments.ModulesFragment.OnModulesFragmentInteractionListener; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.types.News; import de.sebse.fuplanner.tools.types.NewsList; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/NewsFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/NewsFragment.java index 7e5dcb6..b497406 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/NewsFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/NewsFragment.java @@ -11,22 +11,11 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Locale; - import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.tools.DateSortedList; import de.sebse.fuplanner.tools.MainActivityListener; -import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; -import de.sebse.fuplanner.tools.types.News; import de.sebse.fuplanner.tools.types.NewsList; /** diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/ScheduleFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/ScheduleFragment.java index 01329b2..703c172 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/ScheduleFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/ScheduleFragment.java @@ -16,8 +16,8 @@ import java.util.List; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Event; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Event; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherAdapter.java index d9bfcca..b47436c 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherAdapter.java @@ -4,7 +4,7 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentStatePagerAdapter; -import de.sebse.fuplanner.services.Canteen.types.Canteen; +import de.sebse.fuplanner.services.canteen.types.Canteen; import de.sebse.fuplanner.tools.UtilsDate; class DaySwitcherAdapter extends FragmentStatePagerAdapter { diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherFragment.java index 0150508..5fe8bf8 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherFragment.java @@ -11,8 +11,8 @@ import androidx.fragment.app.Fragment; import androidx.viewpager.widget.ViewPager; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.Canteen.CanteenBrowser; -import de.sebse.fuplanner.services.Canteen.types.Canteen; +import de.sebse.fuplanner.services.canteen.CanteenBrowser; +import de.sebse.fuplanner.services.canteen.types.Canteen; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.network.NetworkCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherListener.java b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherListener.java index 8fdc87d..909deca 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherListener.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherListener.java @@ -1,6 +1,6 @@ package de.sebse.fuplanner.fragments.canteen; -import de.sebse.fuplanner.services.Canteen.types.Canteen; +import de.sebse.fuplanner.services.canteen.types.Canteen; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealAdapter.java index 1534f54..21fee6b 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealAdapter.java @@ -13,8 +13,8 @@ import androidx.annotation.NonNull; import androidx.annotation.StringRes; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.Canteen.types.Day; -import de.sebse.fuplanner.services.Canteen.types.Meal; +import de.sebse.fuplanner.services.canteen.types.Day; +import de.sebse.fuplanner.services.canteen.types.Meal; import de.sebse.fuplanner.tools.Preferences; import de.sebse.fuplanner.tools.ui.MealViewHolder; import de.sebse.fuplanner.tools.ui.StringViewHolder; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealFragment.java index 4b42f30..ad1e46b 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealFragment.java @@ -13,9 +13,9 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.Canteen.CanteenBrowser; -import de.sebse.fuplanner.services.Canteen.types.Canteen; -import de.sebse.fuplanner.services.Canteen.types.Day; +import de.sebse.fuplanner.services.canteen.CanteenBrowser; +import de.sebse.fuplanner.services.canteen.types.Canteen; +import de.sebse.fuplanner.services.canteen.types.Day; import de.sebse.fuplanner.tools.logging.Logger; /** diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java index c416336..1e26f9d 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java @@ -16,9 +16,9 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.ui.Download; -import de.sebse.fuplanner.services.KVV.types.Announcement; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.ui.Download; +import de.sebse.fuplanner.services.kvv.types.Announcement; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceFragment.java index 102ee62..fcbd7cf 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceFragment.java @@ -14,8 +14,8 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Modules; -import de.sebse.fuplanner.services.KVV.ui.Download; +import de.sebse.fuplanner.services.kvv.types.Modules; +import de.sebse.fuplanner.services.kvv.ui.Download; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java index 7e115d4..d2fc2a9 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java @@ -16,9 +16,9 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.ui.Download; -import de.sebse.fuplanner.services.KVV.types.Assignment; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.ui.Download; +import de.sebse.fuplanner.services.kvv.types.Assignment; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java index 28f2514..19b4af6 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java @@ -14,8 +14,8 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.ui.Download; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.ui.Download; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java index 7773664..6de6a20 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java @@ -14,10 +14,10 @@ import java.util.Map; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Event; -import de.sebse.fuplanner.services.KVV.types.EventList; -import de.sebse.fuplanner.services.KVV.types.GroupedEvents; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Event; +import de.sebse.fuplanner.services.kvv.types.EventList; +import de.sebse.fuplanner.services.kvv.types.GroupedEvents; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.ui.CustomViewHolder; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailFragment.java index b673cb2..7bc80fa 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailFragment.java @@ -10,7 +10,7 @@ import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.viewpager.widget.ViewPager; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookAdapter.java index cd0bb74..8a1e3c9 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookAdapter.java @@ -12,8 +12,8 @@ import java.util.ArrayList; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Grade; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Grade; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.ui.StringViewHolder; class ModDetailGradebookAdapter extends RecyclerView.Adapter { diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailOverviewAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailOverviewAdapter.java index 6b616d4..1f444cd 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailOverviewAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailOverviewAdapter.java @@ -15,11 +15,11 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Announcement; -import de.sebse.fuplanner.services.KVV.types.Assignment; -import de.sebse.fuplanner.services.KVV.types.Event; -import de.sebse.fuplanner.services.KVV.types.Lecturer; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Announcement; +import de.sebse.fuplanner.services.kvv.types.Assignment; +import de.sebse.fuplanner.services.kvv.types.Event; +import de.sebse.fuplanner.services.kvv.types.Lecturer; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.ui.CustomViewHolder; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java index ba5f006..b91ef2a 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java @@ -3,8 +3,8 @@ package de.sebse.fuplanner.fragments.moddetails; import java.util.ArrayList; import java.util.List; -import de.sebse.fuplanner.services.KVV.types.Modules; -import de.sebse.fuplanner.services.KVV.types.Resource; +import de.sebse.fuplanner.services.kvv.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Resource; import de.sebse.fuplanner.tools.ui.treeview.TreeNode; import de.sebse.fuplanner.tools.ui.treeview.TreeViewAdapter; import de.sebse.fuplanner.tools.ui.treeview.TreeViewBinder; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java index 9d23e95..56f5249 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java @@ -18,9 +18,9 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.ui.Download; -import de.sebse.fuplanner.services.KVV.types.Modules; -import de.sebse.fuplanner.services.KVV.types.Resource; +import de.sebse.fuplanner.services.kvv.ui.Download; +import de.sebse.fuplanner.services.kvv.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Resource; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.ui.treeview.DirectoryNodeBinder; diff --git a/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/ConnectedListener.java b/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/ConnectedListener.java deleted file mode 100644 index b0b625b..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/ConnectedListener.java +++ /dev/null @@ -1,9 +0,0 @@ -package de.sebse.fuplanner.services.GoogleAuth; - -/** - * Created by sebastian on 07.11.17. - */ - -public interface ConnectedListener { - void connected(); -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/Credentials.java b/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/Credentials.java deleted file mode 100644 index 907ef70..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/Credentials.java +++ /dev/null @@ -1,23 +0,0 @@ -package de.sebse.fuplanner.services.GoogleAuth; - -/** - * Created by Sebastian on 06.11.2017. - */ - -public class Credentials { - private final String username; - private final String password; - - public Credentials(String username, String password) { - this.username = username; - this.password = password; - } - - public String getUsername() { - return username; - } - - public String getPassword() { - return password; - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/CredentialsListener.java b/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/CredentialsListener.java deleted file mode 100644 index 29f9d38..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/CredentialsListener.java +++ /dev/null @@ -1,9 +0,0 @@ -package de.sebse.fuplanner.services.GoogleAuth; - -/** - * Created by Sebastian on 06.11.2017. - */ - -public interface CredentialsListener { - void onCredentials(Credentials credentials); -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/GoogleAuth.java b/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/GoogleAuth.java deleted file mode 100644 index eb82495..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/GoogleAuth.java +++ /dev/null @@ -1,224 +0,0 @@ -package de.sebse.fuplanner.services.GoogleAuth; - -import android.content.Intent; -import android.content.IntentSender; -import android.util.Log; -import android.widget.Toast; - -import com.google.android.gms.auth.api.credentials.Credential; -import com.google.android.gms.auth.api.credentials.CredentialRequest; -import com.google.android.gms.auth.api.credentials.CredentialsClient; -import com.google.android.gms.auth.api.credentials.CredentialsOptions; -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GoogleApiAvailability; -import com.google.android.gms.common.api.ApiException; -import com.google.android.gms.common.api.CommonStatusCodes; -import com.google.android.gms.common.api.ResolvableApiException; - -import androidx.annotation.Nullable; -import androidx.fragment.app.FragmentActivity; - -import static android.app.Activity.RESULT_OK; - -/** - * Created by Sebastian on 06.11.2017. - */ - -public class GoogleAuth { - // https://developers.google.com/identity/smartlock-passwords/android/retrieve-credentials - - private static final String TAG = "GoogleAuth"; - private final FragmentActivity activity; - private static final String FU_PLANNER_PROVIDER = "FUPlanner"; - private CredentialsClient mCredentialsClient; - private boolean mIsResolving; - @Nullable - private CredentialsListener mCredentialsListener; - private boolean isConnected = false; - - public GoogleAuth(FragmentActivity activity) { - this.activity = activity; - } - - private void connect() { - if (this.isUnavailable()) { - Log.w(TAG, "STATUS: Google auth not available!"); - return; - } - this.mCredentialsClient = getClient(); - this.isConnected = true; - } - - - - - public void getLoginState(final CredentialsListener credentialsListener) { - if (this.isUnavailable()) { - Log.w(TAG, "STATUS: Google auth not available!"); - credentialsListener.onCredentials(null); - return; - } - if (!this.isConnected) - connect(); - CredentialRequest request = new CredentialRequest.Builder() - .setPasswordLoginSupported(true) - .setAccountTypes(FU_PLANNER_PROVIDER) - .build(); - - - mCredentialsClient.request(request).addOnCompleteListener(task -> { - if (task.isSuccessful()) { - // Successfully read the credential without any user interaction, this - // means there was only a single credential and the user has auto - // sign-in enabled. - Credential credential = task.getResult().getCredential(); - credentialsListener.onCredentials(new Credentials(credential.getId(), credential.getPassword())); - return; - } - - Exception e = task.getException(); - if (e instanceof ResolvableApiException) { - // This is most likely the case where the user has multiple saved - // credentials and needs to pick one. This requires showing UI to - // resolve the read request. - GoogleAuth.this.mCredentialsListener = credentialsListener; - ResolvableApiException rae = (ResolvableApiException) e; - resolveResult(rae, RequestCode.RC_READ); - return; - } - - if (e instanceof ApiException) { - ApiException ae = (ApiException) e; - if (ae.getStatusCode() == CommonStatusCodes.SIGN_IN_REQUIRED) { - // This means only a hint is available, but we are handling that - // elsewhere so no need to act here. - } else { - credentialsListener.onCredentials(null); - Log.w(TAG, "Unexpected status code: " + ae.getStatusCode()); - } - } - }); - } - - public void setLoginState(String username, String password) { - if (this.isUnavailable()) { - Log.w(TAG, "STATUS: Google auth not available!"); - Toast.makeText(activity, "Google auth not available!", Toast.LENGTH_SHORT).show(); - return; - } - if (!this.isConnected) - connect(); - Credential credential = new Credential.Builder(username) - .setPassword(password) - .build(); - mCredentialsClient.save(credential).addOnCompleteListener(task -> { - if (task.isSuccessful()) { - showToast("Credential saved."); - return; - } - - Exception e = task.getException(); - if (e instanceof ResolvableApiException) { - // The first time a credential is saved, the user is shown UI - // to confirm the action. This requires resolution. - ResolvableApiException rae = (ResolvableApiException) e; - resolveResult(rae, RequestCode.RC_SAVE); - } else { - // Save failure cannot be resolved. - Log.w(TAG, "Save failed.", e); - showToast("Credential Save Failed"); - } - }); - } - - public void deleteLoginState(String username, String password) { - if (this.isUnavailable()) { - Log.w(TAG, "STATUS: Google auth not available!"); - return; - } - if (!this.isConnected) - connect(); - Credential credential = new Credential.Builder(username) - .setPassword(password) - .build(); - mCredentialsClient.delete(credential).addOnCompleteListener(task -> { - if (task.isSuccessful()) { - // Credential was deleted successfully - } - }); - } - - - private boolean isUnavailable() { - return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this.activity) != ConnectionResult.SUCCESS; - } - - private CredentialsClient getClient() { - CredentialsOptions options = new CredentialsOptions.Builder() - .forceEnableSaveDialog() - .build(); - return com.google.android.gms.auth.api.credentials.Credentials.getClient(this.activity, options); - } - - public void onActivityResult(int requestCode, int resultCode, Intent data) { - Log.w(TAG, "onActivityResult:" + requestCode + ":" + resultCode + ":" + data); - - switch (requestCode) { - case RequestCode.RC_HINT: - // Drop into handling for RC_READ - case RequestCode.RC_READ: - if (resultCode == RESULT_OK) { - boolean isHint = (requestCode == RequestCode.RC_HINT); - Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY); - if (mCredentialsListener != null) - this.mCredentialsListener.onCredentials(new Credentials(credential.getId(), credential.getPassword())); - else - Log.w(TAG, "No Credentials Listener"); - } else { - if (mCredentialsListener != null) - this.mCredentialsListener.onCredentials(null); - else - Log.w(TAG, "No Credentials Listener"); - Log.e(TAG, "Credential Read: NOT OK"); - showToast("Credential Read Failed"); - } - - mIsResolving = false; - break; - case RequestCode.RC_SAVE: - if (resultCode == RESULT_OK) { - Log.w(TAG, "Credential Save: OK"); - showToast("Credential Save Success"); - } else { - Log.e(TAG, "Credential Save: NOT OK"); - showToast("Credential Save Failed"); - } - - mIsResolving = false; - break; - } - } - - - private void resolveResult(ResolvableApiException rae, int requestCode) { - // We don't want to fire multiple resolutions at once since that can result - // in stacked dialogs after rotation or another similar event. - if (mIsResolving) { - Log.w(TAG, "resolveResult: already resolving."); - return; - } - - Log.w(TAG, "Resolving: " + rae); - try { - rae.startResolutionForResult(this.activity, requestCode); - mIsResolving = true; - } catch (IntentSender.SendIntentException e) { - Log.e(TAG, "STATUS: Failed to send resolution.", e); - } - } - - /** Display a short Toast message **/ - private void showToast(String msg) { - Toast.makeText(this.activity, msg, Toast.LENGTH_SHORT).show(); - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/RequestCode.java b/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/RequestCode.java deleted file mode 100644 index 150a5b4..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/RequestCode.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.sebse.fuplanner.services.GoogleAuth; - -/** - * Created by sebastian on 07.11.17. - */ - -class RequestCode { - public static final int RC_SAVE = 1; - public static final int RC_HINT = 2; - public static final int RC_READ = 3; -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java deleted file mode 100644 index 9747f7f..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java +++ /dev/null @@ -1,23 +0,0 @@ -package de.sebse.fuplanner.services.KVV; - -import com.android.volley.NetworkResponse; - -import de.sebse.fuplanner.services.GoogleAuth.Credentials; -import de.sebse.fuplanner.services.KVV.types.LoginToken; -import de.sebse.fuplanner.tools.CustomAccountManager; -import de.sebse.fuplanner.tools.network.NetworkCallback; -import de.sebse.fuplanner.tools.network.NetworkErrorCallback; - -public interface KVVListener { - void getCredentials(NetworkCallback callback, NetworkErrorCallback error); - - void onLogin(LoginToken token, boolean enteringOnlineMode); - - void onLogout(); - - void onModuleListChange(); - - void onKVVNetworkResponse(NetworkResponse error); - - CustomAccountManager getAccountManager(); -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/Canteen/CanteenBrowser.java b/app/src/main/java/de/sebse/fuplanner/services/canteen/CanteenBrowser.java similarity index 97% rename from app/src/main/java/de/sebse/fuplanner/services/Canteen/CanteenBrowser.java rename to app/src/main/java/de/sebse/fuplanner/services/canteen/CanteenBrowser.java index 9ae6fdb..3869c63 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/Canteen/CanteenBrowser.java +++ b/app/src/main/java/de/sebse/fuplanner/services/canteen/CanteenBrowser.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.Canteen; +package de.sebse.fuplanner.services.canteen; import android.content.Context; @@ -8,10 +8,10 @@ import org.json.JSONObject; import java.io.IOException; -import de.sebse.fuplanner.services.Canteen.types.Canteen; -import de.sebse.fuplanner.services.Canteen.types.CanteenListener; -import de.sebse.fuplanner.services.Canteen.types.Canteens; -import de.sebse.fuplanner.services.Canteen.types.Day; +import de.sebse.fuplanner.services.canteen.types.Canteen; +import de.sebse.fuplanner.services.canteen.types.CanteenListener; +import de.sebse.fuplanner.services.canteen.types.Canteens; +import de.sebse.fuplanner.services.canteen.types.Day; import de.sebse.fuplanner.tools.AsyncQueue; import de.sebse.fuplanner.tools.network.HTTPService; import de.sebse.fuplanner.tools.network.NetworkCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteen.java b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/Canteen.java similarity index 98% rename from app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteen.java rename to app/src/main/java/de/sebse/fuplanner/services/canteen/types/Canteen.java index b74aa1b..a6d928b 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteen.java +++ b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/Canteen.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.Canteen.types; +package de.sebse.fuplanner.services.canteen.types; import androidx.annotation.NonNull; diff --git a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/CanteenListener.java b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/CanteenListener.java similarity index 62% rename from app/src/main/java/de/sebse/fuplanner/services/Canteen/types/CanteenListener.java rename to app/src/main/java/de/sebse/fuplanner/services/canteen/types/CanteenListener.java index f6d36c1..1ed10d4 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/CanteenListener.java +++ b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/CanteenListener.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.Canteen.types; +package de.sebse.fuplanner.services.canteen.types; public interface CanteenListener { void onCanteenRefreshCompleted(boolean b); diff --git a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteens.java b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/Canteens.java similarity index 98% rename from app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteens.java rename to app/src/main/java/de/sebse/fuplanner/services/canteen/types/Canteens.java index a02cf56..d3ddfee 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteens.java +++ b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/Canteens.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.Canteen.types; +package de.sebse.fuplanner.services.canteen.types; import android.content.Context; import androidx.annotation.NonNull; diff --git a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Day.java b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/Day.java similarity index 96% rename from app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Day.java rename to app/src/main/java/de/sebse/fuplanner/services/canteen/types/Day.java index 4367d40..3699614 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Day.java +++ b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/Day.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.Canteen.types; +package de.sebse.fuplanner.services.canteen.types; import androidx.annotation.NonNull; diff --git a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Meal.java b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/Meal.java similarity index 98% rename from app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Meal.java rename to app/src/main/java/de/sebse/fuplanner/services/canteen/types/Meal.java index b265a67..ac019ae 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Meal.java +++ b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/Meal.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.Canteen.types; +package de.sebse.fuplanner.services.canteen.types; import java.io.Serializable; import java.util.ArrayList; diff --git a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/SortedListCanteen.java b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/SortedListCanteen.java similarity index 91% rename from app/src/main/java/de/sebse/fuplanner/services/Canteen/types/SortedListCanteen.java rename to app/src/main/java/de/sebse/fuplanner/services/canteen/types/SortedListCanteen.java index 6beaa18..b57f98b 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/SortedListCanteen.java +++ b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/SortedListCanteen.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.Canteen.types; +package de.sebse.fuplanner.services.canteen.types; import de.sebse.fuplanner.tools.SortedList; diff --git a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/SortedListDay.java b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/SortedListDay.java similarity index 91% rename from app/src/main/java/de/sebse/fuplanner/services/Canteen/types/SortedListDay.java rename to app/src/main/java/de/sebse/fuplanner/services/canteen/types/SortedListDay.java index 8ded38d..790880b 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/SortedListDay.java +++ b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/SortedListDay.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.Canteen.types; +package de.sebse.fuplanner.services.canteen.types; import java.util.Calendar; diff --git a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/SortedListMeal.java b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/SortedListMeal.java similarity index 90% rename from app/src/main/java/de/sebse/fuplanner/services/Canteen/types/SortedListMeal.java rename to app/src/main/java/de/sebse/fuplanner/services/canteen/types/SortedListMeal.java index 8c5d090..57064f4 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/SortedListMeal.java +++ b/app/src/main/java/de/sebse/fuplanner/services/canteen/types/SortedListMeal.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.Canteen.types; +package de.sebse.fuplanner.services.canteen.types; import de.sebse.fuplanner.tools.SortedList; diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/AccountGeneral.java b/app/src/main/java/de/sebse/fuplanner/services/fulogin/AccountGeneral.java similarity index 65% rename from app/src/main/java/de/sebse/fuplanner/services/newkvv/AccountGeneral.java rename to app/src/main/java/de/sebse/fuplanner/services/fulogin/AccountGeneral.java index 2d98253..af6749e 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/newkvv/AccountGeneral.java +++ b/app/src/main/java/de/sebse/fuplanner/services/fulogin/AccountGeneral.java @@ -1,7 +1,8 @@ -package de.sebse.fuplanner.services.newkvv; +package de.sebse.fuplanner.services.fulogin; public class AccountGeneral { public static final String ACCOUNT_TYPE = "de.sebse.fuplanner.fuauth"; public static final String AUTHTOKEN_TYPE_KVV = "KVV"; public static final String AUTHTOKEN_TYPE_BLACKBOARD = "Blackboard"; + public static final long SYNC_INTERVAL = 6 * 60 * 60; // defined in seconds } diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticator.java b/app/src/main/java/de/sebse/fuplanner/services/fulogin/FUAuthenticator.java similarity index 98% rename from app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticator.java rename to app/src/main/java/de/sebse/fuplanner/services/fulogin/FUAuthenticator.java index 6dfba9c..ae8e79d 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticator.java +++ b/app/src/main/java/de/sebse/fuplanner/services/fulogin/FUAuthenticator.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.newkvv; +package de.sebse.fuplanner.services.fulogin; import android.accounts.AbstractAccountAuthenticator; import android.accounts.Account; diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java b/app/src/main/java/de/sebse/fuplanner/services/fulogin/FUAuthenticatorActivity.java similarity index 95% rename from app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java rename to app/src/main/java/de/sebse/fuplanner/services/fulogin/FUAuthenticatorActivity.java index 03ee6cd..79b6e14 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/services/fulogin/FUAuthenticatorActivity.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.newkvv; +package de.sebse.fuplanner.services.fulogin; import android.accounts.Account; import android.accounts.AccountAuthenticatorActivity; @@ -27,7 +27,7 @@ import android.widget.EditText; import androidx.annotation.NonNull; import de.sebse.fuplanner.R; -import static de.sebse.fuplanner.services.newkvv.UserLoginTask.PARAM_USER_PASS; +import static de.sebse.fuplanner.services.fulogin.UserLoginTask.PARAM_USER_PASS; /** * A login screen that offers login via email/password. @@ -169,10 +169,6 @@ public class FUAuthenticatorActivity extends AccountAuthenticatorActivity implem mEmailView.setError(getString(R.string.error_field_required)); focusView = mEmailView; cancel = true; - } else if (!isEmailValid(email)) { - mEmailView.setError(getString(R.string.error_invalid_email)); - focusView = mEmailView; - cancel = true; } if (cancel) { @@ -188,11 +184,6 @@ public class FUAuthenticatorActivity extends AccountAuthenticatorActivity implem } } - private boolean isEmailValid(String email) { - //TODO: Replace this with your own logic - return true;//email.contains("@"); - } - private boolean isPasswordValid(String password) { //TODO: Replace this with your own logic return password.length() > 4; diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorService.java b/app/src/main/java/de/sebse/fuplanner/services/fulogin/FUAuthenticatorService.java similarity index 87% rename from app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorService.java rename to app/src/main/java/de/sebse/fuplanner/services/fulogin/FUAuthenticatorService.java index a6f1516..62519a6 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorService.java +++ b/app/src/main/java/de/sebse/fuplanner/services/fulogin/FUAuthenticatorService.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.newkvv; +package de.sebse.fuplanner.services.fulogin; import android.app.Service; import android.content.Intent; diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java b/app/src/main/java/de/sebse/fuplanner/services/fulogin/UserLoginTask.java similarity index 91% rename from app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java rename to app/src/main/java/de/sebse/fuplanner/services/fulogin/UserLoginTask.java index 3338106..577fe7f 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java +++ b/app/src/main/java/de/sebse/fuplanner/services/fulogin/UserLoginTask.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.newkvv; +package de.sebse.fuplanner.services.fulogin; import android.accounts.AccountManager; import android.annotation.SuppressLint; @@ -14,8 +14,8 @@ import java.util.concurrent.atomic.AtomicReference; import androidx.annotation.Nullable; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.LoginToken; -import de.sebse.fuplanner.services.newkvv.network.Login; +import de.sebse.fuplanner.services.kvv.types.LoginToken; +import de.sebse.fuplanner.services.kvv.sync.Login; import de.sebse.fuplanner.tools.logging.Logger; @@ -62,8 +62,14 @@ public class UserLoginTask extends AsyncTask { mVolleyLogin.testLoginToken(success, success1 -> { login.set(success); latch.countDown(); - }, error -> latch.countDown()); - }, error -> latch.countDown()); + }, error -> { + log.e(error); + latch.countDown(); + }); + }, error -> { + log.e(error); + latch.countDown(); + }); try { latch.await(); } catch (InterruptedException e) { diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVV.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/KVV.java similarity index 96% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/KVV.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/KVV.java index 076947f..3a0770b 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVV.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/KVV.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV; +package de.sebse.fuplanner.services.kvv; import android.content.Context; diff --git a/app/src/main/java/de/sebse/fuplanner/services/kvv/KVVListener.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/KVVListener.java new file mode 100644 index 0000000..2699364 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/KVVListener.java @@ -0,0 +1,18 @@ +package de.sebse.fuplanner.services.kvv; + +import com.android.volley.NetworkResponse; + +import de.sebse.fuplanner.services.kvv.types.LoginToken; +import de.sebse.fuplanner.tools.CustomAccountManager; + +public interface KVVListener { + default void onLogin(LoginToken token) {} + + default void onLogout() {} + + default void onModuleListChange() {} + + default void onKVVNetworkResponse(NetworkResponse error) {} + + CustomAccountManager getAccountManager(); +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/Login.java similarity index 60% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/Login.java index ca47f2e..206eaf5 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/Login.java @@ -1,14 +1,12 @@ -package de.sebse.fuplanner.services.KVV; +package de.sebse.fuplanner.services.kvv; import android.content.Context; import org.jetbrains.annotations.NotNull; -import org.json.JSONException; -import org.json.JSONObject; import androidx.annotation.Nullable; -import de.sebse.fuplanner.services.KVV.types.LoginToken; -import de.sebse.fuplanner.services.newkvv.AccountGeneral; +import de.sebse.fuplanner.services.kvv.types.LoginToken; +import de.sebse.fuplanner.services.fulogin.AccountGeneral; import de.sebse.fuplanner.tools.CustomAccountManager; import de.sebse.fuplanner.tools.NetworkCallbackCollector; import de.sebse.fuplanner.tools.network.HTTPService; @@ -20,7 +18,6 @@ public class Login extends HTTPService { private final KVVListener mListener; @Nullable private LoginToken mToken; private boolean mLoginPending = false; - private boolean mOnlineMode = false; private final NetworkCallbackCollector mRefreshCallbacks = new NetworkCallbackCollector<>(); Login(KVVListener listener, Context context) { @@ -28,25 +25,6 @@ public class Login extends HTTPService { this.mListener = listener; } - @Deprecated - public void reset() { - mToken = null; - mLoginPending = false; - mOnlineMode = false; - } - - public void doOnlineLogin(@NotNull String username, @NotNull String password, NetworkCallback callback, NetworkErrorCallback errorCallback) { - - } - - //public boolean restoreOnlineLogin() { - // return restoreLogin(true); - //} - - //public boolean doOfflineLogin() { - // return restoreLogin(false); - //} - public void restoreOnlineLogin(BooleanInterface callback) { if (mLoginPending) { callback.run(false); @@ -54,7 +32,7 @@ public class Login extends HTTPService { } mLoginPending = true; LoginToken.load(mListener.getAccountManager(), token -> { - boolean result = setToken(token, true); + boolean result = setToken(token); mLoginPending = false; log.d("loginToken", token != null ? token.toString() : null); callback.run(result); @@ -86,12 +64,8 @@ public class Login extends HTTPService { return mToken != null; } - public boolean isInOfflineMode() { - return isLoggedIn() && !mOnlineMode; - } - public boolean isInOnlineMode() { - return isLoggedIn() && mOnlineMode; + return isLoggedIn(); } void testLoginToken(@NotNull NetworkCallback callback, @NotNull NetworkErrorCallback errorCallback) { @@ -103,22 +77,7 @@ public class Login extends HTTPService { } private void testLoginToken(@NotNull LoginToken token, @NotNull NetworkCallback callback, @NotNull NetworkErrorCallback errorCallback) { - get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", token.getUsername()), token.getCookies(), response -> { - String body = response.getParsed(); - if (body == null) { - errorCallback.onError(new NetworkError(100172, 403, "Testing login failed!")); - return; - } - try { - JSONObject json = new JSONObject(body); - String displayName = json.getString("displayName"); - String email = json.getString("email"); - token.setAdditionals(displayName, email); - callback.onResponse(token); - } catch (JSONException e) { - errorCallback.onError(new NetworkError(100171, 403, "Cannot parse profile!")); - } - }, error -> errorCallback.onError(new NetworkError(100170, error.networkResponse.statusCode, "Testing login failed!"))); + new de.sebse.fuplanner.services.kvv.sync.Login(getContext()).testLoginToken(token, callback, errorCallback); } @Nullable public LoginToken getLoginToken() { @@ -132,9 +91,7 @@ public class Login extends HTTPService { return; CustomAccountManager manager = mListener.getAccountManager(); manager.doInvalidateToken(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV, ignored -> { - log.d("try restore", ignored); restoreOnlineLogin(isRestored -> { - log.d("restore", isRestored, mToken); if (isRestored) testLoginToken(mRefreshCallbacks::responseResponse, mRefreshCallbacks::responseError); else { @@ -143,21 +100,13 @@ public class Login extends HTTPService { } }); }); - /* mListener.getCredentials(credentials -> { - doOnlineLogin(credentials.getUsername(), credentials.getPassword(), - mRefreshCallbacks::responseResponse, - mRefreshCallbacks::responseError); - }, e -> { - logout(false); - mRefreshCallbacks.responseError(e); - });*/ } private boolean handleCallbacks() { if (mToken != null) { - mListener.onLogin(mToken, mOnlineMode); + mListener.onLogin(mToken); return true; } else { mListener.onLogout(); @@ -165,12 +114,11 @@ public class Login extends HTTPService { } } - private boolean setToken(@Nullable LoginToken token, boolean enteringOnlineMode) { + private boolean setToken(@Nullable LoginToken token) { if (token == null) return false; boolean isOnlyRefresh = mToken != null; mToken = token; - mOnlineMode = enteringOnlineMode; return isOnlyRefresh || handleCallbacks(); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/Modules.java similarity index 98% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/Modules.java index 6923138..f2e8868 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/Modules.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV; +package de.sebse.fuplanner.services.kvv; import android.content.Context; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAnnouncements.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesAnnouncements.java similarity index 96% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAnnouncements.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesAnnouncements.java index b13df13..d6b4877 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAnnouncements.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesAnnouncements.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV; +package de.sebse.fuplanner.services.kvv; import android.content.Context; @@ -8,8 +8,8 @@ import org.json.JSONObject; import java.util.ArrayList; -import de.sebse.fuplanner.services.KVV.types.Announcement; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Announcement; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAssignments.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesAssignments.java similarity index 94% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAssignments.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesAssignments.java index 357be2c..c7948a5 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAssignments.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesAssignments.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV; +package de.sebse.fuplanner.services.kvv; import android.content.Context; @@ -8,9 +8,9 @@ import org.json.JSONObject; import java.util.ArrayList; -import de.sebse.fuplanner.services.KVV.types.Assignment; -import de.sebse.fuplanner.services.KVV.types.AssignmentList; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Assignment; +import de.sebse.fuplanner.services.kvv.types.AssignmentList; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesDetails.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesDetails.java similarity index 94% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesDetails.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesDetails.java index a08fda4..ffc491c 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesDetails.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesDetails.java @@ -1,11 +1,11 @@ -package de.sebse.fuplanner.services.KVV; +package de.sebse.fuplanner.services.kvv; import android.content.Context; import android.util.Pair; import java.util.concurrent.atomic.AtomicReference; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesEvents.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesEvents.java similarity index 94% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesEvents.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesEvents.java index 66ba5c1..13417f9 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesEvents.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesEvents.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV; +package de.sebse.fuplanner.services.kvv; import android.content.Context; @@ -6,9 +6,9 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import de.sebse.fuplanner.services.KVV.types.Event; -import de.sebse.fuplanner.services.KVV.types.EventList; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Event; +import de.sebse.fuplanner.services.kvv.types.EventList; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesGradebook.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesGradebook.java similarity index 95% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesGradebook.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesGradebook.java index d346289..74672d9 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesGradebook.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesGradebook.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV; +package de.sebse.fuplanner.services.kvv; import android.content.Context; @@ -8,8 +8,8 @@ import org.json.JSONObject; import java.util.ArrayList; -import de.sebse.fuplanner.services.KVV.types.Grade; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Grade; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesList.java similarity index 91% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesList.java index 7c1d279..2707c52 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesList.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV; +package de.sebse.fuplanner.services.kvv; import android.content.Context; @@ -13,9 +13,9 @@ import java.util.HashSet; import java.util.LinkedHashSet; import java.util.regex.MatchResult; -import de.sebse.fuplanner.services.KVV.types.Lecturer; -import de.sebse.fuplanner.services.KVV.types.Modules; -import de.sebse.fuplanner.services.KVV.types.Semester; +import de.sebse.fuplanner.services.kvv.types.Lecturer; +import de.sebse.fuplanner.services.kvv.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Semester; import de.sebse.fuplanner.tools.NewAsyncQueue; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.network.HTTPService; @@ -23,7 +23,7 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -import static de.sebse.fuplanner.services.KVV.PartModules.RETRY_COUNT; +import static de.sebse.fuplanner.services.kvv.PartModules.RETRY_COUNT; public class ModulesList extends HTTPService { private final Login mLogin; @@ -46,6 +46,16 @@ public class ModulesList extends HTTPService { return null; } + public void reloadIfOutdated() { + try { + if (mModules != null && mModules.isNewerVersionInStorage(getContext())) { + restore(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + public void find(String moduleID, NetworkCallback moduleNetworkCallback, NetworkErrorCallback errorCallback) { find(moduleID, moduleNetworkCallback, errorCallback, RETRY_COUNT); } @@ -115,10 +125,10 @@ public class ModulesList extends HTTPService { this.upgrade(success -> { if (this.mModules == null) this.mModules = success; - else - this.mModules.updateList(success); - mListener.onModuleListChange(); - store(); + else if(this.mModules.updateList(success)) { + mListener.onModuleListChange(); + store(); + } callback.onResponse(this.mModules); mQueue.next(); }, error -> { @@ -139,6 +149,7 @@ public class ModulesList extends HTTPService { } private void upgrade(final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + log.d(mLogin.isInOnlineMode(), mLogin.getLoginToken()); if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) { errorCallback.onError(new NetworkError(101105, 500, "Currently running in offline mode!")); return; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesResources.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesResources.java similarity index 98% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesResources.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesResources.java index 3c7df2c..5fd6c43 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesResources.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesResources.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV; +package de.sebse.fuplanner.services.kvv; import android.content.Context; import android.os.Build; @@ -15,8 +15,8 @@ import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import de.sebse.fuplanner.services.KVV.types.Modules; -import de.sebse.fuplanner.services.KVV.types.Resource; +import de.sebse.fuplanner.services.kvv.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Resource; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.network.NetworkCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Part.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/Part.java similarity index 93% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/Part.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/Part.java index a9b11d7..763af76 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/Part.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/Part.java @@ -1,8 +1,8 @@ -package de.sebse.fuplanner.services.KVV; +package de.sebse.fuplanner.services.kvv; import android.content.Context; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.network.HTTPService; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/PartModules.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/PartModules.java similarity index 96% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/PartModules.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/PartModules.java index 8798c8c..eae3b53 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/PartModules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/PartModules.java @@ -1,11 +1,11 @@ -package de.sebse.fuplanner.services.KVV; +package de.sebse.fuplanner.services.kvv; import android.content.Context; import android.os.Build; import android.text.Html; import android.text.Spanned; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.tools.NewAsyncQueue; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVContentProvider.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVContentProvider.java new file mode 100644 index 0000000..ec78580 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVContentProvider.java @@ -0,0 +1,67 @@ +package de.sebse.fuplanner.services.kvv.sync; + +import android.content.ContentProvider; +import android.content.ContentValues; +import android.content.UriMatcher; +import android.database.Cursor; +import android.net.Uri; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class KVVContentProvider extends ContentProvider { + + public static final String PROVIDER_NAME = "de.sebse.fuplanner.contentprovider.kvv.modules"; + private static final Uri CONTENT_URI = Uri.parse("content://" + PROVIDER_NAME + "/modules"); + private static final int MODULE = 1; + private static final int MODULE_ID = 2; + private static final UriMatcher uriMatcher = getUriMatcher(); + + private static UriMatcher getUriMatcher() { + UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); + uriMatcher.addURI(PROVIDER_NAME, "modules", MODULE); + uriMatcher.addURI(PROVIDER_NAME, "modules/#", MODULE_ID); + return uriMatcher; + } + + + @Override + public boolean onCreate() { + return true; + } + + @Nullable + @Override + public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) { + return null; + } + + @Nullable + @Override + public String getType(@NonNull Uri uri) { + switch (uriMatcher.match(uri)) { + case MODULE: + return "vnd.android.cursor.dir/vnd.com."+PROVIDER_NAME; + case MODULE_ID: + return "vnd.android.cursor.item/vnd.com."+PROVIDER_NAME; + + } + return null; + } + + @Nullable + @Override + public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) { + return null; + } + + @Override + public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) { + return 0; + } + + @Override + public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) { + return 0; + } +} 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 new file mode 100644 index 0000000..108f787 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVSyncAdapter.java @@ -0,0 +1,161 @@ +package de.sebse.fuplanner.services.kvv.sync; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.content.AbstractThreadedSyncAdapter; +import android.content.ContentProviderClient; +import android.content.Context; +import android.content.SyncResult; +import android.os.Bundle; + +import java.util.ArrayList; +import java.util.Iterator; + +import androidx.annotation.StringRes; +import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.kvv.KVV; +import de.sebse.fuplanner.services.kvv.KVVListener; +import de.sebse.fuplanner.services.kvv.types.Announcement; +import de.sebse.fuplanner.services.kvv.types.Assignment; +import de.sebse.fuplanner.services.kvv.types.AssignmentList; +import de.sebse.fuplanner.services.kvv.types.Event; +import de.sebse.fuplanner.services.kvv.types.EventList; +import de.sebse.fuplanner.services.kvv.types.Grade; +import de.sebse.fuplanner.services.kvv.types.Modules; +import de.sebse.fuplanner.services.kvv.types.Resource; +import de.sebse.fuplanner.tools.CustomAccountManager; +import de.sebse.fuplanner.tools.CustomNotificationManager; +import de.sebse.fuplanner.tools.NewAsyncQueue; +import de.sebse.fuplanner.tools.UtilsDate; +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 + */ + public KVVSyncAdapter(Context context, boolean autoInitialize) { + super(context, autoInitialize); + init(context); + } + /** + * Set up the sync adapter. This form of the + * constructor maintains compatibility with Android 3.0 + * and later platform versions + */ + public KVVSyncAdapter( + Context context, + boolean autoInitialize, + boolean allowParallelSyncs) { + super(context, autoInitialize, allowParallelSyncs); + init(context); + } + + private void init(Context context) { + mKVV = new KVV(new KVVListener() { + CustomAccountManager accountManager = null; + @Override + public CustomAccountManager getAccountManager() { + if (accountManager == null) + accountManager = new CustomAccountManager(AccountManager.get(context), () -> null); + return accountManager; + } + }, context); + mQueue.add(() -> { + mKVV.account().restoreOnlineLogin(bool -> { + log.d("login restored"); + mQueue.next(); + }); + }); + } + + /* + * Specify the code you want to run in the sync adapter. The entire + * sync adapter runs in a background thread, so you don't have to set + * up your own background processing. + */ + @Override + public void onPerformSync( + Account account, + Bundle extras, + String authority, + ContentProviderClient provider, + SyncResult syncResult) { + 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); + final ArrayList announcements = module.announcements; + final AssignmentList assignments = module.assignments; + final EventList events = module.events; + final ArrayList gradebook = module.gradebook; + final ArrayList resources = module.resources; + mKVV.modules().details().recv(module, success1 -> { + if (success1.second) { + log.d("Sync Successful for Module '"+module.title+"'!"); + sendNotifications(announcements, module.announcements, module.title, Announcement::getTitle, Announcement::getId, + R.string.announcement_updated, R.string.announcement_added, R.string.announcement_removed); + sendNotifications(assignments, module.assignments, module.title, Assignment::getTitle, Assignment::getId, + R.string.assignment_updated, R.string.assignment_added, R.string.assignment_removed); + sendNotifications(events, module.events, module.title, evt -> evt.getTitle()+" - "+UtilsDate.getModifiedDate(evt.getStartDate()), Event::getId, + R.string.event_updated, R.string.event_added, R.string.event_removed); + sendNotifications(gradebook, module.gradebook, module.title, Grade::getItemName, Grade::getItemName, + R.string.gradebook_updated, R.string.gradebook_added, R.string.gradebook_removed); + sendNotifications(resources, module.resources, module.title, Resource::getTitle, Resource::getUrl, + R.string.resource_updated, R.string.resource_added, R.string.resource_removed); + mQueue.next(); + } + }, msg -> { + log.e(msg); + mQueue.next(); + }, true); + } + }, msg -> { + log.e(msg); + mQueue.next(); + }, true); + log.d("finished"); + }); + } + + private void sendNotifications(Iterable oldList, Iterable newList, String title, StringInterface titleInterface, StringInterface idInterface, @StringRes int updateRes, @StringRes int addRes, @StringRes int removeRes) { + if (oldList == null || newList == null) { + return; + } + ArrayList obsoletes = new ArrayList(); + for (T old: oldList) { + obsoletes.add(old); + } + for (T newEntry: newList) { + boolean found = false; + for (T oldEntry: oldList) { + if (idInterface.get(newEntry).equals(idInterface.get(oldEntry))) { + found = true; + if (newEntry.hashCode() != oldEntry.hashCode()) { + CustomNotificationManager.sendNotification(getContext(), getContext().getString(updateRes, title), titleInterface.get(newEntry)); + } + obsoletes.remove(oldEntry); + break; + } + } + if (!found) { + CustomNotificationManager.sendNotification(getContext(), getContext().getString(addRes, title), titleInterface.get(newEntry)); + } + } + for (T oldEntry: obsoletes) { + CustomNotificationManager.sendNotification(getContext(), getContext().getString(removeRes, title), titleInterface.get(oldEntry)); + } + } + + @FunctionalInterface + interface StringInterface { + String get(T element); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVSyncService.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVSyncService.java new file mode 100644 index 0000000..8000812 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVSyncService.java @@ -0,0 +1,24 @@ +package de.sebse.fuplanner.services.kvv.sync; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; + +public class KVVSyncService extends Service { + + private static final Object sSyncAdapterLock = new Object(); + private static KVVSyncAdapter sSyncAdapter = null; + + @Override + public void onCreate() { + synchronized (sSyncAdapterLock) { + if (sSyncAdapter == null) + sSyncAdapter = new KVVSyncAdapter(getApplicationContext(), true); + } + } + + @Override + public IBinder onBind(Intent intent) { + return sSyncAdapter.getSyncAdapterBinder(); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/Login.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/Login.java new file mode 100644 index 0000000..94ab31f --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/Login.java @@ -0,0 +1,265 @@ +package de.sebse.fuplanner.services.kvv.sync; + +import android.content.Context; + +import org.jetbrains.annotations.NotNull; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import de.sebse.fuplanner.services.kvv.types.LoginToken; +import de.sebse.fuplanner.tools.network.HTTPService; +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkError; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; + +public class Login extends HTTPService { + public Login(Context context) { + super(context); + } + + + public void testLoginToken(@NotNull LoginToken token, @NotNull NetworkCallback callback, @NotNull NetworkErrorCallback errorCallback) { + get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", token.getUsername()), token.getCookies(), response -> { + String body = response.getParsed(); + if (body == null) { + errorCallback.onError(new NetworkError(100172, 403, "Testing login failed!")); + return; + } + try { + JSONObject json = new JSONObject(body); + String displayName = json.getString("displayName"); + String email = json.getString("email"); + token.setAdditionals(displayName, email); + callback.onResponse(token); + } catch (JSONException e) { + errorCallback.onError(new NetworkError(100171, 403, "Cannot parse profile!")); + } + }, error -> errorCallback.onError(new NetworkError(100170, error.networkResponse.statusCode, "Testing login failed!"))); + } + + + + + + + + + + + + + + + + public void doLogin(String username, String password, NetworkCallback callback, NetworkErrorCallback error) { + step1(success1 -> { + String samlLocation = success1.get("Location"); + step2(samlLocation, success2 -> { + String fuJSESSIONID = success2.get("JSESSIONID"); + step3(fuJSESSIONID, success3 -> { + step4(username, password, fuJSESSIONID, success4 -> { + String fuSHIBSession = success4.get("shib_idp_session"); + String samlResponse = success4.get("SAMLResponse"); + step5(samlResponse, success5 -> { + String shibsessionKey = success5.get("shibsessionKey"); + String shibsessionName = success5.get("shibsessionName"); + step6(shibsessionKey, shibsessionName, success6 -> { + String kvvJSESSIONID = success6.get("JSESSIONID"); + LoginToken token = new LoginToken(username, shibsessionKey, shibsessionName, kvvJSESSIONID); + callback.onResponse(token); + }, error); + }, error); + }, error); + }, error); + }, error); + }, error); + } + + /* + 1= GET https://kvv.imp.fu-berlin.de/Shibboleth.sso/Login?entityID=https://identity.fu-berlin.de/idp-fub + -> Location-Header: https://identity.fu-berlin.de:9443/idp-fub-qa/profile/SAML2/Redirect/SSO?SAMLResponse=[SAMLResponse]&RelayState=[RelayState] + */ + private void step1(final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + get("https://kvv.imp.fu-berlin.de/Shibboleth.sso/Login?entityID=https://identity.fu-berlin.de/idp-fub", null, response -> { + String location = response.getHeaders().get("Location"); + if (location==null) { + errorCallback.onError(new NetworkError(100111, -1, "Error on getting SAML request!")); + return; + } + HashMap object = new HashMap<>(); + object.put("Location", location); + callback.onResponse(object); + }, error -> errorCallback.onError(new NetworkError(100110, error.networkResponse.statusCode, "Error on getting SAML request!"))); + } + + /* + 2= GET [Location-Header 1] + -> Set-Cookie: JSESSIONID=[JSESSION-FU] + -> Location: /idp-fub-qa/profile/SAML2/Redirect/SSO?execution=e1s1 + */ + private void step2(String url, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + get(url, null, response -> { + String cookies = response.getHeaders().get("Set-Cookie"); + if (cookies==null) { + errorCallback.onError(new NetworkError(100121, -1, "Error on starting FU session!")); + return; + } + HashMap object; + try { + object = getCookie(cookies, new String[]{"JSESSIONID"}); + } catch (NoSuchFieldException e) { + errorCallback.onError(new NetworkError(100122, -1, "Error on starting FU session!")); + return; + } + callback.onResponse(object); + }, error -> errorCallback.onError(new NetworkError(100120, error.networkResponse.statusCode, "Error on starting FU session!"))); + } + + /* + 3= GET [Location-Header 2] + + Cookie: JSESSIONID=[JSESSION-FU] + */ + private void step3(String JSESSIONID_FU, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + HashMap cookies = new HashMap<>(); + cookies.put("JSESSIONID", JSESSIONID_FU); + get("https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO?execution=e1s1", cookies, response -> { + callback.onResponse(true); + }, error -> errorCallback.onError(new NetworkError(100130, error.networkResponse.statusCode, "Error starting login page!"))); + } + + /* + 4= POST [Location-Header 2] + + Body: j_username=[USERNAME]&j_password=[PASSWORD]&_eventId_proceed= + + Header: Content-Type: application/x-www-form-urlencoded + + Header: Referer: [Location-Header 2] + + Cookie: JSESSIONID=[JSESSION-FU] + -> Set-Cookie: shib_idp_session=[SHIB-IDP-SESSION] + -> Body SAMLResponse-Input-value + */ + private void step4(String username, String password, String JSESSIONID_FU, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + HashMap cookies = new HashMap<>(); + cookies.put("JSESSIONID", JSESSIONID_FU); + HashMap body = new HashMap<>(); + body.put("j_username", username); + body.put("j_password", password); + body.put("_eventId_proceed", ""); + post("https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO?execution=e1s1", cookies, body, response -> { + String cookies1 = response.getHeaders().get("Set-Cookie"); + if (cookies1 ==null) { + errorCallback.onError(new NetworkError(100141, -1, "Error on logging in to FU Identity Server!")); + return; + } + HashMap object; + try { + object = getCookie(cookies1, new String[]{"shib_idp_session"}); + } catch (NoSuchFieldException e) { + errorCallback.onError(new NetworkError(100142, -1, "Error on logging in to FU Identity Server!")); + return; + } + + String content = response.getParsed(); + if (content == null) { + errorCallback.onError(new NetworkError(100143, -1, "Error on getting SAML response!")); + return; + } + Pattern pattern = Pattern.compile("name=\"SAMLResponse\" value=\"([0-9a-zA-Z+]+=*)"); + Matcher matcher = pattern.matcher(content); + if (!matcher.find()) { + errorCallback.onError(new NetworkError(100144, -1, "Error on getting SAML response!")); + return; + } + object.put("SAMLResponse", matcher.group(1)); + callback.onResponse(object); + }, error -> errorCallback.onError(new NetworkError(100145, error.networkResponse.statusCode, "Error on logging in to FU Identity Server!"))); + } + + /* + 5= POST https://kvv.imp.fu-berlin.de/Shibboleth.sso/SAML2/POST + + Body: SAMLResponse=[SAML-RESPONSE] + + Header: Content-Type: application/x-www-form-urlencoded + -> Set-Cookie: _shibsession_[SESS-NR]: [SESS-VALUE] + */ + private void step5(String SAMLResponse, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + HashMap body = new HashMap<>(); + body.put("SAMLResponse", SAMLResponse); + post("https://kvv.imp.fu-berlin.de/Shibboleth.sso/SAML2/POST", null, body, response -> { + String cookies = response.getHeaders().get("Set-Cookie"); + if (cookies ==null) { + errorCallback.onError(new NetworkError(100151, -1, "Error on starting KVV session!")); + return; + } + HashMap object = new HashMap<>(); + + + Pattern pattern = Pattern.compile("(_shibsession_[0-9a-f]+)=([^;]+);"); + Matcher matcher = pattern.matcher(cookies); + if (!matcher.find()) { + errorCallback.onError(new NetworkError(100152, -1, "Error on starting KVV session!")); + } + object.put("shibsessionKey", matcher.group(1)); + object.put("shibsessionName", matcher.group(2)); + + callback.onResponse(object); + }, error -> errorCallback.onError(new NetworkError(100150, error.networkResponse.statusCode, "Error on starting KVV session!"))); + } + + + /* + 6= https://kvv.imp.fu-berlin.de/sakai-login-tool/container + + Cookie: _shibsession_[SESS-NR]: [SESS-VALUE] + -> Set-Cookie: JSESSIONID: [JSESSION-KVV] + */ + private void step6(String shibsessionKey, String shibsessionName, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + HashMap cookies = new HashMap<>(); + cookies.put(shibsessionKey, shibsessionName); + get("https://kvv.imp.fu-berlin.de/sakai-login-tool/container", cookies, response -> { + String cookies1 = response.getHeaders().get("Set-Cookie"); + if (cookies1 ==null) { + errorCallback.onError(new NetworkError(100161, -1, "Cannot finish login process!")); + return; + } + HashMap object; + try { + object = getCookie(cookies1, new String[]{"JSESSIONID"}); + } catch (NoSuchFieldException e) { + errorCallback.onError(new NetworkError(100162, -1, "Cannot finish login process!")); + return; + } + callback.onResponse(object); + }, error -> errorCallback.onError(new NetworkError(100160, error.networkResponse.statusCode, "Cannot finish login process!"))); + } + + + + + + + + + + + + + private String getCookie(String cookies, String name) throws NoSuchFieldException { + Pattern pattern = Pattern.compile(name+"=([^;]+);"); + Matcher matcher = pattern.matcher(cookies); + if (!matcher.find()) { + log.e("GETcookie failed", name); + log.e("GETcookie failed", cookies); + throw new NoSuchFieldException(); + } + return matcher.group(1); + } + + private HashMap getCookie(String cookies, String[] names) throws NoSuchFieldException { + HashMap result = new HashMap<>(); + for (String name: names) { + result.put(name,this.getCookie(cookies, name)); + } + return result; + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Announcement.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Announcement.java similarity index 95% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/types/Announcement.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/Announcement.java index 9ad8656..909d297 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Announcement.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Announcement.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV.types; +package de.sebse.fuplanner.services.kvv.types; import com.google.android.gms.common.internal.Objects; @@ -16,7 +16,6 @@ public class Announcement implements Serializable { private final ArrayList urls; public Announcement(String id, String title, String body, String createdBy, long createdOn, ArrayList urls) { - this.id = id; this.title = title; this.body = body; @@ -29,7 +28,7 @@ public class Announcement implements Serializable { return urls; } - private String getId() { + public String getId() { return id; } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Assignment.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Assignment.java similarity index 95% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/types/Assignment.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/Assignment.java index 2e72d00..cdb4d55 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Assignment.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Assignment.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV.types; +package de.sebse.fuplanner.services.kvv.types; import com.google.android.gms.common.internal.Objects; @@ -22,7 +22,7 @@ public class Assignment implements Serializable { this.instructions = instructions; } - private String getId() { + public String getId() { return id; } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/AssignmentList.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/AssignmentList.java similarity index 86% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/types/AssignmentList.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/AssignmentList.java index 0516b60..4600f8f 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/AssignmentList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/AssignmentList.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV.types; +package de.sebse.fuplanner.services.kvv.types; import de.sebse.fuplanner.tools.DateSortedList; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Event.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Event.java similarity index 98% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/types/Event.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/Event.java index 22177d3..8a6005c 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Event.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Event.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV.types; +package de.sebse.fuplanner.services.kvv.types; import com.google.android.gms.common.internal.Objects; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/EventList.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/EventList.java similarity index 85% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/types/EventList.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/EventList.java index 5957c0e..a0ce825 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/EventList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/EventList.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV.types; +package de.sebse.fuplanner.services.kvv.types; import de.sebse.fuplanner.tools.DateSortedList; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Grade.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Grade.java similarity index 95% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/types/Grade.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/Grade.java index 1310429..fefba7f 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Grade.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Grade.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV.types; +package de.sebse.fuplanner.services.kvv.types; import com.google.android.gms.common.internal.Objects; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/GroupedEvents.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/GroupedEvents.java similarity index 98% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/types/GroupedEvents.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/GroupedEvents.java index 08835e3..7e4409b 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/GroupedEvents.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/GroupedEvents.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV.types; +package de.sebse.fuplanner.services.kvv.types; import android.annotation.SuppressLint; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Lecturer.java similarity index 96% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/Lecturer.java index 5bacd94..48842c5 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Lecturer.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV.types; +package de.sebse.fuplanner.services.kvv.types; import java.io.Serializable; import java.util.regex.Matcher; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/LoginToken.java similarity index 86% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/LoginToken.java index 544729f..b08905f 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/LoginToken.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV.types; +package de.sebse.fuplanner.services.kvv.types; import android.content.Context; @@ -11,7 +11,7 @@ import java.util.HashMap; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import de.sebse.fuplanner.services.newkvv.AccountGeneral; +import de.sebse.fuplanner.services.fulogin.AccountGeneral; import de.sebse.fuplanner.tools.CustomAccountManager; import de.sebse.fuplanner.tools.logging.Logger; @@ -39,32 +39,19 @@ public class LoginToken implements Serializable { @Nullable public static void load(CustomAccountManager manager, LoginTokenInterface callback) { - log.d("try to login"); if (!manager.hasAccounts(AccountGeneral.ACCOUNT_TYPE)) { callback.run(null); return; } - log.d("has accounts"); manager.getTokenByType(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV, tokenString -> { - //manager.getTokenByTypeSync(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV); if (tokenString == null) { callback.run(null); return; } - log.d("got token string", tokenString); callback.run(LoginToken.fromJsonString(tokenString)); - //return LoginToken.fromJsonString(tokenString); }); } - public void save(Context context) throws IOException { - /*FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); - ObjectOutputStream os = new ObjectOutputStream(fos); - os.writeObject(this); - os.close(); - fos.close();*/ - } - public void delete(CustomAccountManager manager) { manager.deleteAccount(AccountGeneral.ACCOUNT_TYPE); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Modules.java similarity index 74% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/Modules.java index 9e5b6d7..128ba8e 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Modules.java @@ -1,7 +1,9 @@ -package de.sebse.fuplanner.services.KVV.types; +package de.sebse.fuplanner.services.kvv.types; import android.content.Context; +import com.google.android.gms.common.internal.Objects; + import org.jetbrains.annotations.NotNull; import java.io.FileInputStream; @@ -25,8 +27,10 @@ import androidx.annotation.Nullable; public class Modules implements Iterable, Serializable { private SortedListModule list; private final String mUsername; + private transient long mLastTimestamp = 0; //private transient Logger log = new Logger(this); private static final String FILE_NAME = "ModuleListSaving"; + private static final String FILE_NAME_TIMESTAMP = "ModuleListSavingTimestamp"; public Modules(String username) { this.mUsername = username; @@ -75,15 +79,38 @@ public class Modules implements Iterable, Serializable { Modules modules = (Modules) readObject; is.close(); fis.close(); + + fis = context.openFileInput(FILE_NAME_TIMESTAMP); + is = new ObjectInputStream(fis); + modules.mLastTimestamp = is.readLong(); + is.close(); + fis.close(); + return modules; } + public boolean isNewerVersionInStorage(Context context) throws IOException { + FileInputStream fis = context.openFileInput(FILE_NAME_TIMESTAMP); + ObjectInputStream is = new ObjectInputStream(fis); + boolean result = this.mLastTimestamp < is.readLong(); + is.close(); + fis.close(); + return result; + } + public void save(Context context) throws IOException { FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); ObjectOutputStream os = new ObjectOutputStream(fos); os.writeObject(this); os.close(); fos.close(); + + fos = context.openFileOutput(FILE_NAME_TIMESTAMP, Context.MODE_PRIVATE); + os = new ObjectOutputStream(fos); + this.mLastTimestamp = System.currentTimeMillis(); + os.writeLong(this.mLastTimestamp); + os.close(); + fos.close(); } public void delete(Context context) { @@ -94,19 +121,36 @@ public class Modules implements Iterable, Serializable { return mUsername; } - public void updateList(Modules modules) { + public boolean updateList(Modules modules) { SortedListModule old = this.list; this.list = modules.list; + boolean isChanged = false; for (Module oldModule : old) { Module newModule = this.list.getById(oldModule.getID()); if (newModule != null) { + if (!isChanged && !hashEquals(oldModule, newModule)) + isChanged = true; newModule.announcements = oldModule.announcements; newModule.assignments = oldModule.assignments; newModule.events = oldModule.events; newModule.gradebook = oldModule.gradebook; newModule.resources = oldModule.resources; + } else { + isChanged = true; } } + if (this.list.size() != old.size()) + isChanged = true; + return isChanged; + } + + private boolean hashEquals(Module o1, Module o2) { + if (o1 == null && o2 == null) + return true; + else if (o1 == null || o2 == null) + return false; + else + return o1.hashCode() == o2.hashCode(); } public class Module implements Serializable { @@ -166,5 +210,10 @@ public class Modules implements Iterable, Serializable { "\ntype: "+type+ "\nID: "+ID; } + + @Override + public int hashCode() { + return Objects.hashCode(semester, lvNumber, title, lecturer, type, description, ID); + } } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Resource.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Resource.java similarity index 98% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/types/Resource.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/Resource.java index 5cb7e4d..829e53f 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Resource.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Resource.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV.types; +package de.sebse.fuplanner.services.kvv.types; import com.google.android.gms.common.internal.Objects; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Semester.java similarity index 97% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/Semester.java index 76605aa..80823cb 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Semester.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV.types; +package de.sebse.fuplanner.services.kvv.types; import java.io.Serializable; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/SortedListModule.java similarity index 97% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/SortedListModule.java index 5c226f4..b85f862 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/SortedListModule.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV.types; +package de.sebse.fuplanner.services.kvv.types; import androidx.annotation.Nullable; import de.sebse.fuplanner.tools.SortedList; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ui/Download.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/ui/Download.java similarity index 99% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/ui/Download.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/ui/Download.java index 637d143..47b8898 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ui/Download.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/ui/Download.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV.ui; +package de.sebse.fuplanner.services.kvv.ui; import android.Manifest; import android.app.AlertDialog; @@ -18,7 +18,7 @@ import androidx.core.app.ActivityCompat; import androidx.core.content.FileProvider; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Resource; +import de.sebse.fuplanner.services.kvv.types.Resource; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.RequestPermissionsResultListener; import de.sebse.fuplanner.tools.UtilsDate; diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/network/Login.java b/app/src/main/java/de/sebse/fuplanner/services/newkvv/network/Login.java deleted file mode 100644 index 5c67b22..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/newkvv/network/Login.java +++ /dev/null @@ -1,297 +0,0 @@ -package de.sebse.fuplanner.services.newkvv.network; - -import android.content.Context; - -import org.jetbrains.annotations.NotNull; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.HashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import de.sebse.fuplanner.services.KVV.types.LoginToken; -import de.sebse.fuplanner.tools.network.HTTPService; -import de.sebse.fuplanner.tools.network.NetworkCallback; -import de.sebse.fuplanner.tools.network.NetworkError; -import de.sebse.fuplanner.tools.network.NetworkErrorCallback; - -public class Login extends HTTPService { - public Login(Context context) { - super(context); - } - - - public void testLoginToken(@NotNull LoginToken token, @NotNull NetworkCallback callback, @NotNull NetworkErrorCallback errorCallback) { - get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", token.getUsername()), token.getCookies(), response -> { - String body = response.getParsed(); - if (body == null) { - errorCallback.onError(new NetworkError(100172, 403, "Testing login failed!")); - return; - } - try { - JSONObject json = new JSONObject(body); - String displayName = json.getString("displayName"); - String email = json.getString("email"); - token.setAdditionals(displayName, email); - callback.onResponse(token); - } catch (JSONException e) { - errorCallback.onError(new NetworkError(100171, 403, "Cannot parse profile!")); - } - }, error -> errorCallback.onError(new NetworkError(100170, error.networkResponse.statusCode, "Testing login failed!"))); - } - - - - - - - public void doLogin(String username, String password, NetworkCallback callback, NetworkErrorCallback error) { - startKVVSession(success -> { - String kvvJSESSIONID = success.get("JSESSIONID"); - getSAMLRequest(kvvJSESSIONID, success1 -> startIdentSession(success1.get("Location"), success11 -> { - String identJSESSIONID = success11.get("JSESSIONID"); - String ident_idp_authn_lc_key = success11.get("_idp_authn_lc_key"); - String identROUTEID = success11.get("ROUTEID"); - loginIdent(true, username, password, identJSESSIONID, ident_idp_authn_lc_key, identROUTEID, success111 -> loginIdent(false, username, password, identJSESSIONID, ident_idp_authn_lc_key, identROUTEID, success11112 -> { - String ident_idp_session = success11112.get("_idp_session"); - getSAMLResponse(identJSESSIONID, ident_idp_authn_lc_key, identROUTEID, ident_idp_session, success1111 -> loginKVV(success1111.get("RelayState"), success1111.get("SAMLResponse"), kvvJSESSIONID, success111112 -> { - LoginToken token = new LoginToken(username, success111112.get("shibsessionKey"), success111112.get("shibsessionName"), kvvJSESSIONID); - finishKVVlogin(token, success11111 -> callback.onResponse(token), error); - }, error), error); - }, error), error); - }, error), error); - }, error); - } - - /* - GET https://kvv.imp.fu-berlin.de/portal/login - -> JSESSIONID 5c10406f-588c-4c16-96e9-c80d115417de.tomcat1 - */ - private void startKVVSession(final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - get("https://kvv.imp.fu-berlin.de/portal/login", null, response -> { - String cookies = response.getHeaders().get("Set-Cookie"); - if (cookies==null) { - errorCallback.onError(new NetworkError(100101, -1, "Error on starting KVV session!")); - return; - } - HashMap object; - try { - object = getCookie(cookies, new String[]{"JSESSIONID"}); - } catch (NoSuchFieldException e) { - errorCallback.onError(new NetworkError(100102, -1, "Error on starting KVV session!")); - return; - } - callback.onResponse(object); - }, error -> errorCallback.onError(new NetworkError(100100, error.networkResponse.statusCode, "Error on starting KVV session!"))); - } - - /* - GET https://kvv.imp.fu-berlin.de/sakai-login-tool/container - <- JSESSIONID - -> (Location-Header) https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO - ?SAMLRequest=fZLLb.....Q8yre3X1IHwkJKE0Mnpy/V9TH4A - &RelayState=ss:mem:7ea01e29157b8bd906f7002176.....0d1a505f2c8bf - */ - private void getSAMLRequest(String JSESSIONID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - HashMap cookies = new HashMap<>(); - cookies.put("JSESSIONID", JSESSIONID); - get("https://kvv.imp.fu-berlin.de/sakai-login-tool/container", cookies, response -> { - String location = response.getHeaders().get("Location"); - if (location==null) { - errorCallback.onError(new NetworkError(100111, -1, "Error on getting SAML request!")); - return; - } - HashMap object = new HashMap<>(); - object.put("Location", location); - callback.onResponse(object); - }, error -> errorCallback.onError(new NetworkError(100110, error.networkResponse.statusCode, "Error on getting SAML request!"))); - } - - /* - GET https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO - ?SAMLRequest=fZLLbsIwEEV/JfI+cWJAUIsgpbAoEi2IpF10UznxUKw6dupxaPn7hkdb2LD29bkzRzNGUeuGZ63fmjV8toA++K61QX58SEnrDLcCFXIjakDuK55njwvOopg3znpbWU2CDBGcV9ZMrcG2BpeD26kKnteLlGy9b5BT+rHbRapuok0bluC0MpEEmm9VWVoNfhshWnpgM7pa5gUJZt0wyogD9h+iJBiv/P6aomQTbtqSdhNtlIYzZg1SOag8zfMlCeazlLyNqpHsy1gO2V1fVsNBMuqJoUyAJaxXDUaiiyG2MDfohfEpYXEyDJM4ZKxgCe/FPI5fSbA6L36vjFTm/bal8hRC/lAUq/C02gs4PK7VBchkfHDNj8Xuwv5trPhVTiY3BeOf4DG96DmVNvypA89nK6tVtQ8yre3X1IHwkJKE0Mnpy/V9TH4A - &RelayState=ss:mem:7ea01e29157b8bd906f7002176213b6db5e1f45ebb88716a9820d1a505f2c8bf - -> JSESSIONID C4B6A428BA1F50746235D03F5D107A57 - -> _idp_authn_lc_key 57a6ae26067f374cc3d0ccfc47e27b04b47752d2a3d4eb2782af0d3994535395 - -> ROUTEID .1 - */ - private void startIdentSession(String url, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - get(url, null, response -> { - String cookies = response.getHeaders().get("Set-Cookie"); - if (cookies==null) { - errorCallback.onError(new NetworkError(100121, -1, "Error on starting Ident session!")); - return; - } - HashMap object; - try { - object = getCookie(cookies, new String[]{"JSESSIONID", "_idp_authn_lc_key", "ROUTEID"}); - } catch (NoSuchFieldException e) { - errorCallback.onError(new NetworkError(100122, -1, "Error on starting Ident session!")); - return; - } - callback.onResponse(object); - }, error -> errorCallback.onError(new NetworkError(100120, error.networkResponse.statusCode, "Error on starting Ident session!"))); - } - - /* - POST https://identity.fu-berlin.de/idp-fub/Authn/UserPassword - <- j_username seedorf96 - <- j_password neinhieristpatrick - <- (Header-"Content-Type") application/x-www-form-urlencoded - <- JSESSIONID - <- _idp_authn_lc_key - <- ROUTEID - -> _idp_session OTMuMTkzLjg1LjMz|LQ==|OGYxOWI4MjA2NTQ4YWUwYzJkOWM4Mjk4YzcwZDMwZmJiZjBmMTdmMzkyZGU2OWIwY2JkNmZlNjlmNTRmNzBlMQ==|wLlzQal7VqyntmG2vLNn06wt8wQ= - */ - private void loginIdent(final boolean first, String username, String password, String JSESSIONID, String _idp_authn_lc_key, String ROUTEID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - HashMap cookies = new HashMap<>(); - cookies.put("JSESSIONID", JSESSIONID); - cookies.put("_idp_authn_lc_key", _idp_authn_lc_key); - cookies.put("ROUTEID", ROUTEID); - HashMap body = new HashMap<>(); - body.put("j_username", username); - body.put("j_password", password); - post("https://identity.fu-berlin.de/idp-fub/Authn/UserPassword", cookies, body, response -> { - if (first) { - callback.onResponse(new HashMap<>()); - return; - } - - String cookies1 = response.getHeaders().get("Set-Cookie"); - if (cookies1 ==null) { - errorCallback.onError(new NetworkError(100131, -1, "Error on logging in to Identity Server!")); - return; - } - HashMap object; - try { - object = getCookie(cookies1, new String[]{"_idp_session"}); - } catch (NoSuchFieldException e) { - errorCallback.onError(new NetworkError(100132, -1, "Error on logging in to Identity Server!")); - return; - } - callback.onResponse(object); - }, error -> errorCallback.onError(new NetworkError(100130, error.networkResponse.statusCode, "Error on logging in to Identity Server!"))); - } - - /* - GET https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO - <- JSESSIONID - <- _idp_authn_lc_key - <- ROUTEID - <- _idp_session - -> (BODY) RelayState 7ea01e29157b8bd906f7002176213b6db5e1f45ebb88716a9820d1a505f2c8bf - -> (BODY) SAMLResponse PD94bWwgdmVyc2lvbj0...........wvc2FtbDJwOlJlc3BvbnNlPg== - */ - private void getSAMLResponse(String JSESSIONID, String _idp_authn_lc_key, String ROUTEID, String _idp_session, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - HashMap cookies = new HashMap<>(); - cookies.put("JSESSIONID", JSESSIONID); - cookies.put("_idp_authn_lc_key", _idp_authn_lc_key); - cookies.put("ROUTEID", ROUTEID); - cookies.put("_idp_session", _idp_session); - get("https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO", cookies, response -> { - String body = response.getParsed(); - if (body == null) { - errorCallback.onError(new NetworkError(100143, -1, "Error on getting SAML response!")); - return; - } - - HashMap object = new HashMap<>(); - - Pattern pattern = Pattern.compile("ss:mem:([0-9a-f]+)"); - Matcher matcher = pattern.matcher(body); - if (!matcher.find()) { - errorCallback.onError(new NetworkError(100142, -1, "Error on getting SAML response!")); - return; - } - object.put("RelayState", "ss:mem:"+matcher.group(1)); - - pattern = Pattern.compile("name=\"SAMLResponse\" value=\"([0-9a-zA-Z+]+=*)"); - matcher = pattern.matcher(body); - if (!matcher.find()) { - errorCallback.onError(new NetworkError(100141, -1, "Error on getting SAML response!")); - return; - } - object.put("SAMLResponse", matcher.group(1)); - - callback.onResponse(object); - }, error -> errorCallback.onError(new NetworkError(100140, error.networkResponse.statusCode, "Error on getting SAML response!"))); - } - - - /* - POST https://kvv.imp.fu-berlin.de/Shibboleth.sso/SAML2/POST - <- RelayState 7ea01e29157b8bd906f7002176213b6db5e1f45ebb88716a9820d1a505f2c8bf - <- SAMLResponse PD94bWwgdmVyc2lvbj0...........wvc2FtbDJwOlJlc3BvbnNlPg== - <- JSESSIONID - -> _shibsession_64656661756c7468747470733a2f2f6b76762e696d702e66752d6265726c696e2e64652f73686962626f6c657468 - _b1912c5a03d733a80bd3fee772bf68d4 - */ - private void loginKVV(String RelayState, String SAMLResponse, String JSESSIONID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - HashMap cookies = new HashMap<>(); - cookies.put("JSESSIONID", JSESSIONID); - HashMap body = new HashMap<>(); - body.put("RelayState", RelayState); - body.put("SAMLResponse", SAMLResponse); - post("https://kvv.imp.fu-berlin.de/Shibboleth.sso/SAML2/POST", cookies, body, response -> { - String cookies1 = response.getHeaders().get("Set-Cookie"); - if (cookies1 ==null) { - errorCallback.onError(new NetworkError(100151, -1, "Error on starting KVV session!")); - return; - } - HashMap object = new HashMap<>(); - - - Pattern pattern = Pattern.compile("(_shibsession_[0-9a-f]+)=([^;]+);"); - Matcher matcher = pattern.matcher(cookies1); - if (!matcher.find()) { - errorCallback.onError(new NetworkError(100152, -1, "Error on starting Ident session!")); - } - object.put("shibsessionKey", matcher.group(1)); - object.put("shibsessionName", matcher.group(2)); - - callback.onResponse(object); - }, error -> errorCallback.onError(new NetworkError(100150, error.networkResponse.statusCode, "Error on starting Ident session!"))); - } - - - /* - GET https://kvv.imp.fu-berlin.de/sakai-login-tool/container - <- JSESSIONID - <- _shibsession_64656661756c7468747470733a2f2f6b76762e696d702e66752d6265726c696e2e64652f73686962626f6c657468 - _b1912c5a03d733a80bd3fee772bf68d4 - */ - private void finishKVVlogin(LoginToken loginToken, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - get("https://kvv.imp.fu-berlin.de/sakai-login-tool/container", loginToken.getCookies(), response -> callback.onResponse(new HashMap<>()), error -> errorCallback.onError(new NetworkError(100160, error.networkResponse.statusCode, "Cannot finish login process!"))); - } - - - - - - - - - - - - - private String getCookie(String cookies, String name) throws NoSuchFieldException { - Pattern pattern = Pattern.compile(name+"=([^;]+);"); - Matcher matcher = pattern.matcher(cookies); - if (!matcher.find()) { - log.e("GETcookie failed", name); - log.e("GETcookie failed", cookies); - throw new NoSuchFieldException(); - } - return matcher.group(1); - } - - private HashMap getCookie(String cookies, String[] names) throws NoSuchFieldException { - HashMap result = new HashMap<>(); - for (String name: names) { - result.put(name,this.getCookie(cookies, name)); - } - return result; - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/News/NewsManager.java b/app/src/main/java/de/sebse/fuplanner/services/news/NewsManager.java similarity index 98% rename from app/src/main/java/de/sebse/fuplanner/services/News/NewsManager.java rename to app/src/main/java/de/sebse/fuplanner/services/news/NewsManager.java index 8a67a7b..1ffd446 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/News/NewsManager.java +++ b/app/src/main/java/de/sebse/fuplanner/services/news/NewsManager.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.News; +package de.sebse.fuplanner.services.news; import android.content.Context; diff --git a/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java b/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java index 25d13d9..82b0643 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java @@ -2,16 +2,17 @@ package de.sebse.fuplanner.tools; import android.accounts.Account; import android.accounts.AccountManager; +import android.accounts.AccountManagerCallback; import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; +import android.app.Activity; import android.os.Build; import android.os.Bundle; import java.io.IOException; import androidx.annotation.Nullable; -import de.sebse.fuplanner.MainActivity; -import de.sebse.fuplanner.services.KVV.Login; +import de.sebse.fuplanner.services.kvv.Login; import de.sebse.fuplanner.tools.logging.Logger; public class CustomAccountManager { @@ -77,8 +78,8 @@ public class CustomAccountManager { } public void getTokenByType(String accountType, String authTokenType, @Nullable StringInterface callback) { - //Account account = mAccountManager.getAccountsByType(accountType)[0]; - mAccountManager.getAuthTokenByFeatures(accountType, authTokenType, null, mActivityInterface.get(), null, null, accountManagerFuture -> { + Activity activity = mActivityInterface.get(); + AccountManagerCallback cb = (accountManagerFuture -> { try { Bundle bnd = accountManagerFuture.getResult(); final String authtoken = bnd.getString(AccountManager.KEY_AUTHTOKEN); @@ -94,22 +95,25 @@ public class CustomAccountManager { } if (callback != null) callback.run(null); - }, null); + }); + if (activity != null) { + mAccountManager.getAuthTokenByFeatures(accountType, authTokenType, null, mActivityInterface.get(), null, null, cb, null); + } else { + Account account = mAccountManager.getAccountsByType(accountType)[0]; + mAccountManager.getAuthToken(account, authTokenType, null, true, cb, null); + } } public String getTokenByTypeSync(String accountType, String authTokenType) { Account account = mAccountManager.getAccountsByType(accountType)[0]; - MainActivity activity = this.mActivityInterface.get(); - if (activity != null) { - try { - return mAccountManager.blockingGetAuthToken(account, authTokenType, true); - } catch (AuthenticatorException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (OperationCanceledException e) { - e.printStackTrace(); - } + try { + return mAccountManager.blockingGetAuthToken(account, authTokenType, true); + } catch (AuthenticatorException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (OperationCanceledException e) { + e.printStackTrace(); } return null; } @@ -118,10 +122,17 @@ public class CustomAccountManager { return mAccountManager.getAccountsByType(accountType).length != 0; } + public Account getAccountByType(String accountType) { + Account[] accountsByType = mAccountManager.getAccountsByType(accountType); + if (accountsByType.length > 0) + return accountsByType[0]; + return null; + } + @FunctionalInterface public interface ActivityInterface { @Nullable - MainActivity get(); + Activity get(); } public interface StringInterface { 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/MainActivityListener.java b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java index c37daa2..eb4b80e 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java @@ -2,10 +2,9 @@ package de.sebse.fuplanner.tools; import androidx.annotation.StringRes; -import de.sebse.fuplanner.services.Canteen.CanteenBrowser; -import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth; -import de.sebse.fuplanner.services.KVV.KVV; -import de.sebse.fuplanner.services.News.NewsManager; +import de.sebse.fuplanner.services.canteen.CanteenBrowser; +import de.sebse.fuplanner.services.kvv.KVV; +import de.sebse.fuplanner.services.news.NewsManager; public interface MainActivityListener { void onTitleTextChange(String newTitle); @@ -18,8 +17,6 @@ public interface MainActivityListener { KVV getKVV(); - GoogleAuth getGoogleAuth(); - CanteenBrowser getCanteenBrowser(); NewsManager getNewsManager(); 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/java/de/sebse/fuplanner/tools/types/News.java b/app/src/main/java/de/sebse/fuplanner/tools/types/News.java index eb1336d..11a59e7 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/types/News.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/types/News.java @@ -1,7 +1,5 @@ package de.sebse.fuplanner.tools.types; -import androidx.annotation.NonNull; - public class News { public static final int CATEGORY_TRICKS = 0; public static final int CATEGORY_UPDATE = 1; diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java index b086207..2b14360 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java @@ -5,7 +5,7 @@ import android.widget.ImageView; import android.widget.TextView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Resource; +import de.sebse.fuplanner.services.kvv.types.Resource; /** * Created by tlh on 2016/10/1 :) diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java index dbb592b..53653fb 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java @@ -4,7 +4,7 @@ import android.view.View; import android.widget.TextView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Resource; +import de.sebse.fuplanner.services.kvv.types.Resource; /** * Created by tlh on 2016/10/1 :) 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/layout/activity_fu_authenticator.xml b/app/src/main/res/layout/activity_fu_authenticator.xml index 6cae445..9c170d4 100644 --- a/app/src/main/res/layout/activity_fu_authenticator.xml +++ b/app/src/main/res/layout/activity_fu_authenticator.xml @@ -9,7 +9,7 @@ android:paddingTop="@dimen/activity_vertical_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingBottom="@dimen/activity_vertical_margin" - tools:context=".services.newkvv.FUAuthenticatorActivity"> + tools:context=".services.fulogin.FUAuthenticatorActivity"> + tools:context="de.sebse.fuplanner.services.fulogin.FUAuthenticatorActivity"> - - + tools:context="de.sebse.fuplanner.services.fulogin.FUAuthenticatorActivity"> Update-News Tipps/Tricks Klicke ZURÜCK erneut zum Beenden! + Sign in + + Benutzername + Passwort (optional) + Log in + Log in + Das Passwort ist zu kurz. + Das Passwort ist nicht korrekt. + Pflichtfeld + KVV-Synchronisation + Neue Daten verfügbar + Benachrichtigen, wenn neue Ankündigungen, Aufgaben, Noten oder Resourcen verfügbar sind + Ankündigung aktualisiert: %1$s + Aufgabe aktualisiert: %1$s + Event aktualisiert: %1$s + Noteneintrag aktualisiert: %1$s + Ressource aktualisiert: %1$s + Neue Ankündigung: %1$s + Neue Aufgabe: %1$ + Neues Event: %1$ + Neuer Noteneintrag: %1$ + Neue Ressource: %1$ + Ankündigung entfernt: %1$s + Aufgabe entfernt: %1$s + Event entfernt: %1$s + Noteneintrag entfernt: %1$s + Ressource entfernt: %1$s \ 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 f750d1e..40b35d6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -92,15 +92,29 @@ Please click BACK again to exit! Sign in - Email + Username Password (optional) Sign in or register Sign in - This email address is invalid This password is too short This password is incorrect This field is required - "Contacts permissions are needed for providing email - completions." - + KVV Synchronization + New data available + Notify when new announcements, assignments, grades or resources are available + Announcement updated: %1$s + New announcement: %1$s + Announcement removed: %1$s + Assignment updated: %1$s + New assignment: %1$s + Assignment removed: %1$s + Event updated: %1$s + New event: %1$s + Event removed: %1$s + Gradebook entry updated: %1$s + New gradebook entry: %1$s + Gradebook entry removed: %1$s + Resource updated: %1$s + New resource: %1$s + Resource removed: %1$s diff --git a/app/src/main/res/xml/syncadapter_kvv.xml b/app/src/main/res/xml/syncadapter_kvv.xml new file mode 100644 index 0000000..1dbe851 --- /dev/null +++ b/app/src/main/res/xml/syncadapter_kvv.xml @@ -0,0 +1,8 @@ + +