diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index cbf51d06..0e160141 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -16,6 +16,8 @@ jobs: runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 + - name: Set release version + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - name: Set up ruby uses: ruby/setup-ruby@v1 with: diff --git a/README.md b/README.md index 54e1e249..d4bf8ba6 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,21 @@ Medic Mobile Android App ======================== - - The medic-android application is a thin wrapper to load the [CHT Core Framework](https://github.com/medic/cht-core/) web application in a webview. This allows the application to be hardcoded to a specific CHT deployment and have a partner specific logo and display name. This app also provides some deeper integration with other android apps and native phone functions that are otherwise unavailable to webapps. # Release notes +## 0.7.0 + +### Changes + +- [feature] [medic-android#136](https://github.com/medic/medic-android/issues/136): Add UI for prominent disclosure when requesting location permissions. + +### Notes + +The text used in the new location permission request is in the Android wrapper app itself (`medic-android`), and translated differently than [CHT Core labels](https://docs.communityhealthtoolkit.org/core/overview/translations/). Any additions or modifications to translations in `medic-android` are done in the `strings.xml` files according to the [Android localization framework](https://developer.android.com/guide/topics/resources/localization). + + ## 0.6.0 ### Upgrade notes @@ -64,7 +73,7 @@ To add a new brand: 1. add `productFlavors { { ... } }` in `build.gradle` 1. add icons, strings etc. in `src/` -1. to enable automated deployments, add the `new_brand` to `.travis.yml` +1. to enable automated deployments, add the `new_brand` to `.github/workflows/publish.yml` # Releasing diff --git a/build.gradle b/build.gradle index 34f208a2..9986bc2c 100644 --- a/build.gradle +++ b/build.gradle @@ -36,11 +36,11 @@ def simprintsApiKey, simprintsModuleId, simprintsUserId def getVersionCode = { int versionCode = 1 - if(System.env.TRAVIS == 'true' && System.env.TRAVIS_TAG && System.env.TRAVIS_TAG.startsWith('v')) { - def versionParts = System.env.TRAVIS_TAG.split(/[^0-9]+/) + if(System.env.CI == 'true' && System.env.RELEASE_VERSION && System.env.RELEASE_VERSION.startsWith('v')) { + def versionParts = System.env.RELEASE_VERSION.split(/[^0-9]+/) if (versionParts.length != 4 && versionParts.length != 5) - throw new RuntimeException("Unexpected version number - should be of formatted as 'v1.2.3' or 'v1.2.3-alpha.4', but was: $System.env.TRAVIS_TAG") + throw new RuntimeException("Unexpected version number - should be of formatted as 'v1.2.3' or 'v1.2.3-alpha.4', but was: $System.env.RELEASE_VERSION") versionParts = versionParts.drop(1).collect { Integer.parseInt(it) } int alphaPart = versionParts.size() == 4 ? versionParts[3] : 99; @@ -56,7 +56,7 @@ def getVersionCode = { } def getVersionName = { - System.env.TRAVIS_TAG ?: 'SNAPSHOT' + System.env.RELEASE_VERSION ?: 'SNAPSHOT' } android { @@ -141,12 +141,14 @@ android { disable 'UnusedResources' // linter can't handle static imports, so just skip this test disable 'GradleDependency' // TODO update to latest support-v4 lib and re-enable this rule disable 'OldTargetApi' + disable 'MissingTranslation' + disable 'StringFormatCount' warningsAsErrors true xmlReport false - if(System.env.TRAVIS == 'true') { + if(System.env.CI == 'true') { abortOnError true htmlReport false textReport true @@ -303,7 +305,11 @@ android { abi { enable true reset() - include 'armeabi-v7a', 'arm64-v8a' + include( + 'armeabi-v7a', + 'arm64-v8a', + //'x86', //--> uncomment to be able to deploy the app in Android 10+ virtual devices + ) universalApk false } } diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 95735a51..670abcba 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -11,7 +11,7 @@ platform :android do end lane :deploy do |options| - version = ENV['TRAVIS_TAG'].empty? ? 'SNAPSHOT' : ENV['TRAVIS_TAG'] + version = ENV['RELEASE_VERSION'].empty? ? 'SNAPSHOT' : ENV['RELEASE_VERSION'] package_name = options[:flavor] == 'unbranded' ? "org.medicmobile.webapp.mobile" : "org.medicmobile.webapp.mobile.#{options[:flavor]}" supply( diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 5ad24305..002ab083 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -43,6 +43,8 @@ android:screenOrientation="portrait"/> + diff --git a/src/main/java/org/medicmobile/webapp/mobile/MrdtSupport.java b/src/main/java/org/medicmobile/webapp/mobile/MrdtSupport.java index 93c58499..b3553ec8 100644 --- a/src/main/java/org/medicmobile/webapp/mobile/MrdtSupport.java +++ b/src/main/java/org/medicmobile/webapp/mobile/MrdtSupport.java @@ -6,7 +6,7 @@ //import org.json.JSONException; -import static org.medicmobile.webapp.mobile.EmbeddedBrowserActivity.GRAB_MRDT_PHOTO; +import static org.medicmobile.webapp.mobile.EmbeddedBrowserActivity.GRAB_MRDT_PHOTO_ACTIVITY_REQUEST_CODE; import static org.medicmobile.webapp.mobile.JavascriptUtils.safeFormat; import static org.medicmobile.webapp.mobile.MedicLog.trace; import static org.medicmobile.webapp.mobile.MedicLog.warn; @@ -26,14 +26,14 @@ boolean isAppInstalled() { } void startVerify() { - ctx.startActivityForResult(verifyIntent(), GRAB_MRDT_PHOTO); + ctx.startActivityForResult(verifyIntent(), GRAB_MRDT_PHOTO_ACTIVITY_REQUEST_CODE); } String process(int requestCode, int resultCode, Intent i) { trace(this, "process() :: requestCode=%s", requestCode); switch(requestCode) { - case GRAB_MRDT_PHOTO: { + case GRAB_MRDT_PHOTO_ACTIVITY_REQUEST_CODE: { try { byte[] data = i.getByteArrayExtra("data"); String base64data = Base64.encodeToString(data, Base64.NO_WRAP); diff --git a/src/main/java/org/medicmobile/webapp/mobile/RequestPermissionActivity.java b/src/main/java/org/medicmobile/webapp/mobile/RequestPermissionActivity.java new file mode 100644 index 00000000..957224ff --- /dev/null +++ b/src/main/java/org/medicmobile/webapp/mobile/RequestPermissionActivity.java @@ -0,0 +1,43 @@ +package org.medicmobile.webapp.mobile; + +import android.os.Bundle; +import android.view.View; +import android.view.Window; +import android.widget.TextView; + +import static org.medicmobile.webapp.mobile.MedicLog.trace; + +/** + * Shows a confirmation view that displays a "prominent" disclosure about how + * the user geolocation data is used, asking to confirm whether to allow the app to + * access the location or not. + * + * If the user accepts, a request to the API to access the location is made by the main activity, + * but Android will show another confirmation dialog. If the user decline the first + * confirmation, the request to the API is omitted and the decision recorded to avoid + * requesting the same next time. + */ +public class RequestPermissionActivity extends LockableActivity { + + @Override public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(R.layout.request_permission); + String message = getResources().getString(R.string.locRequestMessage); + String appName = getResources().getString(R.string.app_name); + TextView field = (TextView) findViewById(R.id.locMessageText); + field.setText(String.format(message, appName)); + } + + public void onClickOk(View view) { + trace(this, "onClickOk() :: user accepted to share the location"); + setResult(RESULT_OK); + finish(); + } + + public void onClickNegative(View view) { + trace(this, ":: onClickNegative() :: user denied to share the location"); + setResult(RESULT_CANCELED); + finish(); + } +} diff --git a/src/main/java/org/medicmobile/webapp/mobile/SettingsStore.java b/src/main/java/org/medicmobile/webapp/mobile/SettingsStore.java index 48be77cd..41ac9ea3 100644 --- a/src/main/java/org/medicmobile/webapp/mobile/SettingsStore.java +++ b/src/main/java/org/medicmobile/webapp/mobile/SettingsStore.java @@ -45,13 +45,32 @@ void updateWithUnlockCode(String unlockCode) throws SettingsException { ed.putString("unlock-code", unlockCode); if(!ed.commit()) throw new SettingsException( - "Failed to save to SharedPreferences."); + "Failed to save 'unlock-code' to SharedPreferences."); } String get(String key) { return prefs.getString(key, null); } + /** + * Returns true if the user has denied to provide its geolocation data. + * The rejection is taken from the first view with the "prominent" disclosure + * about the location data, not from the native dialog displayed by Android. + */ + boolean hasUserDeniedGeolocation() { + return prefs.getBoolean("denied-geolocation", false); + } + + /** + * @see #hasUserDeniedGeolocation() + */ + void setUserDeniedGeolocation() throws SettingsException { + SharedPreferences.Editor ed = prefs.edit(); + ed.putBoolean("denied-geolocation", true); + if(!ed.commit()) throw new SettingsException( + "Failed to save 'denied-geolocation' to SharedPreferences."); + } + static SettingsStore in(Context ctx) { if(DEBUG) log("Loading settings for context %s...", ctx); diff --git a/src/main/res/drawable-hdpi/location_pin.png b/src/main/res/drawable-hdpi/location_pin.png new file mode 100644 index 00000000..0d1fd948 Binary files /dev/null and b/src/main/res/drawable-hdpi/location_pin.png differ diff --git a/src/main/res/drawable-mdpi/location_pin.png b/src/main/res/drawable-mdpi/location_pin.png new file mode 100644 index 00000000..94a038c8 Binary files /dev/null and b/src/main/res/drawable-mdpi/location_pin.png differ diff --git a/src/main/res/drawable-xhdpi/location_pin.png b/src/main/res/drawable-xhdpi/location_pin.png new file mode 100644 index 00000000..6dc7fd09 Binary files /dev/null and b/src/main/res/drawable-xhdpi/location_pin.png differ diff --git a/src/main/res/drawable-xxhdpi/location_pin.png b/src/main/res/drawable-xxhdpi/location_pin.png new file mode 100644 index 00000000..b74b4585 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/location_pin.png differ diff --git a/src/main/res/layout/request_permission.xml b/src/main/res/layout/request_permission.xml new file mode 100644 index 00000000..330e7265 --- /dev/null +++ b/src/main/res/layout/request_permission.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + +