From e7ccbf436e97ab6da611ee6f9b2f07e5fbbed55b Mon Sep 17 00:00:00 2001 From: chelseahao Date: Fri, 24 Jan 2025 13:12:24 +0800 Subject: [PATCH] Update audio sharing dialog text. Also add a radius to the qr code image. Test: atest Bug: 381775542 Flag: com.android.settingslib.flags.enable_le_audio_sharing Change-Id: I6b06b02f63bc46ec20b7a9e0aa236f2547a5f612 --- .../bluetooth_audio_streams_qr_code.xml | 4 +-- .../bluetooth_audio_streams_qr_code.xml | 6 ++-- .../dialog_custom_body_audio_sharing.xml | 9 +++++ res/values/dimens.xml | 1 + res/values/strings.xml | 4 +++ .../AudioSharingDialogFactory.java | 23 +++++++++--- .../AudioSharingDialogFragment.java | 23 ++++++++---- .../AudioStreamsQrCodeFragment.java | 36 ++++++++++++------- .../AudioSharingDialogFragmentTest.java | 13 +++++++ 9 files changed, 90 insertions(+), 29 deletions(-) diff --git a/res/layout-land/bluetooth_audio_streams_qr_code.xml b/res/layout-land/bluetooth_audio_streams_qr_code.xml index 432d75e69d6..918b3ac60b9 100644 --- a/res/layout-land/bluetooth_audio_streams_qr_code.xml +++ b/res/layout-land/bluetooth_audio_streams_qr_code.xml @@ -45,8 +45,8 @@ diff --git a/res/layout/bluetooth_audio_streams_qr_code.xml b/res/layout/bluetooth_audio_streams_qr_code.xml index ab61f50e836..7c023551ab1 100644 --- a/res/layout/bluetooth_audio_streams_qr_code.xml +++ b/res/layout/bluetooth_audio_streams_qr_code.xml @@ -38,11 +38,11 @@ + android:layout_marginTop="70dp"/> + + 16dp 264dp + 1.8dp 300dp 30dp 16dp diff --git a/res/values/strings.xml b/res/values/strings.xml index 9930c3685c0..4470161da78 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -13873,6 +13873,10 @@ Close Connect another pair of compatible headphones, or share your stream\'s name and password with the other person + + Let others scan this code and listen to your audio\n\nStream name: %1$s\nPassword: %2$s + + or pair another set of compatible headphones Pair another set of compatible headphones, or share your audio stream QR code with the other person diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFactory.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFactory.java index b16bceb7c10..3d46361f983 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFactory.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFactory.java @@ -18,7 +18,7 @@ package com.android.settings.connecteddevice.audiosharing; import android.content.Context; import android.content.DialogInterface; -import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; @@ -162,13 +162,13 @@ public class AudioSharingDialogFactory { /** * Sets the custom image of the dialog custom body. * - * @param bitmap The bitmap to be used for the image. + * @param drawable The drawable to be used for the image. * @return This builder. */ @NonNull - public AudioSharingDialogFactory.DialogBuilder setCustomImage(Bitmap bitmap) { + public AudioSharingDialogFactory.DialogBuilder setCustomImage(Drawable drawable) { ImageView image = mCustomBody.findViewById(R.id.description_image); - image.setImageBitmap(bitmap); + image.setImageDrawable(drawable); image.setVisibility(View.VISIBLE); return this; } @@ -202,6 +202,21 @@ public class AudioSharingDialogFactory { return this; } + /** + * Sets the custom message below image. + * + * @param messageRes Resource ID of the string to be used for the message body. + * @return This builder. + */ + @NonNull + public AudioSharingDialogFactory.DialogBuilder setCustomMessage2( + @StringRes int messageRes) { + TextView subTitle = mCustomBody.findViewById(R.id.description_text_2); + subTitle.setText(messageRes); + subTitle.setVisibility(View.VISIBLE); + return this; + } + /** * Sets the custom device actions of the dialog custom body. * diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java index c121f550687..cf71d5f4685 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java @@ -17,13 +17,13 @@ package com.android.settings.connecteddevice.audiosharing; import static com.android.settings.connecteddevice.audiosharing.AudioSharingDashboardFragment.SHARE_THEN_PAIR_REQUEST_CODE; -import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsQrCodeFragment.getQrCodeBitmap; +import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsQrCodeFragment.getQrCodeDrawable; import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.EXTRA_PAIR_AND_JOIN_SHARING; import android.app.Dialog; import android.app.settings.SettingsEnums; import android.bluetooth.BluetoothLeBroadcastMetadata; -import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.util.Log; import android.util.Pair; @@ -45,6 +45,7 @@ import com.android.settingslib.bluetooth.BluetoothUtils; import com.google.common.collect.Iterables; +import java.nio.charset.StandardCharsets; import java.util.List; public class AudioSharingDialogFragment extends InstrumentedDialogFragment { @@ -159,7 +160,6 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment { } if (deviceItems.isEmpty()) { builder.setTitle(R.string.audio_sharing_share_dialog_title) - .setCustomMessage(R.string.audio_sharing_dialog_connect_device_content) .setCustomPositiveButton( R.string.audio_sharing_pair_button_label, v -> { @@ -183,14 +183,23 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment { }); BluetoothLeBroadcastMetadata metadata = arguments.getParcelable( BUNDLE_KEY_BROADCAST_METADATA, BluetoothLeBroadcastMetadata.class); - Bitmap qrCodeBitmap = metadata == null ? null : getQrCodeBitmap(metadata, + Drawable qrCodeDrawable = metadata == null ? null : getQrCodeDrawable(metadata, getContext()).orElse(null); - if (qrCodeBitmap != null) { - builder.setCustomImage(qrCodeBitmap) - .setCustomNegativeButton(com.android.settings.R.string.cancel, + if (qrCodeDrawable != null) { + builder.setCustomImage(qrCodeDrawable) + .setCustomMessage( + getString( + R.string.audio_sharing_dialog_qr_code_content, + metadata.getBroadcastName(), + new String( + metadata.getBroadcastCode(), + StandardCharsets.UTF_8))) + .setCustomMessage2(R.string.audio_sharing_dialog_pair_new_device_content) + .setCustomNegativeButton(R.string.audio_streams_dialog_close, v -> onCancelClick()); } else { builder.setCustomImage(R.drawable.audio_sharing_guidance) + .setCustomMessage(R.string.audio_sharing_dialog_connect_device_content) .setCustomNegativeButton( R.string.audio_sharing_qrcode_button_label, v -> { diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeFragment.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeFragment.java index 656694d1b2b..daa7a2e1c23 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeFragment.java +++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeFragment.java @@ -19,7 +19,9 @@ package com.android.settings.connecteddevice.audiosharing.audiostreams; import android.app.settings.SettingsEnums; import android.bluetooth.BluetoothLeBroadcastMetadata; import android.content.Context; +import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; @@ -30,6 +32,8 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; import com.android.settings.R; import com.android.settings.bluetooth.Utils; @@ -70,15 +74,16 @@ public class AudioStreamsQrCodeFragment extends InstrumentedFragment { if (broadcastMetadata == null) { return; } - Bitmap bm = getQrCodeBitmap(broadcastMetadata, getActivity()).orElse(null); - if (bm == null) { + Drawable drawable = getQrCodeDrawable(broadcastMetadata, getActivity()).orElse( + null); + if (drawable == null) { return; } ThreadUtils.postOnMainThread( () -> { ((ImageView) view.requireViewById(R.id.qrcode_view)) - .setImageBitmap(bm); + .setImageDrawable(drawable); if (broadcastMetadata.getBroadcastCode() != null) { String password = new String( @@ -101,28 +106,33 @@ public class AudioStreamsQrCodeFragment extends InstrumentedFragment { }); } - /** Gets an optional bitmap from metadata. */ - public static Optional getQrCodeBitmap(@Nullable BluetoothLeBroadcastMetadata metadata, + /** Gets an optional drawable from metadata. */ + public static Optional getQrCodeDrawable( + @Nullable BluetoothLeBroadcastMetadata metadata, Context context) { if (metadata == null) { - Log.d(TAG, "getQrCodeBitmap: broadcastMetadata is empty!"); + Log.d(TAG, "getQrCodeDrawable: broadcastMetadata is empty!"); return Optional.empty(); } String metadataStr = BluetoothLeBroadcastMetadataExt.INSTANCE.toQrCodeString(metadata); if (metadataStr.isEmpty()) { - Log.d(TAG, "getQrCodeBitmap: metadataStr is empty!"); + Log.d(TAG, "getQrCodeDrawable: metadataStr is empty!"); return Optional.empty(); } - Log.d(TAG, "getQrCodeBitmap: metadata : " + metadata); + Log.d(TAG, "getQrCodeDrawable: metadata : " + metadata); try { - int qrcodeSize = - context.getResources().getDimensionPixelSize(R.dimen.audio_streams_qrcode_size); - Bitmap bitmap = QrCodeGenerator.encodeQrCode(metadataStr, qrcodeSize); - return Optional.of(bitmap); + Resources resources = context.getResources(); + int qrcodeSize = resources.getDimensionPixelSize(R.dimen.audio_streams_qrcode_size); + int margin = resources.getDimensionPixelSize(R.dimen.audio_streams_qrcode_margin); + Bitmap bitmap = QrCodeGenerator.encodeQrCode(metadataStr, qrcodeSize, margin); + RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(resources, bitmap); + drawable.setCornerRadius(resources.getDimensionPixelSize( + R.dimen.audio_streams_qrcode_preview_radius)); + return Optional.of(drawable); } catch (WriterException e) { Log.d( TAG, - "getQrCodeBitmap: broadcastMetadata " + "getQrCodeDrawable: broadcastMetadata " + metadata + " qrCode generation exception " + e); diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragmentTest.java index b4c0a2047be..145a5c7a549 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragmentTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragmentTest.java @@ -60,6 +60,7 @@ import org.robolectric.annotation.Config; import org.robolectric.shadow.api.Shadow; import org.robolectric.shadows.androidx.fragment.FragmentController; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; @@ -263,6 +264,18 @@ public class AudioSharingDialogFragmentTest { assertThat(dialog).isNotNull(); ImageView image = dialog.findViewById(R.id.description_image); assertThat(image).isNotNull(); + TextView text = dialog.findViewById(R.id.description_text); + assertThat(text).isNotNull(); + assertThat(METADATA).isNotNull(); + assertThat(text.getText().toString()).isEqualTo( + mParent.getString(R.string.audio_sharing_dialog_qr_code_content, + METADATA.getBroadcastName(), new String( + METADATA.getBroadcastCode(), + StandardCharsets.UTF_8))); + TextView textBottom = dialog.findViewById(R.id.description_text_2); + assertThat(textBottom).isNotNull(); + assertThat(textBottom.getText().toString()).isEqualTo( + mParent.getString(R.string.audio_sharing_dialog_pair_new_device_content)); Button cancelBtn = dialog.findViewById(R.id.negative_btn); assertThat(cancelBtn).isNotNull(); cancelBtn.performClick();