Skip to content

Commit 3803d6b

Browse files
committed
Merge branch 'release-2.5.6'
* release-2.5.6: Update version code and name for release 2.5.6 Translations: Squashed commit of the following: strings: add a proper set of duration names for future use CONTRIBUTING: translations PRs should be done to the translation branch circle.yml: disable coverage report for now Make PIN timeout actually work Make app lock timeout configurable PinLockActivity: make fingerprint work with the new pin verification model Privacy prefs: require PIN confirmation before PIN delete/modify StartActivity: close app if PIN input is canceled PinLockActivity: make the back button undo input if possible PinLockActivity: make PIN verification a result call as well Display that AEMPS database is from Spain. Update kotlin version to 1.2.50 Update gradle plugin to 3.1.3
2 parents 770d046 + c276ff9 commit 3803d6b

27 files changed

+938
-132
lines changed

CONTRIBUTING.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ Non-code contributions are also welcome!. You can do a lot of things:
3838

3939
> Join the BETA channel: [click here!](https://play.google.com/apps/testing/es.usc.citius.servando.calendula)
4040
41-
4241
### Help with app translations
42+
4343
Contributing translations is now easier than ever! Just join us at POEditor using [this link](https://poeditor.com/join/project/kIdyqFodDn) and start translating Calendula to one of the existing languages, or suggest a new one. **This is the recommended method for translations**.
4444
You can also contribute with better translations for particular words or sentences.
4545

4646
Alternatively, you can contribute translations via pull request:
4747

48-
* Add a new folder named `values-{LANG}/` at `Calendula/src/main/res/`
49-
* Translate the `strings_translatable.xml` file from `values` to your desired language.
50-
* Send a pull request.
48+
* Add a new folder named `values-{LANG}/` at `Calendula/src/main/res/`.
49+
* Translate the `strings_translatable.xml` file from `Calendula/src/main/res/values` to your desired language.
50+
* Send a pull request to the `translations` branch.
5151

5252
You can also improve an existing `strings_translatable.xml` file and make a PR with that!

Calendula/build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ android {
7777
defaultConfig {
7878
minSdkVersion 16
7979
targetSdkVersion 25
80-
versionCode 36
81-
versionName "2.5.5"
80+
versionCode 37
81+
versionName "2.5.6"
8282
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
8383
applicationId "es.usc.citius.servando.calendula"
8484
multiDexEnabled true

Calendula/src/main/java/es/usc/citius/servando/calendula/CalendulaActivity.java

+18
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import android.annotation.SuppressLint;
2222
import android.app.AlertDialog;
2323
import android.content.DialogInterface;
24+
import android.content.Intent;
2425
import android.content.pm.PackageManager;
2526
import android.graphics.Color;
2627
import android.graphics.drawable.Drawable;
@@ -38,6 +39,11 @@
3839
import java.util.HashMap;
3940
import java.util.Map;
4041

42+
import es.usc.citius.servando.calendula.activities.StartActivity;
43+
import es.usc.citius.servando.calendula.pinlock.PINManager;
44+
import es.usc.citius.servando.calendula.pinlock.PinLockActivity;
45+
import es.usc.citius.servando.calendula.pinlock.UnlockStateManager;
46+
import es.usc.citius.servando.calendula.util.LogUtil;
4147
import es.usc.citius.servando.calendula.util.PermissionUtils;
4248
import es.usc.citius.servando.calendula.util.ScreenUtils;
4349

@@ -177,4 +183,16 @@ public void onClick(DialogInterface dialog, int id) {
177183
alert.show();
178184
}
179185

186+
@Override
187+
protected void onResume() {
188+
super.onResume();
189+
if (PINManager.isPINSet() && !UnlockStateManager.getInstance().isUnlocked() && !(this instanceof PinLockActivity)) {
190+
// If we get unlock timeout on resume, we'll call StartActivity to ask for a PIN
191+
LogUtil.d("CalendulaActivity", "Unlock has expired");
192+
final Intent i = new Intent(this, StartActivity.class);
193+
i.putExtra(StartActivity.EXTRA_RETURN_TO_PREVIOUS, true);
194+
//i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
195+
startActivity(i);
196+
}
197+
}
180198
}

Calendula/src/main/java/es/usc/citius/servando/calendula/activities/StartActivity.java

-44
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Calendula - An assistant for personal medication management.
3+
* Copyright (C) 2014-2018 CiTIUS - University of Santiago de Compostela
4+
*
5+
* Calendula is free software; you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation; either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this software. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
package es.usc.citius.servando.calendula.activities
20+
21+
22+
import android.app.Activity
23+
import android.content.Intent
24+
import android.os.Bundle
25+
26+
import es.usc.citius.servando.calendula.HomePagerActivity
27+
import es.usc.citius.servando.calendula.pinlock.PINManager
28+
import es.usc.citius.servando.calendula.pinlock.PinLockActivity
29+
import es.usc.citius.servando.calendula.pinlock.UnlockStateManager
30+
31+
32+
class StartActivity : Activity() {
33+
34+
companion object {
35+
const val EXTRA_RETURN_TO_PREVIOUS = "StartActivity.extras.return_to_previous"
36+
}
37+
38+
override fun onCreate(savedInstanceState: Bundle?) {
39+
super.onCreate(savedInstanceState)
40+
verifyUnlockAndLaunch()
41+
}
42+
43+
private fun verifyUnlockAndLaunch() {
44+
if (PINManager.isPINSet() && !UnlockStateManager.getInstance().isUnlocked) {
45+
val i = Intent(this, PinLockActivity::class.java)
46+
i.action = PinLockActivity.ACTION_VERIFY_PIN
47+
startActivityForResult(i, PinLockActivity.REQUEST_VERIFY)
48+
} else {
49+
val returnToPrevious = intent.getBooleanExtra(EXTRA_RETURN_TO_PREVIOUS,false)
50+
if (!returnToPrevious) {
51+
// if "return to previous" is specified, just finish this activity to go back in the stack
52+
startActivity(Intent(this, HomePagerActivity::class.java))
53+
}
54+
finish()
55+
}
56+
}
57+
58+
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
59+
super.onActivityResult(requestCode, resultCode, data)
60+
if (requestCode == PinLockActivity.REQUEST_VERIFY) {
61+
if (resultCode == Activity.RESULT_CANCELED) {
62+
finish()
63+
} else {
64+
verifyUnlockAndLaunch()
65+
}
66+
}
67+
}
68+
}

Calendula/src/main/java/es/usc/citius/servando/calendula/pinlock/PinLockActivity.java

+64-30
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,12 @@
5757

5858
public class PinLockActivity extends CalendulaActivity {
5959

60-
public static final String EXTRA_PIN = "PinLockActivity.result";
60+
public static final String EXTRA_NEW_PIN = "PinLockActivity.newpin.result";
61+
public static final String EXTRA_VERIFY_PIN_RESULT = "PinLockActivity.verify.result";
62+
public static final String ACTION_NEW_PIN = "PinLockActivity.action.new_pin";
63+
public static final String ACTION_VERIFY_PIN = "PinLockActivity.action.verify_pin";
6164
public static final int REQUEST_PIN = 15765;
65+
public static final int REQUEST_VERIFY = 15766;
6266
private static final int PIN_SIZE = 4;
6367

6468
private static final String TAG = "PinLockActivity";
@@ -125,6 +129,7 @@ void launchFingerprintAuth() {
125129
fpHelper.startAuthentication(new LoginFPCallbackAdapter(this, fingerprintDialog));
126130
}
127131

132+
@RequiresApi(Build.VERSION_CODES.M)
128133
private void showFingerprintDialog() {
129134
fingerprintDialog = new MaterialDialog.Builder(this)
130135
.icon(IconUtils.icon(this, CommunityMaterial.Icon.cmd_fingerprint, R.color.android_blue_dark, 48))
@@ -148,6 +153,15 @@ protected void onCreate(Bundle savedInstanceState) {
148153
setContentView(R.layout.activity_pin_lock);
149154
ButterKnife.bind(this);
150155

156+
if (!isCalledForResult()) {
157+
throw new IllegalStateException("This activity can only be called for result");
158+
}
159+
160+
final String action = getIntent().getAction();
161+
if (action == null) {
162+
throw new IllegalArgumentException("Action required!");
163+
}
164+
151165
pinInputStateManager = new PinInputStateManager(PIN_SIZE);
152166
indicatorDotView.setSize(PIN_SIZE);
153167

@@ -176,23 +190,25 @@ public void onPinChange(String currentPin, int pinLength) {
176190
android.graphics.PorterDuff.Mode.MULTIPLY);
177191

178192
setupStatusBar(ContextCompat.getColor(this, R.color.android_blue_dark));
179-
if (isCalledForResult()) {
180-
// if called for result we will return a PIN
181-
pinInputStateManager.setPinCompleteListener(new NewPinListener());
182-
promptMessage.setText(R.string.text_pinlock_new_prompt);
183-
setupToolbar(null, ContextCompat.getColor(this, R.color.android_blue_dark));
184-
} else {
185-
// if not called for result, we will authorize access
186-
pinInputStateManager.setPinCompleteListener(new AuthorizeAccessListener());
187-
errorMessage.setVisibility(View.GONE); // indicator shows error
188-
promptMessage.setText(R.string.text_pinlock_auth_prompt);
189-
footer.setVisibility(View.VISIBLE);
190-
toolbar = (android.support.v7.widget.Toolbar) findViewById(R.id.toolbar);
191-
toolbar.setVisibility(View.GONE);
192-
193-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
194-
setupFingerprintAuth();
195-
}
193+
194+
switch (action) {
195+
case ACTION_NEW_PIN:
196+
pinInputStateManager.setPinCompleteListener(new NewPinListener());
197+
promptMessage.setText(R.string.text_pinlock_new_prompt);
198+
setupToolbar(null, ContextCompat.getColor(this, R.color.android_blue_dark));
199+
break;
200+
case ACTION_VERIFY_PIN:
201+
pinInputStateManager.setPinCompleteListener(new AuthorizeAccessListener());
202+
errorMessage.setVisibility(View.GONE); // indicator shows error
203+
promptMessage.setText(R.string.text_pinlock_auth_prompt);
204+
footer.setVisibility(View.VISIBLE);
205+
toolbar = (android.support.v7.widget.Toolbar) findViewById(R.id.toolbar);
206+
toolbar.setVisibility(View.GONE);
207+
208+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
209+
setupFingerprintAuth();
210+
}
211+
break;
196212
}
197213
}
198214

@@ -233,6 +249,14 @@ private boolean isCalledForResult() {
233249
return calledForResult;
234250
}
235251

252+
@Override
253+
public void onBackPressed() {
254+
// delete a number if possible, else go back
255+
if (!pinInputStateManager.delete()) {
256+
super.onBackPressed();
257+
}
258+
}
259+
236260
private class NewPinListener implements PinInputStateManager.PinInputCompleteListener {
237261

238262
private String firstPin;
@@ -256,7 +280,7 @@ public void run() {
256280
if (pin.equals(firstPin)) {
257281
// everything's fine, return the PIN
258282
Intent returnIntent = new Intent();
259-
returnIntent.putExtra(EXTRA_PIN, pin);
283+
returnIntent.putExtra(EXTRA_NEW_PIN, pin);
260284
setResult(Activity.RESULT_OK, returnIntent);
261285
LogUtil.d(TAG, "PIN input correct");
262286
finish();
@@ -291,11 +315,8 @@ public void onComplete(String pin) {
291315
boolean checkPIN = PINManager.checkPIN(pin);
292316
if (checkPIN) {
293317
//PIN is correct, forward to main activity
294-
LogUtil.d(TAG, "PIN is correct, setting unlock and forwarding to main activity");
295-
UnlockStateManager.getInstance().unlock();
296-
Intent i = new Intent(PinLockActivity.this, StartActivity.class);
297-
startActivity(i);
298-
finish();
318+
LogUtil.d(TAG, "PIN is correct");
319+
returnVerifiedResult();
299320
} else {
300321
new Handler().postDelayed(new Runnable() {
301322
@Override
@@ -314,13 +335,21 @@ public void run() {
314335

315336
}
316337

338+
private void returnVerifiedResult() {
339+
Intent returnIntent = new Intent();
340+
returnIntent.putExtra(EXTRA_VERIFY_PIN_RESULT, true);
341+
setResult(Activity.RESULT_OK, returnIntent);
342+
UnlockStateManager.getInstance().unlock();
343+
finish();
344+
}
345+
317346

318347
private static class LoginFPCallbackAdapter implements FingerprintHelper.FingerprintCallbackAdapter {
319348

320-
private Activity activity;
349+
private PinLockActivity activity;
321350
private MaterialDialog fingerprintDialog;
322351

323-
LoginFPCallbackAdapter(Activity activity, MaterialDialog fingerprintDialog) {
352+
LoginFPCallbackAdapter(PinLockActivity activity, MaterialDialog fingerprintDialog) {
324353
this.activity = activity;
325354
this.fingerprintDialog = fingerprintDialog;
326355
}
@@ -344,10 +373,15 @@ public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult re
344373
fingerprintDialog.setContent(R.string.fingerprint_unlock_dialog_successful_message);
345374
fingerprintDialog.setIcon(IconUtils.icon(activity, GoogleMaterial.Icon.gmd_check_circle, R.color.android_green, 48));
346375
}
347-
UnlockStateManager.getInstance().unlock();
348-
Intent i = new Intent(activity, StartActivity.class);
349-
activity.startActivity(i);
350-
activity.finish();
376+
377+
switch (activity.getIntent().getAction()) {
378+
case ACTION_NEW_PIN:
379+
throw new IllegalArgumentException("No fingerprint allowed for new pin recording");
380+
case ACTION_VERIFY_PIN:
381+
activity.returnVerifiedResult();
382+
break;
383+
}
384+
351385
}
352386
}
353387
}

Calendula/src/main/java/es/usc/citius/servando/calendula/pinlock/UnlockStateManager.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@
2222
import org.joda.time.Duration;
2323

2424
import es.usc.citius.servando.calendula.util.LogUtil;
25+
import es.usc.citius.servando.calendula.util.PreferenceKeys;
26+
import es.usc.citius.servando.calendula.util.PreferenceUtils;
2527

2628
/**
2729
* Utility class to handle unlock state (for PIN lock)
2830
*/
2931
public class UnlockStateManager {
3032

31-
private final static Duration MAX_UNLOCK_DURATION = Duration.standardMinutes(5);
33+
private final static String DEFAULT_UNLOCK_DURATION_SECONDS = "120";
3234
private final static String TAG = "UnlockStateManager";
3335
private static UnlockStateManager theInstance;
3436
private DateTime unlockTimestamp;
@@ -76,7 +78,11 @@ public boolean isUnlocked() {
7678
LogUtil.v(TAG, "isUnlocked() called");
7779
if (unlockTimestamp != null) {
7880
Duration diff = new Duration(unlockTimestamp, DateTime.now());
79-
if (diff.compareTo(MAX_UNLOCK_DURATION) <= 0) {
81+
// need to be a string to use a ListPreference
82+
final String maxDurationStr = PreferenceUtils.getString(PreferenceKeys.UNLOCK_PIN_TIMEOUT, DEFAULT_UNLOCK_DURATION_SECONDS);
83+
Duration maxDuration = Duration.standardSeconds(Integer.parseInt(maxDurationStr));
84+
LogUtil.d(TAG, "Max unlock duration is " + maxDuration.toString());
85+
if (diff.compareTo(maxDuration) <= 0) {
8086
LogUtil.d(TAG, "isUnlocked() returned: " + true);
8187
return true;
8288
} else {

Calendula/src/main/java/es/usc/citius/servando/calendula/settings/privacy/PrivacyPrefsContract.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@ interface PrivacyPrefsContract {
2828
interface View : IView {
2929

3030
fun recordPIN()
31+
fun verifyPIN(requestCode: Int)
3132
fun showPINOptions()
3233
fun showConfirmDeletePinChoice()
3334
fun setPINPrefText(@StringRes pinPrefText: Int)
3435
fun setFingerprintPrefEnabled(enabled: Boolean)
36+
fun setPINDependentPrefsEnabled(enabled: Boolean)
3537
fun showEnableFingerprintDialog()
36-
3738
}
3839

3940
interface Presenter : IPresenter<View> {

0 commit comments

Comments
 (0)