diff --git a/.gitignore b/.gitignore index f24fa06b..8f04c3b1 100644 --- a/.gitignore +++ b/.gitignore @@ -60,9 +60,14 @@ fastlane/test_output fastlane/readme.md app/release/output.json -.DS_Store # Custom product flavours *custom-flavours.gradle *.aab + +#DS_Store files +*.DS_Store +.DS_Store +./.DS_Store +./.git/.DS_Store diff --git a/README.md b/README.md index cc418862..a03f229f 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ Parameters: * ```RAR_PASSWORD``` represents the password to be used for the offline extract. * ```SHOW_CONTROL_NUMBER_MENU``` allow to show or hide the Control Number menu item in case the implementation does not implement the ePayment module. * ```app_name_policies``` is a resource string allowing to change the name of the application. +* ```sentry_dsn``` allow to define the sentry dsn of your project where error and exception events from your application will be sent Escape procedures can be configured and language resource files can be changed. Please follow the ```sourceSets``` record. Look in ```app\src\demo``` folder for an example. diff --git a/app/build.gradle b/app/build.gradle index 2135c835..39d12eb8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -52,6 +52,7 @@ android { buildConfigField "boolean", "IS_PAYMENT_ENABLED", 'false' resValue "string", "app_name_policies", "Policies" resValue "string", "ReleaseDateValue", getDate() + resValue "string", "sentry_dsn", "" } buildTypes { release { @@ -192,8 +193,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } packagingOptions { @@ -245,4 +246,5 @@ dependencies { exclude group: 'com.android.support', module: 'support-annotations' }) testImplementation 'junit:junit:4.13.2' + implementation 'io.sentry:sentry-android:4.2.0' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5a88ad6d..ad266e97 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -63,6 +63,8 @@ android:resource="@xml/paths" /> + + policies = familyPolicyFromJSONObject(family.getUuid(), policiesArray); new UpdateFamily().execute(family, policies); } catch (Exception e) { + Sentry.captureException(e); e.printStackTrace(); enrolMessages.add(Objects.requireNonNullElse(e.getMessage(), "Something went wrong updating the family")); return -400; @@ -3571,8 +3580,8 @@ protected void onPostExecute(Boolean aBoolean) { } private void DeleteUploadedData(final int FamilyId, ArrayList FamilyIDs, int CallerId) { - if (FamilyIDs.size() == 0) { - FamilyIDs = new ArrayList<>() {{ + if (FamilyIDs.isEmpty()) { + FamilyIDs = new ArrayList() {{ add(String.valueOf(FamilyId)); }}; } @@ -3663,6 +3672,7 @@ public void uploadFeedbacks() { MoveFile(xmlFiles[i], 1); MoveFile(jsonFiles[i], 1); } catch (Exception e) { + Sentry.captureException(e); e.printStackTrace(); if ( e instanceof HttpException && @@ -3901,6 +3911,7 @@ public void downloadMasterData() { ((MainActivity) activity).ShowEnrolmentOfficerDialog(); }); } catch (JSONException e) { + Sentry.captureException(e); Log.e("MASTERDATA", "Error while parsing master data", e); } catch (UserException e) { Log.e("MASTERDATA", "Error while downloading master data", e); @@ -3923,6 +3934,7 @@ public void importMasterData(String data) throws JSONException, UserException { try { processOldFormat(new JSONArray(data)); } catch (JSONException e) { + Sentry.captureException(e); try { processNewFormat(new JSONObject(data)); } catch (JSONException e2) { @@ -3937,6 +3949,7 @@ public void startDownloadingMasterData() throws JSONException, UserException, Us try { importMasterData(new FetchMasterData().execute()); } catch (Exception e) { + Sentry.captureException(e); if (e instanceof UserNotAuthenticatedException) { throw (UserNotAuthenticatedException) e; } @@ -4054,6 +4067,7 @@ private void processOldFormat(@NonNull JSONArray masterData) throws UserExceptio insertPhoneDefaults(PhoneDefaults); insertGenders(Genders); } catch (JSONException e) { + Sentry.captureException(e); e.printStackTrace(); throw new UserException(activity.getResources().getString(R.string.DownloadMasterDataFailed), e); } @@ -4561,6 +4575,7 @@ public void SaveInsureePolicy(int InsureId, int FamilyId, Boolean Activate, int ExpiryDate = PolicyObject2.getString("ExpiryDate"); EnrollDate = PolicyObject2.getString("EnrollDate"); } catch (JSONException e) { + Sentry.captureException(e); e.printStackTrace(); } values.put("InsureePolicyId", MaxInsureePolicyId); diff --git a/app/src/main/java/org/openimis/imispolicies/MainActivity.java b/app/src/main/java/org/openimis/imispolicies/MainActivity.java index 9298d82a..2165a808 100644 --- a/app/src/main/java/org/openimis/imispolicies/MainActivity.java +++ b/app/src/main/java/org/openimis/imispolicies/MainActivity.java @@ -71,6 +71,7 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.openimis.imispolicies.network.exception.HttpException; import org.openimis.imispolicies.network.exception.UserNotAuthenticatedException; import org.openimis.imispolicies.tools.LanguageManager; import org.openimis.imispolicies.tools.Log; @@ -88,6 +89,8 @@ import java.io.OutputStream; import java.lang.ref.WeakReference; +import io.sentry.Sentry; + public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { @@ -161,6 +164,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (f.exists() || f.createNewFile()) new FileOutputStream(f).write(bytes); } catch (IOException e) { + Sentry.captureException(e); e.printStackTrace(); } ShowDialogTex2(); @@ -230,100 +234,100 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis protected void onCreate(Bundle savedInstanceState) { global = (Global) getApplicationContext(); super.onCreate(savedInstanceState); - instance = this; - setContentView(R.layout.activity_main); - SQLHandler sqlHandler = new SQLHandler(this); - sqlHandler.isPrivate = true; - //Set the Image folder path - global.setImageFolder(global.getSubdirectory("Images")); - //Check if database exists - File database = global.getDatabasePath(SQLHandler.DBNAME); - if (!database.exists()) { - sqlHandler.getReadableDatabase(); - if (copyDatabase(this)) { - Toast.makeText(this, "Copy database success", Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(this, "Copy database failed", Toast.LENGTH_SHORT).show(); - return; - } - } else - sqlHandler.getReadableDatabase(); - - //Create image folder - createImageFolder(); - - Toolbar toolbar = findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - - FloatingActionButton fab = findViewById(R.id.fab); - fab.setOnClickListener(view -> Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) - .setAction("Action", null).show()); - - DrawerLayout drawer = findViewById(R.id.drawer_layout); - ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( - this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); - //noinspection deprecation - drawer.setDrawerListener(toggle); - toggle.syncState(); - - navigationView = findViewById(R.id.nav_view); + try { + instance = this; + setContentView(R.layout.activity_main); + SQLHandler sqlHandler = new SQLHandler(this); + sqlHandler.isPrivate = true; + //Set the Image folder path + global.setImageFolder(global.getSubdirectory("Images")); + //Check if database exists + File database = global.getDatabasePath(SQLHandler.DBNAME); + if (!database.exists()) { + sqlHandler.getReadableDatabase(); + if (copyDatabase(this)) { + Toast.makeText(this, "Copy database success", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(this, "Copy database failed", Toast.LENGTH_SHORT).show(); + return; + } + } else + sqlHandler.getReadableDatabase(); + + //Create image folder + createImageFolder(); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + FloatingActionButton fab = findViewById(R.id.fab); + fab.setOnClickListener(view -> Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) + .setAction("Action", null).show()); + + DrawerLayout drawer = findViewById(R.id.drawer_layout); + ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( + this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); + //noinspection deprecation + drawer.setDrawerListener(toggle); + toggle.syncState(); + + navigationView = findViewById(R.id.nav_view); + + navigationView.setNavigationItemSelectedListener(this); + wv = findViewById(R.id.webview); + WebSettings settings = wv.getSettings(); + wv.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); + settings.setJavaScriptEnabled(true); + //noinspection deprecation + settings.setRenderPriority(WebSettings.RenderPriority.HIGH); + settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); + settings.setDomStorageEnabled(true); + settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); + settings.setUseWideViewPort(true); + settings.setSaveFormData(true); + settings.setAllowFileAccess(true); + //noinspection deprecation + settings.setEnableSmoothTransition(true); + settings.setLoadWithOverviewMode(true); + wv.addJavascriptInterface(new ClientAndroidInterface(this), "Android"); + + //Register for context acquire_menu + registerForContextMenu(wv); - navigationView.setNavigationItemSelectedListener(this); - wv = findViewById(R.id.webview); - WebSettings settings = wv.getSettings(); - wv.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); - settings.setJavaScriptEnabled(true); - //noinspection deprecation - settings.setRenderPriority(WebSettings.RenderPriority.HIGH); - settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); - settings.setDomStorageEnabled(true); - settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); - settings.setUseWideViewPort(true); - settings.setSaveFormData(true); - settings.setAllowFileAccess(true); - //noinspection deprecation - settings.setEnableSmoothTransition(true); - settings.setLoadWithOverviewMode(true); - wv.addJavascriptInterface(new ClientAndroidInterface(this), "Android"); - - //Register for context acquire_menu - registerForContextMenu(wv); - - wv.loadUrl("file:///android_asset/pages/Home.html"); - wv.setWebViewClient(new MyWebViewClient(MainActivity.this)); - - wv.setWebChromeClient(new WebChromeClient() { - @Override - public void onReceivedTitle(WebView view, String title) { - super.onReceivedTitle(view, title); - //noinspection ConstantConditions - getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE); - getSupportActionBar().setSubtitle(title); + wv.loadUrl("file:///android_asset/pages/Home.html"); + wv.setWebViewClient(new MyWebViewClient(MainActivity.this)); + + wv.setWebChromeClient(new WebChromeClient() { + @Override + public void onReceivedTitle(WebView view, String title) { + super.onReceivedTitle(view, title); + //noinspection ConstantConditions + getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE); + getSupportActionBar().setSubtitle(title); + } + }); + NavigationView navigationView = findViewById(R.id.nav_view); + View headerview = navigationView.getHeaderView(0); + Login = headerview.findViewById(R.id.tvLogin); + OfficerName = headerview.findViewById(R.id.tvOfficerName); + + Login.setOnClickListener(v -> { + wv.loadUrl("file:///android_asset/pages/Login.html?s=3"); + drawer.closeDrawer(GravityCompat.START); + SetLoggedIn(); + }); + ca = new ClientAndroidInterface(this); + if (ca.isMasterDataAvailable() > 0) { + loadLanguages(); } - }); - NavigationView navigationView = findViewById(R.id.nav_view); - View headerview = navigationView.getHeaderView(0); - Login = headerview.findViewById(R.id.tvLogin); - OfficerName = headerview.findViewById(R.id.tvOfficerName); - - Login.setOnClickListener(v -> { - wv.loadUrl("file:///android_asset/pages/Login.html?s=3"); - drawer.closeDrawer(GravityCompat.START); - SetLoggedIn(); - }); - ca = new ClientAndroidInterface(this); - if (ca.isMasterDataAvailable() > 0) { - loadLanguages(); - } - - - navigationView.setCheckedItem(R.id.nav_home); - - if (checkRequirements()) { - onAllRequirementsMet(); + navigationView.setCheckedItem(R.id.nav_home); + if (checkRequirements()) { + onAllRequirementsMet(); + } + setVisibilityOfPaymentMenu(); + } catch (Exception e) { + Sentry.captureException(e); } - - setVisibilityOfPaymentMenu(); } private void setVisibilityOfPaymentMenu() { @@ -508,6 +512,7 @@ public void ShowEnrolmentOfficerDialog() { //ShowDialogTex(); } } catch (JSONException e) { + Sentry.captureException(e); e.printStackTrace(); } }) @@ -567,6 +572,7 @@ public void ShowDialogTex2() { ConfirmDialogPage((f.getName())); } } catch (Exception e) { + Sentry.captureException(e); e.getMessage(); } }) diff --git a/app/src/main/java/org/openimis/imispolicies/domain/entity/Family.java b/app/src/main/java/org/openimis/imispolicies/domain/entity/Family.java index cea15a84..09f85d2a 100644 --- a/app/src/main/java/org/openimis/imispolicies/domain/entity/Family.java +++ b/app/src/main/java/org/openimis/imispolicies/domain/entity/Family.java @@ -207,7 +207,7 @@ public List getMembers() { @Nullable public List getPolicies (){ return policies; } - public static final Creator CREATOR = new Creator<>() { + public static final Creator CREATOR = new Creator() { @Override public Family createFromParcel(Parcel in) { return new Family(in); @@ -259,7 +259,7 @@ public String getLanguage() { return language; } - public static final Creator CREATOR = new Creator<>() { + public static final Creator CREATOR = new Creator() { @Override public SMS createFromParcel(Parcel in) { return new SMS(in); @@ -634,7 +634,7 @@ public String toString() { return getLastName() + " " + getOtherNames() + " [" + getChfId() + "]"; } - public static final Creator CREATOR = new Creator<>() { + public static final Creator CREATOR = new Creator() { @Override public Member createFromParcel(Parcel in) { return new Member(in); @@ -855,7 +855,7 @@ public List getPremiums() { return premiums; } - public static final Creator CREATOR = new Creator<>() { + public static final Creator CREATOR = new Creator() { @Override public Policy createFromParcel(Parcel in) { return new Policy(in); @@ -1006,7 +1006,7 @@ public boolean isOffline() { return isOffline; } - public static final Creator CREATOR = new Creator<>() { + public static final Creator CREATOR = new Creator() { @Override public Premium createFromParcel(Parcel in) { return new Premium(in); diff --git a/app/src/main/java/org/openimis/imispolicies/domain/entity/FeedbackRequest.java b/app/src/main/java/org/openimis/imispolicies/domain/entity/FeedbackRequest.java index be1ae41c..f1afdf10 100644 --- a/app/src/main/java/org/openimis/imispolicies/domain/entity/FeedbackRequest.java +++ b/app/src/main/java/org/openimis/imispolicies/domain/entity/FeedbackRequest.java @@ -177,7 +177,7 @@ public String getPhone() { return Objects.requireNonNullElse(phone, ""); } - public static final Creator CREATOR = new Creator<>() { + public static final Creator CREATOR = new Creator() { @Override public FeedbackRequest createFromParcel(Parcel in) { return new FeedbackRequest(in); diff --git a/app/src/main/java/org/openimis/imispolicies/domain/entity/Insuree.java b/app/src/main/java/org/openimis/imispolicies/domain/entity/Insuree.java index 7a243cc4..6333dc44 100644 --- a/app/src/main/java/org/openimis/imispolicies/domain/entity/Insuree.java +++ b/app/src/main/java/org/openimis/imispolicies/domain/entity/Insuree.java @@ -105,7 +105,7 @@ public List getPolicies() { return policies; } - public static final Creator CREATOR = new Creator<>() { + public static final Creator CREATOR = new Creator() { @Override public Insuree createFromParcel(Parcel in) { return new Insuree(in); diff --git a/app/src/main/java/org/openimis/imispolicies/domain/entity/PendingFeedback.java b/app/src/main/java/org/openimis/imispolicies/domain/entity/PendingFeedback.java index 5837e088..7f3287ea 100644 --- a/app/src/main/java/org/openimis/imispolicies/domain/entity/PendingFeedback.java +++ b/app/src/main/java/org/openimis/imispolicies/domain/entity/PendingFeedback.java @@ -93,7 +93,7 @@ public int getAssessment() { return assessment; } - public static final Creator CREATOR = new Creator<>() { + public static final Creator CREATOR = new Creator() { @Override public PendingFeedback createFromParcel(Parcel in) { return new PendingFeedback(in); diff --git a/app/src/main/java/org/openimis/imispolicies/domain/entity/Policy.java b/app/src/main/java/org/openimis/imispolicies/domain/entity/Policy.java index 7ce14488..43f0399e 100644 --- a/app/src/main/java/org/openimis/imispolicies/domain/entity/Policy.java +++ b/app/src/main/java/org/openimis/imispolicies/domain/entity/Policy.java @@ -425,7 +425,7 @@ public enum Status { IDLE, ACTIVE, SUSPENDED, EXPIRED, READY } - public static final Creator CREATOR = new Creator<>() { + public static final Creator CREATOR = new Creator() { @Override public Policy createFromParcel(Parcel in) { return new Policy(in); diff --git a/app/src/main/java/org/openimis/imispolicies/domain/entity/PolicyRenewal.java b/app/src/main/java/org/openimis/imispolicies/domain/entity/PolicyRenewal.java index 63ef92c4..a438fcfa 100644 --- a/app/src/main/java/org/openimis/imispolicies/domain/entity/PolicyRenewal.java +++ b/app/src/main/java/org/openimis/imispolicies/domain/entity/PolicyRenewal.java @@ -164,7 +164,7 @@ public String getPhone() { return phone; } - public static final Creator CREATOR = new Creator<>() { + public static final Creator CREATOR = new Creator() { @Override public PolicyRenewal createFromParcel(Parcel in) { return new PolicyRenewal(in); diff --git a/app/src/main/java/org/openimis/imispolicies/domain/entity/PolicyRenewalRequest.java b/app/src/main/java/org/openimis/imispolicies/domain/entity/PolicyRenewalRequest.java index e4408208..a1b6ce45 100644 --- a/app/src/main/java/org/openimis/imispolicies/domain/entity/PolicyRenewalRequest.java +++ b/app/src/main/java/org/openimis/imispolicies/domain/entity/PolicyRenewalRequest.java @@ -142,7 +142,7 @@ public int describeContents() { return 0; } - public static final Creator CREATOR = new Creator<>() { + public static final Creator CREATOR = new Creator() { @Override public PolicyRenewalRequest createFromParcel(Parcel in) { return new PolicyRenewalRequest(in);