Skip to content

Commit

Permalink
Add support for Android 12 and for requesting SMS permission (#262)
Browse files Browse the repository at this point in the history
Co-authored-by: Joshua Kuestersteffen <[email protected]>
  • Loading branch information
latin-panda and jkuester authored May 9, 2022
1 parent 88a980c commit e642664
Show file tree
Hide file tree
Showing 31 changed files with 1,346 additions and 249 deletions.
24 changes: 11 additions & 13 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.1'
classpath 'com.android.tools.build:gradle:7.1.3'
classpath 'com.github.spotbugs.snom:spotbugs-gradle-plugin:5.0.5'
}
}
Expand Down Expand Up @@ -42,8 +42,8 @@ task pmd(type: Pmd) {
exclude '**/**.mp3'
exclude '**/**.bats'
dependencies {
pmd 'net.sourceforge.pmd:pmd-java:6.36.0'
pmd 'net.sourceforge.pmd:pmd-xml:6.36.0'
pmd 'net.sourceforge.pmd:pmd-java:6.44.0'
pmd 'net.sourceforge.pmd:pmd-xml:6.44.0'
}
}

Expand Down Expand Up @@ -95,7 +95,7 @@ def getVersionName = {
}

android {
compileSdkVersion 30
compileSdkVersion 31
buildToolsVersion '30.0.3'
packagingOptions {
exclude 'META-INF/LICENSE'
Expand All @@ -104,7 +104,7 @@ android {

defaultConfig {
//noinspection OldTargetApi
targetSdkVersion 30
targetSdkVersion 31
minSdkVersion 21 // Android 5.0
versionCode getVersionCode()
versionName getVersionName()
Expand Down Expand Up @@ -394,21 +394,19 @@ android {

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Latest version of androidx.core requires Android 12+
// noinspection GradleDependency
implementation 'androidx.core:core:1.6.0'
implementation 'androidx.activity:activity:1.3.1'
implementation 'androidx.fragment:fragment:1.3.6'
implementation 'androidx.core:core:1.7.0'
implementation 'androidx.activity:activity:1.4.0'
implementation 'androidx.fragment:fragment:1.4.1'
compileOnly 'com.github.spotbugs:spotbugs-annotations:4.5.3'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.mockito:mockito-inline:4.0.0'
testImplementation 'com.google.android:android-test:4.1.1.4'
testImplementation 'org.robolectric:robolectric:4.7'
testImplementation 'androidx.test.espresso:espresso-core:3.5.0-alpha03'
testImplementation 'androidx.test.espresso:espresso-intents:3.5.0-alpha03'
testImplementation 'androidx.test.espresso:espresso-core:3.5.0-alpha05'
testImplementation 'androidx.test.espresso:espresso-intents:3.5.0-alpha05'
testImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-web:3.5.0-alpha03'
androidTestImplementation 'androidx.test.espresso:espresso-web:3.5.0-alpha05'
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test:rules:1.4.0'
androidTestImplementation 'androidx.test:core:1.4.0'
Expand Down
2 changes: 1 addition & 1 deletion config/pmd.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<exclude name="AvoidDuplicateLiterals"/>
<exclude name="AvoidDuplicateLiterals"/>
<exclude name="AvoidFieldNameMatchingMethodName"/>
<exclude name="MissingBreakInSwitch"/>
<exclude name="ImplicitSwitchFallThrough"/>
<exclude name="ConstructorCallsOverridableMethod"/>
<exclude name="NullAssignment"/>
<exclude name="DataflowAnomalyAnalysis"/>
Expand Down
9 changes: 8 additions & 1 deletion src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@
<!-- READ_EXTERNAL_STORAGE required if users want to include photos from their phone -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

<!-- SEND_SMS required if users want to send reports as SMS -->
<uses-permission android:name="android.permission.SEND_SMS"/>

<application android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:allowBackup="false"
android:fullBackupContent="@xml/backup_rules_sdk_30_and_lower"
android:dataExtractionRules="@xml/backup_rules"
android:largeHeap="true"
tools:ignore="GoogleAppIndexingWarning,LockedOrientationActivity,Instantiatable">
tools:ignore="LockedOrientationActivity,UnusedAttribute">
<activity android:name="StartupActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
Expand All @@ -48,6 +53,8 @@
android:screenOrientation="portrait"/>
<activity android:name="RequestStoragePermissionActivity"
android:screenOrientation="portrait"/>
<activity android:name="RequestSendSmsPermissionActivity"
android:screenOrientation="portrait"/>
<activity android:name="AppUrlIntentActivity"
android:launchMode="singleInstance"
android:exported="true">
Expand Down
47 changes: 0 additions & 47 deletions src/main/java/medic/android/ActivityBackgroundTask.java

This file was deleted.

17 changes: 9 additions & 8 deletions src/main/java/org/medicmobile/webapp/mobile/Alert.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@

import android.content.Context;
import android.media.MediaPlayer;
import android.os.Vibrator;

import org.medicmobile.webapp.mobile.util.Vibrator;

public class Alert {
private final MediaPlayer m;
private final Vibrator v;
private final MediaPlayer mediaPlayer;
private final Vibrator vibrator;

public Alert(Context ctx) {
m = MediaPlayer.create(ctx, R.raw.sound_alert);
v = (Vibrator) ctx.getSystemService(Context.VIBRATOR_SERVICE);
public Alert(Context context) {
mediaPlayer = MediaPlayer.create(context, R.raw.sound_alert);
vibrator = Vibrator.createInstance(context);
}

public void trigger() {
if(v != null) v.vibrate(1500L);
m.start();
vibrator.vibrate(1500L);
mediaPlayer.start();
}
}
66 changes: 38 additions & 28 deletions src/main/java/org/medicmobile/webapp/mobile/AppUrlVerifier.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,43 @@
package org.medicmobile.webapp.mobile;

import java.io.IOException;
import java.net.MalformedURLException;
import org.json.JSONException;
import org.json.JSONObject;
import static org.medicmobile.webapp.mobile.MedicLog.trace;
import static org.medicmobile.webapp.mobile.R.string.errAppUrl_apiNotReady;
import static org.medicmobile.webapp.mobile.R.string.errAppUrl_appNotFound;
import static org.medicmobile.webapp.mobile.R.string.errAppUrl_serverNotFound;
import static org.medicmobile.webapp.mobile.R.string.errInvalidUrl;
import static org.medicmobile.webapp.mobile.SimpleJsonClient2.redactUrl;

public class AppUrlVerifier {
import org.json.JSONException;
import org.json.JSONObject;
import org.medicmobile.webapp.mobile.AppUrlVerifier.AppUrlVerification;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.concurrent.Callable;

public class AppUrlVerifier implements Callable<AppUrlVerification> {

private final SimpleJsonClient2 jsonClient;
private final String appUrl;

AppUrlVerifier(SimpleJsonClient2 jsonClient, String appUrl) {
if (Utils.isDebug() && (appUrl == null || appUrl.trim().isEmpty())) {
throw new RuntimeException("AppUrlVerifier :: Cannot verify APP URL because it is not defined.");
}

AppUrlVerifier(SimpleJsonClient2 jsonClient) {
this.jsonClient = jsonClient;
this.appUrl = appUrl;
}

public AppUrlVerifier() {
this(new SimpleJsonClient2());
public AppUrlVerifier(String appUrl) {
this(new SimpleJsonClient2(), appUrl);
}

/**
* Verify the string passed is a valid CHT-Core URL.
*/
public AppUrlVerification verify(String appUrl) {
appUrl = clean(appUrl);
public AppUrlVerification call() {
String appUrl = clean(this.appUrl);

try {
JSONObject json = jsonClient.get(appUrl + "/setup/poll");
Expand Down Expand Up @@ -57,33 +67,33 @@ public AppUrlVerification verify(String appUrl) {
* Clean-up the URL passed, removing leading and trailing spaces, and trailing "/" char
* that the user may input by mistake.
*/
protected String clean(String appUrl) {
public static String clean(String appUrl) {
appUrl = appUrl.trim();
if (appUrl.endsWith("/")) {
return appUrl.substring(0, appUrl.length()-1);
}
return appUrl;
}
}

@SuppressWarnings("PMD.ShortMethodName")
class AppUrlVerification {
public final String appUrl;
public final boolean isOk;
public final int failure;
@SuppressWarnings("PMD.ShortMethodName")
public static class AppUrlVerification {
public final String appUrl;
public final boolean isOk;
public final int failure;

private AppUrlVerification(String appUrl, boolean isOk, int failure) {
this.appUrl = appUrl;
this.isOk = isOk;
this.failure = failure;
}
private AppUrlVerification(String appUrl, boolean isOk, int failure) {
this.appUrl = appUrl;
this.isOk = isOk;
this.failure = failure;
}

//> FACTORIES
public static AppUrlVerification ok(String appUrl) {
return new AppUrlVerification(appUrl, true, 0);
}
//> FACTORIES
public static AppUrlVerification ok(String appUrl) {
return new AppUrlVerification(appUrl, true, 0);
}

public static AppUrlVerification failure(String appUrl, int failure) {
return new AppUrlVerification(appUrl, false, failure);
public static AppUrlVerification failure(String appUrl, int failure) {
return new AppUrlVerification(appUrl, false, failure);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void onReceiveValue(String result) {
this.chtExternalAppHandler = new ChtExternalAppHandler(this);

try {
this.smsSender = new SmsSender(this);
this.smsSender = SmsSender.createInstance(this);
} catch(Exception ex) {
error(ex, "Failed to create SmsSender.");
}
Expand Down Expand Up @@ -205,6 +205,9 @@ protected void onActivityResult(int requestCd, int resultCode, Intent intent) {
case ACCESS_LOCATION_PERMISSION:
processLocationPermissionResult(resultCode);
return;
case ACCESS_SEND_SMS_PERMISSION:
this.smsSender.resumeProcess(resultCode);
return;
default:
trace(this, "onActivityResult() :: no handling for requestCode=%s", requestCode.name());
}
Expand Down Expand Up @@ -417,9 +420,10 @@ private void registerRetryConnectionBroadcastReceiver() {
public enum RequestCode {
ACCESS_LOCATION_PERMISSION(100),
ACCESS_STORAGE_PERMISSION(101),
CHT_EXTERNAL_APP_ACTIVITY(102),
GRAB_MRDT_PHOTO_ACTIVITY(103),
FILE_PICKER_ACTIVITY(104);
ACCESS_SEND_SMS_PERMISSION(102),
CHT_EXTERNAL_APP_ACTIVITY(103),
GRAB_MRDT_PHOTO_ACTIVITY(104),
FILE_PICKER_ACTIVITY(105);

private final int requestCode;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public boolean sms_available() {
public void sms_send(String id, String destination, String content) throws Exception {
try {
// TODO we may need to do this on a background thread to avoid the browser UI from blocking while the SMS is being sent. Check.
smsSender.send(id, destination, content);
smsSender.send(new SmsSender.Sms(id, destination, content));
} catch(Exception ex) {
logException(ex);
throw ex;
Expand Down
Loading

0 comments on commit e642664

Please sign in to comment.