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(); - }; }