如何判断Intent.createChooser选择了哪个应用?

时间:2015-08-25 11:50:32

标签: android android-intent

代码:

compile

我没有看到任何方法来判断选择了哪个Intent(HOME类别启动器)。没有Intent.addOnActionSetListener,也没有chooser.addOnIntentChosenListener等。

那我怎么知道选哪个?我是否必须为此编写自己的选择器?

3 个答案:

答案 0 :(得分:16)

这适用于早期版本的Android。

使用intent PICKER而不是CHOOSER。不同之处在于,选择器不会自动启动目标意图,而是返回onActivityResult()目标意图,并附加所选应用程序的组件名称。然后,您将在回调中启动目标意图作为第二步。

一些代码应该解释,

// In MyActivity class
static final int REQUEST_CODE_MY_PICK = 1;

// Getting ready to start intent. Note: call startActivityForResult()
... launchIntent = the target intent you want to start;
Intent intentPick = new Intent();
intentPick.setAction(Intent.ACTION_PICK_ACTIVITY);
intentPick.putExtra(Intent.EXTRA_TITLE, "Launch using");
intentPick.putExtra(Intent.EXTRA_INTENT, launchIntent);
this.startActivityForResult(intentPick, REQUEST_CODE_MY_PICK);
// You have just started a picker activity, 
// let's see what user will pick in the following callback

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (requestCode == REQUEST_CODE_MY_PICK) {
         String appName = data.getComponent().flattenToShortString();
         // Now you know the app being picked.
         // data is a copy of your launchIntent with this important extra info added.

         // Don't forget to start it!
         startActivity(data);
    }
}

答案 1 :(得分:15)

BinHe提供的答案有效但问题是显示了大量的应用程序。在此解决方案中,我使用Intent.ACTION_PICK_ACTIVITY,但只显示与Intent.ACTION_SEND兼容的应用程序,您将知道用户选择了哪个选项。

public void doSocialShare(String title, String text, String url){
    // First search for compatible apps with sharing (Intent.ACTION_SEND)
    List<Intent> targetedShareIntents = new ArrayList<Intent>();
    Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
    shareIntent.setType("text/plain");
    // Set title and text to share when the user selects an option.
    shareIntent.putExtra(Intent.EXTRA_TITLE, title);
    shareIntent.putExtra(Intent.EXTRA_TEXT, url);
    shareIntent.putExtra(Intent.EXTRA_TEXT, text);
    List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(shareIntent, 0);
    if (!resInfo.isEmpty()) {
        for (ResolveInfo info : resInfo) {
            Intent targetedShare = new Intent(android.content.Intent.ACTION_SEND);
            targetedShare.setType("text/plain"); // put here your mime type
            targetedShare.setPackage(info.activityInfo.packageName.toLowerCase());
            targetedShareIntents.add(targetedShare);
        }
        // Then show the ACTION_PICK_ACTIVITY to let the user select it
        Intent intentPick = new Intent();
        intentPick.setAction(Intent.ACTION_PICK_ACTIVITY);
        // Set the title of the dialog
        intentPick.putExtra(Intent.EXTRA_TITLE, title);
        intentPick.putExtra(Intent.EXTRA_INTENT, shareIntent);
        intentPick.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray());
        // Call StartActivityForResult so we can get the app name selected by the user
        this.startActivityForResult(intentPick, REQUEST_CODE_MY_PICK);
    }
}

最后,为了能够获取用户选择的应用,您必须覆盖活动的onActivityResult:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode == REQUEST_CODE_MY_PICK) {
        if(data != null && data.getComponent() != null && !TextUtils.isEmpty(data.getComponent().flattenToShortString()) ) {
            String appName = data.getComponent().flattenToShortString();
            // Now you know the app being picked.
            // data is a copy of your launchIntent with this important extra info added.

            // Start the selected activity
            startActivity(data);
        }
    } 
}

答案 2 :(得分:2)

CommonsWare的解决方案仅适用于Android 5.1(API级别22)。这是我通过创建自己的应用选择器对话框与所有Android版本一起使用的解决方案。

步骤1::为应用选择器对话框创建自定义布局。

dialog_app_chooser.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/text_view_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:paddingStart="20dp"
        android:paddingTop="14dp"
        android:paddingEnd="0dp"
        android:paddingBottom="14dp"
        android:text="Select an action"
        android:textColor="#000"
        android:textSize="16sp"
        android:textStyle="bold" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view_apps"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingStart="16dp"
        android:paddingEnd="16dp" />
</LinearLayout>

第2步:在应用选择器对话框中为项目创建布局。

item_app.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout_app"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/image_view_app_icon"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp" />

    <TextView
        android:id="@+id/text_view_app_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingBottom="20dp"
        android:textColor="#000"
        android:textSize="12sp" />
</LinearLayout>

步骤3:创建一个模型类,该类在应用选择器对话框中指示一个应用。

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<App> CREATOR = new Creator<App>() {
        @Override
        public App createFromParcel(Parcel in) {
            return new App(in);
        }

        @Override
        public App[] newArray(int size) {
            return new App[size];
        }
    };
}

步骤4::创建一个自定义适配器,以在应用选择器对话框中显示所有应用。

AppAdapter.java

public class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> {
    private List<App> apps;
    private OnItemClickListener listener;

    public AppAdapter(List<App> 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);
    }
}

第5步:创建应用选择器对话框。

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<Intent> targets, String title, int requestCode) {
        PackageManager packageManager = activity.getPackageManager();
        ArrayList<App> apps = new ArrayList<>();
        for (Intent intent : targets) {
            List<ResolveInfo> 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<App> 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);
    }
}

步骤6:使用活动中的应用选择器对话框。

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<Intent> 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.
        }
    }
}

结果:

enter image description here