more tweaks around SMS permission

Explicit "ask again" and "skip" buttons in alert showing rationale;
check/ask for permission before sending invitation via SMS; warn each
time SMS-enabled game is opened without permission but allow it to stay
open and if necessary send an invitation.
This commit is contained in:
Eric House 2017-01-07 08:38:48 -08:00
parent b898637666
commit 558a20f2db
9 changed files with 816 additions and 769 deletions

File diff suppressed because it is too large Load diff

View file

@ -125,7 +125,6 @@
<string name="key_nag_intervals">key_nag_intervals</string> <string name="key_nag_intervals">key_nag_intervals</string>
<string name="key_download_path">key_download_path</string> <string name="key_download_path">key_download_path</string>
<string name="key_got_langdict">key_got_langdict</string> <string name="key_got_langdict">key_got_langdict</string>
<string name="key_notagain_missing_perms">key_notagain_missing_perms</string>
<string name="key_xlations_locale">key_xlations_locale</string> <string name="key_xlations_locale">key_xlations_locale</string>
<string name="key_xlations_enabled">key_xlations_enabled</string> <string name="key_xlations_enabled">key_xlations_enabled</string>
<string name="key_invite_multi">key_invite_multi</string> <string name="key_invite_multi">key_invite_multi</string>

View file

@ -2719,7 +2719,7 @@
<string name="after_restart">This change will not take effect until <string name="after_restart">This change will not take effect until
you restart Crosswords.</string> you restart Crosswords.</string>
<string name="not_again_missing_perms">This game is configured to <string name="missing_perms">This game is configured to
communicate via SMS but Crosswords does not have permission to do communicate via SMS but Crosswords does not have permission to do
so. You can still open the game, but it may not be able to send or so. You can still open the game, but it may not be able to send or
receive moves.\n\nYou can re-open it to be asked for permission receive moves.\n\nYou can re-open it to be asked for permission
@ -2729,6 +2729,10 @@
temporary storage to keep what you\'re about to download. temporary storage to keep what you\'re about to download.
</string> </string>
<string name="sms_invite_rationale">
Crosswords needs permission to send an invitation via SMS.
</string>
<string name="dicts_storage_rationale"> <string name="dicts_storage_rationale">
Crosswords can store and read wordlists in your device\'s Crosswords can store and read wordlists in your device\'s
Downloads area but it needs permission to access them Downloads area but it needs permission to access them
@ -2766,8 +2770,15 @@
Downloads area requires permission.</string> Downloads area requires permission.</string>
<string name="remove_sms">Remove SMS</string> <string name="remove_sms">Remove SMS</string>
<!-- In the permissions rationale explanation, means go ahead and
have the OS ask for permission -->
<string name="button_ask_again">Ask again</string>
<string name="contact_not_found">Not in Contacts</string> <string name="contact_not_found">Not in Contacts</string>
<!-- Displayed as a toast -->
<string name="sms_send_failed">SMS send failed</string> <string name="sms_send_failed">SMS send failed</string>
<!-- In the permissions rationale explanation, means don't have the
OS ask for permission: user is denying it implicitly -->
<string name="button_skip">Skip</string>
<string name="perms_rationale_title">Android Permissions</string> <string name="perms_rationale_title">Android Permissions</string>
<string name="toast_no_permission">Permission not granted</string> <string name="toast_no_permission">Permission not granted</string>

View file

@ -2321,7 +2321,7 @@
<string name="dualpane_restart">Gnitixe ppa…</string> <string name="dualpane_restart">Gnitixe ppa…</string>
<string name="after_restart">Siht egnahc lliw ton ekat tceffe litnu <string name="after_restart">Siht egnahc lliw ton ekat tceffe litnu
uoy tratser Sdrowssorc.</string> uoy tratser Sdrowssorc.</string>
<string name="not_again_missing_perms">Siht emag si derugifnoc ot <string name="missing_perms">Siht emag si derugifnoc ot
etacinummoc aiv SMS tub Sdrowssorc seod ton evah noissimrep ot od etacinummoc aiv SMS tub Sdrowssorc seod ton evah noissimrep ot od
os. Uoy nac llits nepo eht ,emag tub ti yam ton eb elba ot dnes ro os. Uoy nac llits nepo eht ,emag tub ti yam ton eb elba ot dnes ro
eviecer sevom.\n\nUoy nac nepo-er ti ot eb deksa rof noissimrep eviecer sevom.\n\nUoy nac nepo-er ti ot eb deksa rof noissimrep
@ -2329,6 +2329,9 @@
<string name="download_rationale">Sdrowssorc sdeen ssecca ot <string name="download_rationale">Sdrowssorc sdeen ssecca ot
yraropmet egarots ot peek tahw uoy\'er tuoba ot daolnwod. yraropmet egarots ot peek tahw uoy\'er tuoba ot daolnwod.
</string> </string>
<string name="sms_invite_rationale">
Sdrowssorc sdeen noissimrep ot dnes na noitativni aiv SMS.
</string>
<string name="dicts_storage_rationale"> <string name="dicts_storage_rationale">
Sdrowssorc nac erots dna daer stsildrow ni ruoy ecived\'s Sdrowssorc nac erots dna daer stsildrow ni ruoy ecived\'s
Sdaolnwod aera tub ti sdeen noissimrep ot ssecca meht Sdaolnwod aera tub ti sdeen noissimrep ot ssecca meht
@ -2360,8 +2363,15 @@
<string name="move_dict_rationale">Gnirots a tsildrow ni eht <string name="move_dict_rationale">Gnirots a tsildrow ni eht
Sdaolnwod aera seriuqer noissimrep.</string> Sdaolnwod aera seriuqer noissimrep.</string>
<string name="remove_sms">Evomer SMS</string> <string name="remove_sms">Evomer SMS</string>
<!-- In the permissions rationale explanation, means go ahead and
have the OS ask for permission -->
<string name="button_ask_again">Ksa niaga</string>
<string name="contact_not_found">Ton ni Stcatnoc</string> <string name="contact_not_found">Ton ni Stcatnoc</string>
<!-- Displayed as a toast -->
<string name="sms_send_failed">SMS dnes deliaf</string> <string name="sms_send_failed">SMS dnes deliaf</string>
<!-- In the permissions rationale explanation, means don't have the
OS ask for permission: user is denying it implicitly -->
<string name="button_skip">Piks</string>
<string name="perms_rationale_title">Diordna Snoissimrep</string> <string name="perms_rationale_title">Diordna Snoissimrep</string>
<string name="toast_no_permission">Noissimrep ton detnarg</string> <string name="toast_no_permission">Noissimrep ton detnarg</string>
</resources> </resources>

View file

@ -2321,7 +2321,7 @@
<string name="dualpane_restart">EXITING APP…</string> <string name="dualpane_restart">EXITING APP…</string>
<string name="after_restart">THIS CHANGE WILL NOT TAKE EFFECT UNTIL <string name="after_restart">THIS CHANGE WILL NOT TAKE EFFECT UNTIL
YOU RESTART CROSSWORDS.</string> YOU RESTART CROSSWORDS.</string>
<string name="not_again_missing_perms">THIS GAME IS CONFIGURED TO <string name="missing_perms">THIS GAME IS CONFIGURED TO
COMMUNICATE VIA SMS BUT CROSSWORDS DOES NOT HAVE PERMISSION TO DO COMMUNICATE VIA SMS BUT CROSSWORDS DOES NOT HAVE PERMISSION TO DO
SO. YOU CAN STILL OPEN THE GAME, BUT IT MAY NOT BE ABLE TO SEND OR SO. YOU CAN STILL OPEN THE GAME, BUT IT MAY NOT BE ABLE TO SEND OR
RECEIVE MOVES.\n\nYOU CAN RE-OPEN IT TO BE ASKED FOR PERMISSION RECEIVE MOVES.\n\nYOU CAN RE-OPEN IT TO BE ASKED FOR PERMISSION
@ -2329,6 +2329,9 @@
<string name="download_rationale">CROSSWORDS NEEDS ACCESS TO <string name="download_rationale">CROSSWORDS NEEDS ACCESS TO
TEMPORARY STORAGE TO KEEP WHAT YOU\'RE ABOUT TO DOWNLOAD. TEMPORARY STORAGE TO KEEP WHAT YOU\'RE ABOUT TO DOWNLOAD.
</string> </string>
<string name="sms_invite_rationale">
CROSSWORDS NEEDS PERMISSION TO SEND AN INVITATION VIA SMS.
</string>
<string name="dicts_storage_rationale"> <string name="dicts_storage_rationale">
CROSSWORDS CAN STORE AND READ WORDLISTS IN YOUR DEVICE\'S CROSSWORDS CAN STORE AND READ WORDLISTS IN YOUR DEVICE\'S
DOWNLOADS AREA BUT IT NEEDS PERMISSION TO ACCESS THEM DOWNLOADS AREA BUT IT NEEDS PERMISSION TO ACCESS THEM
@ -2360,8 +2363,15 @@
<string name="move_dict_rationale">STORING A WORDLIST IN THE <string name="move_dict_rationale">STORING A WORDLIST IN THE
DOWNLOADS AREA REQUIRES PERMISSION.</string> DOWNLOADS AREA REQUIRES PERMISSION.</string>
<string name="remove_sms">REMOVE SMS</string> <string name="remove_sms">REMOVE SMS</string>
<!-- In the permissions rationale explanation, means go ahead and
have the OS ask for permission -->
<string name="button_ask_again">ASK AGAIN</string>
<string name="contact_not_found">NOT IN CONTACTS</string> <string name="contact_not_found">NOT IN CONTACTS</string>
<!-- Displayed as a toast -->
<string name="sms_send_failed">SMS SEND FAILED</string> <string name="sms_send_failed">SMS SEND FAILED</string>
<!-- In the permissions rationale explanation, means don't have the
OS ask for permission: user is denying it implicitly -->
<string name="button_skip">SKIP</string>
<string name="perms_rationale_title">ANDROID PERMISSIONS</string> <string name="perms_rationale_title">ANDROID PERMISSIONS</string>
<string name="toast_no_permission">PERMISSION NOT GRANTED</string> <string name="toast_no_permission">PERMISSION NOT GRANTED</string>
</resources> </resources>

View file

@ -1037,7 +1037,7 @@ public class BoardDelegate extends DelegateBase
break; break;
case RETRY_PHONE_STATE_ACTION: case RETRY_PHONE_STATE_ACTION:
Action stateAction = (Action)params[0]; Action stateAction = (Action)params[0];
DBUtils.SentInvitesInfo info = (DBUtils.SentInvitesInfo)params[1]; SentInvitesInfo info = (SentInvitesInfo)params[1];
callInviteChoices( stateAction, info, false ); callInviteChoices( stateAction, info, false );
break; break;
@ -1102,13 +1102,18 @@ public class BoardDelegate extends DelegateBase
case DROP_RELAY_ACTION: case DROP_RELAY_ACTION:
dropConViaAndRestart(CommsConnType.COMMS_CONN_RELAY); dropConViaAndRestart(CommsConnType.COMMS_CONN_RELAY);
break; break;
case DROP_SMS_ACTION:
dropConViaAndRestart(CommsConnType.COMMS_CONN_SMS);
break;
case DELETE_AND_EXIT: case DELETE_AND_EXIT:
deleteAndClose(); deleteAndClose();
break; break;
case DROP_SMS_ACTION: // do nothing; work done in onNegButton case
break;
case INVITE_SMS:
int nMissing = (Integer)params[0];
info = (SentInvitesInfo)params[1];
SMSInviteDelegate.launchForResult( m_activity, nMissing, info,
RequestCode.SMS_INVITE_RESULT );
break;
case ENABLE_SMS_DO: case ENABLE_SMS_DO:
post( new Runnable() { post( new Runnable() {
@ -1133,6 +1138,9 @@ public class BoardDelegate extends DelegateBase
case ENABLE_RELAY_DO_OR: case ENABLE_RELAY_DO_OR:
m_dropOnDismiss = true; m_dropOnDismiss = true;
break; break;
case DROP_SMS_ACTION:
dropConViaAndRestart(CommsConnType.COMMS_CONN_SMS);
break;
case DELETE_AND_EXIT: case DELETE_AND_EXIT:
finish(); finish();
break; break;
@ -1182,8 +1190,8 @@ public class BoardDelegate extends DelegateBase
RequestCode.BT_INVITE_RESULT ); RequestCode.BT_INVITE_RESULT );
break; break;
case SMS: case SMS:
SMSInviteDelegate.launchForResult( m_activity, m_nMissing, info, Perms23.tryGetPerms( this, Perm.SEND_SMS, R.string.sms_invite_rationale,
RequestCode.SMS_INVITE_RESULT ); Action.INVITE_SMS, this, m_nMissing, info );
break; break;
case RELAY: case RELAY:
RelayInviteDelegate.launchForResult( m_activity, m_nMissing, RelayInviteDelegate.launchForResult( m_activity, m_nMissing,
@ -2245,16 +2253,11 @@ public class BoardDelegate extends DelegateBase
&& null == m_permCbck ) { // already asked? && null == m_permCbck ) { // already asked?
m_permCbck = new Perms23.PermCbck() { m_permCbck = new Perms23.PermCbck() {
@Override @Override
public void onPermissionResult( Map<Perm, public void onPermissionResult( Map<Perm, Boolean> perms ) {
Boolean> perms )
{
ActionPair pair = new ActionPair( Action.DROP_SMS_ACTION,
R.string.remove_sms );
if ( ! perms.get(Perm.SEND_SMS) ) { if ( ! perms.get(Perm.SEND_SMS) ) {
makeNotAgainBuilder( R.string.not_again_missing_perms, makeConfirmThenBuilder( R.string.missing_perms,
R.string.key_notagain_missing_perms ) Action.DROP_SMS_ACTION )
.setActionPair( pair ) .setNegButton(R.string.remove_sms)
.show(); .show();
} }
} }

View file

@ -658,7 +658,7 @@ public class DelegateBase implements DlgClickNotify,
break; break;
default: default:
DbgUtils.logd( TAG, "unhandled action %s", action.toString() ); DbgUtils.logd( TAG, "unhandled action %s", action.toString() );
Assert.fail(); Assert.assertTrue( !BuildConfig.DEBUG );
break; break;
} }
} }

View file

@ -94,6 +94,7 @@ public class DlgDelegate {
NFC_TO_SELF, NFC_TO_SELF,
DROP_RELAY_ACTION, DROP_RELAY_ACTION,
DROP_SMS_ACTION, DROP_SMS_ACTION,
INVITE_SMS,
RETRY_PHONE_STATE_ACTION, RETRY_PHONE_STATE_ACTION,
// Dict Browser // Dict Browser

View file

@ -171,6 +171,8 @@ public class Perms23 {
m_delegate.makeConfirmThenBuilder( m_rationaleId, m_delegate.makeConfirmThenBuilder( m_rationaleId,
Action.PERMS_QUERY ) Action.PERMS_QUERY )
.setTitle( R.string.perms_rationale_title ) .setTitle( R.string.perms_rationale_title )
.setPosButton( R.string.button_ask_again )
.setNegButton( R.string.button_skip )
.setParams( QueryInfo.this ) .setParams( QueryInfo.this )
.show(); .show();
} }
@ -255,6 +257,7 @@ public class Perms23 {
private static int s_nextRecord = 0; private static int s_nextRecord = 0;
private static int register( PermCbck cbck ) private static int register( PermCbck cbck )
{ {
Assert.assertTrue( !BuildConfig.DEBUG || 0 == s_map.size() );
DbgUtils.assertOnUIThread(); DbgUtils.assertOnUIThread();
int code = ++s_nextRecord; int code = ++s_nextRecord;
s_map.put( code, cbck ); s_map.put( code, cbck );