WelcomeActivity.java

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