Option to show your own QR code from the QR code scanner

Stephen Paul Weber created

Change summary

build.gradle                                              |  2 
src/cheogram/res/menu/scan_activity.xml                   | 11 ++
src/main/AndroidManifest.xml                              |  1 
src/main/java/eu/siacs/conversations/ui/ScanActivity.java | 24 ++++
src/main/java/eu/siacs/conversations/ui/XmppActivity.java | 25 ++++
src/main/res/layout/activity_scan.xml                     | 46 ++++++--
6 files changed, 91 insertions(+), 18 deletions(-)

Detailed changes

build.gradle 🔗

@@ -317,7 +317,7 @@ android {
             if (baseAbiVersionCode != null) {
                 output.versionCodeOverride = (100 * project.android.defaultConfig.versionCode) + baseAbiVersionCode
             } else {
-                output.versionCodeOverride = (100 * project.android.defaultConfig.versionCode) + 1
+                output.versionCodeOverride = (100 * project.android.defaultConfig.versionCode) + 2
             }
         }
 

src/cheogram/res/menu/scan_activity.xml 🔗

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+      xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <item
+        app:showAsAction="always"
+        android:icon="@drawable/ic_qr_code_24dp"
+        android:id="@+id/action_show_qr_code"
+        android:title="@string/show_qr_code"/>
+
+</menu>

src/main/AndroidManifest.xml 🔗

@@ -211,7 +211,6 @@
             android:name=".ui.ScanActivity"
             android:exported="false"
             android:screenOrientation="portrait"
-            android:theme="@style/Theme.Conversations3.FullScreen"
             android:windowSoftInputMode="stateAlwaysHidden" />
         <activity
             android:name=".ui.UriHandlerActivity"

src/main/java/eu/siacs/conversations/ui/ScanActivity.java 🔗

@@ -35,6 +35,7 @@ import android.os.Process;
 import android.os.Vibrator;
 import android.util.Log;
 import android.view.KeyEvent;
+import android.view.Menu;
 import android.view.Surface;
 import android.view.TextureView;
 import android.view.TextureView.SurfaceTextureListener;
@@ -67,7 +68,7 @@ import eu.siacs.conversations.ui.widget.ScannerView;
  * @author Andreas Schildbach
  */
 @SuppressWarnings("deprecation")
-public final class ScanActivity extends Activity implements SurfaceTextureListener, ActivityCompat.OnRequestPermissionsResultCallback {
+public final class ScanActivity extends XmppActivity implements SurfaceTextureListener, ActivityCompat.OnRequestPermissionsResultCallback {
 	public static final String INTENT_EXTRA_RESULT = "result";
 
 	public static final int REQUEST_SCAN_QR_CODE = 0x0987;
@@ -170,6 +171,12 @@ public final class ScanActivity extends Activity implements SurfaceTextureListen
 		vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
 
 		setContentView(R.layout.activity_scan);
+		setSupportActionBar(findViewById(R.id.toolbar));
+		final var actionBar = getSupportActionBar();
+		configureActionBar(actionBar);
+		actionBar.setTitle("Scan Contact QR Code");
+		Activities.setStatusAndNavigationBarColors(this, findViewById(android.R.id.content));
+
 		scannerView = findViewById(R.id.scan_activity_mask);
 		previewView = findViewById(R.id.scan_activity_preview);
 		previewView.setSurfaceTextureListener(this);
@@ -186,7 +193,7 @@ public final class ScanActivity extends Activity implements SurfaceTextureListen
 	}
 
 	@Override
-	protected void onPause() {
+	public void onPause() {
 		cameraHandler.post(closeRunnable);
 
 		super.onPause();
@@ -203,6 +210,19 @@ public final class ScanActivity extends Activity implements SurfaceTextureListen
 		super.onDestroy();
 	}
 
+	@Override
+	public void onBackendConnected() { }
+
+	@Override
+	public void refreshUiReal() { }
+
+	@Override
+	public boolean onCreateOptionsMenu(final Menu menu) {
+		super.onCreateOptionsMenu(menu);
+		getMenuInflater().inflate(R.menu.scan_activity, menu);
+		return true;
+	}
+
 	private void maybeOpenCamera() {
 		if (surfaceCreated && ContextCompat.checkSelfPermission(this,
 				Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)

src/main/java/eu/siacs/conversations/ui/XmppActivity.java 🔗

@@ -59,6 +59,7 @@ import androidx.databinding.DataBindingUtil;
 import com.google.android.material.color.MaterialColors;
 import com.google.android.material.dialog.MaterialAlertDialogBuilder;
 import com.google.common.base.Strings;
+import com.google.common.collect.Collections2;
 
 import java.io.IOException;
 import java.lang.ref.WeakReference;
@@ -66,6 +67,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.PriorityQueue;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.RejectedExecutionException;
 
 import eu.siacs.conversations.AppSettings;
@@ -967,7 +969,28 @@ public abstract class XmppActivity extends ActionBarActivity {
     }
 
     protected void showQrCode() {
-        showQrCode(getShareableUri());
+        final var uri = getShareableUri();
+        if (uri != null) {
+            showQrCode(uri);
+            return;
+        }
+
+        final var accounts = xmppConnectionService.getAccounts();
+        if (accounts.size() < 1) return;
+
+        if (accounts.size() == 1) {
+            showQrCode(accounts.get(0).getShareableUri());
+            return;
+        }
+
+        final AtomicReference<Account> selectedAccount = new AtomicReference<>(accounts.get(0));
+        final MaterialAlertDialogBuilder alertDialogBuilder = new MaterialAlertDialogBuilder(this);
+        alertDialogBuilder.setTitle(R.string.choose_account);
+        final String[] asStrings = Collections2.transform(accounts, a -> a.getJid().asBareJid().toEscapedString()).toArray(new String[0]);
+        alertDialogBuilder.setSingleChoiceItems(asStrings, 0, (dialog, which) -> selectedAccount.set(accounts.get(which)));
+        alertDialogBuilder.setNegativeButton(R.string.cancel, null);
+        alertDialogBuilder.setPositiveButton(R.string.ok, (dialog, which) -> showQrCode(selectedAccount.get().getShareableUri()));
+        alertDialogBuilder.create().show();
     }
 
     protected void showQrCode(final String uri) {

src/main/res/layout/activity_scan.xml 🔗

@@ -1,17 +1,37 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<merge xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent" >
-
-    <TextureView
-        android:id="@+id/scan_activity_preview"
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:keepScreenOn="true" />
+        android:orientation="vertical">
 
-    <eu.siacs.conversations.ui.widget.ScannerView
-        android:id="@+id/scan_activity_mask"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
+        <com.google.android.material.appbar.AppBarLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+            <com.google.android.material.appbar.MaterialToolbar
+                android:id="@+id/toolbar"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:minHeight="?attr/actionBarSize" />
+
+        </com.google.android.material.appbar.AppBarLayout>
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+
+            <TextureView
+                android:id="@+id/scan_activity_preview"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:keepScreenOn="true" />
+
+            <eu.siacs.conversations.ui.widget.ScannerView
+                android:id="@+id/scan_activity_mask"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent" />
+        </RelativeLayout>
 
-</merge>
+    </LinearLayout>
+</layout>