diff --git a/.gitignore b/.gitignore
index 116fa474..3b524b65 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,7 @@ local.properties
# User-specific configurations
.idea/copyright/profiles_settings.xml
.idea/libraries/
+.idea/inspectionProfiles/
.idea/.name
.idea/compiler.xml
.idea/encodings.xml
diff --git a/app/build.gradle b/app/build.gradle
index 70b2c1db..4b9275b5 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -42,6 +42,7 @@ dependencies {
compile 'com.thoughtbot:expandablerecyclerview:1.3'
compile 'com.android.support:cardview-v7:25.3.1'
compile 'com.google.code.gson:gson:2.8.1'
+ compile 'com.firebase:firebase-jobdispatcher:0.8.1'
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:2.9.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 820ae8f9..d0bebe51 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,12 +5,13 @@
android:installLocation="internalOnly">
-
+
+
-
+
+ android:theme="@style/WulkanowyTheme.noActionBar">
@@ -29,13 +30,21 @@
+ android:configChanges="orientation|screenSize"
+ android:label="@string/activity_dashboard_text" />
+
+
+
+
+
+
\ No newline at end of file
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 c0eb15a5..badcd423 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
@@ -16,8 +16,11 @@ import io.github.wulkanowy.activity.dashboard.lessonplan.LessonPlanFragment;
public class DashboardActivity extends AppCompatActivity {
private GradesFragment gradesFragment = new GradesFragment();
+
private AttendanceFragment attendanceFragment = new AttendanceFragment();
+
private BoardFragment boardFragment = new BoardFragment();
+
private LessonPlanFragment lessonPlanFragment = new LessonPlanFragment();
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
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 a339b2b7..434d711a 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
@@ -10,23 +10,11 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import io.github.wulkanowy.R;
-import io.github.wulkanowy.api.Cookies;
-import io.github.wulkanowy.api.StudentAndParent;
-import io.github.wulkanowy.api.grades.GradesList;
import io.github.wulkanowy.api.grades.Subject;
-import io.github.wulkanowy.api.grades.SubjectsList;
-import io.github.wulkanowy.database.accounts.Account;
-import io.github.wulkanowy.database.accounts.AccountsDatabase;
-import io.github.wulkanowy.database.cookies.CookiesDatabase;
import io.github.wulkanowy.database.grades.GradesDatabase;
import io.github.wulkanowy.database.subjects.SubjectsDatabase;
@@ -63,66 +51,30 @@ public class GradesFragment extends Fragment {
public class MarksTask extends AsyncTask {
- private Context mContext;
-
- private Map loginCookies = new HashMap<>();
+ private Context context;
MarksTask(Context context) {
- mContext = context;
+ this.context = context;
}
@Override
protected Void doInBackground(Void... params) {
- long userId = mContext.getSharedPreferences("LoginData", Context.MODE_PRIVATE).getLong("isLogin", 0);
- try {
- Gson gson = new GsonBuilder().enableComplexMapKeySerialization()
- .setPrettyPrinting().create();
- CookiesDatabase cookiesDatabase = new CookiesDatabase(mContext);
- cookiesDatabase.open();
- loginCookies = gson.fromJson(cookiesDatabase.getCookies(), loginCookies.getClass());
- cookiesDatabase.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
+ SubjectsDatabase subjectsDatabase = new SubjectsDatabase(context);
+ GradesDatabase gradesDatabase = new GradesDatabase(context);
- try {
- Cookies cookies = new Cookies();
- cookies.setItems(loginCookies);
+ gradesDatabase.open();
- AccountsDatabase accountsDatabase = new AccountsDatabase(mContext);
- accountsDatabase.open();
- Account account = accountsDatabase.getAccount(userId);
- accountsDatabase.close();
-
- StudentAndParent snp = new StudentAndParent(cookies, account.getSymbol());
- SubjectsList subjectsList = new SubjectsList(snp);
-
- SubjectsDatabase subjectsDatabase = new SubjectsDatabase(mContext);
- subjectsDatabase.open();
- subjectsDatabase.put(subjectsList.getAll());
- subjectsDatabase.close();
-
-
- GradesList gradesList = new GradesList(snp);
- GradesDatabase gradesDatabase = new GradesDatabase(mContext);
- gradesDatabase.open();
- gradesDatabase.put(gradesList.getAll());
-
- for (Subject subject : subjectsDatabase.getAllSubjectsNames()) {
- List gradeItems = gradesDatabase.getSubjectGrades(userId, SubjectsDatabase.getSubjectId(subject.getName()));
- if (gradeItems.size() > 0) {
- subjectWithGradesList.add(new SubjectWithGrades(subject.getName(), gradeItems));
- }
+ for (Subject subject : subjectsDatabase.getAllSubjectsNames()) {
+ List gradeItems = gradesDatabase.getSubjectGrades(context.getSharedPreferences("LoginData", Context.MODE_PRIVATE).getLong("isLogin", 0),
+ SubjectsDatabase.getSubjectId(subject.getName()));
+ if (gradeItems.size() > 0) {
+ subjectWithGradesList.add(new SubjectWithGrades(subject.getName(), gradeItems));
}
-
- gradesDatabase.close();
-
-
- } catch (Exception e) {
- e.printStackTrace();
}
+ gradesDatabase.close();
+
return null;
}
diff --git a/app/src/main/java/io/github/wulkanowy/activity/main/LoginTask.java b/app/src/main/java/io/github/wulkanowy/activity/main/LoginTask.java
index 3bec0d96..d04756f7 100644
--- a/app/src/main/java/io/github/wulkanowy/activity/main/LoginTask.java
+++ b/app/src/main/java/io/github/wulkanowy/activity/main/LoginTask.java
@@ -1,137 +1,86 @@
package io.github.wulkanowy.activity.main;
-import android.app.Activity;
import android.app.ProgressDialog;
+import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
-import android.database.SQLException;
import android.os.AsyncTask;
import android.widget.Toast;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
import java.io.IOException;
import io.github.wulkanowy.R;
import io.github.wulkanowy.activity.dashboard.DashboardActivity;
-import io.github.wulkanowy.api.Cookies;
-import io.github.wulkanowy.api.StudentAndParent;
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.user.BasicInformation;
-import io.github.wulkanowy.api.user.PersonalData;
-import io.github.wulkanowy.database.accounts.Account;
-import io.github.wulkanowy.database.accounts.AccountsDatabase;
-import io.github.wulkanowy.database.cookies.CookiesDatabase;
import io.github.wulkanowy.security.CryptoException;
-import io.github.wulkanowy.security.Safety;
+import io.github.wulkanowy.services.jobs.GradesSync;
+import io.github.wulkanowy.services.synchronisation.DataSynchronisation;
+import io.github.wulkanowy.services.synchronisation.VulcanSynchronisation;
+import io.github.wulkanowy.utilities.ConnectionUtilities;
public class LoginTask extends AsyncTask {
- private Activity activity;
-
- private boolean save;
+ private Context context;
private ProgressDialog progress;
- public LoginTask(Activity activity, boolean save) {
- this.activity = activity;
- this.save = save;
-
- this.progress = new ProgressDialog(activity);
+ public LoginTask(Context context) {
+ this.context = context;
+ this.progress = new ProgressDialog(context);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
- progress.setTitle(activity.getText(R.string.login_text));
- progress.setMessage(activity.getText(R.string.please_wait_text));
+ progress.setTitle(context.getText(R.string.login_text));
+ progress.setMessage(context.getText(R.string.please_wait_text));
progress.setCancelable(false);
progress.show();
}
@Override
protected Integer doInBackground(String... credentials) {
- Cookies cookies = new Cookies();
- Login login = new Login(cookies);
- try {
- login.login(credentials[0], credentials[1], credentials[2]);
- } catch (BadCredentialsException e) {
- return R.string.login_bad_credentials_text;
- } catch (AccountPermissionException e) {
- return R.string.login_bad_account_permission_text;
- } catch (LoginErrorException e) {
- return R.string.login_denied_text;
- }
- try {
- Gson gson = new GsonBuilder().enableComplexMapKeySerialization()
- .setPrettyPrinting().create();
- CookiesDatabase cookiesDatabase = new CookiesDatabase(activity);
- cookiesDatabase.open();
- cookiesDatabase.put(gson.toJson(login.getCookies()));
- cookiesDatabase.close();
- } catch (SQLException e) {
- return R.string.login_cookies_save_failed_text;
- }
-
- if (save) {
+ if (ConnectionUtilities.isOnline(context)) {
+ VulcanSynchronisation vulcanSynchronisation = new VulcanSynchronisation();
try {
- StudentAndParent snp = new StudentAndParent(login.getCookiesObject(),
- credentials[2]);
- BasicInformation userInfo = new BasicInformation(snp);
- PersonalData personalData = userInfo.getPersonalData();
- String firstAndLastName = personalData.getFirstAndLastName();
-
- Safety safety = new Safety(activity);
-
- Account account = new Account()
- .setName(firstAndLastName)
- .setEmail(credentials[0])
- .setPassword(safety.encrypt(credentials[0], credentials[1]))
- .setSymbol(credentials[2]);
-
- AccountsDatabase accountsDatabase = new AccountsDatabase(activity);
-
- accountsDatabase.open();
- long idUser = accountsDatabase.put(account);
- accountsDatabase.close();
-
- SharedPreferences sharedPreferences = activity.getSharedPreferences("LoginData", activity.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedPreferences.edit();
- editor.putLong("isLogin", idUser);
- editor.apply();
-
- } catch (SQLException e) {
- return R.string.SQLite_ioError_text;
- } catch (IOException | LoginErrorException e) {
- return R.string.login_denied_text;
+ vulcanSynchronisation.loginNewUser(credentials[0], credentials[1], credentials[2], context);
+ } catch (BadCredentialsException e) {
+ return R.string.login_bad_credentials_text;
+ } catch (AccountPermissionException e) {
+ return R.string.login_bad_account_permission_text;
} catch (CryptoException e) {
return R.string.encrypt_failed_text;
- } catch (UnsupportedOperationException e) {
- return R.string.root_failed_text;
+ } catch (LoginErrorException | IOException e) {
+ return R.string.login_denied_text;
}
- }
- //Map cookiesList = login.getJar();
- return R.string.login_accepted_text;
+ DataSynchronisation dataSynchronisation = new DataSynchronisation(context);
+ dataSynchronisation.syncGradesAndSubjects(vulcanSynchronisation);
+
+ return R.string.login_accepted_text;
+
+ } else {
+ return R.string.noInternet_text;
+ }
}
protected void onPostExecute(Integer messageID) {
super.onPostExecute(messageID);
+ GradesSync gradesSync = new GradesSync();
+ gradesSync.scheduledJob(context);
+
progress.dismiss();
- Toast.makeText(activity, activity.getString(messageID), Toast.LENGTH_LONG).show();
+ Toast.makeText(context, context.getString(messageID), Toast.LENGTH_LONG).show();
if (messageID == R.string.login_accepted_text || messageID == R.string.root_failed_text
|| messageID == R.string.encrypt_failed_text) {
- Intent intent = new Intent(activity, DashboardActivity.class);
- activity.startActivity(intent);
+ Intent intent = new Intent(context, DashboardActivity.class);
+ context.startActivity(intent);
}
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/activity/main/MainActivity.java b/app/src/main/java/io/github/wulkanowy/activity/main/MainActivity.java
index 28b17d21..a7ee5f1b 100644
--- a/app/src/main/java/io/github/wulkanowy/activity/main/MainActivity.java
+++ b/app/src/main/java/io/github/wulkanowy/activity/main/MainActivity.java
@@ -20,6 +20,7 @@ import io.github.wulkanowy.R;
public class MainActivity extends AppCompatActivity {
private float mTouchPosition;
+
private float mReleasePosition;
@Override
@@ -71,7 +72,7 @@ public class MainActivity extends AppCompatActivity {
}
if (!email.isEmpty() && !password.isEmpty() && !symbol.isEmpty()) {
- new LoginTask(this, true).execute(email, password, symbol);
+ new LoginTask(this).execute(email, password, symbol);
} else {
Toast.makeText(this, R.string.data_text, Toast.LENGTH_SHORT).show();
}
diff --git a/app/src/main/java/io/github/wulkanowy/activity/started/LoadingTask.java b/app/src/main/java/io/github/wulkanowy/activity/started/LoadingTask.java
index 64dc1cb3..363d747f 100644
--- a/app/src/main/java/io/github/wulkanowy/activity/started/LoadingTask.java
+++ b/app/src/main/java/io/github/wulkanowy/activity/started/LoadingTask.java
@@ -1,36 +1,26 @@
package io.github.wulkanowy.activity.started;
-import android.app.Activity;
+import android.content.Context;
import android.content.Intent;
-import android.database.SQLException;
import android.os.AsyncTask;
import android.widget.Toast;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketAddress;
-
import io.github.wulkanowy.R;
-import io.github.wulkanowy.activity.main.LoginTask;
+import io.github.wulkanowy.activity.dashboard.DashboardActivity;
import io.github.wulkanowy.activity.main.MainActivity;
-import io.github.wulkanowy.database.accounts.Account;
-import io.github.wulkanowy.database.accounts.AccountsDatabase;
-import io.github.wulkanowy.security.CryptoException;
-import io.github.wulkanowy.security.Safety;
+import io.github.wulkanowy.services.jobs.GradesSync;
+import io.github.wulkanowy.utilities.ConnectionUtilities;
-public class LoadingTask extends AsyncTask {
+public class LoadingTask extends AsyncTask {
- private final boolean SAVE_DATA = true;
- private Activity activity;
- private boolean isOnline;
+ private Context context;
- LoadingTask(Activity main) {
- activity = main;
+ LoadingTask(Context context) {
+ this.context = context;
}
@Override
- protected Void doInBackground(Void... voids) {
+ protected Boolean doInBackground(Void... voids) {
try {
Thread.sleep(500);
@@ -38,74 +28,27 @@ public class LoadingTask extends AsyncTask {
e.printStackTrace();
}
- isOnline = isOnline();
-
- return null;
+ return ConnectionUtilities.isOnline(context);
}
- protected void onPostExecute(Void result) {
+ protected void onPostExecute(Boolean result) {
+ super.onPostExecute(result);
- if (isOnline) {
- signIn();
+ if (!result) {
+ Toast.makeText(context, R.string.noInternet_text, Toast.LENGTH_LONG).show();
+ }
+
+ if (context.getSharedPreferences("LoginData", Context.MODE_PRIVATE).getLong("isLogin", 0) == 0) {
+ Intent intent = new Intent(context, MainActivity.class);
+ context.startActivity(intent);
} else {
- Intent intent = new Intent(activity, MainActivity.class);
- activity.startActivity(intent);
+ GradesSync gradesSync = new GradesSync();
+ gradesSync.scheduledJob(context);
- Toast.makeText(activity, R.string.noInternet_text, Toast.LENGTH_SHORT).show();
- }
- }
-
- private boolean isOnline() {
- try {
- int timeoutMs = 1500;
- Socket sock = new Socket();
- SocketAddress address = new InetSocketAddress("8.8.8.8", 53);
-
- sock.connect(address, timeoutMs);
- sock.close();
-
- return true;
- } catch (IOException e) {
- return false;
- }
- }
-
- private boolean signIn() {
-
- if (SAVE_DATA) {
- AccountsDatabase accountsDatabase = new AccountsDatabase(activity);
- accountsDatabase.open();
-
- if (accountsDatabase.checkExist("accounts")) {
- try {
- Account account = accountsDatabase.getAccount(activity.getSharedPreferences("LoginData", activity.MODE_PRIVATE).getLong("isLogin", 0));
- accountsDatabase.close();
-
- if (account != null) {
-
- Safety safety = new Safety(activity);
-
- new LoginTask(activity, false).execute(
- account.getEmail(),
- safety.decrypt(account.getEmail(), account.getPassword()),
- account.getSymbol()
- );
-
- return true;
- }
- } catch (SQLException e) {
- Toast.makeText(activity, R.string.SQLite_ioError_text,
- Toast.LENGTH_LONG).show();
- } catch (CryptoException e) {
- Toast.makeText(activity, R.string.decrypt_failed_text, Toast.LENGTH_LONG).show();
- }
- }
- accountsDatabase.close();
+ Intent intent = new Intent(context, DashboardActivity.class);
+ context.startActivity(intent);
}
- Intent intent = new Intent(activity, MainActivity.class);
- activity.startActivity(intent);
- return false;
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/database/DatabaseAdapter.java b/app/src/main/java/io/github/wulkanowy/database/DatabaseAdapter.java
index 65da3f29..82fa0fe2 100644
--- a/app/src/main/java/io/github/wulkanowy/database/DatabaseAdapter.java
+++ b/app/src/main/java/io/github/wulkanowy/database/DatabaseAdapter.java
@@ -10,7 +10,7 @@ public class DatabaseAdapter {
private final String DATABASE_NAME = "accountdatabase.db";
- private final int DATABASE_VERSION = 5;
+ private final int DATABASE_VERSION = 6;
public static SQLiteDatabase database;
@@ -44,7 +44,7 @@ public class DatabaseAdapter {
Log.d(DatabaseHelper.DEBUG_TAG, "Close database");
}
- public boolean checkExist(String tableName, String dbfield, String fieldValue) {
+ protected boolean checkExist(String tableName, String dbfield, String fieldValue) {
Cursor cursor;
@@ -73,17 +73,16 @@ public class DatabaseAdapter {
return false;
}
- public boolean checkExist(String tableName) {
+ protected boolean checkExist(String tableName) {
return checkExist(tableName, null, null);
}
- public void deleteAndCreate(String tableName) {
+ protected void deleteAndCreate(String tableName) {
database.execSQL(databaseHelper.DROP_TABLE + tableName);
database.execSQL(databaseHelper.SUBJECT_TABLE);
database.execSQL(databaseHelper.ACCOUNT_TABLE);
database.execSQL(databaseHelper.GRADE_TABLE);
- database.execSQL(databaseHelper.COOKIES_TABLE);
Log.d(DatabaseHelper.DEBUG_TAG, "Recreate table " + tableName);
diff --git a/app/src/main/java/io/github/wulkanowy/database/DatabaseHelper.java b/app/src/main/java/io/github/wulkanowy/database/DatabaseHelper.java
index 7a2ae7af..3011eff6 100644
--- a/app/src/main/java/io/github/wulkanowy/database/DatabaseHelper.java
+++ b/app/src/main/java/io/github/wulkanowy/database/DatabaseHelper.java
@@ -40,10 +40,6 @@ public class DatabaseHelper extends SQLiteOpenHelper {
"semester INTEGER, " +
"isNew INTEGER );";
- public final String COOKIES_TABLE = "CREATE TABLE IF NOT EXISTS cookies( " +
- "id INTEGER PRIMARY KEY AUTOINCREMENT, " +
- "cookies TEXT );";
-
public final String DROP_TABLE = "DROP TABLE IF EXISTS ";
public DatabaseHelper(Context context, String name, CursorFactory factory, int version) {
@@ -55,7 +51,6 @@ public class DatabaseHelper extends SQLiteOpenHelper {
db.execSQL(ACCOUNT_TABLE);
db.execSQL(SUBJECT_TABLE);
db.execSQL(GRADE_TABLE);
- db.execSQL(COOKIES_TABLE);
Log.d(DEBUG_TAG, "Create database");
}
@@ -64,7 +59,6 @@ public class DatabaseHelper extends SQLiteOpenHelper {
db.execSQL(DROP_TABLE + "accounts");
db.execSQL(DROP_TABLE + "subjects");
db.execSQL(DROP_TABLE + "grades");
- db.execSQL(DROP_TABLE + "cookies");
onCreate(db);
Log.d(DEBUG_TAG, "Database upgrade from ver." + oldVersion + " to ver." + newVersion);
}
diff --git a/app/src/main/java/io/github/wulkanowy/database/accounts/AccountsDatabase.java b/app/src/main/java/io/github/wulkanowy/database/accounts/AccountsDatabase.java
index fd40521e..b367bdba 100644
--- a/app/src/main/java/io/github/wulkanowy/database/accounts/AccountsDatabase.java
+++ b/app/src/main/java/io/github/wulkanowy/database/accounts/AccountsDatabase.java
@@ -13,10 +13,15 @@ import io.github.wulkanowy.database.DatabaseHelper;
public class AccountsDatabase extends DatabaseAdapter {
private String name = "name";
+
private String email = "email";
+
private String password = "password";
+
private String symbol = "symbol";
+
private String idText = "id";
+
private String accounts = "accounts";
public AccountsDatabase(Context context) {
diff --git a/app/src/main/java/io/github/wulkanowy/database/cookies/CookiesDatabase.java b/app/src/main/java/io/github/wulkanowy/database/cookies/CookiesDatabase.java
deleted file mode 100644
index 6cd40b06..00000000
--- a/app/src/main/java/io/github/wulkanowy/database/cookies/CookiesDatabase.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package io.github.wulkanowy.database.cookies;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.SQLException;
-import android.util.Log;
-
-import io.github.wulkanowy.database.DatabaseAdapter;
-import io.github.wulkanowy.database.DatabaseHelper;
-
-public class CookiesDatabase extends DatabaseAdapter {
-
- private String cookies = "cookies";
-
- public CookiesDatabase(Context context) {
- super(context);
- }
-
- public long put(String serializableCookiesMap) {
-
- ContentValues newCookie = new ContentValues();
- newCookie.put(cookies, serializableCookiesMap);
-
- if (!database.isReadOnly()) {
- if (!checkExist(cookies)) {
- long newId = database.insertOrThrow(cookies, null, newCookie);
- Log.d(DatabaseHelper.DEBUG_TAG, "Put cookies into database");
- return newId;
- } else {
- deleteAndCreate(cookies);
- long newId = database.insertOrThrow(cookies, null, newCookie);
- Log.d(DatabaseHelper.DEBUG_TAG, "Put cookies into database");
- return newId;
- }
- } else {
- Log.e(DatabaseHelper.DEBUG_TAG, "Attempt to write on read-only database");
- throw new SQLException("Attempt to write on read-only database");
- }
- }
-
- public String getCookies() {
-
- String exec = "SELECT " + cookies + " FROM " + cookies;
-
- Cursor cursor = database.rawQuery(exec, null);
-
- cursor.moveToFirst();
-
- String cookie = cursor.getString(0);
-
- cursor.close();
-
- Log.d(DatabaseHelper.DEBUG_TAG, "Extract cookies from database");
-
- return cookie;
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/database/subjects/SubjectsDatabase.java b/app/src/main/java/io/github/wulkanowy/database/subjects/SubjectsDatabase.java
index 4b8d99ae..093b9999 100644
--- a/app/src/main/java/io/github/wulkanowy/database/subjects/SubjectsDatabase.java
+++ b/app/src/main/java/io/github/wulkanowy/database/subjects/SubjectsDatabase.java
@@ -18,11 +18,17 @@ import io.github.wulkanowy.database.DatabaseHelper;
public class SubjectsDatabase extends DatabaseAdapter {
private static String idText = "id";
+
private static String name = "name";
+
private static String predictedRating1 = "predictedRating1";
+
private static String finalRating1 = "finalRating1";
+
private static String predictedRating2 = "predictedRating2";
+
private static String finalRating2 = "finalRating2";
+
private static String subjects = "subjects";
public SubjectsDatabase(Context context) {
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 33df50b4..1bf344c7 100644
--- a/app/src/main/java/io/github/wulkanowy/security/Scrambler.java
+++ b/app/src/main/java/io/github/wulkanowy/security/Scrambler.java
@@ -31,8 +31,11 @@ import javax.security.auth.x500.X500Principal;
public class Scrambler {
private KeyStore keyStore;
+
private static final String ANDROID_KEYSTORE = "AndroidKeyStore";
+
public final static String DEBUG_TAG = "KeyStoreSecurity";
+
public Context context;
public Scrambler(Context context) {
diff --git a/app/src/main/java/io/github/wulkanowy/services/jobs/GradesSync.java b/app/src/main/java/io/github/wulkanowy/services/jobs/GradesSync.java
new file mode 100644
index 00000000..29a0835b
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/services/jobs/GradesSync.java
@@ -0,0 +1,53 @@
+package io.github.wulkanowy.services.jobs;
+
+import com.firebase.jobdispatcher.Constraint;
+import com.firebase.jobdispatcher.FirebaseJobDispatcher;
+import com.firebase.jobdispatcher.Job;
+import com.firebase.jobdispatcher.Lifetime;
+import com.firebase.jobdispatcher.RetryStrategy;
+import com.firebase.jobdispatcher.Trigger;
+
+import java.io.IOException;
+
+import io.github.wulkanowy.api.login.AccountPermissionException;
+import io.github.wulkanowy.api.login.BadCredentialsException;
+import io.github.wulkanowy.api.login.LoginErrorException;
+import io.github.wulkanowy.security.CryptoException;
+import io.github.wulkanowy.services.synchronisation.DataSynchronisation;
+import io.github.wulkanowy.services.synchronisation.VulcanSynchronisation;
+
+public class GradesSync extends VulcanSync {
+
+ public static final String UNIQUE_TAG = "GradesSync34512";
+
+ public static final int DEFAULT_INTERVAL_START = 60 * 50;
+
+ public static final int DEFAULT_INTERVAL_END = DEFAULT_INTERVAL_START + (60 * 10);
+
+ @Override
+ protected Job createJob(FirebaseJobDispatcher dispatcher) {
+ return dispatcher.newJobBuilder()
+ .setLifetime(Lifetime.FOREVER)
+ .setService(GradeJob.class)
+ .setTag(UNIQUE_TAG)
+ .setRecurring(true)
+ .setTrigger(Trigger.executionWindow(DEFAULT_INTERVAL_START, DEFAULT_INTERVAL_END))
+ .setConstraints(Constraint.ON_ANY_NETWORK)
+ .setReplaceCurrent(true)
+ .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
+ .build();
+ }
+
+ public static class GradeJob extends VulcanJob {
+
+ @Override
+ public void workToBePerformed() throws CryptoException, BadCredentialsException,
+ LoginErrorException, AccountPermissionException, IOException {
+
+ VulcanSynchronisation vulcanSynchronisation = new VulcanSynchronisation();
+ DataSynchronisation dataSynchronisation = new DataSynchronisation(getApplicationContext());
+ vulcanSynchronisation.loginCurrentUser(getApplicationContext());
+ dataSynchronisation.syncGrades(vulcanSynchronisation);
+ }
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/services/jobs/SubjectsSync.java b/app/src/main/java/io/github/wulkanowy/services/jobs/SubjectsSync.java
new file mode 100644
index 00000000..f6882fc8
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/services/jobs/SubjectsSync.java
@@ -0,0 +1,54 @@
+package io.github.wulkanowy.services.jobs;
+
+import com.firebase.jobdispatcher.Constraint;
+import com.firebase.jobdispatcher.FirebaseJobDispatcher;
+import com.firebase.jobdispatcher.Job;
+import com.firebase.jobdispatcher.Lifetime;
+import com.firebase.jobdispatcher.RetryStrategy;
+import com.firebase.jobdispatcher.Trigger;
+
+import java.io.IOException;
+
+import io.github.wulkanowy.api.login.AccountPermissionException;
+import io.github.wulkanowy.api.login.BadCredentialsException;
+import io.github.wulkanowy.api.login.LoginErrorException;
+import io.github.wulkanowy.security.CryptoException;
+import io.github.wulkanowy.services.synchronisation.DataSynchronisation;
+import io.github.wulkanowy.services.synchronisation.VulcanSynchronisation;
+
+public class SubjectsSync extends VulcanSync {
+
+ public static final String UNIQUE_TAG = "SubjectsSync34512";
+
+ public static final int DEFAULT_INTERVAL_START = 0;
+
+ public static final int DEFAULT_INTERVAL_END = DEFAULT_INTERVAL_START + 10;
+
+ @Override
+ protected Job createJob(FirebaseJobDispatcher dispatcher) {
+ return dispatcher.newJobBuilder()
+ .setLifetime(Lifetime.UNTIL_NEXT_BOOT)
+ .setService(SubjectJob.class)
+ .setTag(UNIQUE_TAG)
+ .setRecurring(false)
+ .setTrigger(Trigger.executionWindow(DEFAULT_INTERVAL_START, DEFAULT_INTERVAL_END))
+ .setConstraints(Constraint.ON_ANY_NETWORK)
+ .setReplaceCurrent(true)
+ .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
+ .build();
+ }
+
+ private class SubjectJob extends VulcanJob {
+
+ @Override
+ public void workToBePerformed() throws CryptoException, BadCredentialsException,
+ LoginErrorException, AccountPermissionException, IOException {
+
+ VulcanSynchronisation vulcanSynchronisation = new VulcanSynchronisation();
+ DataSynchronisation dataSynchronisation = new DataSynchronisation(getApplicationContext());
+ vulcanSynchronisation.loginCurrentUser(getApplicationContext());
+ dataSynchronisation.syncSubjects(vulcanSynchronisation);
+
+ }
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/services/jobs/VulcanJob.java b/app/src/main/java/io/github/wulkanowy/services/jobs/VulcanJob.java
new file mode 100644
index 00000000..9c787e57
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/services/jobs/VulcanJob.java
@@ -0,0 +1,51 @@
+package io.github.wulkanowy.services.jobs;
+
+import android.os.AsyncTask;
+import android.util.Log;
+
+import com.firebase.jobdispatcher.JobParameters;
+import com.firebase.jobdispatcher.JobService;
+
+import java.io.IOException;
+
+import io.github.wulkanowy.api.login.AccountPermissionException;
+import io.github.wulkanowy.api.login.BadCredentialsException;
+import io.github.wulkanowy.api.login.LoginErrorException;
+import io.github.wulkanowy.security.CryptoException;
+
+public abstract class VulcanJob extends JobService {
+
+ private SyncTask syncTask = new SyncTask();
+
+ @Override
+ public boolean onStartJob(JobParameters params) {
+ Log.d(VulcanSync.DEBUG_TAG, "Start job");
+ syncTask.execute(params);
+ return true;
+ }
+
+ @Override
+ public boolean onStopJob(JobParameters params) {
+ Log.d(VulcanSync.DEBUG_TAG, "Stop job");
+ syncTask.cancel(true);
+ return true;
+ }
+
+ public abstract void workToBePerformed() throws CryptoException, BadCredentialsException,
+ LoginErrorException, AccountPermissionException, IOException;
+
+ private class SyncTask extends AsyncTask {
+
+ @Override
+ protected Void doInBackground(JobParameters... params) {
+ try {
+ workToBePerformed();
+ } catch (Exception e) {
+ Log.e(VulcanSync.DEBUG_TAG, "User logging in the background failed", e);
+ } finally {
+ jobFinished(params[0], false);
+ }
+ return null;
+ }
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/services/jobs/VulcanSync.java b/app/src/main/java/io/github/wulkanowy/services/jobs/VulcanSync.java
new file mode 100644
index 00000000..8ff1d485
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/services/jobs/VulcanSync.java
@@ -0,0 +1,21 @@
+package io.github.wulkanowy.services.jobs;
+
+
+import android.content.Context;
+
+import com.firebase.jobdispatcher.FirebaseJobDispatcher;
+import com.firebase.jobdispatcher.GooglePlayDriver;
+import com.firebase.jobdispatcher.Job;
+
+public abstract class VulcanSync {
+
+ public static final String DEBUG_TAG = "SynchronizationService";
+
+ public void scheduledJob(Context context) {
+ FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
+ dispatcher.mustSchedule(createJob(dispatcher));
+ }
+
+ protected abstract Job createJob(FirebaseJobDispatcher dispatcher);
+
+}
diff --git a/app/src/main/java/io/github/wulkanowy/services/synchronisation/DataSynchronisation.java b/app/src/main/java/io/github/wulkanowy/services/synchronisation/DataSynchronisation.java
new file mode 100644
index 00000000..d77607f4
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/services/synchronisation/DataSynchronisation.java
@@ -0,0 +1,40 @@
+package io.github.wulkanowy.services.synchronisation;
+
+import android.content.Context;
+import android.util.Log;
+
+import io.github.wulkanowy.services.jobs.VulcanSync;
+
+public class DataSynchronisation {
+
+ private Context context;
+
+ public DataSynchronisation(Context context) {
+ this.context = context;
+ }
+
+ public void syncGrades(VulcanSynchronisation vulcanSynchronisation) {
+ GradesSynchronisation gradesSynchronisation = new GradesSynchronisation();
+
+ try {
+ gradesSynchronisation.sync(vulcanSynchronisation, context);
+ } catch (Exception e) {
+ Log.e(VulcanSync.DEBUG_TAG, "Synchronisation of grades failed", e);
+ }
+ }
+
+ public void syncSubjects(VulcanSynchronisation vulcanSynchronisation) {
+ SubjectsSynchronisation subjectsSynchronisation = new SubjectsSynchronisation();
+
+ try {
+ subjectsSynchronisation.sync(vulcanSynchronisation, context);
+ } catch (Exception e) {
+ Log.e(VulcanSync.DEBUG_TAG, "Synchronisation of subjects failed", e);
+ }
+ }
+
+ public void syncGradesAndSubjects(VulcanSynchronisation vulcanSynchronisation) {
+ syncSubjects(vulcanSynchronisation);
+ syncGrades(vulcanSynchronisation);
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/services/synchronisation/GradesSynchronisation.java b/app/src/main/java/io/github/wulkanowy/services/synchronisation/GradesSynchronisation.java
new file mode 100644
index 00000000..91507b9f
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/services/synchronisation/GradesSynchronisation.java
@@ -0,0 +1,23 @@
+package io.github.wulkanowy.services.synchronisation;
+
+import android.content.Context;
+
+import java.io.IOException;
+import java.text.ParseException;
+
+import io.github.wulkanowy.api.grades.GradesList;
+import io.github.wulkanowy.api.login.LoginErrorException;
+import io.github.wulkanowy.database.grades.GradesDatabase;
+
+public class GradesSynchronisation {
+
+ public void sync(VulcanSynchronisation vulcanSynchronisation, Context context) throws IOException, ParseException, LoginErrorException {
+
+ GradesList gradesList = new GradesList(vulcanSynchronisation.getStudentAndParent());
+
+ GradesDatabase gradesDatabase = new GradesDatabase(context);
+ gradesDatabase.open();
+ gradesDatabase.put(gradesList.getAll());
+ gradesDatabase.close();
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/services/synchronisation/SubjectsSynchronisation.java b/app/src/main/java/io/github/wulkanowy/services/synchronisation/SubjectsSynchronisation.java
new file mode 100644
index 00000000..a3d33a0c
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/services/synchronisation/SubjectsSynchronisation.java
@@ -0,0 +1,23 @@
+package io.github.wulkanowy.services.synchronisation;
+
+import android.content.Context;
+
+import java.io.IOException;
+import java.text.ParseException;
+
+import io.github.wulkanowy.api.grades.SubjectsList;
+import io.github.wulkanowy.api.login.LoginErrorException;
+import io.github.wulkanowy.database.subjects.SubjectsDatabase;
+
+public class SubjectsSynchronisation {
+
+ public void sync(VulcanSynchronisation vulcanSynchronisation, Context context) throws IOException, ParseException, LoginErrorException {
+
+ SubjectsList subjectsList = new SubjectsList(vulcanSynchronisation.getStudentAndParent());
+
+ SubjectsDatabase subjectsDatabase = new SubjectsDatabase(context);
+ subjectsDatabase.open();
+ subjectsDatabase.put(subjectsList.getAll());
+ subjectsDatabase.close();
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/services/synchronisation/VulcanSynchronisation.java b/app/src/main/java/io/github/wulkanowy/services/synchronisation/VulcanSynchronisation.java
new file mode 100644
index 00000000..e7114dfc
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/services/synchronisation/VulcanSynchronisation.java
@@ -0,0 +1,106 @@
+package io.github.wulkanowy.services.synchronisation;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.Map;
+
+import io.github.wulkanowy.api.Cookies;
+import io.github.wulkanowy.api.StudentAndParent;
+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.user.BasicInformation;
+import io.github.wulkanowy.api.user.PersonalData;
+import io.github.wulkanowy.database.accounts.Account;
+import io.github.wulkanowy.database.accounts.AccountsDatabase;
+import io.github.wulkanowy.security.CryptoException;
+import io.github.wulkanowy.security.Safety;
+import io.github.wulkanowy.services.jobs.VulcanSync;
+
+public class VulcanSynchronisation {
+
+ private StudentAndParent studentAndParent;
+
+ public void loginCurrentUser(Context context) throws CryptoException, BadCredentialsException, LoginErrorException, AccountPermissionException, IOException {
+
+ long userId = context.getSharedPreferences("LoginData", Context.MODE_PRIVATE).getLong("isLogin", 0);
+
+ if (userId != 0) {
+ AccountsDatabase accountsDatabase = new AccountsDatabase(context);
+ accountsDatabase.open();
+ Account account = accountsDatabase.getAccount(userId);
+ accountsDatabase.close();
+ Safety safety = new Safety(context);
+
+ Login login = loginUser(
+ account.getEmail(),
+ safety.decrypt(account.getEmail(), account.getPassword()),
+ account.getSymbol());
+
+ getAndSetStudentAndParentFromApi(account.getSymbol(), login.getCookies());
+ } else {
+ Log.wtf(VulcanSync.DEBUG_TAG, "loginCurrentUser - USERID IS EMPTY");
+ }
+ }
+
+ public void loginNewUser(String email, String password, String symbol, Context context) throws BadCredentialsException, LoginErrorException, AccountPermissionException, IOException, CryptoException {
+
+ Login login = loginUser(email, password, symbol);
+
+ Safety safety = new Safety(context);
+ AccountsDatabase accountsDatabase = new AccountsDatabase(context);
+ BasicInformation basicInformation = new BasicInformation(getAndSetStudentAndParentFromApi(symbol, login.getCookies()));
+ PersonalData personalData = basicInformation.getPersonalData();
+
+ Account account = new Account()
+ .setName(personalData.getFirstAndLastName())
+ .setEmail(email)
+ .setPassword(safety.encrypt(email, password))
+ .setSymbol(symbol);
+
+ accountsDatabase.open();
+ long idNewUser = accountsDatabase.put(account);
+ accountsDatabase.close();
+
+ SharedPreferences sharedPreferences = context.getSharedPreferences("LoginData", Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putLong("isLogin", idNewUser);
+ editor.apply();
+ }
+
+ public StudentAndParent getStudentAndParent() {
+ return studentAndParent;
+ }
+
+ private void setStudentAndParent(StudentAndParent studentAndParent) {
+ this.studentAndParent = studentAndParent;
+ }
+
+ private Login loginUser(String email, String password, String symbol) throws BadCredentialsException, LoginErrorException, AccountPermissionException {
+
+ Cookies cookies = new Cookies();
+ Login login = new Login(cookies);
+ login.login(email, password, symbol);
+ return login;
+
+ }
+
+ private StudentAndParent getAndSetStudentAndParentFromApi(String symbol, Map cookiesMap) throws IOException, LoginErrorException {
+
+ if (studentAndParent == null) {
+ Cookies cookies = new Cookies();
+ cookies.setItems(cookiesMap);
+
+ StudentAndParent snp = new StudentAndParent(cookies, symbol);
+
+ setStudentAndParent(snp);
+ return snp;
+ } else {
+ return studentAndParent;
+ }
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/utilities/ConnectionUtilities.java b/app/src/main/java/io/github/wulkanowy/utilities/ConnectionUtilities.java
new file mode 100644
index 00000000..aa8792e5
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/utilities/ConnectionUtilities.java
@@ -0,0 +1,15 @@
+package io.github.wulkanowy.utilities;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+
+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();
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/utilities/DateHelper.java b/app/src/main/java/io/github/wulkanowy/utilities/DateHelper.java
index 5677f721..bb759129 100644
--- a/app/src/main/java/io/github/wulkanowy/utilities/DateHelper.java
+++ b/app/src/main/java/io/github/wulkanowy/utilities/DateHelper.java
@@ -10,6 +10,7 @@ import java.util.TimeZone;
abstract public class DateHelper {
private static final long TICKS_AT_EPOCH = 621355968000000000L;
+
private static final long TICKS_PER_MILLISECOND = 10000;
public static long getTicks(Date date) {
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 596cd0e0..25840104 100644
--- a/app/src/main/java/io/github/wulkanowy/utilities/RootUtilities.java
+++ b/app/src/main/java/io/github/wulkanowy/utilities/RootUtilities.java
@@ -5,7 +5,7 @@ import android.os.Build;
import java.io.File;
-public class RootUtilities {
+abstract public class RootUtilities {
public static boolean isRooted() {