diff --git a/src/conversations/AndroidManifest.xml b/src/conversations/AndroidManifest.xml index a91f4c129..0491acfbf 100644 --- a/src/conversations/AndroidManifest.xml +++ b/src/conversations/AndroidManifest.xml @@ -11,32 +11,42 @@ + android:launchMode="singleTask" /> + android:launchMode="singleTask" /> + android:launchMode="singleTask" /> - + + - + + + + + + + diff --git a/src/conversations/java/eu/siacs/conversations/services/InstallReferrerService.java b/src/conversations/java/eu/siacs/conversations/services/InstallReferrerService.java new file mode 100644 index 000000000..7fdaf4c48 --- /dev/null +++ b/src/conversations/java/eu/siacs/conversations/services/InstallReferrerService.java @@ -0,0 +1,39 @@ +package eu.siacs.conversations.services; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.util.Log; + +import java.net.URLDecoder; + +import eu.siacs.conversations.Config; +import eu.siacs.conversations.ui.StartConversationActivity; +import eu.siacs.conversations.utils.SignupUtils; + +public class InstallReferrerService extends BroadcastReceiver { + + public static final String INSTALL_REFERRER_BROADCAST_ACTION = "eu.siacs.conversations.install_referrer"; + + @Override + public void onReceive(final Context context, final Intent intent) { + final String referrer = intent == null ? null : intent.getStringExtra("referrer"); + if (referrer == null) { + Log.d(Config.LOGTAG, "received empty referrer"); + return; + } + try { + final String decoded = URLDecoder.decode(referrer, "UTF-8"); + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + preferences.edit().putString(SignupUtils.INSTALL_REFERRER, decoded).apply(); + Log.d(Config.LOGTAG, "stored referrer: " + decoded); + final Intent broadcastIntent = new Intent(INSTALL_REFERRER_BROADCAST_ACTION); + broadcastIntent.putExtra(StartConversationActivity.EXTRA_INVITE_URI, decoded); + context.sendBroadcast(broadcastIntent); + } catch (final Exception e) { + Log.d(Config.LOGTAG, "unable to process referrer", e); + } + } +} diff --git a/src/conversations/java/eu/siacs/conversations/ui/MagicCreateActivity.java b/src/conversations/java/eu/siacs/conversations/ui/MagicCreateActivity.java index 7c8bbeac4..b76e2c3bb 100644 --- a/src/conversations/java/eu/siacs/conversations/ui/MagicCreateActivity.java +++ b/src/conversations/java/eu/siacs/conversations/ui/MagicCreateActivity.java @@ -1,12 +1,15 @@ package eu.siacs.conversations.ui; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.databinding.DataBindingUtil; import android.os.Bundle; +import android.preference.PreferenceManager; import android.support.v7.widget.Toolbar; import android.text.Editable; import android.text.TextWatcher; +import android.util.Log; import android.view.View; import android.widget.Toast; @@ -17,6 +20,7 @@ import eu.siacs.conversations.R; import eu.siacs.conversations.databinding.MagicCreateBinding; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.utils.CryptoHelper; +import eu.siacs.conversations.utils.SignupUtils; import rocks.xmpp.addr.Jid; public class MagicCreateActivity extends XmppActivity implements TextWatcher { @@ -121,6 +125,14 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher { binding.username.addTextChangedListener(this); } + @Override + public void onDestroy() { + Log.d(Config.LOGTAG,"purge install referrer"); + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + preferences.edit().remove(SignupUtils.INSTALL_REFERRER).apply(); + super.onDestroy(); + } + @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { diff --git a/src/conversations/java/eu/siacs/conversations/ui/WelcomeActivity.java b/src/conversations/java/eu/siacs/conversations/ui/WelcomeActivity.java index 02613f368..a63846fc8 100644 --- a/src/conversations/java/eu/siacs/conversations/ui/WelcomeActivity.java +++ b/src/conversations/java/eu/siacs/conversations/ui/WelcomeActivity.java @@ -1,21 +1,32 @@ package eu.siacs.conversations.ui; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.databinding.DataBindingUtil; import android.os.Bundle; +import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; import java.util.List; +import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.databinding.ActivityWelcomeBinding; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.services.InstallReferrerService; +import eu.siacs.conversations.utils.SignupUtils; +import eu.siacs.conversations.utils.XmppUri; +import rocks.xmpp.addr.Jid; import static eu.siacs.conversations.utils.PermissionUtils.allGranted; import static eu.siacs.conversations.utils.PermissionUtils.writeGranted; @@ -24,6 +35,44 @@ public class WelcomeActivity extends XmppActivity { private static final int REQUEST_IMPORT_BACKUP = 0x63fb; + private XmppUri inviteUri; + + private BroadcastReceiver installReferrerBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent data) { + final String invite = data.getStringExtra(StartConversationActivity.EXTRA_INVITE_URI); + if (invite == null) { + return; + } + Log.d(Config.LOGTAG, "welcome activity received install referrer uri: " + invite); + final XmppUri xmppUri = new XmppUri(invite); + processXmppUri(xmppUri); + } + }; + + private boolean processXmppUri(final XmppUri xmppUri) { + if (xmppUri.isValidJid()) { + final String preauth = xmppUri.getParamater("preauth"); + final Jid jid = xmppUri.getJid(); + final Intent intent; + if (xmppUri.isAction(XmppUri.ACTION_REGISTER)) { + intent = SignupUtils.getTokenRegistrationIntent(this, jid, preauth); + } else if (xmppUri.isAction(XmppUri.ACTION_ROSTER) && "y".equals(xmppUri.getParamater("ibr"))) { + intent = SignupUtils.getTokenRegistrationIntent(this, Jid.ofDomain(jid.getDomain()), preauth); + intent.putExtra(StartConversationActivity.EXTRA_INVITE_URI, xmppUri.toString()); + } else { + intent = null; + } + if (intent != null) { + startActivity(intent); + finish(); + return true; + } + this.inviteUri = xmppUri; + } + return false; + } + @Override protected void refreshUiReal() { @@ -41,6 +90,15 @@ public class WelcomeActivity extends XmppActivity { if (this.mTheme != theme) { recreate(); } + final IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(InstallReferrerService.INSTALL_REFERRER_BROADCAST_ACTION); + registerReceiver(installReferrerBroadcastReceiver, intentFilter); + } + + @Override + public void onStop() { + unregisterReceiver(installReferrerBroadcastReceiver); + super.onStop(); } @Override @@ -56,7 +114,13 @@ public class WelcomeActivity extends XmppActivity { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } super.onCreate(savedInstanceState); - ActivityWelcomeBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_welcome); + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + final String referrer = preferences.getString(SignupUtils.INSTALL_REFERRER,null); + final XmppUri referrerUri = referrer == null ? null : new XmppUri(referrer); + if (referrerUri != null && processXmppUri(referrerUri)) { + return; + } + ActivityWelcomeBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_welcome); setSupportActionBar((Toolbar) binding.toolbar); configureActionBar(getSupportActionBar(), false); binding.registerNewAccount.setOnClickListener(v -> { @@ -67,7 +131,7 @@ public class WelcomeActivity extends XmppActivity { binding.useExisting.setOnClickListener(v -> { List accounts = xmppConnectionService.getAccounts(); Intent intent = new Intent(WelcomeActivity.this, EditAccountActivity.class); - intent.putExtra(EditAccountActivity.EXTRA_FORCE_REGISTER,false); + intent.putExtra(EditAccountActivity.EXTRA_FORCE_REGISTER, false); if (accounts.size() == 1) { intent.putExtra("jid", accounts.get(0).getJid().asBareJid().toString()); intent.putExtra("init", true); @@ -117,8 +181,15 @@ public class WelcomeActivity extends XmppActivity { } } - public void addInviteUri(Intent intent) { - StartConversationActivity.addInviteUri(intent, getIntent()); + public void addInviteUri(Intent to) { + final Intent from = getIntent(); + if (from != null && from.hasExtra(StartConversationActivity.EXTRA_INVITE_URI)) { + final String invite = from.getStringExtra(StartConversationActivity.EXTRA_INVITE_URI); + to.putExtra(StartConversationActivity.EXTRA_INVITE_URI, invite); + } else if (this.inviteUri != null) { + Log.d(Config.LOGTAG,"injecting referrer uri into on-boarding flow"); + to.putExtra(StartConversationActivity.EXTRA_INVITE_URI, this.inviteUri.toString()); + } } public static void launch(AppCompatActivity activity) { diff --git a/src/conversations/java/eu/siacs/conversations/utils/SignupUtils.java b/src/conversations/java/eu/siacs/conversations/utils/SignupUtils.java index a47dfbca8..bcf601a8f 100644 --- a/src/conversations/java/eu/siacs/conversations/utils/SignupUtils.java +++ b/src/conversations/java/eu/siacs/conversations/utils/SignupUtils.java @@ -17,6 +17,8 @@ import rocks.xmpp.addr.Jid; public class SignupUtils { + public static final String INSTALL_REFERRER = "install_referrer"; + public static boolean isSupportTokenRegistry() { return true; } diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index 9273df976..9e7555a6f 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -193,7 +193,7 @@ public class PresenceParser extends AbstractParser implements final Jid alternate; if (gone != null) { final XmppUri xmppUri = new XmppUri(gone); - if (xmppUri.isJidValid()) { + if (xmppUri.isValidJid()) { alternate = xmppUri.getJid(); } else { alternate = null; diff --git a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java index b79c32f5c..df2f7d849 100644 --- a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java @@ -348,7 +348,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im if (activityResult.resultCode == RESULT_OK && activityResult.requestCode == ScanActivity.REQUEST_SCAN_QR_CODE) { String result = activityResult.data.getStringExtra(ScanActivity.INTENT_EXTRA_RESULT); XmppUri uri = new XmppUri(result == null ? "" : result); - if (uri.isJidValid()) { + if (uri.isValidJid()) { showEnterJidDialog(uri); } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java index 72d6b3006..833149221 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java @@ -41,12 +41,10 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.databinding.DataBindingUtil; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.support.annotation.IdRes; import android.support.annotation.NonNull; -import android.support.annotation.RequiresApi; import android.support.v7.app.ActionBar; import android.support.v7.app.AlertDialog; import android.support.v7.widget.Toolbar; @@ -73,7 +71,6 @@ import eu.siacs.conversations.ui.interfaces.OnConversationArchived; import eu.siacs.conversations.ui.interfaces.OnConversationRead; import eu.siacs.conversations.ui.interfaces.OnConversationSelected; import eu.siacs.conversations.ui.interfaces.OnConversationsListItemUpdated; -import eu.siacs.conversations.ui.service.EmojiService; import eu.siacs.conversations.ui.util.ActivityResult; import eu.siacs.conversations.ui.util.ConversationMenuConfigurator; import eu.siacs.conversations.ui.util.MenuDoubleTabUtil; @@ -460,7 +457,7 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio public boolean onXmppUriClicked(Uri uri) { XmppUri xmppUri = new XmppUri(uri); - if (xmppUri.isJidValid() && !xmppUri.hasFingerprints()) { + if (xmppUri.isValidJid() && !xmppUri.hasFingerprints()) { final Conversation conversation = xmppConnectionService.findUniqueConversationByJid(xmppUri); if (conversation != null) { openConversation(conversation, null); diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index 4e6b8fe51..a75ef519b 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -823,7 +823,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne if (inviteUri != null) { final Invite invite = new Invite(inviteUri); invite.account = intent.getStringExtra(EXTRA_ACCOUNT); - if (invite.isJidValid()) { + if (invite.isValidJid()) { return invite.invite(); } } @@ -1020,7 +1020,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne conferenceJid = Jid.of(input); } catch (final IllegalArgumentException e) { final XmppUri xmppUri = new XmppUri(input); - if (xmppUri.isJidValid() && xmppUri.isAction(XmppUri.ACTION_JOIN)) { + if (xmppUri.isValidJid() && xmppUri.isAction(XmppUri.ACTION_JOIN)) { final Editable editable = jid.getEditableText(); editable.clear(); editable.append(xmppUri.getJid().toEscapedString()); @@ -1301,7 +1301,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne } boolean invite() { - if (!isJidValid()) { + if (!isValidJid()) { Toast.makeText(StartConversationActivity.this, R.string.invalid_jid, Toast.LENGTH_SHORT).show(); return false; } diff --git a/src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java b/src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java index 621ca629b..d5a88ebcd 100644 --- a/src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java @@ -9,14 +9,12 @@ import android.os.Build; import android.os.Bundle; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; -import android.util.Log; import android.widget.Toast; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.persistance.DatabaseBackend; import eu.siacs.conversations.utils.SignupUtils; @@ -89,7 +87,7 @@ public class UriHandlerActivity extends AppCompatActivity { final XmppUri xmppUri = new XmppUri(uri); final List accounts = DatabaseBackend.getInstance(this).getAccountJids(true); - if (SignupUtils.isSupportTokenRegistry() && xmppUri.isJidValid()) { + if (SignupUtils.isSupportTokenRegistry() && xmppUri.isValidJid()) { final String preauth = xmppUri.getParamater("preauth"); final Jid jid = xmppUri.getJid(); if (xmppUri.isAction(XmppUri.ACTION_REGISTER)) { @@ -110,7 +108,7 @@ public class UriHandlerActivity extends AppCompatActivity { } if (accounts.size() == 0) { - if (xmppUri.isJidValid()) { + if (xmppUri.isValidJid()) { intent = SignupUtils.getSignUpIntent(this); intent.putExtra(StartConversationActivity.EXTRA_INVITE_URI, xmppUri.toString()); startActivity(intent); @@ -157,7 +155,7 @@ public class UriHandlerActivity extends AppCompatActivity { intent.putExtra("jid", xmppUri.getJid().asBareJid().toString()); intent.setData(uri); intent.putExtra("scanned", scanned); - } else if (xmppUri.isJidValid()) { + } else if (xmppUri.isValidJid()) { intent = new Intent(getApplicationContext(), StartConversationActivity.class); intent.setAction(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); diff --git a/src/main/java/eu/siacs/conversations/ui/util/MyLinkify.java b/src/main/java/eu/siacs/conversations/ui/util/MyLinkify.java index d944f2d08..aa2aeb704 100644 --- a/src/main/java/eu/siacs/conversations/ui/util/MyLinkify.java +++ b/src/main/java/eu/siacs/conversations/ui/util/MyLinkify.java @@ -91,7 +91,7 @@ public class MyLinkify { private static final Linkify.MatchFilter XMPPURI_MATCH_FILTER = (s, start, end) -> { XmppUri uri = new XmppUri(s.subSequence(start, end).toString()); - return uri.isJidValid(); + return uri.isValidJid(); }; private static boolean isAlphabetic(final int code) { diff --git a/src/main/java/eu/siacs/conversations/ui/util/ShareUtil.java b/src/main/java/eu/siacs/conversations/ui/util/ShareUtil.java index 459be645b..b39de5cf9 100644 --- a/src/main/java/eu/siacs/conversations/ui/util/ShareUtil.java +++ b/src/main/java/eu/siacs/conversations/ui/util/ShareUtil.java @@ -132,7 +132,7 @@ public class ShareUtil { Matcher xmppPatternMatcher = Patterns.XMPP_PATTERN.matcher(body); if (xmppPatternMatcher.find()) { try { - return new XmppUri(body.substring(xmppPatternMatcher.start(), xmppPatternMatcher.end())).isJidValid(); + return new XmppUri(body.substring(xmppPatternMatcher.start(), xmppPatternMatcher.end())).isValidJid(); } catch (Exception e) { return false; } diff --git a/src/main/java/eu/siacs/conversations/utils/XmppUri.java b/src/main/java/eu/siacs/conversations/utils/XmppUri.java index df8ea09bc..e17c2ff3b 100644 --- a/src/main/java/eu/siacs/conversations/utils/XmppUri.java +++ b/src/main/java/eu/siacs/conversations/utils/XmppUri.java @@ -176,7 +176,7 @@ public class XmppUri { } } - public boolean isJidValid() { + public boolean isValidJid() { if (jid == null) { return false; }