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
 | 
			
		||||
    - wget -O libs/libwebrtc-m87.aar https://gultsch.de/files/libwebrtc-m87.aar
 | 
			
		||||
script:
 | 
			
		||||
    - ./gradlew assembleConversationsFreeSystemRelease
 | 
			
		||||
    - ./gradlew assembleQuicksyFreeCompatRelease
 | 
			
		||||
    - ./gradlew assembleDebug
 | 
			
		||||
 | 
			
		||||
before_install:
 | 
			
		||||
    - yes | sdkmanager "platforms;android-28"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								build.gradle
									
									
									
									
									
								
							@ -26,6 +26,8 @@ configurations {
 | 
			
		||||
    conversationsFreeCompatImplementation
 | 
			
		||||
    conversationsPlaystoreCompatImplementation
 | 
			
		||||
    conversationsPlaystoreSystemImplementation
 | 
			
		||||
    quicksyPlaystoreCompatImplementation
 | 
			
		||||
    quicksyPlaystoreSystemImplementation
 | 
			
		||||
    quicksyFreeCompatImplementation
 | 
			
		||||
    quicksyImplementation
 | 
			
		||||
}
 | 
			
		||||
@ -41,6 +43,8 @@ dependencies {
 | 
			
		||||
    }
 | 
			
		||||
    conversationsPlaystoreCompatImplementation("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 'com.theartofdev.edmodo:android-image-cropper:2.8.0'
 | 
			
		||||
    implementation 'androidx.appcompat:appcompat:1.2.0'
 | 
			
		||||
@ -156,14 +160,21 @@ android {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sourceSets {
 | 
			
		||||
        quicksyFreeSystem {
 | 
			
		||||
            java {
 | 
			
		||||
                srcDir 'src/quicksyFree/java'
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        quicksyFreeCompat {
 | 
			
		||||
            java {
 | 
			
		||||
                srcDir 'src/freeCompat/java'
 | 
			
		||||
                srcDir 'src/quicksyFree/java'
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        quicksyPlaystoreCompat {
 | 
			
		||||
            java {
 | 
			
		||||
                srcDir 'src/playstoreCompat/java'
 | 
			
		||||
                srcDir 'src/quicksyPlaystore/java'
 | 
			
		||||
            }
 | 
			
		||||
            res {
 | 
			
		||||
                srcDir 'src/playstoreCompat/res'
 | 
			
		||||
@ -171,6 +182,9 @@ android {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        quicksyPlaystoreSystem {
 | 
			
		||||
            java {
 | 
			
		||||
                srcDir 'src/quicksyPlaystore/java'
 | 
			
		||||
            }
 | 
			
		||||
            res {
 | 
			
		||||
                srcDir 'src/quicksyPlaystore/res'
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,10 @@
 | 
			
		||||
package eu.siacs.conversations.services;
 | 
			
		||||
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
 | 
			
		||||
import eu.siacs.conversations.Config;
 | 
			
		||||
 | 
			
		||||
public class QuickConversationsService extends AbstractQuickConversationsService {
 | 
			
		||||
 | 
			
		||||
    QuickConversationsService(XmppConnectionService xmppConnectionService) {
 | 
			
		||||
@ -25,4 +30,9 @@ public class QuickConversationsService extends AbstractQuickConversationsService
 | 
			
		||||
    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" />
 | 
			
		||||
 | 
			
		||||
        <receiver android:name=".services.EventReceiver">
 | 
			
		||||
        <receiver android:name=".services.EventReceiver"
 | 
			
		||||
            android:permission="com.google.android.gms.auth.api.phone.permission.SEND">
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
                <action android:name="android.intent.action.BOOT_COMPLETED" />
 | 
			
		||||
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
 | 
			
		||||
                <action android:name="android.intent.action.ACTION_SHUTDOWN" />
 | 
			
		||||
                <action android:name="android.media.RINGER_MODE_CHANGED" />
 | 
			
		||||
                <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
        </receiver>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,14 @@
 | 
			
		||||
package eu.siacs.conversations.services;
 | 
			
		||||
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
 | 
			
		||||
import eu.siacs.conversations.BuildConfig;
 | 
			
		||||
 | 
			
		||||
public abstract class AbstractQuickConversationsService {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public static final String SMS_RETRIEVED_ACTION = "com.google.android.gms.auth.api.phone.SMS_RETRIEVED";
 | 
			
		||||
 | 
			
		||||
    protected final XmppConnectionService service;
 | 
			
		||||
 | 
			
		||||
    public AbstractQuickConversationsService(XmppConnectionService service) {
 | 
			
		||||
@ -25,4 +30,6 @@ public abstract class AbstractQuickConversationsService {
 | 
			
		||||
    public abstract boolean isSynchronizing();
 | 
			
		||||
 | 
			
		||||
    public abstract void considerSyncBackground(boolean force);
 | 
			
		||||
 | 
			
		||||
    public abstract void handleSmsReceived(Intent intent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,7 @@ public class EventReceiver extends BroadcastReceiver {
 | 
			
		||||
        if (extras != null) {
 | 
			
		||||
            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);
 | 
			
		||||
        } else {
 | 
			
		||||
            Log.d(Config.LOGTAG, "EventReceiver ignored action " + intentForService.getAction());
 | 
			
		||||
 | 
			
		||||
@ -32,10 +32,6 @@ import android.os.SystemClock;
 | 
			
		||||
import android.preference.PreferenceManager;
 | 
			
		||||
import android.provider.ContactsContract;
 | 
			
		||||
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.TelephonyManager;
 | 
			
		||||
import android.text.TextUtils;
 | 
			
		||||
@ -44,6 +40,11 @@ import android.util.Log;
 | 
			
		||||
import android.util.LruCache;
 | 
			
		||||
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.Strings;
 | 
			
		||||
 | 
			
		||||
@ -135,6 +136,7 @@ import eu.siacs.conversations.utils.WakeLockHelper;
 | 
			
		||||
import eu.siacs.conversations.utils.XmppUri;
 | 
			
		||||
import eu.siacs.conversations.xml.Element;
 | 
			
		||||
import eu.siacs.conversations.xml.Namespace;
 | 
			
		||||
import eu.siacs.conversations.xmpp.Jid;
 | 
			
		||||
import eu.siacs.conversations.xmpp.OnBindListener;
 | 
			
		||||
import eu.siacs.conversations.xmpp.OnContactStatusChanged;
 | 
			
		||||
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.PresencePacket;
 | 
			
		||||
import me.leolin.shortcutbadger.ShortcutBadger;
 | 
			
		||||
import eu.siacs.conversations.xmpp.Jid;
 | 
			
		||||
 | 
			
		||||
public class XmppConnectionService extends Service {
 | 
			
		||||
 | 
			
		||||
@ -633,6 +634,9 @@ public class XmppConnectionService extends Service {
 | 
			
		||||
        if (action != null) {
 | 
			
		||||
            final String uuid = intent.getStringExtra("uuid");
 | 
			
		||||
            switch (action) {
 | 
			
		||||
                case QuickConversationsService.SMS_RETRIEVED_ACTION:
 | 
			
		||||
                    mQuickConversationsService.handleSmsReceived(intent);
 | 
			
		||||
                break;
 | 
			
		||||
                case ConnectivityManager.CONNECTIVITY_ACTION:
 | 
			
		||||
                    if (hasInternetConnection()) {
 | 
			
		||||
                        if (Config.POST_CONNECTIVITY_CHANGE_PING_INTERVAL > 0) {
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,10 @@
 | 
			
		||||
package eu.siacs.conversations.services;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.os.SystemClock;
 | 
			
		||||
import android.preference.PreferenceManager;
 | 
			
		||||
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.PhoneNumberUtilWrapper;
 | 
			
		||||
import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
 | 
			
		||||
import eu.siacs.conversations.utils.SmsRetrieverWrapper;
 | 
			
		||||
import eu.siacs.conversations.xml.Element;
 | 
			
		||||
import eu.siacs.conversations.xml.Namespace;
 | 
			
		||||
import eu.siacs.conversations.xmpp.Jid;
 | 
			
		||||
@ -122,6 +125,7 @@ public class QuickConversationsService extends AbstractQuickConversationsService
 | 
			
		||||
    public void requestVerification(Phonenumber.PhoneNumber phoneNumber) {
 | 
			
		||||
        final String e164 = PhoneNumberUtilWrapper.normalize(service, phoneNumber);
 | 
			
		||||
        if (mVerificationRequestInProgress.compareAndSet(false, true)) {
 | 
			
		||||
            SmsRetrieverWrapper.start(service);
 | 
			
		||||
            new Thread(() -> {
 | 
			
		||||
                try {
 | 
			
		||||
                    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) {
 | 
			
		||||
        Map<String, PhoneNumberContact> contacts = PhoneNumberContact.load(service);
 | 
			
		||||
@ -429,11 +455,13 @@ public class QuickConversationsService extends AbstractQuickConversationsService
 | 
			
		||||
        void onVerificationSucceeded();
 | 
			
		||||
 | 
			
		||||
        void onVerificationRetryAt(long timestamp);
 | 
			
		||||
 | 
			
		||||
        void startBackgroundVerification(String pin);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static class Attempt {
 | 
			
		||||
        private final long timestamp;
 | 
			
		||||
        private int hash;
 | 
			
		||||
        private final int hash;
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void startBackgroundVerification(String pin) {
 | 
			
		||||
        pinEntryWrapper.setPin(pin);
 | 
			
		||||
        setVerifyingState(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //send sms again button callback
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onVerificationRequestFailed(int code) {
 | 
			
		||||
@ -329,6 +335,7 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onVerificationRequested() {
 | 
			
		||||
        runOnUiThread(() -> {
 | 
			
		||||
            pinEntryWrapper.clear();
 | 
			
		||||
            setRequestingVerificationState(false);
 | 
			
		||||
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
 | 
			
		||||
            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
	
	Block a user