From 48b7e3f855c165a9196a37d0a64b0d998fbc2711 Mon Sep 17 00:00:00 2001 From: Shen Lin Date: Thu, 13 Apr 2023 14:32:23 +0800 Subject: [PATCH] Refactor AppPicker page to adopt Settings main theme AppPicker in Development options has been existed since 2012 without too much maintanace. This CL mainly adopt Settings main theme into it, and migrate from depreaced ListActvity to androidx while reamining restraint. Bug: 277978841 Preview: https://docs.google.com/spreadsheets/d/1vwzriR1mZj2B2Flw1eu1OwfZY5wRz6YOaq7bDcXxStE Test: manual, presubmit Change-Id: I8bf3be499202eba894070cffd5f20f44d3d45de5 Signed-off-by: Pranav Vashi --- AndroidManifest.xml | 10 +- .../settings/development/AppPicker.java | 304 ++++++++++-------- 2 files changed, 184 insertions(+), 130 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 41ec207a226..b3058603fc8 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -3330,8 +3330,14 @@ android:value="@string/menu_key_connected_devices"/> - + + + + diff --git a/src/com/android/settings/development/AppPicker.java b/src/com/android/settings/development/AppPicker.java index a11788cb83d..1026ff27d5b 100644 --- a/src/com/android/settings/development/AppPicker.java +++ b/src/com/android/settings/development/AppPicker.java @@ -16,8 +16,6 @@ package com.android.settings.development; -import android.app.ActionBar; -import android.app.ListActivity; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -33,15 +31,19 @@ import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ListView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.ListFragment; + +import com.android.settings.SettingsActivity; + import java.text.Collator; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; -public class AppPicker extends ListActivity { - private AppListAdapter mAdapter; - +public class AppPicker extends SettingsActivity { public static final String EXTRA_REQUESTIING_PERMISSION = "com.android.settings.extra.REQUESTIING_PERMISSION"; public static final String EXTRA_DEBUGGABLE = "com.android.settings.extra.DEBUGGABLE"; @@ -50,32 +52,20 @@ public class AppPicker extends ListActivity { public static final int RESULT_NO_MATCHING_APPS = -2; - private String mPermissionName; - private boolean mDebuggableOnly; - private boolean mNonSystemOnly; - private boolean mIncludeNothing; - @Override protected void onCreate(Bundle icicle) { + final Intent intent = getIntent(); + + String permissionName = getIntent().getStringExtra(EXTRA_REQUESTIING_PERMISSION); + boolean debuggableOnly = getIntent().getBooleanExtra(EXTRA_DEBUGGABLE, false); + boolean nonSystemOnly = getIntent().getBooleanExtra(EXTRA_NON_SYSTEM, false); + boolean includeNothing = getIntent().getBooleanExtra(EXTRA_INCLUDE_NOTHING, true); + + intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, + AppPickerListFragment.withArgs(permissionName, debuggableOnly, nonSystemOnly, + includeNothing)); + super.onCreate(icicle); - - ActionBar actionBar = getActionBar(); - if (actionBar != null) { - actionBar.setDisplayHomeAsUpEnabled(true); - } - - mPermissionName = getIntent().getStringExtra(EXTRA_REQUESTIING_PERMISSION); - mDebuggableOnly = getIntent().getBooleanExtra(EXTRA_DEBUGGABLE, false); - mNonSystemOnly = getIntent().getBooleanExtra(EXTRA_NON_SYSTEM, false); - mIncludeNothing = getIntent().getBooleanExtra(EXTRA_INCLUDE_NOTHING, true); - - mAdapter = new AppListAdapter(this); - if (mAdapter.getCount() <= 0) { - setResult(RESULT_NO_MATCHING_APPS); - finish(); - } else { - setListAdapter(mAdapter); - } } @Override @@ -88,16 +78,12 @@ public class AppPicker extends ListActivity { } @Override - protected void onListItemClick(ListView l, View v, int position, long id) { - MyApplicationInfo app = mAdapter.getItem(position); - Intent intent = new Intent(); - if (app.info != null) intent.setAction(app.info.packageName); - setResult(RESULT_OK, intent); - finish(); + protected boolean isValidFragment(String fragmentName) { + return AppPickerListFragment.class.getName().equals(fragmentName); } private void handleBackPressed() { - if (getFragmentManager().getBackStackEntryCount() > 1) { + if (getSupportFragmentManager().getBackStackEntryCount() > 1) { super.onBackPressed(); } else { setResult(RESULT_CANCELED); @@ -105,106 +91,168 @@ public class AppPicker extends ListActivity { } } - class MyApplicationInfo { - ApplicationInfo info; - CharSequence label; - } + public static class AppPickerListFragment extends ListFragment { + private static final String EXTRA_PERMISSION_NAME = "extra_permission_name"; + private static final String EXTRA_DEBUGGABLE_ONLY = "extra_debuggable_only"; + private static final String EXTRA_NON_SYSTEM_ONLY = "extra_non_system_only"; + private static final String EXTRA_INCLUDE_NOTHING = "extra_include_nothing"; - public class AppListAdapter extends ArrayAdapter { - private final List mPackageInfoList = new ArrayList(); - private final LayoutInflater mInflater; + private String mPermissionName = ""; + private boolean mDebuggableOnly; + private boolean mNonSystemOnly; + private boolean mIncludeNothing; - public AppListAdapter(Context context) { - super(context, 0); - mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - List pkgs = context.getPackageManager().getInstalledApplications(0); - for (int i=0; i { + private final List mPackageInfoList = + new ArrayList(); + private final LayoutInflater mInflater; + + public AppListAdapter(Context context) { + super(context, 0); + mInflater = (LayoutInflater) context.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + List pkgs = context.getPackageManager().getInstalledApplications( + 0); + for (int i = 0; i < pkgs.size(); i++) { + ApplicationInfo ai = pkgs.get(i); + if (ai.uid == Process.SYSTEM_UID) { + continue; + } + + // Filter out apps that are not debuggable if required. + if (mDebuggableOnly) { + // On a user build, we only allow debugging of apps that + // are marked as debuggable. Otherwise (for platform development) + // we allow all apps. + if ((ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0 + && "user".equals(Build.TYPE)) { + continue; + } + } + + // Filter out apps that are system apps if requested + if (mNonSystemOnly && ai.isSystemApp()) { + continue; + } + + // Filter out apps that do not request the permission if required. + if (mPermissionName != null) { + boolean requestsPermission = false; + try { + PackageInfo pi = getContext().getPackageManager().getPackageInfo( + ai.packageName, PackageManager.GET_PERMISSIONS); + if (pi.requestedPermissions == null) { + continue; + } + for (String requestedPermission : pi.requestedPermissions) { + if (requestedPermission.equals(mPermissionName)) { + requestsPermission = true; + break; + } + } + if (!requestsPermission) { + continue; + } + } catch (PackageManager.NameNotFoundException e) { + continue; + } + } + + MyApplicationInfo info = new MyApplicationInfo(); + info.info = ai; + info.label = info.info.loadLabel(getContext().getPackageManager()).toString(); + mPackageInfoList.add(info); + } + Collections.sort(mPackageInfoList, sDisplayNameComparator); + if (mIncludeNothing) { + MyApplicationInfo info = new MyApplicationInfo(); + info.label = context.getText(com.android.settingslib.R.string.no_application); + mPackageInfoList.add(0, info); + } + addAll(mPackageInfoList); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + // A ViewHolder keeps references to children views to avoid unnecessary calls + // to findViewById() on each row. + AppViewHolder holder = AppViewHolder.createOrRecycle(mInflater, convertView); + convertView = holder.rootView; + MyApplicationInfo info = getItem(position); + holder.appName.setText(info.label); + if (info.info != null) { + holder.appIcon.setImageDrawable( + info.info.loadIcon(getContext().getPackageManager())); + holder.summary.setText(info.info.packageName); + } else { + holder.appIcon.setImageDrawable(null); + holder.summary.setText(""); + } + holder.disabled.setVisibility(View.GONE); + holder.widget.setVisibility(View.GONE); + return convertView; + } + } + + private final static Comparator sDisplayNameComparator + = new Comparator() { + public final int + compare(MyApplicationInfo a, MyApplicationInfo b) { + return collator.compare(a.label, b.label); + } + + private final Collator collator = Collator.getInstance(); + }; } - - private final static Comparator sDisplayNameComparator - = new Comparator() { - public final int - compare(MyApplicationInfo a, MyApplicationInfo b) { - return collator.compare(a.label, b.label); - } - - private final Collator collator = Collator.getInstance(); - }; }