javaandroidandroid-fragmentscommonsware-cwaccwac-camera

How to correctly subclass SimpleCameraHost for use in caac-camera?


This is the full error that I am getting when trying my current method.

05-28 09:33:13.022    8163-8163/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.snappiesticker.cwac4, PID: 8163
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.snappiesticker.cwac4/com.snappiesticker.cwac4.MainActivity}: android.view.InflateException: Binary XML file line #5: Error inflating class com.commonsware.cwac.camera.CameraView
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
     Caused by: android.view.InflateException: Binary XML file line #5: Error inflating class com.commonsware.cwac.camera.CameraView
            at android.view.LayoutInflater.createView(LayoutInflater.java:633)
            at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:743)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
            at com.snappiesticker.cwac4.DemoCameraFragment.onCreateView(DemoCameraFragment.java:28)
            at android.app.Fragment.performCreateView(Fragment.java:2053)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:894)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
            at android.app.BackStackRecord.run(BackStackRecord.java:834)
            at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1452)
            at android.app.Activity.performStart(Activity.java:6005)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
     Caused by: java.lang.reflect.InvocationTargetException
            at java.lang.reflect.Constructor.newInstance(Native Method)
            at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
            at android.view.LayoutInflater.createView(LayoutInflater.java:607)
            at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:743)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
            at com.snappiesticker.cwac4.DemoCameraFragment.onCreateView(DemoCameraFragment.java:28)
            at android.app.Fragment.performCreateView(Fragment.java:2053)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:894)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
            at android.app.BackStackRecord.run(BackStackRecord.java:834)
            at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1452)
            at android.app.Activity.performStart(Activity.java:6005)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
     Caused by: java.lang.IllegalArgumentException: To use the two- or three-parameter constructors on CameraView, your activity needs to implement the CameraHostProvider interface
            at com.commonsware.cwac.camera.CameraView.<init>(CameraView.java:74)
            at com.commonsware.cwac.camera.CameraView.<init>(CameraView.java:62)
            at java.lang.reflect.Constructor.newInstance(Native Method)
            at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
            at android.view.LayoutInflater.createView(LayoutInflater.java:607)
            at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:743)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
            at com.snappiesticker.cwac4.DemoCameraFragment.onCreateView(DemoCameraFragment.java:28)
            at android.app.Fragment.performCreateView(Fragment.java:2053)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:894)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
            at android.app.BackStackRecord.run(BackStackRecord.java:834)
            at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1452)
            at android.app.Activity.performStart(Activity.java:6005)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

I believe it stems from me using the wrong context in my Fragment here:

public class DemoCameraFragment extends CameraFragment implements View.OnClickListener {
    //private CapturedImage next = null;

    @Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container,
                             Bundle savedInstanceState) {
        View content=inflater.inflate(R.layout.camera, container, false);
        CameraView cameraView=(CameraView)content.findViewById(R.id.camera);

        setCameraView(cameraView);

        return(content);
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHost(new DemoCameraHost(getActivity()));
    }

    @Override
    public void onStart() {
        super.onStart();

        getView().setOnClickListener(this);
    }
    @Override

    public void onClick(View v) {
        takePicture();
        Toast.makeText(getActivity(), "picture taken!",
                Toast.LENGTH_LONG).show();
    }
    public class DemoCameraHost extends SimpleCameraHost {
        public DemoCameraHost(Context _ctxt) {
            super(_ctxt);
        }

        @Override
        public boolean useFrontFacingCamera() {
            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);

            next = new CapturedImage();
            getFragmentManager().beginTransaction()
                    .replace(R.id.fragment_container, next).addToBackStack(null).commit();
        }*/
    }
}

The line I believe needs work is setHost(new DemoCameraHost(getActivity())); I used getActivity assuming that the context of the camera fragment is equivalent to the context of the main activity that it lives in but Im not sure

All I am trying to do is subclass SimpleCameraHost so that I can override methods instead of using the default.

However, it also mentions a binary xml issue on main activity, so maybe the issue is here

Here is MainActivity.java:

public class MainActivity extends Activity {
    private DemoCameraFragment current = null;

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

        setContentView(R.layout.activity_main);

        current = new DemoCameraFragment();

        getFragmentManager().beginTransaction()
                .replace(R.id.fragment_container, current).commit();
    }
}

along with activity_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Solution

  • Quoting the exception:

    Caused by: java.lang.IllegalArgumentException: To use the two- or three-parameter constructors on CameraView, your activity needs to implement the CameraHostProvider interface
    

    Your activity does not implement the CameraHostProvider interface. See "Using CameraView in a Layout Resource" in the documentation (I'd love to directly link to the section, but GitHub and my browser aren't getting along at the moment...).