WelcomeActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.Manifest;
  4import android.content.ActivityNotFoundException;
  5import android.content.Intent;
  6import android.content.pm.ActivityInfo;
  7import android.net.Uri;
  8import android.os.Bundle;
  9import android.security.KeyChain;
 10import android.security.KeyChainAliasCallback;
 11import android.util.Log;
 12import android.view.Menu;
 13import android.view.MenuItem;
 14import android.widget.Toast;
 15
 16import androidx.annotation.NonNull;
 17import androidx.appcompat.app.AppCompatActivity;
 18import androidx.databinding.DataBindingUtil;
 19
 20import java.util.Arrays;
 21import java.util.List;
 22
 23import eu.siacs.conversations.Config;
 24import eu.siacs.conversations.R;
 25import eu.siacs.conversations.databinding.ActivityWelcomeBinding;
 26import eu.siacs.conversations.entities.Account;
 27import eu.siacs.conversations.services.XmppConnectionService;
 28import eu.siacs.conversations.utils.Compatibility;
 29import eu.siacs.conversations.utils.InstallReferrerUtils;
 30import eu.siacs.conversations.utils.SignupUtils;
 31import eu.siacs.conversations.utils.XmppUri;
 32import eu.siacs.conversations.xmpp.Jid;
 33
 34import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
 35import static eu.siacs.conversations.utils.PermissionUtils.writeGranted;
 36
 37import com.google.common.base.Strings;
 38
 39public class WelcomeActivity extends XmppActivity
 40        implements XmppConnectionService.OnAccountCreated, KeyChainAliasCallback {
 41
 42    private static final int REQUEST_IMPORT_BACKUP = 0x63fb;
 43
 44    private XmppUri inviteUri;
 45
 46    public static void launch(AppCompatActivity activity) {
 47        Intent intent = new Intent(activity, WelcomeActivity.class);
 48        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
 49        activity.startActivity(intent);
 50        activity.overridePendingTransition(0, 0);
 51    }
 52
 53    public void onInstallReferrerDiscovered(final Uri referrer) {
 54        Log.d(Config.LOGTAG, "welcome activity: on install referrer discovered " + referrer);
 55        if ("xmpp".equalsIgnoreCase(referrer.getScheme())) {
 56            final XmppUri xmppUri = new XmppUri(referrer);
 57            runOnUiThread(() -> processXmppUri(xmppUri));
 58        } else {
 59            Log.i(Config.LOGTAG, "install referrer was not an XMPP uri");
 60        }
 61    }
 62
 63    private void processXmppUri(final XmppUri xmppUri) {
 64        if (!xmppUri.isValidJid()) {
 65            return;
 66        }
 67        final String preAuth = xmppUri.getParameter(XmppUri.PARAMETER_PRE_AUTH);
 68        final Jid jid = xmppUri.getJid();
 69        final Intent intent;
 70        if (xmppUri.isAction(XmppUri.ACTION_REGISTER)) {
 71            intent = SignupUtils.getTokenRegistrationIntent(this, jid, preAuth);
 72        } else if (xmppUri.isAction(XmppUri.ACTION_ROSTER)
 73                && "y".equals(xmppUri.getParameter(XmppUri.PARAMETER_IBR))) {
 74            intent = SignupUtils.getTokenRegistrationIntent(this, jid.getDomain(), preAuth);
 75            intent.putExtra(StartConversationActivity.EXTRA_INVITE_URI, xmppUri.toString());
 76        } else {
 77            intent = null;
 78        }
 79        if (intent != null) {
 80            startActivity(intent);
 81            finish();
 82            return;
 83        }
 84        this.inviteUri = xmppUri;
 85    }
 86
 87    @Override
 88    protected void refreshUiReal() {}
 89
 90    @Override
 91    protected void onBackendConnected() {}
 92
 93    @Override
 94    public void onStart() {
 95        super.onStart();
 96        new InstallReferrerUtils(this);
 97    }
 98
 99    @Override
100    public void onStop() {
101        super.onStop();
102    }
103
104    @Override
105    public void onNewIntent(final Intent intent) {
106        super.onNewIntent(intent);
107        if (intent != null) {
108            setIntent(intent);
109        }
110    }
111
112    @Override
113    protected void onCreate(final Bundle savedInstanceState) {
114        if (getResources().getBoolean(R.bool.portrait_only)) {
115            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
116        }
117        super.onCreate(savedInstanceState);
118        ActivityWelcomeBinding binding =
119                DataBindingUtil.setContentView(this, R.layout.activity_welcome);
120        Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
121        setSupportActionBar(binding.toolbar);
122        configureActionBar(getSupportActionBar(), false);
123        setTitle(null);
124        binding.registerNewAccount.setOnClickListener(
125                v -> {
126                    final Intent intent = new Intent(this, PickServerActivity.class);
127                    addInviteUri(intent);
128                    startActivity(intent);
129                });
130        binding.useExisting.setOnClickListener(
131                v -> {
132                    final List<Account> accounts = xmppConnectionService.getAccounts();
133                    Intent intent = new Intent(this, EditAccountActivity.class);
134                    intent.putExtra(EditAccountActivity.EXTRA_FORCE_REGISTER, false);
135                    if (accounts.size() == 1) {
136                        intent.putExtra("jid", accounts.get(0).getJid().asBareJid().toString());
137                        intent.putExtra("init", true);
138                    } else if (!accounts.isEmpty()) {
139                        intent = new Intent(this, ManageAccountActivity.class);
140                    }
141                    addInviteUri(intent);
142                    startActivity(intent);
143                });
144    }
145
146    @Override
147    public boolean onCreateOptionsMenu(final Menu menu) {
148        getMenuInflater().inflate(R.menu.welcome_menu, menu);
149        final MenuItem scan = menu.findItem(R.id.action_scan_qr_code);
150        scan.setVisible(Compatibility.hasFeatureCamera(this));
151        return super.onCreateOptionsMenu(menu);
152    }
153
154    @Override
155    public boolean onOptionsItemSelected(final MenuItem item) {
156        switch (item.getItemId()) {
157            case R.id.action_import_backup:
158                if (hasStoragePermission(REQUEST_IMPORT_BACKUP)) {
159                    startActivity(new Intent(this, ImportBackupActivity.class));
160                }
161                break;
162            case R.id.action_scan_qr_code:
163                UriHandlerActivity.scan(this, true);
164                break;
165            case R.id.action_add_account_with_cert:
166                addAccountFromKey();
167                break;
168        }
169        return super.onOptionsItemSelected(item);
170    }
171
172    private void addAccountFromKey() {
173        try {
174            KeyChain.choosePrivateKeyAlias(this, this, null, null, null, -1, null);
175        } catch (final ActivityNotFoundException e) {
176            Toast.makeText(this, R.string.device_does_not_support_certificates, Toast.LENGTH_LONG)
177                    .show();
178        }
179    }
180
181    @Override
182    public void alias(final String alias) {
183        if (Strings.isNullOrEmpty(alias)) {
184            runOnUiThread(
185                    () ->
186                            Toast.makeText(
187                                            this,
188                                            R.string.no_certificate_selected,
189                                            Toast.LENGTH_LONG)
190                                    .show());
191            return;
192        }
193        xmppConnectionService.createAccountFromKey(alias, this);
194    }
195
196    @Override
197    public void onAccountCreated(final Account account) {
198        final Intent intent = new Intent(this, EditAccountActivity.class);
199        intent.putExtra("jid", account.getJid().asBareJid().toEscapedString());
200        intent.putExtra("init", true);
201        addInviteUri(intent);
202        startActivity(intent);
203    }
204
205    @Override
206    public void informUser(final int r) {
207        runOnUiThread(() -> Toast.makeText(this, r, Toast.LENGTH_LONG).show());
208    }
209
210    @Override
211    public void onRequestPermissionsResult(
212            int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
213        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
214        UriHandlerActivity.onRequestPermissionResult(this, requestCode, grantResults);
215        if (grantResults.length > 0) {
216            if (allGranted(grantResults)) {
217                switch (requestCode) {
218                    case REQUEST_IMPORT_BACKUP:
219                        startActivity(new Intent(this, ImportBackupActivity.class));
220                        break;
221                }
222            } else if (Arrays.asList(permissions)
223                    .contains(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
224                Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show();
225            }
226        }
227        if (writeGranted(grantResults, permissions)) {
228            if (xmppConnectionService != null) {
229                xmppConnectionService.restartFileObserver();
230            }
231        }
232    }
233
234    public void addInviteUri(Intent to) {
235        final Intent from = getIntent();
236        if (from != null && from.hasExtra(StartConversationActivity.EXTRA_INVITE_URI)) {
237            final String invite = from.getStringExtra(StartConversationActivity.EXTRA_INVITE_URI);
238            to.putExtra(StartConversationActivity.EXTRA_INVITE_URI, invite);
239        } else if (this.inviteUri != null) {
240            Log.d(Config.LOGTAG, "injecting referrer uri into on-boarding flow");
241            to.putExtra(StartConversationActivity.EXTRA_INVITE_URI, this.inviteUri.toString());
242        }
243    }
244}