From 0d3e358628615d4397842dedb22b37cd1130b05e Mon Sep 17 00:00:00 2001 From: Dan Sandler Date: Fri, 22 Nov 2019 11:58:58 -0500 Subject: [PATCH] Action chips in share sheet. (DO NOT MERGE) Move the Copy button to a new row of chips below the (now larger) preview. Optionally, if a proximity-sharing service is installed, show that chip as well. Bug: 143229724 Fixes: 144290152 Test: atest SystemUITests frameworks/base/core/tests/coretests Change-Id: I0d6457df85bc937f72ca97da6b4b84b634a90daf --- core/java/android/provider/Settings.java | 8 ++ .../com/android/internal/app/ChooserActivity.java | 105 ++++++++++++++++++++- core/res/res/drawable/chooser_action_button_bg.xml | 33 +++++++ core/res/res/drawable/ic_content_copy_gm2.xml | 25 ----- core/res/res/drawable/ic_menu_copy_material.xml | 39 ++++---- core/res/res/layout/chooser_action_button.xml | 28 ++++++ core/res/res/layout/chooser_action_row.xml | 26 +++++ core/res/res/layout/chooser_grid_preview_file.xml | 15 +-- core/res/res/layout/chooser_grid_preview_image.xml | 9 ++ core/res/res/layout/chooser_grid_preview_text.xml | 43 ++------- core/res/res/values/config.xml | 4 + core/res/res/values/dimens.xml | 1 + core/res/res/values/ids.xml | 3 + core/res/res/values/symbols.xml | 8 +- .../android/internal/app/ChooserActivityTest.java | 4 +- 15 files changed, 257 insertions(+), 94 deletions(-) create mode 100644 core/res/res/drawable/chooser_action_button_bg.xml delete mode 100644 core/res/res/drawable/ic_content_copy_gm2.xml create mode 100644 core/res/res/layout/chooser_action_button.xml create mode 100644 core/res/res/layout/chooser_action_row.xml diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index f48be0e3242f..b9f5348027e6 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -8946,6 +8946,14 @@ public final class Settings { new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1", "2"}); /** + * Current provider of proximity-based sharing services. + * Default value in @string/config_defaultNearbySharingComponent. + * No VALIDATOR as this setting will not be backed up. + * @hide + */ + public static final String NEARBY_SHARING_COMPONENT = "nearby_sharing_component"; + + /** * Controls whether aware is enabled. * @hide */ diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index cae1f3831b4a..76f5099b51a3 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -81,6 +81,7 @@ import android.provider.DeviceConfig; import android.provider.DocumentsContract; import android.provider.Downloads; import android.provider.OpenableColumns; +import android.provider.Settings; import android.service.chooser.ChooserTarget; import android.service.chooser.ChooserTargetService; import android.service.chooser.IChooserTargetResult; @@ -103,6 +104,7 @@ import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.widget.AbsListView; import android.widget.BaseAdapter; +import android.widget.Button; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; @@ -122,6 +124,7 @@ import com.google.android.collect.Lists; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.net.URISyntaxException; import java.text.Collator; import java.util.ArrayList; import java.util.Arrays; @@ -152,6 +155,9 @@ public class ChooserActivity extends ResolverActivity { private static final String PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions"; + private static final String CHIP_LABEL_METADATA_KEY = "android.service.chooser.chip_label"; + private static final String CHIP_ICON_METADATA_KEY = "android.service.chooser.chip_icon"; + private static final boolean DEBUG = false; /** @@ -515,6 +521,15 @@ public class ChooserActivity extends ResolverActivity { mIsSuccessfullySelected = false; Intent intent = getIntent(); Parcelable targetParcelable = intent.getParcelableExtra(Intent.EXTRA_INTENT); + if (targetParcelable instanceof Uri) { + try { + targetParcelable = Intent.parseUri(targetParcelable.toString(), + Intent.URI_INTENT_SCHEME); + } catch (URISyntaxException ex) { + // doesn't parse as an intent; let the next test fail and error out + } + } + if (!(targetParcelable instanceof Intent)) { Log.w("ChooserActivity", "Target is not an intent: " + targetParcelable); finish(); @@ -864,6 +879,85 @@ public class ChooserActivity extends ResolverActivity { } } + private ComponentName getNearbySharingComponent() { + String nearbyComponent = Settings.Secure.getString( + getContentResolver(), + Settings.Secure.NEARBY_SHARING_COMPONENT); + if (TextUtils.isEmpty(nearbyComponent)) { + nearbyComponent = getString(R.string.config_defaultNearbySharingComponent); + } + if (TextUtils.isEmpty(nearbyComponent)) { + return null; + } + return ComponentName.unflattenFromString(nearbyComponent); + } + + private TargetInfo getNearbySharingTarget(Intent originalIntent) { + final ComponentName cn = getNearbySharingComponent(); + if (cn == null) return null; + + final Intent resolveIntent = new Intent(); + resolveIntent.setComponent(cn); + final ResolveInfo ri = getPackageManager().resolveActivity(resolveIntent, 0); + if (ri == null) { + Log.e(TAG, "Device-specified nearby sharing component (" + cn + + ") not available"); + return null; + } + + // TODO(b/144290152): CHIP_LABEL_METADATA_KEY / CHIP_ICON_METADATA_KEY + + CharSequence name = ri.loadLabel(getPackageManager()); + + final DisplayResolveInfo dri = new DisplayResolveInfo( + originalIntent, ri, name, "", null); + dri.setDisplayIcon(ri.loadIcon(getPackageManager())); + return dri; + } + + private Button createActionButton(Drawable icon, CharSequence title, View.OnClickListener r) { + Button b = (Button) LayoutInflater.from(this).inflate(R.layout.chooser_action_button, null); + if (icon != null) { + final int size = getResources() + .getDimensionPixelSize(R.dimen.chooser_action_button_icon_size); + icon.setBounds(0, 0, size, size); + b.setCompoundDrawablesRelative(icon, null, null, null); + } + b.setText(title); + b.setOnClickListener(r); + return b; + } + + private Button createCopyButton() { + final Button b = createActionButton( + getDrawable(R.drawable.ic_menu_copy_material), + getString(R.string.copy), this::onCopyButtonClicked); + b.setId(R.id.chooser_copy_button); + return b; + } + + private @Nullable Button createNearbyButton(Intent originalIntent) { + final TargetInfo ti = getNearbySharingTarget(originalIntent); + if (ti == null) return null; + + return createActionButton( + ti.getDisplayIcon(), + ti.getDisplayLabel(), + (View unused) -> safelyStartActivity(ti) + ); + } + + private void addActionButton(ViewGroup parent, Button b) { + if (b == null) return; + final ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams( + LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT + ); + final int gap = getResources().getDimensionPixelSize(R.dimen.resolver_icon_margin) / 2; + lp.setMarginsRelative(gap, 0, gap, 0); + parent.addView(b, lp); + } + private ViewGroup displayContentPreview(@ContentPreviewType int previewType, Intent targetIntent, LayoutInflater layoutInflater, ViewGroup convertView, ViewGroup parent) { @@ -897,8 +991,10 @@ public class ChooserActivity extends ResolverActivity { ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate( R.layout.chooser_grid_preview_text, parent, false); - contentPreviewLayout.findViewById(R.id.copy_button).setOnClickListener( - this::onCopyButtonClicked); + final ViewGroup actionRow = + (ViewGroup) contentPreviewLayout.findViewById(R.id.chooser_action_row); + addActionButton(actionRow, createCopyButton()); + addActionButton(actionRow, createNearbyButton(targetIntent)); CharSequence sharingText = targetIntent.getCharSequenceExtra(Intent.EXTRA_TEXT); if (sharingText == null) { @@ -1056,7 +1152,8 @@ public class ChooserActivity extends ResolverActivity { // TODO(b/120417119): Disable file copy until after moving to sysui, // due to permissions issues - contentPreviewLayout.findViewById(R.id.file_copy_button).setVisibility(View.GONE); + //((ViewGroup) contentPreviewLayout.findViewById(R.id.chooser_action_row)) + // .addView(createCopyButton()); String action = targetIntent.getAction(); if (Intent.ACTION_SEND.equals(action)) { @@ -1507,7 +1604,7 @@ public class ChooserActivity extends ResolverActivity { } return new IntentFilter(intent.getAction(), dataString); } catch (Exception e) { - Log.e(TAG, "failed to get target intent filter " + e); + Log.e(TAG, "failed to get target intent filter", e); return null; } } diff --git a/core/res/res/drawable/chooser_action_button_bg.xml b/core/res/res/drawable/chooser_action_button_bg.xml new file mode 100644 index 000000000000..a434c0b9b6a9 --- /dev/null +++ b/core/res/res/drawable/chooser_action_button_bg.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + diff --git a/core/res/res/drawable/ic_content_copy_gm2.xml b/core/res/res/drawable/ic_content_copy_gm2.xml deleted file mode 100644 index ee58738b75d0..000000000000 --- a/core/res/res/drawable/ic_content_copy_gm2.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - diff --git a/core/res/res/drawable/ic_menu_copy_material.xml b/core/res/res/drawable/ic_menu_copy_material.xml index c03723b1fb33..ee58738b75d0 100644 --- a/core/res/res/drawable/ic_menu_copy_material.xml +++ b/core/res/res/drawable/ic_menu_copy_material.xml @@ -1,26 +1,25 @@ - + - + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + diff --git a/core/res/res/layout/chooser_action_button.xml b/core/res/res/layout/chooser_action_button.xml new file mode 100644 index 000000000000..562f188bbc6b --- /dev/null +++ b/core/res/res/layout/chooser_action_button.xml @@ -0,0 +1,28 @@ + + +