Search code examples
androidandroid-intentintentfilterandroid-package-managers

Unable to acquire intent filter from ResolveInfo instance


I have a list which contain apps that can handle any of my two actions Intent.ACTION_PICK and MediaStore.ACTION_IMAGE_CAPTURE. i later on use an array adapter to populate my listivew with the information from this list.

In my onItemClickListener, am able to acquire ActivityInfo and ComponentName from ResolveInfo instance.but am not able to get IntentFilter instance from ResolveInfo (attempt to get it throws NullPointerException), AND YET any application that is in my list MUST HAVE resolved one of my intents for it to be ln the list

This is the line throwing nullpointerexception IntentFilter filter = launchable.filter;

private void acquirePicture(){

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

PackageManager pm=getPackageManager();

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

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

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

Question

How can i get the intent(s) which the selected app resolved in my onClickListner body?


Solution

  • You need to explicitly say that you want the filter returned. Instead of:

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

    Use this:

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

    I haven't actually tested this. Please be aware that there are a lot of bugs and missing functionality related to returning IntentFilters. In a lot of cases the documentation is wrong, in a lot of cases the code just doesn't do what you would expect it to do, and there aren't a lot of good working examples.

    Try this and let us know if it works.