0

I'm trying to record video using the cwac-camera android library. I know that the library only supports recording in landscape, but I can't seem to get it to stop throwing the UnsupportedOperationException: Video recording supported only in landscape. I've tried using CameraView's lockToLandscape() method, and forced the screen orientation manually using androids setDisplayOrientation (both in code an in xml configuration), but regardless the CameraInfo tells me that the orientation is 90. And CameraView's getDisplayOrientation() returns -1. Here is my Activity and Fragment:

There is some oddness resulting from being inside a cordova plugin (I can't use R).

public class RecordActivity extends Activity implements CameraHostProvider {

    public static final String TAG = "ApparatusRecordActivity";
    private VideoRecordingFragment current=null;
    private boolean recording_state = false;

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

    //setContentView(R.layout.activity_main);
    String package_name = getApplication().getPackageName();
    int layoutid = getApplication().getResources().getIdentifier("apparatus_activity_main", "layout", package_name);
    int containerid = getApplication().getResources().getIdentifier("container", "id", package_name);
    Log.d(TAG,"layout id: " + layoutid);
    Log.d(TAG,"container id: " + containerid);

    setContentView(layoutid);

    current = new VideoRecordingFragment();

    getFragmentManager().beginTransaction().add(containerid, current, "video_camera_fragment").commit();
    SimpleCameraHost host = getCameraHost();
    current.setHost(host);
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(host.getCameraId(),info);

    Log.d(TAG,"Orientation rotation: " + info.orientation);

    }

    @Override
    public SimpleCameraHost getCameraHost() {
    return (new SimpleCameraHost.Builder(this)
        .recordingHint(CameraHost.RecordingHint.VIDEO_ONLY)
        //.useFrontFacingCamera(true)
        .videoDirectory(new File("/sdcard"))
        .build());
    }

    public void record(View v) {
    try {
        if (recording_state == false) {
        recording_state = true;
        Log.d(TAG,"Start recording");
        current.record();
        current.getButton().setText("Stop");
        } else {
        recording_state = false;
        Log.d(TAG,"Stop recording");
        current.stopRecording();
        current.getButton().setText("Record");
        }
    } catch (Exception e) {
        // Print stack trace and try again.
        Log.e(TAG,Log.getStackTraceString(e));
    }
    }

}

And here is the VideoRecordingFragment that it calls:

public class VideoRecordingFragment extends CameraFragment {

    public static final String TAG = "ApparatusVideoRecordingFragment";
    public String package_name;
    public int camera_layout_id;
    public int camera_component_id;
    public CameraView camera_view;
    public View content;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    package_name = getActivity().getApplication().getPackageName();
    camera_layout_id = getActivity().getApplication().getResources().getIdentifier("apparatus_camera", "layout", package_name);
    Log.d(TAG,"camera_layout_id: " + camera_layout_id);
    content = inflater.inflate(camera_layout_id, container, false);
    camera_component_id = getActivity().getApplication().getResources().getIdentifier("camera", "id", package_name);
    Log.d(TAG,"camera_component_id: " + camera_component_id);
    CameraView camera_view = (CameraView) content.findViewById(camera_component_id);
    //camera_view.lockToLandscape(true);
    Log.d(TAG,"camera_view orientation: " + camera_view.getDisplayOrientation());
    setCameraView(camera_view);
    return(content);
    }

    public int getIdentifier(String asset, String type) {
    return getActivity().getApplication().getResources().getIdentifier(asset,type,package_name);
    }

    public Button getButton() {
    return ((Button)content.findViewById(getIdentifier("record_button","id")));
    }


}
Max
  • 1
  • 1
  • That exception is thrown if `displayOrientation != 0 && displayOrientation != 180`. That is set in `setCameraDisplayOrientation()`, triggered by `onResume()`. The only way I can see it remaining at its default of -1 is if `onResume()` is never called on the `CameraView`. That should be handled by `CameraFragment` – CommonsWare Mar 02 '15 at 19:35
  • New information: I moved the logging that included getDisplayOrientation() to after the resume runs (derp) and confirmed that it is being set initially. Here is the catch though: If I start up my application in landscape and then launch the video recording activity everything works fine. However, if I launch my application in portrait mode and then switch the orientation to landscape once I'm in the activity (either programmatically with lockToLandscape() or by rotating the device in meatspace) then getDisplayOrientation returns -1. – Max Mar 02 '15 at 19:57
  • I would expect that it would be 90 or 270 in that case because there is nowhere in your code apart from initialization that sets displayOrientation to -1... – Max Mar 02 '15 at 20:05
  • Your fragment is being destroyed and recreated as part of the configuration change, most likely, and the new fragment instance isn't going through `onResume()` for some reason. – CommonsWare Mar 02 '15 at 20:06
  • I built an onDestroyView and onDestroy override into the fragment and found that it is running those whether the orientation is changed programmatically or physically. I did the same for onResume() and from what I can tell it looks like it's running VideoRecordingFragment's onResume() twice. The first shows getDisplayOrientation() as a logical number (0) while the second is -1. I'm guessing that the code I've written to start all these pieces up is incorrect. I'm going to comb through it, but tried to follow the documentation and the demo layout example. Am I running more than I need to? – Max Mar 02 '15 at 20:28
  • If I keep the activity that launches the RecordActivity in landscape then it only runs onResume() once... – Max Mar 02 '15 at 20:33
  • Unless there are *lots* of examples of Cordova plugins using fragments, I'd drop the `CameraFragment` entirely. I suspect that there are more plugins that work with straight `View` widgets, and you may have better luck with that approach, using `CameraView` directly. `CameraHostProvider`, notably, is only for cases where you are using `CameraView` directly. – CommonsWare Mar 02 '15 at 20:37
  • Yeah, I'm going to drop the fragment. Is there a demo app or other docs showing how to use CameraView? – Max Mar 02 '15 at 21:14
  • Found the issue! I had getFragmentManager().beginTransaction().add(...) instead of replace(...). Swapping that out fixed the issue. Thanks for all your help. – Max Mar 02 '15 at 21:25
  • Ah, yeah, I didn't even think about that. You were winding up with two instances of the fragment. "Is there a demo app or other docs showing how to use CameraView?" -- there are some docs in the two-ton project `README`, but no direct samples IIRC. – CommonsWare Mar 02 '15 at 21:42

0 Answers0