UriHandlerActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.Manifest;
  4import android.app.Activity;
  5import android.content.Intent;
  6import android.content.pm.PackageManager;
  7import android.net.Uri;
  8import android.os.Build;
  9import android.os.Bundle;
 10import android.support.v4.content.ContextCompat;
 11import android.support.v7.app.AppCompatActivity;
 12import android.util.Log;
 13import android.widget.Toast;
 14
 15import java.util.List;
 16import java.util.regex.Matcher;
 17import java.util.regex.Pattern;
 18
 19import eu.siacs.conversations.Config;
 20import eu.siacs.conversations.R;
 21import eu.siacs.conversations.persistance.DatabaseBackend;
 22import eu.siacs.conversations.utils.SignupUtils;
 23import eu.siacs.conversations.utils.XmppUri;
 24import rocks.xmpp.addr.Jid;
 25
 26public class UriHandlerActivity extends AppCompatActivity {
 27
 28    public static final String ACTION_SCAN_QR_CODE = "scan_qr_code";
 29    private static final int REQUEST_SCAN_QR_CODE = 0x1234;
 30    private static final int REQUEST_CAMERA_PERMISSIONS_TO_SCAN = 0x6789;
 31    private static final Pattern VCARD_XMPP_PATTERN = Pattern.compile("\nIMPP([^:]*):(xmpp:.+)\n");
 32    private boolean handled = false;
 33
 34    public static void scan(Activity activity) {
 35        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
 36            Intent intent = new Intent(activity, UriHandlerActivity.class);
 37            intent.setAction(UriHandlerActivity.ACTION_SCAN_QR_CODE);
 38            intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
 39            activity.startActivity(intent);
 40        } else {
 41            activity.requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSIONS_TO_SCAN);
 42        }
 43    }
 44
 45    public static void onRequestPermissionResult(Activity activity, int requestCode, int[] grantResults) {
 46        if (requestCode != REQUEST_CAMERA_PERMISSIONS_TO_SCAN) {
 47            return;
 48        }
 49        if (grantResults.length > 0) {
 50            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
 51                scan(activity);
 52            } else {
 53                Toast.makeText(activity, R.string.qr_code_scanner_needs_access_to_camera, Toast.LENGTH_SHORT).show();
 54            }
 55        }
 56    }
 57
 58    @Override
 59    protected void onCreate(Bundle savedInstanceState) {
 60        super.onCreate(savedInstanceState);
 61        this.handled = savedInstanceState != null && savedInstanceState.getBoolean("handled", false);
 62        getLayoutInflater().inflate(R.layout.toolbar, findViewById(android.R.id.content));
 63        setSupportActionBar(findViewById(R.id.toolbar));
 64    }
 65
 66    @Override
 67    public void onStart() {
 68        super.onStart();
 69        handleIntent(getIntent());
 70    }
 71
 72    @Override
 73    public void onSaveInstanceState(Bundle savedInstanceState) {
 74        savedInstanceState.putBoolean("handled", this.handled);
 75        super.onSaveInstanceState(savedInstanceState);
 76    }
 77
 78    @Override
 79    public void onNewIntent(Intent intent) {
 80        handleIntent(intent);
 81    }
 82
 83    private void handleUri(Uri uri) {
 84        handleUri(uri, false);
 85    }
 86
 87    private void handleUri(Uri uri, final boolean scanned) {
 88        final Intent intent;
 89        final XmppUri xmppUri = new XmppUri(uri);
 90        final List<Jid> accounts = DatabaseBackend.getInstance(this).getAccountJids(true);
 91
 92        if (SignupUtils.isSupportTokenRegistry() && xmppUri.isJidValid()) {
 93            final String preauth = xmppUri.getParamater("preauth");
 94            final Jid jid = xmppUri.getJid();
 95            if (xmppUri.isAction(XmppUri.ACTION_REGISTER)) {
 96                if (jid.getEscapedLocal() != null && accounts.contains(jid.asBareJid())) {
 97                    Toast.makeText(this, R.string.account_already_exists, Toast.LENGTH_LONG).show();
 98                    return;
 99                }
100                intent = SignupUtils.getTokenRegistrationIntent(this, jid, preauth);
101                startActivity(intent);
102                return;
103            }
104            if (xmppUri.isAction(XmppUri.ACTION_ROSTER) && "y".equals(xmppUri.getParamater("ibr"))) {
105                intent = SignupUtils.getTokenRegistrationIntent(this, Jid.ofDomain(jid.getDomain()), preauth);
106                intent.putExtra(StartConversationActivity.EXTRA_INVITE_URI, xmppUri.toString());
107                startActivity(intent);
108                return;
109            }
110        }
111
112        if (accounts.size() == 0) {
113            if (xmppUri.isJidValid()) {
114                intent = SignupUtils.getSignUpIntent(this);
115                intent.putExtra(StartConversationActivity.EXTRA_INVITE_URI, xmppUri.toString());
116                startActivity(intent);
117            } else {
118                Toast.makeText(this, R.string.invalid_jid, Toast.LENGTH_SHORT).show();
119            }
120
121            return;
122        }
123
124        if (xmppUri.isAction(XmppUri.ACTION_MESSAGE)) {
125
126            final Jid jid = xmppUri.getJid();
127            final String body = xmppUri.getBody();
128
129            if (jid != null) {
130                Class clazz;
131                try {
132                    clazz = Class.forName("eu.siacs.conversations.ui.ShareViaAccountActivity");
133                } catch (ClassNotFoundException e) {
134                    clazz = null;
135
136                }
137                if (clazz != null) {
138                    intent = new Intent(this, clazz);
139                    intent.putExtra("contact", jid.toEscapedString());
140                    intent.putExtra("body", body);
141                } else {
142                    intent = new Intent(this, StartConversationActivity.class);
143                    intent.setAction(Intent.ACTION_VIEW);
144                    intent.setData(uri);
145                    intent.putExtra("account", accounts.get(0).toEscapedString());
146                }
147
148            } else {
149                intent = new Intent(this, ShareWithActivity.class);
150                intent.setAction(Intent.ACTION_SEND);
151                intent.setType("text/plain");
152                intent.putExtra(Intent.EXTRA_TEXT, body);
153            }
154        } else if (accounts.contains(xmppUri.getJid())) {
155            intent = new Intent(getApplicationContext(), EditAccountActivity.class);
156            intent.setAction(Intent.ACTION_VIEW);
157            intent.putExtra("jid", xmppUri.getJid().asBareJid().toString());
158            intent.setData(uri);
159            intent.putExtra("scanned", scanned);
160        } else if (xmppUri.isJidValid()) {
161            intent = new Intent(getApplicationContext(), StartConversationActivity.class);
162            intent.setAction(Intent.ACTION_VIEW);
163            intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
164            intent.putExtra("scanned", scanned);
165            intent.setData(uri);
166        } else {
167            Toast.makeText(this, R.string.invalid_jid, Toast.LENGTH_SHORT).show();
168            return;
169        }
170
171        startActivity(intent);
172    }
173
174    private void handleIntent(Intent data) {
175        if (handled) {
176            return;
177        }
178        if (data == null || data.getAction() == null) {
179            finish();
180            return;
181        }
182
183        handled = true;
184
185        switch (data.getAction()) {
186            case Intent.ACTION_VIEW:
187            case Intent.ACTION_SENDTO:
188                handleUri(data.getData());
189                break;
190            case ACTION_SCAN_QR_CODE:
191                Intent intent = new Intent(this, ScanActivity.class);
192                startActivityForResult(intent, REQUEST_SCAN_QR_CODE);
193                return;
194        }
195
196        finish();
197    }
198
199    @Override
200    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
201        super.onActivityResult(requestCode, requestCode, intent);
202        if (requestCode == REQUEST_SCAN_QR_CODE && resultCode == RESULT_OK) {
203            String result = intent.getStringExtra(ScanActivity.INTENT_EXTRA_RESULT);
204            if (result != null) {
205                if (result.startsWith("BEGIN:VCARD\n")) {
206                    Matcher matcher = VCARD_XMPP_PATTERN.matcher(result);
207                    if (matcher.find()) {
208                        result = matcher.group(2);
209                    }
210                }
211                Uri uri = Uri.parse(result);
212                handleUri(uri, true);
213            }
214        }
215        finish();
216    }
217}