how to use queryIntentActivityOptions() method

2019-03-06 20:25发布

问题:

Am trying to create a dialog that shows all applications in a user phone that can be used to select a picture from the storage or take one using the camera. below are my two intents that am planning to use.

Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
    photoPickerIntent.setType("image/*");

Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

The best way i have found to populate my listview in my customized dialog with applications that can perform the above actions is to use queryIntentActivityOptions() method but am stucked.

  • i have never used it before and i don't know whether am doing it the right way

  • i don't know how i will populate my listview with the gotten applications from queryIntentActivityOptions() method.

  • How to implement onItemClickListener in my listview which is in my customized dialog.

This is my method that contain the dialog. please i have researched but haven't found a good tutorial to guide me on how i can implement queryIntentActivityOptions()

private void acquirePicture(){
    Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
    photoPickerIntent.setType("image/*");

    Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    startActivityForResult(photoPickerIntent, 1);

    final Dialog dialog = new Dialog(this);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    WindowManager.LayoutParams WMLP = dialog.getWindow().getAttributes();
    WMLP.gravity = Gravity.CENTER;
    dialog.getWindow().setAttributes(WMLP);
    dialog.getWindow().setBackgroundDrawable(
            new ColorDrawable(android.graphics.Color.TRANSPARENT));
    dialog.setCanceledOnTouchOutside(true);
    dialog.setContentView(R.layout.about_dialog);
    dialog.setCancelable(true);
    ListView lv=(ListView)dialog.findViewById(R.id.listView1);
    PackageManager pm=getPackageManager();

    List<ResolveInfo> launchables=pm.queryIntentActivityOptions(
this.getComponentName(),new Intent[]{photoPickerIntent,takePicture},
null,PackageManager.MATCH_DEFAULT_ONLY);

    Collections.sort(launchables,
            new ResolveInfo.DisplayNameComparator(pm));

    appAdapter=new AppAdapter(pm, launchables);

    lv.setAdapter(adapter);
    lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int position,
                                long arg3) {
            // TODO Auto-generated method stub
            ResolveInfo launchable=appAdapter.getItem(position);
            ActivityInfo activity=launchable.activityInfo;
            ComponentName name=new ComponentName(activity.applicationInfo.packageName,
                    activity.name);
            //I DON'T KNOW WHAT TO DO NEXT OR WHETHER AM DOING IT
             THE CORRECT WAY
        }
    });

    dialog.show();
}

class AppAdapter extends ArrayAdapter<ResolveInfo> {
    private PackageManager pm=null;

    AppAdapter(PackageManager pm, List<ResolveInfo> apps) {
        super(Custom_chooser.this, R.layout.row, apps);
        this.pm=pm;
    }

    @Override
    public View getView(int position, View convertView,
                        ViewGroup parent) {
        if (convertView==null) {
            convertView=newView(parent);
        }

        bindView(position, convertView);

        return(convertView);
    }

    private View newView(ViewGroup parent) {
        return(getLayoutInflater().inflate(R.layout.row, parent, false));
    }

    private void bindView(int position, View row) {
        TextView label=(TextView)row.findViewById(R.id.label);

        label.setText(getItem(position).loadLabel(pm));

        ImageView icon=(ImageView)row.findViewById(R.id.icon);

        icon.setImageDrawable(getItem(position).loadIcon(pm));
    }
}

回答1:

check the below working code to open, Camera and browse through gallery at once.

 // Picks Camera first.
final List<Intent> cameraIntents = new ArrayList<Intent>();
final Intent captureIntent = new Intent(
        android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
final PackageManager packageManager = getPackageManager();
final List<ResolveInfo> listCam = packageManager.queryIntentActivities(
        captureIntent, 0);
for (ResolveInfo res : listCam) {
  final String packageName = res.activityInfo.packageName;
  final Intent intent = new Intent(captureIntent);
  intent.setComponent(new ComponentName(res.activityInfo.packageName,
          res.activityInfo.name));
  intent.setPackage(packageName);
  intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
  cameraIntents.add(intent);
}

final Intent galleryIntent = new Intent();
galleryIntent.setType("image/*");
galleryIntent.setAction(Intent.ACTION_PICK);

// Chooser of filesystem options.
final Intent chooserIntent = Intent.createChooser(galleryIntent,
        "Select Image from");

// Add the camera options.
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
        cameraIntents.toArray(new Parcelable[]{}));

startActivityForResult(chooserIntent, TAKE_PHOTO_CODE);

This will help you.!!

Reference links and tutorials click here.



回答2:

lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int position,
                                long arg3) {
            // TODO Auto-generated method stub
            ResolveInfo launchable=appAdapter.getItem(position);
                   String packageName = launchable.activityInfo.packageName;
        String className = launchable.activityInfo.name;
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        ComponentName cn = new ComponentName(packageName, className);
        intent.setComponent(cn);
        startActivity(intent);
        }
    });



 /**
     * Retrieve a set of activities that should be presented to the user as
     * similar options.  This is like {@link #queryIntentActivities}, except it
     * also allows you to supply a list of more explicit Intents that you would
     * like to resolve to particular options, and takes care of returning the
     * final ResolveInfo list in a reasonable order, with no duplicates, based
     * on those inputs.
     *
     * @param caller The class name of the activity that is making the
     *               request.  This activity will never appear in the output
     *               list.  Can be null.
     * @param specifics An array of Intents that should be resolved to the
     *                  first specific results.  Can be null.
     * @param intent The desired intent as per resolveActivity().
     * @param flags Additional option flags.  The most important is
     * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
     * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
     *
     * @return A List&lt;ResolveInfo&gt; containing one entry for each matching
     *         Activity. These are ordered first by all of the intents resolved
     *         in <var>specifics</var> and then any additional activities that
     *         can handle <var>intent</var> but did not get included by one of
     *         the <var>specifics</var> intents.  If there are no matching
     *         activities, an empty list is returned.
     *
     * @see #MATCH_DEFAULT_ONLY
     * @see #GET_INTENT_FILTERS
     * @see #GET_RESOLVED_FILTER
     */
    public abstract List<ResolveInfo> queryIntentActivityOptions(
            ComponentName caller, Intent[] specifics, Intent intent, int flags);


回答3:

First, you need a good understanding of queryIntentActivityOptions() method of class PackageManager.

QueryIntentActivityOptions(ComponentName caller, Intent[] specifics,Intent intent, int flags)

  • caller - This is the name of the class you are currently calling this method from. usually we use this.getComponentName as the value for this parameter.

  • specifics - This is an array of intents that you want to be first resolved. for your case, you can put any of the two intents you have. i.e photoPickerIntent or takePictureIntent like this

    new Intent[] {takePicture}

    NOTE: this parameter value can be null if you have only one intent. in that case, i think it would be better to use QueryIntentActivities. but for your case, since you have more than one intent, continue using this method.

  • intent - Here you place your desired intent. i.e between the two intents that you have, the one you desided not to put in the array because you so it as the most important one

    NOTE: this parameter value cannot be null. putting a null value will throw a NullPointerException!

  • flags - This is like a filter or extra that you want to be included in any of the resolved activites returned by this method.

    • PackageManager.MATCH_DEFAULT_ONLY - puting this option will filter the resolved activities and select the activities that belong to default applications in your device.e.g if ACTION_IMAGE_CAPTURE can be resolved by two apps, one which is the default and the other is third party one, e.g you downloaded it, one the default will be selected

    • PackageManager.GET_INTENT_FILTERS - this option return information about all the intent filters that the resolved app can handle. e.g you can have an app that resolved ACTION_IMAGE_CAPTURE and yet it can also resolve ACTION_PICK

    • PackageManager.GET_RESOLVED_FILTER - this option return the intent filter that each of the apps in the list resolved

A WORKING EXAMPLE

Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);

Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

photoPickerIntent.setType("image/*");

PackageManager pm=getPackageManager();


List<ResolveInfo> launchables=pm.queryIntentActivityOptions(
 this.getComponentName(),new Intent[]{takePicture},
 photoPickerIntent,PackageManager.GET_RESOLVED_FILTER);

  Collections.sort(launchables,
    new ResolveInfo.DisplayNameComparator(pm));

You can then populate your listview using the above list of lauchaubles

 ListView lv=(ListView)dialog.findViewById(R.id.listView1);

 AppAdapter appAdapter=new AppAdapter(pm, launchables);

 lv.setAdapter(adapter);
 lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
 @Override
 public void onItemClick(AdapterView<?> arg0, View arg1, int position,
                        long arg3) {
    // TODO Auto-generated method stub
    ResolveInfo launchable=appAdapter.getItem(position);
    ActivityInfo activity=launchable.activityInfo;
    ComponentName name=new ComponentName(activity.applicationInfo.packageName,
            activity.name);

 IntentFilter filter = launchable.filter;
        if(filter.actionsIterator() != null){
            Iterator<String > actions = filter.actionsIterator();
        }

        int actioncode;
        Intent  intent = new Intent();
        Uri uri;
        if(filter.hasAction(Intent.ACTION_PICK)){
            actioncode = 1;
            uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            intent.setData(uri);
        }else{
            actioncode = 0;
        }
        intent.setComponent(name);
        startActivityForResult(intent,actioncode);

}
});

 }

class AppAdapter extends ArrayAdapter<ResolveInfo> {

private PackageManager pm=null;

AppAdapter(PackageManager pm, List<ResolveInfo> apps) {
super(Custom_chooser.this, R.layout.row, apps);
this.pm=pm;
}

 @Override
public View getView(int position, View convertView,
                ViewGroup parent) {
if (convertView==null) {
    convertView=newView(parent);
}

bindView(position, convertView);

return(convertView);
}

private View newView(ViewGroup parent) {
return(getLayoutInflater().inflate(R.layout.row, parent, false));
}

private void bindView(int position, View row) {
TextView label=(TextView)row.findViewById(R.id.label);

label.setText(getItem(position).loadLabel(pm));

ImageView icon=(ImageView)row.findViewById(R.id.icon);

icon.setImageDrawable(getItem(position).loadIcon(pm));
}
}