diff --git a/app/build.gradle b/app/build.gradle index c2c0330..09ee60c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,8 +34,8 @@ android { applicationId "com.stinnesbeck.nilsmg4" minSdk 27 targetSdk 36 - versionCode 60 - versionName "2.4.2" + versionCode 61 + versionName "2.4.3" // Nothing about the server ships in the APK: its URL and ingest token are entered in // the app's Server tab (ServerConfig), and the database is only reachable by the server. diff --git a/app/src/main/java/com/evsuite/abrp/MainActivity.java b/app/src/main/java/com/evsuite/abrp/MainActivity.java index 3fe59c7..fb7d9d6 100644 --- a/app/src/main/java/com/evsuite/abrp/MainActivity.java +++ b/app/src/main/java/com/evsuite/abrp/MainActivity.java @@ -483,10 +483,17 @@ public class MainActivity extends AppCompatActivity { float density = getResources().getDisplayMetrics().density; int pad = (int) (24 * density); + // On the head unit's wide, low screen the QR code sits left of the text: stacked, the + // code and status below a 240 dp QR code were cut off. Scrollable either way, so + // nothing can be clipped on any screen. + android.util.DisplayMetrics metrics = getResources().getDisplayMetrics(); + boolean wide = metrics.widthPixels > metrics.heightPixels; android.widget.LinearLayout panel = new android.widget.LinearLayout(this); - panel.setOrientation(android.widget.LinearLayout.VERTICAL); - panel.setGravity(android.view.Gravity.CENTER_HORIZONTAL); + panel.setOrientation(wide ? android.widget.LinearLayout.HORIZONTAL : android.widget.LinearLayout.VERTICAL); + panel.setGravity(wide ? android.view.Gravity.CENTER_VERTICAL : android.view.Gravity.CENTER_HORIZONTAL); panel.setPadding(pad, pad, pad, pad); + android.widget.LinearLayout column = new android.widget.LinearLayout(this); + column.setOrientation(android.widget.LinearLayout.VERTICAL); TextView instructions = new TextView(this); instructions.setTextAppearance(R.style.Text_EV_Secondary); ImageView qr = new ImageView(this); @@ -501,17 +508,37 @@ public class MainActivity extends AppCompatActivity { TextView status = new TextView(this); status.setTextAppearance(R.style.Text_EV_Body); status.setText(R.string.pair_starting); - panel.addView(instructions); android.widget.LinearLayout.LayoutParams qrParams = new android.widget.LinearLayout.LayoutParams(qrSize, qrSize); - qrParams.topMargin = pad / 2; - panel.addView(qr, qrParams); - panel.addView(code); - panel.addView(status); + android.widget.LinearLayout.LayoutParams columnParams; + if (wide) { + qrParams.rightMargin = pad; + columnParams = new android.widget.LinearLayout.LayoutParams( + 0, android.view.ViewGroup.LayoutParams.WRAP_CONTENT, 1f); + panel.addView(qr, qrParams); + panel.addView(column, columnParams); + column.addView(instructions); + } else { + qrParams.topMargin = pad / 2; + qrParams.bottomMargin = pad / 2; + columnParams = new android.widget.LinearLayout.LayoutParams( + android.view.ViewGroup.LayoutParams.MATCH_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT); + panel.addView(instructions); + panel.addView(qr, qrParams); + panel.addView(column, columnParams); + } + android.widget.LinearLayout.LayoutParams codeParams = new android.widget.LinearLayout.LayoutParams( + android.view.ViewGroup.LayoutParams.WRAP_CONTENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT); + codeParams.topMargin = pad / 2; + codeParams.bottomMargin = pad / 2; + column.addView(code, codeParams); + column.addView(status); + android.widget.ScrollView scroll = new android.widget.ScrollView(this); + scroll.addView(panel); final boolean[] cancelled = {false}; androidx.appcompat.app.AlertDialog dialog = new MaterialAlertDialogBuilder(this) .setTitle(R.string.pair_title) - .setView(panel) + .setView(scroll) .setNegativeButton(R.string.pair_cancel, null) .create(); // Shown only once the server has answered, so a failure leaves no empty QR frame. @@ -527,7 +554,9 @@ public class MainActivity extends AppCompatActivity { PairingClient.Request request = PairingClient.start(url, installationId); android.graphics.Bitmap bitmap = QrCode.generate(request.verificationUriComplete, 416); runOnUiThread(() -> { - instructions.setText(getString(R.string.pair_scan, request.verificationUri)); + // The code is in the sentence as well as below it, so it is readable + // wherever the text is. + instructions.setText(getString(R.string.pair_scan, request.verificationUri, request.userCode)); if (bitmap != null) { qr.setImageBitmap(bitmap); qr.setVisibility(View.VISIBLE); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f942d80..b92d940 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -58,7 +58,7 @@ Pair with phone Shows a QR code: scan it with your phone and approve with the approval password. The token below is then filled in for you. Pair with phone - Scan with your phone, or open %1$s and enter this code: + Scan the QR code with your phone, or open %1$s and enter the code %2$s: Waiting for approval… Contacting the server… Paired — this car now has its own token