How to tell which app was selected by Intent.createChooser?

前端 未结 5 908
囚心锁ツ
囚心锁ツ 2020-11-29 05:26

Code:

Intent launchIntent = new Intent(Intent.ACTION_MAIN);
launchIntent.addCategory(Intent.CATEGORY_HOME);
Intent chooser = Intent.createChooser(launchInten         


        
5条回答
  •  忘掉有多难
    2020-11-29 05:52

    The CommonsWare's solution only works from Android 5.1 (API level 22). Here is my solution to work with all Android versions, by creating our own app chooser dialog.

    Step 1: Create a custom layout for the app chooser dialog.

    dialog_app_chooser.xml

    
    
    
        
    
        
    
    

    Step 2: Create a layout for an item in app chooser dialog.

    item_app.xml

    
    
    
        
    
        
    
    

    Step 3: Create a model class which indicates an app in the app chooser dialog.

    App.java

    public class App implements Parcelable {
        public Intent intent;
        public ResolveInfo resolveInfo;
    
        public App(Intent intent, ResolveInfo resolveInfo) {
            this.intent = intent;
            this.resolveInfo = resolveInfo;
        }
    
        protected App(Parcel in) {
            intent = in.readParcelable(Intent.class.getClassLoader());
            resolveInfo = in.readParcelable(ResolveInfo.class.getClassLoader());
        }
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeParcelable(intent, flags);
            dest.writeParcelable(resolveInfo, flags);
        }
    
    
        public static final Creator CREATOR = new Creator() {
            @Override
            public App createFromParcel(Parcel in) {
                return new App(in);
            }
    
            @Override
            public App[] newArray(int size) {
                return new App[size];
            }
        };
    }
    

    Step 4: Create a custom adapter which display all apps in the app chooser dialog.

    AppAdapter.java

    public class AppAdapter extends RecyclerView.Adapter {
        private List apps;
        private OnItemClickListener listener;
    
        public AppAdapter(List apps, OnItemClickListener listener) {
            this.apps = apps;
            this.listener = listener;
        }
    
        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_app, parent, false);
            return new ViewHolder(view, listener);
        }
    
        @Override
        public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
            App app = apps.get(viewHolder.getAdapterPosition());
            viewHolder.bind(app);
        }
    
        @Override
        public int getItemCount() {
            return apps.size();
        }
    
        class ViewHolder extends RecyclerView.ViewHolder {
            private ImageView appIcon;
            private TextView appName;
            private App app;
    
            ViewHolder(View itemView, final OnItemClickListener listener) {
                super(itemView);
                appIcon = itemView.findViewById(R.id.image_view_app_icon);
                appName = itemView.findViewById(R.id.text_view_app_name);
                itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        listener.onItemClick(app);
                    }
                });
            }
    
            void bind(App app) {
                this.app = app;
                PackageManager packageManager = appName.getContext().getPackageManager();
                appIcon.setImageDrawable(app.resolveInfo.loadIcon(packageManager));
                appName.setText(app.resolveInfo.loadLabel(packageManager));
            }
        }
    
        interface OnItemClickListener {
            void onItemClick(App app);
        }
    }
    

    Step 5: Create the app chooser dialog.

    AppChooserDialog.java

    public class AppChooserDialog extends BottomSheetDialogFragment implements AppAdapter.OnItemClickListener {
        private static final String KEY_APPS = "KEY_APPS";
        private static final String KEY_TITLE = "KEY_TITLE";
        private static final String KEY_REQUEST_CODE = "KEY_REQUEST_CODE";
    
        public static void show(AppCompatActivity activity, ArrayList targets, String title, int requestCode) {
            PackageManager packageManager = activity.getPackageManager();
            ArrayList apps = new ArrayList<>();
            for (Intent intent : targets) {
                List activities = packageManager.queryIntentActivities(intent, 0);
                for (ResolveInfo resolveInfo : activities) {
                    Intent targetIntent = new Intent(intent);
                    apps.add(new App(targetIntent, resolveInfo));
                }
            }
    
            if (apps.size() > 0) {
                if (apps.size() == 1) {
                    activity.startActivityForResult(apps.get(0).intent, requestCode);
                } else {
                    DialogFragment appChooserDialog = new AppChooserDialog();
                    Bundle data = new Bundle();
                    data.putParcelableArrayList(KEY_APPS, apps);
                    data.putString(KEY_TITLE, title);
                    data.putInt(KEY_REQUEST_CODE, requestCode);
                    appChooserDialog.setArguments(data);
                    appChooserDialog.show(activity.getSupportFragmentManager(), "AppChooserDialog");
                }
            }
        }
    
        @Nullable
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.dialog_app_chooser, container, false);
    
            TextView titleTextView = rootView.findViewById(R.id.text_view_title);
            RecyclerView appsRecyclerView = rootView.findViewById(R.id.recycler_view_apps);
    
            String title = getArguments().getString(KEY_TITLE);
            if (!TextUtils.isEmpty(title)) {
                titleTextView.setText(title);
            }
    
            List apps = getArguments().getParcelableArrayList(KEY_APPS);
            appsRecyclerView.setAdapter(new AppAdapter(apps, this));
    
            DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
            float screenWidthInDp = displayMetrics.widthPixels / displayMetrics.density;
            int recyclerViewItemWidthInDp = 72;
            int recyclerViewStartEndPadding = 32;
            int numberOfColumns = (int) ((screenWidthInDp - recyclerViewStartEndPadding) / recyclerViewItemWidthInDp);
            int spanCount = (apps.size() < numberOfColumns) ? apps.size() : numberOfColumns;
            appsRecyclerView.setLayoutManager(new GridLayoutManager(requireActivity(), spanCount));
    
            return rootView;
        }
    
    
        @Override
        public void onItemClick(App app) {
            ActivityInfo activity = app.resolveInfo.activityInfo;
            String packageName = activity.applicationInfo.packageName;
            ComponentName component = new ComponentName(packageName, activity.name);
    
            Intent intent = new Intent(app.intent);
            intent.setComponent(component);
    
            Uri uri = app.intent.getParcelableExtra(MediaStore.EXTRA_OUTPUT);
            if (uri != null) {
                requireActivity().grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
            }
    
            OnAppSelectedListener listener = null;
            try {
                listener = (OnAppSelectedListener) requireActivity();
            } catch (Exception e) {
                // Ignore exception
            }
            if (listener != null) {
                listener.onAppSelected(intent);
            }
    
            requireActivity().startActivityForResult(intent, getArguments().getInt(KEY_REQUEST_CODE));
            dismiss();
        }
    
        public interface OnAppSelectedListener {
            void onAppSelected(Intent intent);
        }
    }
    

    Step 6: Using the app chooser dialog from an activity.

    public class MainActivity extends AppCompatActivity implements AppChooserDialog.OnAppSelectedListener {
        private static final int REQUEST_CODE_PICK_IMAGE = 100;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            ArrayList intents = new ArrayList<>();
            Intent pickImageIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            intents.add(pickImageIntent);
            AppChooserDialog.show(this, intents, "Pick image from", REQUEST_CODE_PICK_IMAGE);
        }
    
        @Override
        public void onAppSelected(Intent intent) {
            ComponentName componentName = intent.getComponent();
            String packageName = componentName.getPackageName();
            String activityName = componentName.getClassName();
            Log.i("TAG", "packageName = " + packageName + ", activityName = " + activityName);
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == REQUEST_CODE_PICK_IMAGE) {
                Log.i("TAG", "onActivityResult");
                // TODO: Put your logic here.
            }
        }
    }
    

    The result:

提交回复
热议问题