2

I'm trying to implement the wonderful library cwac-camera. I can't seem to figure out how to implement a callback for a picture and how to set the path for the picture.

This is my CustomCameraFragment public class CustomCameraFragment extends CameraFragment { private static final String KEY_USE_FFC = "com.commonsware.cwac.camera.demo.USE_FFC";

public static CustomCameraFragment newInstance(boolean useFFC) {
    CustomCameraFragment f = new CustomCameraFragment();
    Bundle args = new Bundle();

    args.putBoolean(KEY_USE_FFC, useFFC);
    f.setArguments(args);
    return (f);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    SimpleCameraHost.Builder builder =
            new SimpleCameraHost.Builder(new DemoCameraHost(getActivity()));
    builder.useFullBleedPreview(true);
    setHost(builder.build());
    //setHost(builder.useFullBleedPreview(true).build());
}

public class DemoCameraHost extends SimpleCameraHost {
    public DemoCameraHost(Context _ctxt) {
        super(_ctxt);
    }

    @Override
    public boolean useFrontFacingCamera() {
        if (getArguments() == null) {
            return (false);
        }

        return (getArguments().getBoolean(KEY_USE_FFC));
    }

    @Override
    public boolean useSingleShotMode() {
        return true;
    }

    @Override
    public void onCameraFail(CameraHost.FailureReason reason) {
        super.onCameraFail(reason);

        Toast.makeText(getActivity(),
                "Sorry, but you cannot use the camera now!",
                Toast.LENGTH_LONG).show();
    }

    @Override
    public void saveImage(PictureTransaction xact, Bitmap bitmap) {
        super.saveImage(xact, bitmap);
    }
}

}

I'm using it in a framelayout in another fragment, but I can't figure out the correct implementation of the callback.

The fragment where I use the CustomCameraFragment: I have a button to take a picture: @OnClick(R.id.btnTakePicture) public void takePicture(View view) {

    try {
        CustomCameraFragment.DemoCameraHost demoCameraHost = customCameraFragment.demoCameraHost;
        PictureTransaction pictureTransaction = new PictureTransaction(demoCameraHost);
        pictureTransaction.needBitmap(true);
        customCameraFragment.takePicture(pictureTransaction);

    } catch (Exception e) {
        e.printStackTrace();
    }

    showCameraPreview(false);

}

But in this fragment I need : - A callback to know when the picture was taken - When the callback is fired, I need to display the Bitmap, instead of the preview - I need to be able to set the path & filename where to save the picture

These 3 things are unclear to me.

TomCB
  • 3,983
  • 9
  • 40
  • 66

2 Answers2

2

You must override the saveImage(PictureTransaction, byte[]) function, see here for more information:

https://github.com/commonsguy/cwac-camera#overriding-photo-saving

Evripidis Drakos
  • 872
  • 1
  • 7
  • 15
  • In DemoCameraHost I tried: @Override public void saveImage(PictureTransaction xact, Bitmap bitmap) { Logger.d(TAG,"saveImage"); super.saveImage(xact, bitmap); } But it does not get called when I call takePicture on my fragment.. – TomCB Apr 02 '15 at 13:15
  • thats because as the link i posted mentions: "By default, saveImage(PictureTransaction, byte[]) will be called, and not saveImage(PictureTransaction, Bitmap). To change this, call needBitmap(boolean) and/or needByteArray(boolean) on your PictureTransaction, passing that PictureTransaction to takePicture()." – Evripidis Drakos Apr 02 '15 at 13:20
  • That works indeed, which is a great step forward. Still I don't really understand the communication between this CameraFragment and the parentFragment, where I need a callback? – TomCB Apr 02 '15 at 13:36
  • I dont understand what you mean by that – Evripidis Drakos Apr 02 '15 at 13:53
1

A callback to know when the picture was taken

Quoting the documentation:

The default SimpleCameraHost logic for saving photos uses the getPhotoPath() and related methods discussed above. Actually saving the photo is done in saveImage(PictureTransaction, byte[]), called on your CameraHost, where SimpleCameraHost has a saveImage(PictureTransaction, byte[]) implementation that writes the supplied byte[] out to the desired location.

You are welcome to override saveImage(PictureTransaction, byte[]) and do something else with the byte[], such as send it over the Internet. saveImage(PictureTransaction, byte[]) is called on a background thread, so you do not have to do your own asynchronous work.

Another use for this is to find out when the saving is complete, so that you can use the resulting image. Just override saveImage(PictureTransaction, byte[]), chain to the superclass implementation, and when that returns, the image is ready for use.


When the callback is fired, I need to display the Bitmap, instead of the preview

Quoting the documentation:

By default, the result of taking a picture is to return the CameraFragment to preview mode, ready to take the next picture. If, instead, you only need the one picture, or you want to send the user to some other bit of UI first and do not want preview to start up again right away, override useSingleShotMode() in your CameraHost to return true. Or, call useSingleShotMode() on your SimpleCameraHost.Builder, passing in a boolean to use by default. Or, call useSingleShotMode() on your PictureTransaction, to control this for an individual picture.

You will then probably want to use your own saveImage() implementation in your CameraHost to do whatever you want instead of restarting the preview. For example, you could start another activity to do something with the image. However, bear in mind that an Intent is limited to ~1MB, and so passing an image to another activity via a Intent extra is likely to be unreliable. You will need to do something else, such as (carefully) use a static data member.

Preview mode will re-enable automatically after an onPause()/onResume() cycle of your CameraFragment, or you can call restartPreview() on your CameraFragment (or CameraView).


I need to be able to set the path & filename where to save the picture

That's covered in the documentation as well, in something long enough that I don't feel like quoting it here. :-)

Community
  • 1
  • 1
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks a lot for the info! I think my big problem is that I use the customCameraFragment as a "view" in my parent fragment. Because of that I couldn't get the communication between these two fragments (how does the parent fragment know about the saveImage() in the customCameraFragment? What I should do is use the customCameraFragment as my actual fragment :) – TomCB Apr 03 '15 at 06:18
  • @TomCB: "how does the parent fragment know about the saveImage() in the customCameraFragment?" -- the custom camera fragment would call a method on its parent. – CommonsWare Apr 03 '15 at 10:33
  • But then the CustomCameraFragment wouldn't be generic? I can't see the CustomCameraFragment as a "view" that I can use anywhere where I need a camera preview? – TomCB Apr 06 '15 at 12:19
  • 1
    @TomCB: I have no idea why you would need more than one spot in your app for a `CustomCameraFragment`. Certainly the library is not expecting you to have lots of camera fragments used in lots of places. That being said, just because the fragment calls a method on the hosting activity does not mean that the fragment is not "generic". Have a `CustomCameraFragment.Contract` interface that all hosting activities need to implement, and have the fragment call a method on that `Contract`. The fragment can then be hosted by any number of activities. – CommonsWare Apr 06 '15 at 12:23
  • Great input, I fixed it with finding my fragment where I needed to call the method to use my picture, that worked. Now I'm using an interface as you suggested, which works like a charm and is more generic! I think I'm speaking for an entire community when I say: "Thank you!" :) – TomCB Apr 07 '15 at 15:46