From e5ea6e0b4111b23b1e1a544f47259c4b17720577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Mon, 6 Nov 2017 17:25:38 +0100 Subject: [PATCH] Refactorization of the app (#31) * Refactor LoadingTask * Remove LoadingTask class * Fix context leak in LoginTask * Refactorisation GradesFragment * Refactorization synchronization * Fix leak in VulcanService * Update mockito * Add more tests for EntitiesCompare * Fix Instant Run * Add margin to grades * Update ci android image --- .circleci/config.yml | 2 +- .gitlab-ci.yml | 2 +- app/build.gradle | 4 +- ...Test.java => CurrentAccountLoginTest.java} | 12 +- ...onTest.java => FirstAccountLoginTest.java} | 12 +- .../GradeSynchronizationTest.java | 4 +- .../activity/dashboard/DashboardActivity.java | 49 +++--- .../attendance/AttendanceFragment.java | 3 +- .../dashboard/board/BoardFragment.java | 3 +- .../grades/GradesDialogFragment.java | 17 ++- .../dashboard/grades/GradesFragment.java | 144 +++++++++++------- .../lessonplan/LessonPlanFragment.java | 5 +- .../activity/login/LoginActivity.java | 8 +- .../wulkanowy/activity/login/LoginTask.java | 82 +++++----- .../activity/splash/LoadingTask.java | 53 ------- .../activity/splash/SplashActivity.java | 28 +++- .../github/wulkanowy/dao/EntitiesCompare.java | 2 +- .../io/github/wulkanowy/security/Safety.java | 5 +- .../github/wulkanowy/security/Scrambler.java | 2 +- .../services/VulcanSynchronization.java | 71 ++++++--- .../wulkanowy/services/jobs/GradeJob.java | 6 +- .../wulkanowy/services/jobs/SubjectJob.java | 6 +- .../services/jobs/VulcanService.java | 29 +++- ...rization.java => CurrentAccountLogin.java} | 4 +- ...gistration.java => FirstAccountLogin.java} | 10 +- .../utilities/ConnectionUtilities.java | 8 +- .../wulkanowy/utilities/RootUtilities.java | 4 - app/src/main/res/layout/fragment_grades.xml | 24 +-- app/src/main/res/layout/grade_item.xml | 5 +- app/src/main/res/values-pl/strings.xml | 2 +- app/src/main/res/values/strings.xml | 18 ++- .../wulkanowy/dao/EntitiesCompareTest.java | 34 ++++- 32 files changed, 374 insertions(+), 284 deletions(-) rename app/src/androidTest/java/io/github/wulkanowy/services/synchronization/{AccountAuthorizationTest.java => CurrentAccountLoginTest.java} (87%) rename app/src/androidTest/java/io/github/wulkanowy/services/synchronization/{AccountRegistrationTest.java => FirstAccountLoginTest.java} (88%) delete mode 100644 app/src/main/java/io/github/wulkanowy/activity/splash/LoadingTask.java rename app/src/main/java/io/github/wulkanowy/services/synchronisation/{AccountAuthorization.java => CurrentAccountLogin.java} (94%) rename app/src/main/java/io/github/wulkanowy/services/synchronisation/{AccountRegistration.java => FirstAccountLogin.java} (87%) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4e09c3922..dca6107f6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ references: container_config: &container_config docker: - - image: circleci/android:api-26-alpha + - image: circleci/android:api-27-alpha working_directory: *workspace_root environment: environment: diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 00c862b2c..d8fdd0587 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: circleci/android:api-25-alpha +image: circleci/android:api-27-alpha before_script: - export GRADLE_USER_HOME=`pwd`/.gradle diff --git a/app/build.gradle b/app/build.gradle index 4d8a0965c..780485519 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -62,10 +62,10 @@ dependencies { debugCompile 'com.amitshekhar.android:debug-db:1.0.1' debugCompile 'net.zetetic:android-database-sqlcipher:3.5.7@aar' - androidTestCompile 'org.mockito:mockito-android:2.10.0' + androidTestCompile 'org.mockito:mockito-android:2.11.0' testCompile 'junit:junit:4.12' - testCompile 'org.mockito:mockito-core:2.10.0' + testCompile 'org.mockito:mockito-core:2.11.0' androidTestCompile('com.android.support.test.espresso:espresso-core:3.0.1', { exclude group: 'com.android.support', module: 'support-annotations' diff --git a/app/src/androidTest/java/io/github/wulkanowy/services/synchronization/AccountAuthorizationTest.java b/app/src/androidTest/java/io/github/wulkanowy/services/synchronization/CurrentAccountLoginTest.java similarity index 87% rename from app/src/androidTest/java/io/github/wulkanowy/services/synchronization/AccountAuthorizationTest.java rename to app/src/androidTest/java/io/github/wulkanowy/services/synchronization/CurrentAccountLoginTest.java index 164868b63..a20db9599 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/services/synchronization/AccountAuthorizationTest.java +++ b/app/src/androidTest/java/io/github/wulkanowy/services/synchronization/CurrentAccountLoginTest.java @@ -27,10 +27,10 @@ import io.github.wulkanowy.dao.entities.DaoSession; import io.github.wulkanowy.security.CryptoException; import io.github.wulkanowy.security.Safety; import io.github.wulkanowy.services.LoginSession; -import io.github.wulkanowy.services.synchronisation.AccountAuthorization; +import io.github.wulkanowy.services.synchronisation.CurrentAccountLogin; @RunWith(AndroidJUnit4.class) -public class AccountAuthorizationTest { +public class CurrentAccountLoginTest { private static DaoSession daoSession; @@ -62,8 +62,8 @@ public class AccountAuthorizationTest { public void emptyUserIdTest() throws CryptoException, BadCredentialsException, AccountPermissionException, IOException, LoginErrorException { - AccountAuthorization accountAuthorization = new AccountAuthorization(context, daoSession, new Vulcan()); - accountAuthorization.loginCurrentUser(); + CurrentAccountLogin currentAccountLogin = new CurrentAccountLogin(context, daoSession, new Vulcan()); + currentAccountLogin.loginCurrentUser(); } @Test @@ -82,8 +82,8 @@ public class AccountAuthorizationTest { Vulcan vulcan = Mockito.mock(Vulcan.class); Mockito.doNothing().when(vulcan).login("TEST@TEST", "TEST", "TEST_SYMBOL", "TEST_ID"); - AccountAuthorization accountAuthorization = new AccountAuthorization(targetContext, daoSession, vulcan); - LoginSession loginSession = accountAuthorization.loginCurrentUser(); + CurrentAccountLogin currentAccountLogin = new CurrentAccountLogin(targetContext, daoSession, vulcan); + LoginSession loginSession = currentAccountLogin.loginCurrentUser(); Assert.assertNotNull(loginSession); Assert.assertEquals(loginSession.getUserId(), userId); diff --git a/app/src/androidTest/java/io/github/wulkanowy/services/synchronization/AccountRegistrationTest.java b/app/src/androidTest/java/io/github/wulkanowy/services/synchronization/FirstAccountLoginTest.java similarity index 88% rename from app/src/androidTest/java/io/github/wulkanowy/services/synchronization/AccountRegistrationTest.java rename to app/src/androidTest/java/io/github/wulkanowy/services/synchronization/FirstAccountLoginTest.java index 0a68e62fa..612555d35 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/services/synchronization/AccountRegistrationTest.java +++ b/app/src/androidTest/java/io/github/wulkanowy/services/synchronization/FirstAccountLoginTest.java @@ -22,9 +22,9 @@ import io.github.wulkanowy.dao.entities.DaoMaster; import io.github.wulkanowy.dao.entities.DaoSession; import io.github.wulkanowy.security.Safety; import io.github.wulkanowy.services.LoginSession; -import io.github.wulkanowy.services.synchronisation.AccountRegistration; +import io.github.wulkanowy.services.synchronisation.FirstAccountLogin; -public class AccountRegistrationTest { +public class FirstAccountLoginTest { private static DaoSession daoSession; @@ -55,9 +55,9 @@ public class AccountRegistrationTest { Login login = Mockito.mock(Login.class); Mockito.when(login.sendCredentials(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())) .thenReturn(certificate); - AccountRegistration accountRegistration = new AccountRegistration(login, new Vulcan(), "TEST@TEST", "TEST_PASS", "TEST_SYMBOL"); + FirstAccountLogin firstAccountLogin = new FirstAccountLogin(login, new Vulcan(), "TEST@TEST", "TEST_PASS", "TEST_SYMBOL"); - Assert.assertEquals(certificate, accountRegistration.connect()); + Assert.assertEquals(certificate, firstAccountLogin.connect()); } @Test @@ -79,8 +79,8 @@ public class AccountRegistrationTest { Login login = Mockito.mock(Login.class); Mockito.when(login.sendCertificate(Mockito.anyString(), Mockito.anyString())).thenReturn("TEST-SYMBOL"); - AccountRegistration accountRegistration = new AccountRegistration(login, vulcan, "TEST@TEST", "TEST-PASS", "default"); - LoginSession loginSession = accountRegistration.login(targetContext, daoSession, "cert"); + FirstAccountLogin firstAccountLogin = new FirstAccountLogin(login, vulcan, "TEST@TEST", "TEST-PASS", "default"); + LoginSession loginSession = firstAccountLogin.login(targetContext, daoSession, "cert"); Long userId = targetContext.getSharedPreferences("LoginData", Context.MODE_PRIVATE).getLong("userId", 0); diff --git a/app/src/androidTest/java/io/github/wulkanowy/services/synchronization/GradeSynchronizationTest.java b/app/src/androidTest/java/io/github/wulkanowy/services/synchronization/GradeSynchronizationTest.java index 8a7a0a49f..e23f56480 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/services/synchronization/GradeSynchronizationTest.java +++ b/app/src/androidTest/java/io/github/wulkanowy/services/synchronization/GradeSynchronizationTest.java @@ -47,7 +47,7 @@ public class GradeSynchronizationTest { } @Test - public void syncGradesEmptyBaseTest() throws Exception { + public void syncGradesEmptyDatabaseTest() throws Exception { Long userId = daoSession.getAccountDao().insert(new Account().setEmail("TEST@TEST")); Long subjectId = daoSession.getSubjectDao().insert(new Subject().setName("Matematyka").setUserId(userId)); @@ -75,7 +75,7 @@ public class GradeSynchronizationTest { Assert.assertEquals(subjectId, grade.getSubjectId()); Assert.assertEquals("Matematyka", grade.getSubject()); Assert.assertEquals("5", grade.getValue()); - Assert.assertTrue(grade.getIsNew()); + Assert.assertFalse(grade.getIsNew()); } @AfterClass diff --git a/app/src/main/java/io/github/wulkanowy/activity/dashboard/DashboardActivity.java b/app/src/main/java/io/github/wulkanowy/activity/dashboard/DashboardActivity.java index 926927c97..bdfd18d65 100644 --- a/app/src/main/java/io/github/wulkanowy/activity/dashboard/DashboardActivity.java +++ b/app/src/main/java/io/github/wulkanowy/activity/dashboard/DashboardActivity.java @@ -3,6 +3,7 @@ package io.github.wulkanowy.activity.dashboard; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.BottomNavigationView; +import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; import android.view.MenuItem; @@ -15,6 +16,8 @@ import io.github.wulkanowy.activity.dashboard.lessonplan.LessonPlanFragment; public class DashboardActivity extends AppCompatActivity { + private Fragment currentFragment; + private GradesFragment gradesFragment = new GradesFragment(); private AttendanceFragment attendanceFragment = new AttendanceFragment(); @@ -28,35 +31,32 @@ public class DashboardActivity extends AppCompatActivity { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { - - FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); - switch (item.getItemId()) { case R.id.navigation_marks: setTitle(R.string.grades_text); - transaction.replace(R.id.fragment_container, gradesFragment); - transaction.commit(); - return true; + currentFragment = gradesFragment; + break; case R.id.navigation_attendance: setTitle(R.string.attendance_text); - transaction.replace(R.id.fragment_container, attendanceFragment); - transaction.commit(); - return true; + currentFragment = attendanceFragment; + break; case R.id.navigation_lessonplan: setTitle(R.string.lessonplan_text); - transaction.replace(R.id.fragment_container, lessonPlanFragment); - transaction.commit(); - return true; + currentFragment = lessonPlanFragment; + break; case R.id.navigation_dashboard: default: setTitle(R.string.dashboard_text); - transaction.replace(R.id.fragment_container, boardFragment); - transaction.commit(); - return true; + currentFragment = boardFragment; + break; } + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + transaction.replace(R.id.fragment_container, currentFragment); + transaction.commit(); + return true; } }; @@ -65,14 +65,27 @@ public class DashboardActivity extends AppCompatActivity { super.onCreate(savedInstanceState); setContentView(R.layout.activity_dashboard); - setTitle(R.string.dashboard_text); - BottomNavigationView navigation = findViewById(R.id.navigation); navigation.setSelectedItemId(R.id.navigation_dashboard); navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); + if (savedInstanceState != null) { + currentFragment = getSupportFragmentManager().getFragment(savedInstanceState, "currentFragment"); + setTitle(savedInstanceState.getString("activityTitle")); + } else { + currentFragment = boardFragment; + setTitle(R.string.dashboard_text); + } + getSupportFragmentManager().beginTransaction() - .replace(R.id.fragment_container, boardFragment).commit(); + .replace(R.id.fragment_container, currentFragment).commit(); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString("activityTitle", getTitle().toString()); + getSupportFragmentManager().putFragment(outState, "currentFragment", currentFragment); } public void onBackPressed() { diff --git a/app/src/main/java/io/github/wulkanowy/activity/dashboard/attendance/AttendanceFragment.java b/app/src/main/java/io/github/wulkanowy/activity/dashboard/attendance/AttendanceFragment.java index a40a1d223..f410e75cf 100644 --- a/app/src/main/java/io/github/wulkanowy/activity/dashboard/attendance/AttendanceFragment.java +++ b/app/src/main/java/io/github/wulkanowy/activity/dashboard/attendance/AttendanceFragment.java @@ -1,6 +1,7 @@ package io.github.wulkanowy.activity.dashboard.attendance; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; @@ -11,7 +12,7 @@ import io.github.wulkanowy.R; public class AttendanceFragment extends Fragment { @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_attendance, container, false); } diff --git a/app/src/main/java/io/github/wulkanowy/activity/dashboard/board/BoardFragment.java b/app/src/main/java/io/github/wulkanowy/activity/dashboard/board/BoardFragment.java index 2c76dc590..bc808145f 100644 --- a/app/src/main/java/io/github/wulkanowy/activity/dashboard/board/BoardFragment.java +++ b/app/src/main/java/io/github/wulkanowy/activity/dashboard/board/BoardFragment.java @@ -1,6 +1,7 @@ package io.github.wulkanowy.activity.dashboard.board; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; @@ -11,7 +12,7 @@ import io.github.wulkanowy.R; public class BoardFragment extends Fragment { @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_board, container, false); } diff --git a/app/src/main/java/io/github/wulkanowy/activity/dashboard/grades/GradesDialogFragment.java b/app/src/main/java/io/github/wulkanowy/activity/dashboard/grades/GradesDialogFragment.java index 5138e76a5..e7ba236b0 100644 --- a/app/src/main/java/io/github/wulkanowy/activity/dashboard/grades/GradesDialogFragment.java +++ b/app/src/main/java/io/github/wulkanowy/activity/dashboard/grades/GradesDialogFragment.java @@ -1,6 +1,7 @@ package io.github.wulkanowy.activity.dashboard.grades; +import android.app.Dialog; import android.app.DialogFragment; import android.os.Bundle; import android.view.LayoutInflater; @@ -20,6 +21,10 @@ public class GradesDialogFragment extends DialogFragment { return new GradesDialogFragment().setGrade(grade); } + public GradesDialogFragment() { + setRetainInstance(true); + } + public GradesDialogFragment setGrade(Grade grade) { this.grade = grade; return this; @@ -50,7 +55,7 @@ public class GradesDialogFragment extends DialogFragment { descriptionText.setText(grade.getSymbol()); } } else if (!"".equals(grade.getSymbol())) { - descriptionText.setText(grade.getSymbol() + " - " + grade.getDescription()); + descriptionText.setText(String.format("%1$s - %2$s", grade.getSymbol(), grade.getDescription())); } else { descriptionText.setText(grade.getDescription()); } @@ -69,6 +74,16 @@ public class GradesDialogFragment extends DialogFragment { return view; } + @Override + public void onDestroyView() { + Dialog dialog = getDialog(); + if (dialog != null && getRetainInstance()) { + dialog.setDismissMessage(null); + } + super.onDestroyView(); + } + + public static int colorHexToColorName(String hexColor) { switch (hexColor) { case "000000": { diff --git a/app/src/main/java/io/github/wulkanowy/activity/dashboard/grades/GradesFragment.java b/app/src/main/java/io/github/wulkanowy/activity/dashboard/grades/GradesFragment.java index c6037d92a..083e6c78b 100644 --- a/app/src/main/java/io/github/wulkanowy/activity/dashboard/grades/GradesFragment.java +++ b/app/src/main/java/io/github/wulkanowy/activity/dashboard/grades/GradesFragment.java @@ -1,8 +1,10 @@ package io.github.wulkanowy.activity.dashboard.grades; +import android.app.Activity; import android.content.Context; import android.os.AsyncTask; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.widget.SwipeRefreshLayout; @@ -14,6 +16,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Toast; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -33,20 +36,39 @@ import io.github.wulkanowy.utilities.ConnectionUtilities; public class GradesFragment extends Fragment { - private List subjectWithGradesList = new ArrayList<>(); + private static List subjectWithGradesList = new ArrayList<>(); - private SwipeRefreshLayout swipeRefreshLayout; - - private View view; - - private RefreshTask refreshTask; + private static long userId; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - view = inflater.inflate(R.layout.fragment_grades, container, false); + DaoSession daoSession; + + View view = inflater.inflate(R.layout.fragment_grades, container, false); + + if (getActivity() != null) { + daoSession = ((WulkanowyApp) getActivity().getApplication()).getDaoSession(); + userId = getActivity().getSharedPreferences("LoginData", Context.MODE_PRIVATE) + .getLong("userId", 0); + + prepareRefreshLayout(view, daoSession); + + if (subjectWithGradesList.equals(new ArrayList<>())) { + createExpList(view, getActivity()); + new GenerateListTask(getActivity(), view, daoSession).execute(); + } else { + createExpList(view, getActivity()); + view.findViewById(R.id.loadingPanel).setVisibility(View.INVISIBLE); + } + } + return view; + } + + private void prepareRefreshLayout(final View mainView, final DaoSession daoSession) { + + final SwipeRefreshLayout swipeRefreshLayout = mainView.findViewById(R.id.grade_swipe_refresh); - swipeRefreshLayout = view.findViewById(R.id.grade_swipe_refresh); swipeRefreshLayout.setColorSchemeResources(android.R.color.black, android.R.color.holo_blue_bright, android.R.color.holo_green_light, @@ -56,47 +78,27 @@ public class GradesFragment extends Fragment { swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { - if (!ConnectionUtilities.isOnline(view.getContext())) { - swipeRefreshLayout.setRefreshing(false); - Toast.makeText(view.getContext(), R.string.noInternet_text, Toast.LENGTH_SHORT).show(); + if (ConnectionUtilities.isOnline(getContext())) { + new RefreshTask(getActivity(), mainView, daoSession).execute(); } else { - refreshTask = new RefreshTask(); - refreshTask.execute(((WulkanowyApp) getActivity().getApplication()).getDaoSession()); + Toast.makeText(mainView.getContext(), R.string.noInternet_text, Toast.LENGTH_SHORT).show(); + swipeRefreshLayout.setRefreshing(false); } } }); - - if (new ArrayList<>().equals(subjectWithGradesList)) { - createExpListView(); - new GradesTask().execute(((WulkanowyApp) getActivity().getApplication()).getDaoSession()); - } else if (subjectWithGradesList.size() > 0) { - createExpListView(); - view.findViewById(R.id.loadingPanel).setVisibility(View.GONE); - } - return view; } - @Override - public void onDestroyView() { - super.onDestroyView(); - if (refreshTask != null && refreshTask.getStatus() == AsyncTask.Status.RUNNING) { - refreshTask.cancel(true); - } - } + private static void createExpList(View mainView, Activity activity) { - private void createExpListView() { - - RecyclerView recyclerView = view.findViewById(R.id.subject_grade_recycler); - recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); - GradesAdapter gradesAdapter = new GradesAdapter(subjectWithGradesList, getActivity()); + RecyclerView recyclerView = mainView.findViewById(R.id.subject_grade_recycler); + recyclerView.setLayoutManager(new LinearLayoutManager(activity)); + GradesAdapter gradesAdapter = new GradesAdapter(subjectWithGradesList, activity); recyclerView.setAdapter(gradesAdapter); } - private void prepareSubjectsWithGradesList(DaoSession daoSession) { - subjectWithGradesList = new ArrayList<>(); + private static void downloadGradesFormDatabase(DaoSession daoSession) { - long userId = getContext().getSharedPreferences("LoginData", Context.MODE_PRIVATE) - .getLong("userId", 0); + subjectWithGradesList = new ArrayList<>(); AccountDao accountDao = daoSession.getAccountDao(); Account account = accountDao.load(userId); @@ -110,31 +112,54 @@ public class GradesFragment extends Fragment { } } - private class GradesTask extends AsyncTask { + private static class GenerateListTask extends AsyncTask { + + private WeakReference mainView; + + private WeakReference activity; + + private DaoSession daoSession; + + public GenerateListTask(Activity activity, View mainView, DaoSession daoSession) { + this.activity = new WeakReference<>(activity); + this.mainView = new WeakReference<>(mainView); + this.daoSession = daoSession; + } @Override - protected Void doInBackground(DaoSession... params) { - prepareSubjectsWithGradesList(params[0]); + protected Void doInBackground(Void... params) { + downloadGradesFormDatabase(daoSession); return null; } protected void onPostExecute(Void result) { super.onPostExecute(result); - - createExpListView(); - view.findViewById(R.id.loadingPanel).setVisibility(View.GONE); + createExpList(mainView.get(), activity.get()); + mainView.get().findViewById(R.id.loadingPanel).setVisibility(View.INVISIBLE); } } - private class RefreshTask extends AsyncTask { + private static class RefreshTask extends AsyncTask { + + private DaoSession daoSession; + + private WeakReference activity; + + private WeakReference mainView; + + public RefreshTask(Activity activity, View mainView, DaoSession daoSession) { + this.activity = new WeakReference<>(activity); + this.daoSession = daoSession; + this.mainView = new WeakReference<>(mainView); + } @Override - protected Boolean doInBackground(DaoSession... params) { + protected Boolean doInBackground(Void... params) { VulcanSynchronization vulcanSynchronization = new VulcanSynchronization(new LoginSession()); try { - vulcanSynchronization.loginCurrentUser(getContext(), params[0], new Vulcan()); + vulcanSynchronization.loginCurrentUser(activity.get(), daoSession, new Vulcan()); vulcanSynchronization.syncGrades(); - prepareSubjectsWithGradesList(params[0]); + downloadGradesFormDatabase(daoSession); return true; } catch (Exception e) { Log.e(VulcanJobHelper.DEBUG_TAG, "There was a synchronization problem", e); @@ -147,24 +172,27 @@ public class GradesFragment extends Fragment { super.onPostExecute(result); if (result) { - prepareSubjectsWithGradesList(((WulkanowyApp) getActivity().getApplication()).getDaoSession()); - createExpListView(); - swipeRefreshLayout.setRefreshing(false); + if (mainView.get() != null && activity.get() != null) { + createExpList(mainView.get(), activity.get()); + } - - int volumeGrades = DatabaseAccess.getNewGrades(((WulkanowyApp) getActivity().getApplication()).getDaoSession()).size(); + int volumeGrades = DatabaseAccess.getNewGrades(daoSession).size(); if (volumeGrades == 0) { - Snackbar.make(getActivity().findViewById(R.id.fragment_container), + Snackbar.make(activity.get().findViewById(R.id.fragment_container), R.string.snackbar_no_grades, Snackbar.LENGTH_SHORT).show(); } else { - Snackbar.make(getActivity().findViewById(R.id.fragment_container), - getString(R.string.snackbar_new_grade, volumeGrades), + Snackbar.make(activity.get().findViewById(R.id.fragment_container), + activity.get().getString(R.string.snackbar_new_grade, volumeGrades), Snackbar.LENGTH_SHORT).show(); } } else { - Toast.makeText(getContext(), R.string.refresh_error_text, Toast.LENGTH_SHORT).show(); + Toast.makeText(activity.get(), R.string.refresh_error_text, Toast.LENGTH_SHORT).show(); + } + + if (mainView.get() != null) { + SwipeRefreshLayout swipeRefreshLayout = mainView.get().findViewById(R.id.grade_swipe_refresh); swipeRefreshLayout.setRefreshing(false); } } diff --git a/app/src/main/java/io/github/wulkanowy/activity/dashboard/lessonplan/LessonPlanFragment.java b/app/src/main/java/io/github/wulkanowy/activity/dashboard/lessonplan/LessonPlanFragment.java index 71f2532ed..c3b126fa2 100644 --- a/app/src/main/java/io/github/wulkanowy/activity/dashboard/lessonplan/LessonPlanFragment.java +++ b/app/src/main/java/io/github/wulkanowy/activity/dashboard/lessonplan/LessonPlanFragment.java @@ -1,6 +1,7 @@ package io.github.wulkanowy.activity.dashboard.lessonplan; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; @@ -14,8 +15,8 @@ public class LessonPlanFragment extends Fragment { } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_lessonplan, container, false); } } diff --git a/app/src/main/java/io/github/wulkanowy/activity/login/LoginActivity.java b/app/src/main/java/io/github/wulkanowy/activity/login/LoginActivity.java index b690f8c9a..142415899 100644 --- a/app/src/main/java/io/github/wulkanowy/activity/login/LoginActivity.java +++ b/app/src/main/java/io/github/wulkanowy/activity/login/LoginActivity.java @@ -144,8 +144,8 @@ public class LoginActivity extends Activity { symbol = "Default"; } - String[] keys = this.getResources().getStringArray(R.array.symbols); - String[] values = this.getResources().getStringArray(R.array.symbols_values); + String[] keys = getResources().getStringArray(R.array.symbols); + String[] values = getResources().getStringArray(R.array.symbols_values); LinkedHashMap map = new LinkedHashMap<>(); for (int i = 0; i < Math.min(keys.length, values.length); ++i) { @@ -198,9 +198,9 @@ public class LoginActivity extends Activity { float y = ev.getRawY() + view.getTop() - scrcoords[1]; if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom()) { - ((InputMethodManager) this.getSystemService( + ((InputMethodManager) getSystemService( Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow( - (this.getWindow().getDecorView().getApplicationWindowToken()), 0); + (getWindow().getDecorView().getApplicationWindowToken()), 0); } } } diff --git a/app/src/main/java/io/github/wulkanowy/activity/login/LoginTask.java b/app/src/main/java/io/github/wulkanowy/activity/login/LoginTask.java index 57eeda425..d8b5cbb4e 100644 --- a/app/src/main/java/io/github/wulkanowy/activity/login/LoginTask.java +++ b/app/src/main/java/io/github/wulkanowy/activity/login/LoginTask.java @@ -12,21 +12,19 @@ import android.widget.EditText; import android.widget.TextView; import java.io.IOException; +import java.lang.ref.WeakReference; import io.github.wulkanowy.R; import io.github.wulkanowy.activity.WulkanowyApp; import io.github.wulkanowy.activity.dashboard.DashboardActivity; -import io.github.wulkanowy.api.Cookies; -import io.github.wulkanowy.api.Vulcan; import io.github.wulkanowy.api.login.AccountPermissionException; import io.github.wulkanowy.api.login.BadCredentialsException; -import io.github.wulkanowy.api.login.Login; import io.github.wulkanowy.api.login.NotLoggedInErrorException; import io.github.wulkanowy.dao.entities.DaoSession; import io.github.wulkanowy.security.CryptoException; import io.github.wulkanowy.services.LoginSession; import io.github.wulkanowy.services.VulcanSynchronization; -import io.github.wulkanowy.services.synchronisation.AccountRegistration; +import io.github.wulkanowy.services.jobs.GradeJob; import io.github.wulkanowy.utilities.ConnectionUtilities; /** @@ -41,16 +39,16 @@ public class LoginTask extends AsyncTask { private final String symbol; - private Activity activity; + private WeakReference activity; - private View progressView; + private WeakReference progressView; - private View loginFormView; + private WeakReference loginFormView; - private TextView showText; + private WeakReference showText; public LoginTask(Activity activity, String email, String password, String symbol) { - this.activity = activity; + this.activity = new WeakReference<>(activity); this.email = email; this.password = password; this.symbol = symbol; @@ -58,28 +56,24 @@ public class LoginTask extends AsyncTask { @Override protected void onPreExecute() { - showText = activity.findViewById(R.id.login_progress_text); + showText = new WeakReference<>((TextView) activity.get().findViewById(R.id.login_progress_text)); } @Override protected Integer doInBackground(Void... params) { - if (ConnectionUtilities.isOnline(activity)) { - AccountRegistration accountRegistration = new AccountRegistration( - new Login(new Cookies()), - new Vulcan(), - email, password, symbol); + if (ConnectionUtilities.isOnline(activity.get())) { + VulcanSynchronization vulcanSynchronization = new VulcanSynchronization(new LoginSession()); - DaoSession daoSession = ((WulkanowyApp) activity.getApplication()).getDaoSession(); + DaoSession daoSession = ((WulkanowyApp) activity.get().getApplication()).getDaoSession(); try { - publishProgress("1", activity.getResources().getString(R.string.step_connecting)); - String certificate = accountRegistration.connect(); + publishProgress("1", activity.get().getResources().getString(R.string.step_connecting)); + vulcanSynchronization.firstLoginConnectStep(email, password, symbol); - publishProgress("2", activity.getResources().getString(R.string.step_login)); - LoginSession loginSession = accountRegistration.login(activity, daoSession, certificate); + publishProgress("2", activity.get().getResources().getString(R.string.step_login)); + vulcanSynchronization.firstLoginSignInStep(activity.get(), daoSession); - publishProgress("3", activity.getResources().getString(R.string.step_synchronization)); - VulcanSynchronization vulcanSynchronization = new VulcanSynchronization(loginSession); + publishProgress("3", activity.get().getResources().getString(R.string.step_synchronization)); vulcanSynchronization.syncSubjectsAndGrades(); } catch (BadCredentialsException e) { @@ -92,7 +86,8 @@ public class LoginTask extends AsyncTask { return R.string.login_denied_text; } - accountRegistration.scheduleSynchronization(activity); + GradeJob gradeJob = new GradeJob(); + gradeJob.scheduledJob(activity.get()); return R.string.login_accepted_text; @@ -103,7 +98,7 @@ public class LoginTask extends AsyncTask { @Override protected void onProgressUpdate(String... progress) { - showText.setText(progress[0] + "/3 - " + progress[1] + "..."); + showText.get().setText(String.format("%1$s/3 - %2$s...", progress[0], progress[1])); } @Override @@ -113,33 +108,32 @@ public class LoginTask extends AsyncTask { switch (messageID) { // if success case R.string.login_accepted_text: - Intent intent = new Intent(activity, DashboardActivity.class); - activity.finish(); - activity.startActivity(intent); + Intent intent = new Intent(activity.get(), DashboardActivity.class); + activity.get().finish(); + activity.get().startActivity(intent); break; // if bad credentials entered case R.string.login_bad_credentials_text: - EditText passwordView = activity.findViewById(R.id.password); - passwordView.setError(activity.getString(R.string.error_incorrect_password)); + EditText passwordView = activity.get().findViewById(R.id.password); + passwordView.setError(activity.get().getString(R.string.error_incorrect_password)); passwordView.requestFocus(); break; // if no permission case R.string.error_bad_account_permission: // Change to visible symbol input view - TextInputLayout symbolLayout = activity.findViewById(R.id.to_symbol_input_layout); + TextInputLayout symbolLayout = activity.get().findViewById(R.id.to_symbol_input_layout); symbolLayout.setVisibility(View.VISIBLE); - EditText symbolView = activity.findViewById(R.id.symbol); - symbolView.setError(activity.getString(R.string.error_bad_account_permission)); + EditText symbolView = activity.get().findViewById(R.id.symbol); + symbolView.setError(activity.get().getString(R.string.error_bad_account_permission)); symbolView.requestFocus(); break; default: - Snackbar - .make(activity.findViewById(R.id.coordinatorLayout), messageID, Snackbar.LENGTH_LONG) - .show(); + Snackbar.make(activity.get().findViewById(R.id.coordinatorLayout), + messageID, Snackbar.LENGTH_LONG).show(); break; } } @@ -153,33 +147,33 @@ public class LoginTask extends AsyncTask { * Shows the progress UI and hides the login form. */ public void showProgress(final boolean show) { - loginFormView = activity.findViewById(R.id.login_form); - progressView = activity.findViewById(R.id.login_progress); + loginFormView = new WeakReference<>(activity.get().findViewById(R.id.login_form)); + progressView = new WeakReference<>(activity.get().findViewById(R.id.login_progress)); - int animTime = activity.getResources().getInteger(android.R.integer.config_shortAnimTime); + int animTime = activity.get().getResources().getInteger(android.R.integer.config_shortAnimTime); changeLoginFormVisibility(show, animTime); changeProgressVisibility(show, animTime); } private void changeLoginFormVisibility(final boolean show, final int animTime) { - loginFormView.setVisibility(show ? View.GONE : View.VISIBLE); - loginFormView.animate().setDuration(animTime).alpha( + loginFormView.get().setVisibility(show ? View.GONE : View.VISIBLE); + loginFormView.get().animate().setDuration(animTime).alpha( show ? 0 : 1).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - loginFormView.setVisibility(show ? View.GONE : View.VISIBLE); + loginFormView.get().setVisibility(show ? View.GONE : View.VISIBLE); } }); } private void changeProgressVisibility(final boolean show, final int animTime) { - progressView.setVisibility(show ? View.VISIBLE : View.GONE); - progressView.animate().setDuration(animTime).alpha( + progressView.get().setVisibility(show ? View.VISIBLE : View.GONE); + progressView.get().animate().setDuration(animTime).alpha( show ? 1 : 0).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - progressView.setVisibility(show ? View.VISIBLE : View.GONE); + progressView.get().setVisibility(show ? View.VISIBLE : View.GONE); } }); } diff --git a/app/src/main/java/io/github/wulkanowy/activity/splash/LoadingTask.java b/app/src/main/java/io/github/wulkanowy/activity/splash/LoadingTask.java deleted file mode 100644 index cc89082b3..000000000 --- a/app/src/main/java/io/github/wulkanowy/activity/splash/LoadingTask.java +++ /dev/null @@ -1,53 +0,0 @@ -package io.github.wulkanowy.activity.splash; - -import android.content.Context; -import android.content.Intent; -import android.os.AsyncTask; -import android.widget.Toast; - -import io.github.wulkanowy.R; -import io.github.wulkanowy.activity.dashboard.DashboardActivity; -import io.github.wulkanowy.activity.login.LoginActivity; -import io.github.wulkanowy.services.jobs.GradeJob; -import io.github.wulkanowy.utilities.ConnectionUtilities; - -public class LoadingTask extends AsyncTask { - - private Context context; - - LoadingTask(Context context) { - this.context = context; - } - - @Override - protected Boolean doInBackground(Void... voids) { - - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - return ConnectionUtilities.isOnline(context); - } - - protected void onPostExecute(Boolean result) { - super.onPostExecute(result); - - if (!result) { - Toast.makeText(context, R.string.noInternet_text, Toast.LENGTH_LONG).show(); - } - - if (context.getSharedPreferences("LoginData", Context.MODE_PRIVATE).getLong("userId", 0) == 0) { - Intent intent = new Intent(context, LoginActivity.class); - context.startActivity(intent); - } else { - GradeJob gradesSync = new GradeJob(); - gradesSync.scheduledJob(context); - - Intent intent = new Intent(context, DashboardActivity.class); - context.startActivity(intent); - } - - } -} diff --git a/app/src/main/java/io/github/wulkanowy/activity/splash/SplashActivity.java b/app/src/main/java/io/github/wulkanowy/activity/splash/SplashActivity.java index 9b6a1a337..12dbd60ae 100644 --- a/app/src/main/java/io/github/wulkanowy/activity/splash/SplashActivity.java +++ b/app/src/main/java/io/github/wulkanowy/activity/splash/SplashActivity.java @@ -1,11 +1,17 @@ package io.github.wulkanowy.activity.splash; +import android.content.Context; +import android.content.Intent; import android.os.Bundle; +import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.widget.TextView; import io.github.wulkanowy.BuildConfig; import io.github.wulkanowy.R; +import io.github.wulkanowy.activity.dashboard.DashboardActivity; +import io.github.wulkanowy.activity.login.LoginActivity; +import io.github.wulkanowy.services.jobs.GradeJob; public class SplashActivity extends AppCompatActivity { @@ -15,8 +21,26 @@ public class SplashActivity extends AppCompatActivity { setContentView(R.layout.activity_splash); TextView versionName = findViewById(R.id.rawText); - versionName.setText(getText(R.string.version_text) + BuildConfig.VERSION_NAME); + versionName.setText(getString(R.string.version_text, BuildConfig.VERSION_NAME)); - new LoadingTask(this).execute(); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + executeOnRunApp(); + } + }, 500); + } + + private void executeOnRunApp() { + if (getSharedPreferences("LoginData", Context.MODE_PRIVATE).getLong("userId", 0) == 0) { + Intent intent = new Intent(this, LoginActivity.class); + startActivity(intent); + } else { + GradeJob gradesSync = new GradeJob(); + gradesSync.scheduledJob(this); + + Intent intent = new Intent(this, DashboardActivity.class); + startActivity(intent); + } } } diff --git a/app/src/main/java/io/github/wulkanowy/dao/EntitiesCompare.java b/app/src/main/java/io/github/wulkanowy/dao/EntitiesCompare.java index 48b180ad9..50b88eb64 100644 --- a/app/src/main/java/io/github/wulkanowy/dao/EntitiesCompare.java +++ b/app/src/main/java/io/github/wulkanowy/dao/EntitiesCompare.java @@ -18,9 +18,9 @@ public abstract class EntitiesCompare { List lastList = new ArrayList<>(); for (Grade grade : addedOrUpdatedGradeList) { - grade.setIsNew(true); if (oldList.size() != 0) { grade.setRead(false); + grade.setIsNew(true); } updatedList.add(grade); } diff --git a/app/src/main/java/io/github/wulkanowy/security/Safety.java b/app/src/main/java/io/github/wulkanowy/security/Safety.java index 4bc329ba1..65f993986 100644 --- a/app/src/main/java/io/github/wulkanowy/security/Safety.java +++ b/app/src/main/java/io/github/wulkanowy/security/Safety.java @@ -12,13 +12,11 @@ public class Safety extends Scrambler { public String encrypt(String email, String plainText, Context context) throws CryptoException, UnsupportedOperationException { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - loadKeyStore(); generateNewKey(email, context); return encryptString(email, plainText); } else { - - if (RootUtilities.isRooted()) { + if (!RootUtilities.isRooted()) { return new String(Base64.encode(plainText.getBytes(), Base64.DEFAULT)); } else { Log.e(Scrambler.DEBUG_TAG, "Password store in this devices isn't safe because is rooted"); @@ -30,7 +28,6 @@ public class Safety extends Scrambler { public String decrypt(String email, String encryptedText) throws CryptoException { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - loadKeyStore(); return decryptString(email, encryptedText); } else { diff --git a/app/src/main/java/io/github/wulkanowy/security/Scrambler.java b/app/src/main/java/io/github/wulkanowy/security/Scrambler.java index bf4b0257c..08fae7dd6 100644 --- a/app/src/main/java/io/github/wulkanowy/security/Scrambler.java +++ b/app/src/main/java/io/github/wulkanowy/security/Scrambler.java @@ -36,7 +36,7 @@ public class Scrambler { private KeyStore keyStore; - public void loadKeyStore() throws CryptoException { + protected void loadKeyStore() throws CryptoException { try { keyStore = KeyStore.getInstance(ANDROID_KEYSTORE); diff --git a/app/src/main/java/io/github/wulkanowy/services/VulcanSynchronization.java b/app/src/main/java/io/github/wulkanowy/services/VulcanSynchronization.java index 5ce801327..27f25ed0b 100644 --- a/app/src/main/java/io/github/wulkanowy/services/VulcanSynchronization.java +++ b/app/src/main/java/io/github/wulkanowy/services/VulcanSynchronization.java @@ -5,14 +5,18 @@ import android.util.Log; import java.io.IOException; +import io.github.wulkanowy.api.Cookies; import io.github.wulkanowy.api.Vulcan; import io.github.wulkanowy.api.login.AccountPermissionException; import io.github.wulkanowy.api.login.BadCredentialsException; +import io.github.wulkanowy.api.login.Login; import io.github.wulkanowy.api.login.LoginErrorException; +import io.github.wulkanowy.api.login.NotLoggedInErrorException; import io.github.wulkanowy.dao.entities.DaoSession; import io.github.wulkanowy.security.CryptoException; import io.github.wulkanowy.services.jobs.VulcanJobHelper; -import io.github.wulkanowy.services.synchronisation.AccountAuthorization; +import io.github.wulkanowy.services.synchronisation.CurrentAccountLogin; +import io.github.wulkanowy.services.synchronisation.FirstAccountLogin; import io.github.wulkanowy.services.synchronisation.GradesSynchronisation; import io.github.wulkanowy.services.synchronisation.SubjectsSynchronisation; @@ -20,38 +24,67 @@ public class VulcanSynchronization { private LoginSession loginSession; + private FirstAccountLogin firstAccountLogin; + + private String certificate; + public VulcanSynchronization(LoginSession loginSession) { this.loginSession = loginSession; } + public void firstLoginConnectStep(String email, String password, String symbol) + throws BadCredentialsException, IOException { + firstAccountLogin = new FirstAccountLogin(new Login(new Cookies()), new Vulcan(), email, password, symbol); + certificate = firstAccountLogin.connect(); + } + + public void firstLoginSignInStep(Context context, DaoSession daoSession) + throws NotLoggedInErrorException, AccountPermissionException, IOException, CryptoException { + if (firstAccountLogin != null && certificate != null) { + loginSession = firstAccountLogin.login(context, daoSession, certificate); + } else { + Log.e(VulcanJobHelper.DEBUG_TAG, "Before first login, should call firstLoginConnectStep", + new UnsupportedOperationException()); + } + } + public void loginCurrentUser(Context context, DaoSession daoSession, Vulcan vulcan) throws CryptoException, BadCredentialsException, AccountPermissionException, LoginErrorException, IOException { - - AccountAuthorization accountAuthorization = new AccountAuthorization(context, daoSession, vulcan); - loginSession = accountAuthorization.loginCurrentUser(); + CurrentAccountLogin currentAccountLogin = new CurrentAccountLogin(context, daoSession, vulcan); + loginSession = currentAccountLogin.loginCurrentUser(); } public boolean syncGrades() { - GradesSynchronisation gradesSynchronisation = new GradesSynchronisation(); - - try { - gradesSynchronisation.sync(loginSession); - return true; - } catch (Exception e) { - Log.e(VulcanJobHelper.DEBUG_TAG, "Synchronisation of grades failed", e); + if (loginSession != null) { + GradesSynchronisation gradesSynchronisation = new GradesSynchronisation(); + try { + gradesSynchronisation.sync(loginSession); + return true; + } catch (Exception e) { + Log.e(VulcanJobHelper.DEBUG_TAG, "Synchronisation of grades failed", e); + return false; + } + } else { + Log.e(VulcanJobHelper.DEBUG_TAG, "Before synchronization, should login user to log", + new UnsupportedOperationException()); return false; } } public boolean syncSubjectsAndGrades() { - SubjectsSynchronisation subjectsSynchronisation = new SubjectsSynchronisation(); - - try { - subjectsSynchronisation.sync(loginSession); - syncGrades(); - return true; - } catch (Exception e) { - Log.e(VulcanJobHelper.DEBUG_TAG, "Synchronisation of subjects failed", e); + if (loginSession != null) { + SubjectsSynchronisation subjectsSynchronisation = new SubjectsSynchronisation(); + try { + subjectsSynchronisation.sync(loginSession); + syncGrades(); + return true; + } catch (Exception e) { + Log.e(VulcanJobHelper.DEBUG_TAG, "Synchronisation of subjects failed", e); + return false; + } + } else { + Log.e(VulcanJobHelper.DEBUG_TAG, "Before synchronization, should login user to log", + new UnsupportedOperationException()); return false; } } diff --git a/app/src/main/java/io/github/wulkanowy/services/jobs/GradeJob.java b/app/src/main/java/io/github/wulkanowy/services/jobs/GradeJob.java index ed1d90cf7..ddb850cf9 100644 --- a/app/src/main/java/io/github/wulkanowy/services/jobs/GradeJob.java +++ b/app/src/main/java/io/github/wulkanowy/services/jobs/GradeJob.java @@ -21,11 +21,11 @@ import io.github.wulkanowy.services.VulcanSynchronization; public class GradeJob extends VulcanJobHelper { - public static final String UNIQUE_TAG = "GradesSync34512"; + private static final String UNIQUE_TAG = "GradesSync34512"; - public static final int DEFAULT_INTERVAL_START = 60 * 50; + private static final int DEFAULT_INTERVAL_START = 60 * 50; - public static final int DEFAULT_INTERVAL_END = DEFAULT_INTERVAL_START + (60 * 10); + private static final int DEFAULT_INTERVAL_END = DEFAULT_INTERVAL_START + (60 * 10); @Override protected Job createJob(FirebaseJobDispatcher dispatcher) { diff --git a/app/src/main/java/io/github/wulkanowy/services/jobs/SubjectJob.java b/app/src/main/java/io/github/wulkanowy/services/jobs/SubjectJob.java index 810f0d2ec..505151361 100644 --- a/app/src/main/java/io/github/wulkanowy/services/jobs/SubjectJob.java +++ b/app/src/main/java/io/github/wulkanowy/services/jobs/SubjectJob.java @@ -21,11 +21,11 @@ import io.github.wulkanowy.services.VulcanSynchronization; public class SubjectJob extends VulcanJobHelper { - public static final String UNIQUE_TAG = "SubjectsSync34512"; + private static final String UNIQUE_TAG = "SubjectsSync34512"; - public static final int DEFAULT_INTERVAL_START = 0; + private static final int DEFAULT_INTERVAL_START = 0; - public static final int DEFAULT_INTERVAL_END = DEFAULT_INTERVAL_START + 10; + private static final int DEFAULT_INTERVAL_END = DEFAULT_INTERVAL_START + 10; @Override protected Job createJob(FirebaseJobDispatcher dispatcher) { diff --git a/app/src/main/java/io/github/wulkanowy/services/jobs/VulcanService.java b/app/src/main/java/io/github/wulkanowy/services/jobs/VulcanService.java index e85a2217d..ace37d6b7 100644 --- a/app/src/main/java/io/github/wulkanowy/services/jobs/VulcanService.java +++ b/app/src/main/java/io/github/wulkanowy/services/jobs/VulcanService.java @@ -7,6 +7,7 @@ import com.firebase.jobdispatcher.JobParameters; import com.firebase.jobdispatcher.JobService; import java.io.IOException; +import java.lang.ref.WeakReference; import io.github.wulkanowy.api.login.AccountPermissionException; import io.github.wulkanowy.api.login.BadCredentialsException; @@ -15,35 +16,47 @@ import io.github.wulkanowy.security.CryptoException; public abstract class VulcanService extends JobService { - private SyncTask syncTask = new SyncTask(); + private SyncTask syncTask; @Override public boolean onStartJob(JobParameters params) { Log.d(VulcanJobHelper.DEBUG_TAG, "Wulkanowy services start"); - syncTask.execute(params); + syncTask = new SyncTask(this, params); + syncTask.execute(); return true; } @Override public boolean onStopJob(JobParameters params) { - Log.e(VulcanJobHelper.DEBUG_TAG, "Wulkanowy serives stop"); - syncTask.cancel(true); + Log.e(VulcanJobHelper.DEBUG_TAG, "Wulkanowy services stop"); + if (syncTask != null) { + syncTask.cancel(true); + } return true; } public abstract void workToBePerformed() throws CryptoException, BadCredentialsException, NotLoggedInErrorException, AccountPermissionException, IOException; - private class SyncTask extends AsyncTask { + private static class SyncTask extends AsyncTask { + + private JobParameters jobParameters; + + private WeakReference vulcanService; + + public SyncTask(VulcanService vulcanService, JobParameters jobParameters) { + this.jobParameters = jobParameters; + this.vulcanService = new WeakReference<>(vulcanService); + } @Override - protected Void doInBackground(JobParameters... params) { + protected Void doInBackground(Void... voids) { try { - workToBePerformed(); + vulcanService.get().workToBePerformed(); } catch (Exception e) { Log.e(VulcanJobHelper.DEBUG_TAG, "User logging in the background failed", e); } finally { - jobFinished(params[0], false); + vulcanService.get().jobFinished(jobParameters, false); } return null; } diff --git a/app/src/main/java/io/github/wulkanowy/services/synchronisation/AccountAuthorization.java b/app/src/main/java/io/github/wulkanowy/services/synchronisation/CurrentAccountLogin.java similarity index 94% rename from app/src/main/java/io/github/wulkanowy/services/synchronisation/AccountAuthorization.java rename to app/src/main/java/io/github/wulkanowy/services/synchronisation/CurrentAccountLogin.java index 5c7ff62dd..c3ecd04b8 100644 --- a/app/src/main/java/io/github/wulkanowy/services/synchronisation/AccountAuthorization.java +++ b/app/src/main/java/io/github/wulkanowy/services/synchronisation/CurrentAccountLogin.java @@ -17,7 +17,7 @@ import io.github.wulkanowy.security.Safety; import io.github.wulkanowy.services.LoginSession; import io.github.wulkanowy.services.jobs.VulcanJobHelper; -public class AccountAuthorization { +public class CurrentAccountLogin { private final Context context; @@ -25,7 +25,7 @@ public class AccountAuthorization { private final Vulcan vulcan; - public AccountAuthorization(Context context, DaoSession daoSession, Vulcan vulcan) { + public CurrentAccountLogin(Context context, DaoSession daoSession, Vulcan vulcan) { this.context = context; this.daoSession = daoSession; this.vulcan = vulcan; diff --git a/app/src/main/java/io/github/wulkanowy/services/synchronisation/AccountRegistration.java b/app/src/main/java/io/github/wulkanowy/services/synchronisation/FirstAccountLogin.java similarity index 87% rename from app/src/main/java/io/github/wulkanowy/services/synchronisation/AccountRegistration.java rename to app/src/main/java/io/github/wulkanowy/services/synchronisation/FirstAccountLogin.java index 4bfc7817c..9b88de4a7 100644 --- a/app/src/main/java/io/github/wulkanowy/services/synchronisation/AccountRegistration.java +++ b/app/src/main/java/io/github/wulkanowy/services/synchronisation/FirstAccountLogin.java @@ -16,9 +16,8 @@ import io.github.wulkanowy.dao.entities.DaoSession; import io.github.wulkanowy.security.CryptoException; import io.github.wulkanowy.security.Safety; import io.github.wulkanowy.services.LoginSession; -import io.github.wulkanowy.services.jobs.GradeJob; -public class AccountRegistration { +public class FirstAccountLogin { private final Login login; @@ -31,7 +30,7 @@ public class AccountRegistration { private final String symbol; - public AccountRegistration(Login login, Vulcan vulcan, String email, String password, String symbol) { + public FirstAccountLogin(Login login, Vulcan vulcan, String email, String password, String symbol) { this.login = login; this.vulcan = vulcan; this.email = email; @@ -74,9 +73,4 @@ public class AccountRegistration { .setUserId(userId) .setDaoSession(daoSession); } - - public void scheduleSynchronization(Context context) { - GradeJob gradesSync = new GradeJob(); - gradesSync.scheduledJob(context); - } } diff --git a/app/src/main/java/io/github/wulkanowy/utilities/ConnectionUtilities.java b/app/src/main/java/io/github/wulkanowy/utilities/ConnectionUtilities.java index aa8792e51..fa37bfd35 100644 --- a/app/src/main/java/io/github/wulkanowy/utilities/ConnectionUtilities.java +++ b/app/src/main/java/io/github/wulkanowy/utilities/ConnectionUtilities.java @@ -9,7 +9,11 @@ public abstract class ConnectionUtilities { public static boolean isOnline(Context context) { ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); - return networkInfo != null && networkInfo.isConnectedOrConnecting(); + if (connectivityManager != null) { + NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); + return networkInfo != null && networkInfo.isConnectedOrConnecting(); + } else { + return false; + } } } diff --git a/app/src/main/java/io/github/wulkanowy/utilities/RootUtilities.java b/app/src/main/java/io/github/wulkanowy/utilities/RootUtilities.java index 258401048..d71d51c5d 100644 --- a/app/src/main/java/io/github/wulkanowy/utilities/RootUtilities.java +++ b/app/src/main/java/io/github/wulkanowy/utilities/RootUtilities.java @@ -8,8 +8,6 @@ import java.io.File; abstract public class RootUtilities { public static boolean isRooted() { - - String buildTags = Build.TAGS; if (buildTags != null && buildTags.contains("test-keys")) { return true; @@ -23,7 +21,6 @@ abstract public class RootUtilities { } catch (Exception e1) { // ignore } - return canExecuteCommand("/system/xbin/which su") || canExecuteCommand("/system/bin/which su") || canExecuteCommand("which su"); } @@ -36,7 +33,6 @@ abstract public class RootUtilities { } catch (Exception e) { executedSuccesfully = false; } - return executedSuccesfully; } } diff --git a/app/src/main/res/layout/fragment_grades.xml b/app/src/main/res/layout/fragment_grades.xml index 92d81f686..00c867bf5 100644 --- a/app/src/main/res/layout/fragment_grades.xml +++ b/app/src/main/res/layout/fragment_grades.xml @@ -5,6 +5,18 @@ android:layout_height="match_parent" tools:context="io.github.wulkanowy.activity.dashboard.grades.GradesFragment"> + + + + + - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/grade_item.xml b/app/src/main/res/layout/grade_item.xml index 2a4c134ba..2156ebcc4 100644 --- a/app/src/main/res/layout/grade_item.xml +++ b/app/src/main/res/layout/grade_item.xml @@ -8,7 +8,7 @@ android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_marginStart="5dp" - android:layout_marginTop="5dp" + android:layout_marginBottom="10dp" android:foreground="?attr/selectableItemBackgroundBorderless" card_view:cardElevation="0dp"> @@ -19,8 +19,7 @@ android:layout_marginEnd="7dp" android:layout_marginLeft="7dp" android:layout_marginRight="7dp" - android:layout_marginStart="7dp" - android:layout_marginTop="7dp"> + android:layout_marginStart="7dp"> Brak połączenia z internetem To urządzenie posiada posiada podwyższone uprawnienia (root). Automatyczne logowanie zosatło wyłączone. Szyfrowanie nie powiodło się. Automatyczne logowanie zostało wyłączone - Wersja\u0020 + Wersja %1$s Opis Waga Brak opisu diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1266ac87d..172bf83f2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -23,29 +23,33 @@ No account yet? Create one Forgot password? + Black + Red + Blue + Green + No color + Dashboard Activity Dashboard Grades Attendance Lesson Plan Settings + No internet connection This device is rooted. Automatic login has been disabled Encryption failed. Automatic login has been disabled - Version\u0020 + Version %1$s + An error occurred while refreshing the content. + Description Weight No description Teacher Date Color - Black - Red - Blue - Green - No color Close - An error occurred while refreshing the content. + No new grades Number of new grades: %1$d diff --git a/app/src/test/java/io/github/wulkanowy/dao/EntitiesCompareTest.java b/app/src/test/java/io/github/wulkanowy/dao/EntitiesCompareTest.java index fa2938799..8bac5b5e7 100644 --- a/app/src/test/java/io/github/wulkanowy/dao/EntitiesCompareTest.java +++ b/app/src/test/java/io/github/wulkanowy/dao/EntitiesCompareTest.java @@ -46,16 +46,28 @@ public class EntitiesCompareTest extends EntitiesCompare { } @Test - public void testCompareNewGradePositive() { + public void testCompareNewGradeEmptyOldList() { newList.add(grade1); List updatedList = EntitiesCompare.compareGradeList(newList, oldList); - Assert.assertEquals(true, (updatedList.get(0)).getIsNew()); + Assert.assertFalse(updatedList.get(0).getIsNew()); } + @Test + public void testCompareNewGradePositive() { + newList.add(grade1); + newList.add(grade2); + oldList.add(grade2); + + List updatedList = EntitiesCompare.compareGradeList(newList, oldList); + + Assert.assertFalse(updatedList.get(0).getIsNew()); + Assert.assertTrue(updatedList.get(1).getIsNew()); + } + @Test public void testCompareNewGradeNegative() { @@ -66,8 +78,8 @@ public class EntitiesCompareTest extends EntitiesCompare { List updatedList = EntitiesCompare.compareGradeList(newList, oldList); - Assert.assertEquals(false, (updatedList.get(0)).getIsNew()); - Assert.assertEquals(false, (updatedList.get(1)).getIsNew()); + Assert.assertFalse(updatedList.get(0).getIsNew()); + Assert.assertFalse(updatedList.get(1).getIsNew()); } @Test @@ -77,4 +89,18 @@ public class EntitiesCompareTest extends EntitiesCompare { Assert.assertEquals(new ArrayList<>(), updatedList); } + + @Test + public void testCompareReadGradeTest() { + newList.add(grade1); + newList.add(grade2); + oldList.add(grade2.setRead(true)); + + List updatedList = EntitiesCompare.compareGradeList(newList, oldList); + + Assert.assertTrue(updatedList.get(0).getRead()); + Assert.assertFalse(updatedList.get(0).getIsNew()); + Assert.assertFalse(updatedList.get(1).getRead()); + Assert.assertTrue(updatedList.get(1).getIsNew()); + } }