diff --git a/samples/android/CMakeLists.txt b/samples/android/CMakeLists.txt
index bf96bdf5a..36495ccf5 100644
--- a/samples/android/CMakeLists.txt
+++ b/samples/android/CMakeLists.txt
@@ -16,6 +16,7 @@ add_subdirectory(tutorial-1-addopencv)
add_subdirectory(tutorial-2-opencvcamera)
add_subdirectory(tutorial-3-native)
add_subdirectory(tutorial-4-mixed)
+add_subdirectory(tutorial-5-customcamera)
#hello-android sample
if(HAVE_opencv_highgui)
diff --git a/samples/android/tutorial-5-customcamera/.classpath b/samples/android/tutorial-5-customcamera/.classpath
new file mode 100644
index 000000000..3f9691c5d
--- /dev/null
+++ b/samples/android/tutorial-5-customcamera/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/samples/android/tutorial-5-customcamera/.project b/samples/android/tutorial-5-customcamera/.project
new file mode 100644
index 000000000..4d7380723
--- /dev/null
+++ b/samples/android/tutorial-5-customcamera/.project
@@ -0,0 +1,33 @@
+
+
+ OpenCV Tutorial 5 - Custom camera
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/samples/android/tutorial-5-customcamera/.settings/org.eclipse.jdt.core.prefs b/samples/android/tutorial-5-customcamera/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..b080d2ddc
--- /dev/null
+++ b/samples/android/tutorial-5-customcamera/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/samples/android/tutorial-5-customcamera/AndroidManifest.xml b/samples/android/tutorial-5-customcamera/AndroidManifest.xml
new file mode 100644
index 000000000..7779cbe66
--- /dev/null
+++ b/samples/android/tutorial-5-customcamera/AndroidManifest.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/android/tutorial-5-customcamera/CMakeLists.txt b/samples/android/tutorial-5-customcamera/CMakeLists.txt
new file mode 100644
index 000000000..92256bdce
--- /dev/null
+++ b/samples/android/tutorial-5-customcamera/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(sample example-tutorial-5-customcamera)
+
+add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 11 ${ANDROID_SDK_TARGET})
+if(TARGET ${sample})
+ add_dependencies(opencv_android_examples ${sample})
+endif()
+
diff --git a/samples/android/tutorial-5-customcamera/res/drawable/icon.png b/samples/android/tutorial-5-customcamera/res/drawable/icon.png
new file mode 100644
index 000000000..630454927
Binary files /dev/null and b/samples/android/tutorial-5-customcamera/res/drawable/icon.png differ
diff --git a/samples/android/tutorial-5-customcamera/res/layout/tutorial5_surface_view.xml b/samples/android/tutorial-5-customcamera/res/layout/tutorial5_surface_view.xml
new file mode 100644
index 000000000..2b858e493
--- /dev/null
+++ b/samples/android/tutorial-5-customcamera/res/layout/tutorial5_surface_view.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/samples/android/tutorial-5-customcamera/res/values/strings.xml b/samples/android/tutorial-5-customcamera/res/values/strings.xml
new file mode 100644
index 000000000..d4bb35f54
--- /dev/null
+++ b/samples/android/tutorial-5-customcamera/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ OCV T5 Custom Camera
+
diff --git a/samples/android/tutorial-5-customcamera/src/org/opencv/samples/tutorial5/CustomJavaCameraView.java b/samples/android/tutorial-5-customcamera/src/org/opencv/samples/tutorial5/CustomJavaCameraView.java
new file mode 100644
index 000000000..bd6ccc04b
--- /dev/null
+++ b/samples/android/tutorial-5-customcamera/src/org/opencv/samples/tutorial5/CustomJavaCameraView.java
@@ -0,0 +1,19 @@
+package org.opencv.samples.tutorial5;
+
+import org.opencv.android.JavaCameraView;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+public class CustomJavaCameraView extends JavaCameraView {
+
+ public CustomJavaCameraView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected boolean connectCamera(int width, int height) {
+ boolean result = super.connectCamera(width, height);
+ return result;
+ }
+}
diff --git a/samples/android/tutorial-5-customcamera/src/org/opencv/samples/tutorial5/Sample5CustomCamera.java b/samples/android/tutorial-5-customcamera/src/org/opencv/samples/tutorial5/Sample5CustomCamera.java
new file mode 100644
index 000000000..18a1ce6f3
--- /dev/null
+++ b/samples/android/tutorial-5-customcamera/src/org/opencv/samples/tutorial5/Sample5CustomCamera.java
@@ -0,0 +1,125 @@
+package org.opencv.samples.tutorial5;
+
+import org.opencv.android.BaseLoaderCallback;
+import org.opencv.android.LoaderCallbackInterface;
+import org.opencv.android.OpenCVLoader;
+import org.opencv.core.Mat;
+import org.opencv.android.CameraBridgeViewBase;
+import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.SurfaceView;
+import android.view.WindowManager;
+import android.widget.Toast;
+
+public class Sample5CustomCamera extends Activity implements CvCameraViewListener {
+ private static final String TAG = "OCVSample::Activity";
+
+ private CameraBridgeViewBase mOpenCvCameraView;
+ private boolean mIsJavaCamera = true;
+ private MenuItem mItemSwitchCamera = null;
+
+ private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
+ @Override
+ public void onManagerConnected(int status) {
+ switch (status) {
+ case LoaderCallbackInterface.SUCCESS:
+ {
+ Log.i(TAG, "OpenCV loaded successfully");
+ mOpenCvCameraView.enableView();
+ } break;
+ default:
+ {
+ super.onManagerConnected(status);
+ } break;
+ }
+ }
+ };
+
+ public Sample5CustomCamera() {
+ Log.i(TAG, "Instantiated new " + this.getClass());
+ }
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "called onCreate");
+ super.onCreate(savedInstanceState);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ setContentView(R.layout.tutorial5_surface_view);
+
+ if (mIsJavaCamera)
+ mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial5_activity_java_surface_view);
+
+ mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
+
+ mOpenCvCameraView.setCvCameraViewListener(this);
+ }
+
+ @Override
+ public void onPause()
+ {
+ if (mOpenCvCameraView != null)
+ mOpenCvCameraView.disableView();
+ super.onPause();
+ }
+
+ @Override
+ public void onResume()
+ {
+ super.onResume();
+ OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
+ }
+
+ public void onDestroy() {
+ super.onDestroy();
+ if (mOpenCvCameraView != null)
+ mOpenCvCameraView.disableView();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ Log.i(TAG, "called onCreateOptionsMenu");
+ mItemSwitchCamera = menu.add("Switch camera");
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ String toastMesage = new String();
+ Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
+
+ if (item == mItemSwitchCamera) {
+ mOpenCvCameraView.setVisibility(SurfaceView.GONE);
+ mIsJavaCamera = !mIsJavaCamera;
+
+ if (mIsJavaCamera) {
+ mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial5_activity_java_surface_view);
+ toastMesage = "Java Camera";
+ }
+
+ mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
+ mOpenCvCameraView.setCvCameraViewListener(this);
+ mOpenCvCameraView.enableView();
+ Toast toast = Toast.makeText(this, toastMesage, Toast.LENGTH_LONG);
+ toast.show();
+ }
+
+ return true;
+ }
+
+ public void onCameraViewStarted(int width, int height) {
+ }
+
+ public void onCameraViewStopped() {
+ }
+
+ public Mat onCameraFrame(Mat inputFrame) {
+ return inputFrame;
+ }
+}