automatically receive Quicksy SMS. fixes #3962
requires new version of QuicksyServer
This commit is contained in:
		
							parent
							
								
									624bb565a8
								
							
						
					
					
						commit
						26a4598f3c
					
				|  | @ -13,8 +13,7 @@ before_script: | ||||||
|     - mkdir libs |     - mkdir libs | ||||||
|     - wget -O libs/libwebrtc-m87.aar https://gultsch.de/files/libwebrtc-m87.aar |     - wget -O libs/libwebrtc-m87.aar https://gultsch.de/files/libwebrtc-m87.aar | ||||||
| script: | script: | ||||||
|     - ./gradlew assembleConversationsFreeSystemRelease |     - ./gradlew assembleDebug | ||||||
|     - ./gradlew assembleQuicksyFreeCompatRelease |  | ||||||
| 
 | 
 | ||||||
| before_install: | before_install: | ||||||
|     - yes | sdkmanager "platforms;android-28" |     - yes | sdkmanager "platforms;android-28" | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								build.gradle
								
								
								
								
							
							
						
						
									
										14
									
								
								build.gradle
								
								
								
								
							|  | @ -26,6 +26,8 @@ configurations { | ||||||
|     conversationsFreeCompatImplementation |     conversationsFreeCompatImplementation | ||||||
|     conversationsPlaystoreCompatImplementation |     conversationsPlaystoreCompatImplementation | ||||||
|     conversationsPlaystoreSystemImplementation |     conversationsPlaystoreSystemImplementation | ||||||
|  |     quicksyPlaystoreCompatImplementation | ||||||
|  |     quicksyPlaystoreSystemImplementation | ||||||
|     quicksyFreeCompatImplementation |     quicksyFreeCompatImplementation | ||||||
|     quicksyImplementation |     quicksyImplementation | ||||||
| } | } | ||||||
|  | @ -41,6 +43,8 @@ dependencies { | ||||||
|     } |     } | ||||||
|     conversationsPlaystoreCompatImplementation("com.android.installreferrer:installreferrer:2.2") |     conversationsPlaystoreCompatImplementation("com.android.installreferrer:installreferrer:2.2") | ||||||
|     conversationsPlaystoreSystemImplementation("com.android.installreferrer:installreferrer:2.2") |     conversationsPlaystoreSystemImplementation("com.android.installreferrer:installreferrer:2.2") | ||||||
|  |     quicksyPlaystoreCompatImplementation 'com.google.android.gms:play-services-auth-api-phone:17.0.0' | ||||||
|  |     quicksyPlaystoreSystemImplementation 'com.google.android.gms:play-services-auth-api-phone:17.0.0' | ||||||
|     implementation 'org.sufficientlysecure:openpgp-api:10.0' |     implementation 'org.sufficientlysecure:openpgp-api:10.0' | ||||||
|     implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0' |     implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0' | ||||||
|     implementation 'androidx.appcompat:appcompat:1.2.0' |     implementation 'androidx.appcompat:appcompat:1.2.0' | ||||||
|  | @ -156,14 +160,21 @@ android { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     sourceSets { |     sourceSets { | ||||||
|  |         quicksyFreeSystem { | ||||||
|  |             java { | ||||||
|  |                 srcDir 'src/quicksyFree/java' | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         quicksyFreeCompat { |         quicksyFreeCompat { | ||||||
|             java { |             java { | ||||||
|                 srcDir 'src/freeCompat/java' |                 srcDir 'src/freeCompat/java' | ||||||
|  |                 srcDir 'src/quicksyFree/java' | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         quicksyPlaystoreCompat { |         quicksyPlaystoreCompat { | ||||||
|             java { |             java { | ||||||
|                 srcDir 'src/playstoreCompat/java' |                 srcDir 'src/playstoreCompat/java' | ||||||
|  |                 srcDir 'src/quicksyPlaystore/java' | ||||||
|             } |             } | ||||||
|             res { |             res { | ||||||
|                 srcDir 'src/playstoreCompat/res' |                 srcDir 'src/playstoreCompat/res' | ||||||
|  | @ -171,6 +182,9 @@ android { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         quicksyPlaystoreSystem { |         quicksyPlaystoreSystem { | ||||||
|  |             java { | ||||||
|  |                 srcDir 'src/quicksyPlaystore/java' | ||||||
|  |             } | ||||||
|             res { |             res { | ||||||
|                 srcDir 'src/quicksyPlaystore/res' |                 srcDir 'src/quicksyPlaystore/res' | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -1,5 +1,10 @@ | ||||||
| package eu.siacs.conversations.services; | package eu.siacs.conversations.services; | ||||||
| 
 | 
 | ||||||
|  | import android.content.Intent; | ||||||
|  | import android.util.Log; | ||||||
|  | 
 | ||||||
|  | import eu.siacs.conversations.Config; | ||||||
|  | 
 | ||||||
| public class QuickConversationsService extends AbstractQuickConversationsService { | public class QuickConversationsService extends AbstractQuickConversationsService { | ||||||
| 
 | 
 | ||||||
|     QuickConversationsService(XmppConnectionService xmppConnectionService) { |     QuickConversationsService(XmppConnectionService xmppConnectionService) { | ||||||
|  | @ -25,4 +30,9 @@ public class QuickConversationsService extends AbstractQuickConversationsService | ||||||
|     public void considerSyncBackground(boolean force) { |     public void considerSyncBackground(boolean force) { | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void handleSmsReceived(Intent intent) { | ||||||
|  |         Log.d(Config.LOGTAG,"ignoring received SMS"); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | @ -72,12 +72,14 @@ | ||||||
| 
 | 
 | ||||||
|         <service android:name=".services.XmppConnectionService" /> |         <service android:name=".services.XmppConnectionService" /> | ||||||
| 
 | 
 | ||||||
|         <receiver android:name=".services.EventReceiver"> |         <receiver android:name=".services.EventReceiver" | ||||||
|  |             android:permission="com.google.android.gms.auth.api.phone.permission.SEND"> | ||||||
|             <intent-filter> |             <intent-filter> | ||||||
|                 <action android:name="android.intent.action.BOOT_COMPLETED" /> |                 <action android:name="android.intent.action.BOOT_COMPLETED" /> | ||||||
|                 <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> |                 <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> | ||||||
|                 <action android:name="android.intent.action.ACTION_SHUTDOWN" /> |                 <action android:name="android.intent.action.ACTION_SHUTDOWN" /> | ||||||
|                 <action android:name="android.media.RINGER_MODE_CHANGED" /> |                 <action android:name="android.media.RINGER_MODE_CHANGED" /> | ||||||
|  |                 <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/> | ||||||
|             </intent-filter> |             </intent-filter> | ||||||
|         </receiver> |         </receiver> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,9 +1,14 @@ | ||||||
| package eu.siacs.conversations.services; | package eu.siacs.conversations.services; | ||||||
| 
 | 
 | ||||||
|  | import android.content.Intent; | ||||||
|  | 
 | ||||||
| import eu.siacs.conversations.BuildConfig; | import eu.siacs.conversations.BuildConfig; | ||||||
| 
 | 
 | ||||||
| public abstract class AbstractQuickConversationsService { | public abstract class AbstractQuickConversationsService { | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |     public static final String SMS_RETRIEVED_ACTION = "com.google.android.gms.auth.api.phone.SMS_RETRIEVED"; | ||||||
|  | 
 | ||||||
|     protected final XmppConnectionService service; |     protected final XmppConnectionService service; | ||||||
| 
 | 
 | ||||||
|     public AbstractQuickConversationsService(XmppConnectionService service) { |     public AbstractQuickConversationsService(XmppConnectionService service) { | ||||||
|  | @ -25,4 +30,6 @@ public abstract class AbstractQuickConversationsService { | ||||||
|     public abstract boolean isSynchronizing(); |     public abstract boolean isSynchronizing(); | ||||||
| 
 | 
 | ||||||
|     public abstract void considerSyncBackground(boolean force); |     public abstract void considerSyncBackground(boolean force); | ||||||
|  | 
 | ||||||
|  |     public abstract void handleSmsReceived(Intent intent); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ public class EventReceiver extends BroadcastReceiver { | ||||||
|         if (extras != null) { |         if (extras != null) { | ||||||
|             intentForService.putExtras(extras); |             intentForService.putExtras(extras); | ||||||
|         } |         } | ||||||
|         if ("ui".equals(action) || hasEnabledAccounts(context)) { |         if ("ui".equals(action) || QuickConversationsService.SMS_RETRIEVED_ACTION.equals(action)  || hasEnabledAccounts(context)) { | ||||||
|             Compatibility.startService(context, intentForService); |             Compatibility.startService(context, intentForService); | ||||||
|         } else { |         } else { | ||||||
|             Log.d(Config.LOGTAG, "EventReceiver ignored action " + intentForService.getAction()); |             Log.d(Config.LOGTAG, "EventReceiver ignored action " + intentForService.getAction()); | ||||||
|  |  | ||||||
|  | @ -32,10 +32,6 @@ import android.os.SystemClock; | ||||||
| import android.preference.PreferenceManager; | import android.preference.PreferenceManager; | ||||||
| import android.provider.ContactsContract; | import android.provider.ContactsContract; | ||||||
| import android.security.KeyChain; | import android.security.KeyChain; | ||||||
| import androidx.annotation.BoolRes; |  | ||||||
| import androidx.annotation.IntegerRes; |  | ||||||
| import androidx.core.app.RemoteInput; |  | ||||||
| import androidx.core.content.ContextCompat; |  | ||||||
| import android.telephony.PhoneStateListener; | import android.telephony.PhoneStateListener; | ||||||
| import android.telephony.TelephonyManager; | import android.telephony.TelephonyManager; | ||||||
| import android.text.TextUtils; | import android.text.TextUtils; | ||||||
|  | @ -44,6 +40,11 @@ import android.util.Log; | ||||||
| import android.util.LruCache; | import android.util.LruCache; | ||||||
| import android.util.Pair; | import android.util.Pair; | ||||||
| 
 | 
 | ||||||
|  | import androidx.annotation.BoolRes; | ||||||
|  | import androidx.annotation.IntegerRes; | ||||||
|  | import androidx.core.app.RemoteInput; | ||||||
|  | import androidx.core.content.ContextCompat; | ||||||
|  | 
 | ||||||
| import com.google.common.base.Objects; | import com.google.common.base.Objects; | ||||||
| import com.google.common.base.Strings; | import com.google.common.base.Strings; | ||||||
| 
 | 
 | ||||||
|  | @ -135,6 +136,7 @@ import eu.siacs.conversations.utils.WakeLockHelper; | ||||||
| import eu.siacs.conversations.utils.XmppUri; | import eu.siacs.conversations.utils.XmppUri; | ||||||
| import eu.siacs.conversations.xml.Element; | import eu.siacs.conversations.xml.Element; | ||||||
| import eu.siacs.conversations.xml.Namespace; | import eu.siacs.conversations.xml.Namespace; | ||||||
|  | import eu.siacs.conversations.xmpp.Jid; | ||||||
| import eu.siacs.conversations.xmpp.OnBindListener; | import eu.siacs.conversations.xmpp.OnBindListener; | ||||||
| import eu.siacs.conversations.xmpp.OnContactStatusChanged; | import eu.siacs.conversations.xmpp.OnContactStatusChanged; | ||||||
| import eu.siacs.conversations.xmpp.OnIqPacketReceived; | import eu.siacs.conversations.xmpp.OnIqPacketReceived; | ||||||
|  | @ -159,7 +161,6 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket; | ||||||
| import eu.siacs.conversations.xmpp.stanzas.MessagePacket; | import eu.siacs.conversations.xmpp.stanzas.MessagePacket; | ||||||
| import eu.siacs.conversations.xmpp.stanzas.PresencePacket; | import eu.siacs.conversations.xmpp.stanzas.PresencePacket; | ||||||
| import me.leolin.shortcutbadger.ShortcutBadger; | import me.leolin.shortcutbadger.ShortcutBadger; | ||||||
| import eu.siacs.conversations.xmpp.Jid; |  | ||||||
| 
 | 
 | ||||||
| public class XmppConnectionService extends Service { | public class XmppConnectionService extends Service { | ||||||
| 
 | 
 | ||||||
|  | @ -633,6 +634,9 @@ public class XmppConnectionService extends Service { | ||||||
|         if (action != null) { |         if (action != null) { | ||||||
|             final String uuid = intent.getStringExtra("uuid"); |             final String uuid = intent.getStringExtra("uuid"); | ||||||
|             switch (action) { |             switch (action) { | ||||||
|  |                 case QuickConversationsService.SMS_RETRIEVED_ACTION: | ||||||
|  |                     mQuickConversationsService.handleSmsReceived(intent); | ||||||
|  |                 break; | ||||||
|                 case ConnectivityManager.CONNECTIVITY_ACTION: |                 case ConnectivityManager.CONNECTIVITY_ACTION: | ||||||
|                     if (hasInternetConnection()) { |                     if (hasInternetConnection()) { | ||||||
|                         if (Config.POST_CONNECTIVITY_CHANGE_PING_INTERVAL > 0) { |                         if (Config.POST_CONNECTIVITY_CHANGE_PING_INTERVAL > 0) { | ||||||
|  |  | ||||||
|  | @ -1,8 +1,10 @@ | ||||||
| package eu.siacs.conversations.services; | package eu.siacs.conversations.services; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | import android.content.Intent; | ||||||
| import android.content.SharedPreferences; | import android.content.SharedPreferences; | ||||||
| import android.net.Uri; | import android.net.Uri; | ||||||
|  | import android.os.Bundle; | ||||||
| import android.os.SystemClock; | import android.os.SystemClock; | ||||||
| import android.preference.PreferenceManager; | import android.preference.PreferenceManager; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
|  | @ -47,6 +49,7 @@ import eu.siacs.conversations.utils.AccountUtils; | ||||||
| import eu.siacs.conversations.utils.CryptoHelper; | import eu.siacs.conversations.utils.CryptoHelper; | ||||||
| import eu.siacs.conversations.utils.PhoneNumberUtilWrapper; | import eu.siacs.conversations.utils.PhoneNumberUtilWrapper; | ||||||
| import eu.siacs.conversations.utils.SerialSingleThreadExecutor; | import eu.siacs.conversations.utils.SerialSingleThreadExecutor; | ||||||
|  | import eu.siacs.conversations.utils.SmsRetrieverWrapper; | ||||||
| import eu.siacs.conversations.xml.Element; | import eu.siacs.conversations.xml.Element; | ||||||
| import eu.siacs.conversations.xml.Namespace; | import eu.siacs.conversations.xml.Namespace; | ||||||
| import eu.siacs.conversations.xmpp.Jid; | import eu.siacs.conversations.xmpp.Jid; | ||||||
|  | @ -122,6 +125,7 @@ public class QuickConversationsService extends AbstractQuickConversationsService | ||||||
|     public void requestVerification(Phonenumber.PhoneNumber phoneNumber) { |     public void requestVerification(Phonenumber.PhoneNumber phoneNumber) { | ||||||
|         final String e164 = PhoneNumberUtilWrapper.normalize(service, phoneNumber); |         final String e164 = PhoneNumberUtilWrapper.normalize(service, phoneNumber); | ||||||
|         if (mVerificationRequestInProgress.compareAndSet(false, true)) { |         if (mVerificationRequestInProgress.compareAndSet(false, true)) { | ||||||
|  |             SmsRetrieverWrapper.start(service); | ||||||
|             new Thread(() -> { |             new Thread(() -> { | ||||||
|                 try { |                 try { | ||||||
|                     final URL url = new URL(BASE_URL + "/authentication/" + e164); |                     final URL url = new URL(BASE_URL + "/authentication/" + e164); | ||||||
|  | @ -322,6 +326,28 @@ public class QuickConversationsService extends AbstractQuickConversationsService | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public void handleSmsReceived(final Intent intent) { | ||||||
|  |         final Bundle extras = intent.getExtras(); | ||||||
|  |         final String pin = SmsRetrieverWrapper.extractPin(extras); | ||||||
|  |         if (pin == null) { | ||||||
|  |             Log.d(Config.LOGTAG, "unable to extract Pin from received SMS"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         final Account account = AccountUtils.getFirst(service); | ||||||
|  |         if (account == null) { | ||||||
|  |             Log.d(Config.LOGTAG, "no account configured to process PIN received by SMS"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         verify(account, pin); | ||||||
|  |         synchronized (mOnVerification) { | ||||||
|  |             for (OnVerification onVerification : mOnVerification) { | ||||||
|  |                 onVerification.startBackgroundVerification(pin); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
|     private void considerSync(boolean forced) { |     private void considerSync(boolean forced) { | ||||||
|         Map<String, PhoneNumberContact> contacts = PhoneNumberContact.load(service); |         Map<String, PhoneNumberContact> contacts = PhoneNumberContact.load(service); | ||||||
|  | @ -429,11 +455,13 @@ public class QuickConversationsService extends AbstractQuickConversationsService | ||||||
|         void onVerificationSucceeded(); |         void onVerificationSucceeded(); | ||||||
| 
 | 
 | ||||||
|         void onVerificationRetryAt(long timestamp); |         void onVerificationRetryAt(long timestamp); | ||||||
|  | 
 | ||||||
|  |         void startBackgroundVerification(String pin); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static class Attempt { |     private static class Attempt { | ||||||
|         private final long timestamp; |         private final long timestamp; | ||||||
|         private int hash; |         private final int hash; | ||||||
| 
 | 
 | ||||||
|         private static final Attempt NULL = new Attempt(0, 0); |         private static final Attempt NULL = new Attempt(0, 0); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -316,6 +316,12 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP | ||||||
|         runOnUiThread(VERIFICATION_TIMEOUT_UPDATER); |         runOnUiThread(VERIFICATION_TIMEOUT_UPDATER); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public void startBackgroundVerification(String pin) { | ||||||
|  |         pinEntryWrapper.setPin(pin); | ||||||
|  |         setVerifyingState(true); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     //send sms again button callback |     //send sms again button callback | ||||||
|     @Override |     @Override | ||||||
|     public void onVerificationRequestFailed(int code) { |     public void onVerificationRequestFailed(int code) { | ||||||
|  | @ -329,6 +335,7 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP | ||||||
|     @Override |     @Override | ||||||
|     public void onVerificationRequested() { |     public void onVerificationRequested() { | ||||||
|         runOnUiThread(() -> { |         runOnUiThread(() -> { | ||||||
|  |             pinEntryWrapper.clear(); | ||||||
|             setRequestingVerificationState(false); |             setRequestingVerificationState(false); | ||||||
|             AlertDialog.Builder builder = new AlertDialog.Builder(this); |             AlertDialog.Builder builder = new AlertDialog.Builder(this); | ||||||
|             builder.setMessage(R.string.we_have_sent_you_another_sms); |             builder.setMessage(R.string.we_have_sent_you_another_sms); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | package eu.siacs.conversations.utils; | ||||||
|  | 
 | ||||||
|  | import android.os.Bundle; | ||||||
|  | 
 | ||||||
|  | import eu.siacs.conversations.services.XmppConnectionService; | ||||||
|  | 
 | ||||||
|  | public class SmsRetrieverWrapper { | ||||||
|  | 
 | ||||||
|  |     public static void start(XmppConnectionService service) { | ||||||
|  |         //nop | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static String extractPin(Bundle extras) { | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,40 @@ | ||||||
|  | package eu.siacs.conversations.utils; | ||||||
|  | 
 | ||||||
|  | import android.content.Context; | ||||||
|  | import android.os.Bundle; | ||||||
|  | import android.util.Log; | ||||||
|  | 
 | ||||||
|  | import com.google.android.gms.auth.api.phone.SmsRetriever; | ||||||
|  | import com.google.android.gms.auth.api.phone.SmsRetrieverClient; | ||||||
|  | import com.google.android.gms.common.api.CommonStatusCodes; | ||||||
|  | import com.google.android.gms.common.api.Status; | ||||||
|  | import com.google.android.gms.tasks.Task; | ||||||
|  | import com.google.common.base.Strings; | ||||||
|  | 
 | ||||||
|  | import java.util.regex.Matcher; | ||||||
|  | import java.util.regex.Pattern; | ||||||
|  | 
 | ||||||
|  | import eu.siacs.conversations.Config; | ||||||
|  | 
 | ||||||
|  | public class SmsRetrieverWrapper { | ||||||
|  | 
 | ||||||
|  |     public static void start(final Context context) { | ||||||
|  |         final SmsRetrieverClient client = SmsRetriever.getClient(context); | ||||||
|  |         final Task<Void> task = client.startSmsRetriever(); | ||||||
|  |         task.addOnSuccessListener(aVoid -> Log.d(Config.LOGTAG, "successfully started SMS retriever")); | ||||||
|  |         task.addOnFailureListener(e -> Log.d(Config.LOGTAG, "unable to start SMS retriever", e)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static String extractPin(Bundle extras) { | ||||||
|  |         final Status status = extras == null ? null : (Status) extras.get(SmsRetriever.EXTRA_STATUS); | ||||||
|  |         if (status != null && status.getStatusCode() == CommonStatusCodes.SUCCESS) { | ||||||
|  |             Log.d(Config.LOGTAG, "Verification SMS received with status success"); | ||||||
|  |             final String message = extras.getString(SmsRetriever.EXTRA_SMS_MESSAGE); | ||||||
|  |             final Matcher m = Pattern.compile("(?<!\\d)\\d{6}(?!\\d)").matcher(Strings.nullToEmpty(message)); | ||||||
|  |             if (m.find()) { | ||||||
|  |                 return m.group(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	 Daniel Gultsch
						Daniel Gultsch