Search code examples
androidandroid-cameraandroid-galleryandroid-camera-intent

How to access photos and camera in android using one intent


If you use whatsapp and you click the attach button, a menu/popup will be inflated showing you a list of appications you can use to select images and even take pictures from your camera using the photo app

whatapp popup

I making an app that have almost the same functionality as whatapp of accessing and taking pictures. the problem is, I can't take pictures using the photo app listed as one of apps in my popup dialog but i can take pictures when using whatsapp. When I click photo app from the dialog shown in my application, it shows me all my pictures. but when I click the photo app from whatsapp popup, it goes directly to the camera

public class ImagePickerActivity extends Activity {

private final int SELECT_PHOTO = 1;
private ImageView imageView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_image_picker);

    imageView = (ImageView)findViewById(R.id.imageView);

    Button pickImage = (Button) findViewById(R.id.btn_pick);
    pickImage.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View view) {                
            Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
            photoPickerIntent.setType("image/*");
            startActivityForResult(photoPickerIntent, SELECT_PHOTO);
        }
    });
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) { 
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent); 

    switch(requestCode) { 
    case SELECT_PHOTO:
        if(resultCode == RESULT_OK){
            try {
                final Uri imageUri = imageReturnedIntent.getData();
                final InputStream imageStream = getContentResolver().openInputStream(imageUri);
                final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
                imageView.setImageBitmap(selectedImage);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

        }
    }
}

In my android manifest

<uses-feature android:name="android.hardware.camera"
              android:required="true" />

What do I need to change in my code to be able to take pictures from photo app?


Solution

  • To access camera and photos using one intent

    populate a custom dialog's listview with intents from apps that can either take pictures using camera or access photos in the storage like this

    private void acquirePicture(){
    Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
    photoPickerIntent.setType("image/*");
    
    Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    
    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);
    lv=(ListView)dialog.findViewById(R.id.listView1);
    
    populateDialogsListView();
    
    dialog.show();
    }
    

    Poputate dialog's listview (lv) with apps that can perform the two actions

    public void populateDialogListView(){
    
      PackageManager pm=getPackageManager();
    
     List<ResolveInfo> photoIntents = new ArrayList<>();
    
    final List<ResolveInfo> listCam = packageManager.queryIntentActivities(
            captureIntent, PackageManager.GET_RESOLVED_FILTER);
    
    final List<ResolveInfo> listGalley = packageManager.queryIntentActivities(photoPickerIntent, PackageManager.GET_RESOLVED_FILTER);
    
    for (ResolveInfo activity : listCam) {
      photoIntents.add(activity);
    }
    
    for (ResolveInfo activity : listGalley) {
      photoIntents.add(activity);
    }
    
    
    
    Collections.sort(photoIntents,
            new ResolveInfo.DisplayNameComparator(pm));
    
    AppAdapter appAdapter = new AppAdapter(pm, photoIntents);
    
    lv.setAdapter(appAdapter);
    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;
    
            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);
        }
    });
    
    }
    

    Since you are creating a custom dialog with a listview, you have to create adapter for that listview(lv) which will fill the listview with app's name and app's icon

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

    Any problem, let me know