Add instrumentation tests and codecov support (#18)

* Add instrumentation tests

* Run androidTests on api 22

* Fix lint errors

* Nits

* Add codecov support

* Shield
pull/19/head
Mattia Iavarone 7 years ago committed by GitHub
parent 87e73aec5d
commit 41f9f51ef9
  1. 21
      .travis.yml
  2. 4
      README.md
  3. 72
      cameraview/build.gradle
  4. 58
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/AspectRatioTest.java
  5. 132
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraOptions1Test.java
  6. 279
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java
  7. 7
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/ExtraProperties1Test.java
  8. 6
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/Mapper1Test.java
  9. 124
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java
  10. 34
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockPreview.java
  11. 70
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
  12. 4
      cameraview/src/main/views/com/otaliastudios/cameraview/GestureLayout.java

@ -10,6 +10,12 @@ sudo: false
jdk:
- oraclejdk8
env:
global:
# Run android tests on api level 22
- EMULATOR_API=22
- EMULATOR_ABI=armeabi-v7a
android:
components:
- tools
@ -17,9 +23,22 @@ android:
- build-tools-26.0.1
- android-26
- doc-26
# Android tests
- android-$EMULATOR_API
- sys-img-$EMULATOR_ABI-android-$EMULATOR_API
# sys-img-x86-google_apis-26
before_script:
- echo no | android create avd --force --name test --target android-$EMULATOR_API --abi $EMULATOR_ABI
- emulator -avd test -no-audio -no-window &
- android-wait-for-emulator
- adb shell input keyevent 82 &
script:
- ./gradlew clean connectedCheck testDebugUnitTest
- ./gradlew clean testDebugUnitTest connectedCheck coverageReport
after_success:
- bash <(curl -s https://codecov.io/bash)
cache:
directories:

@ -1,3 +1,6 @@
[![Build Status](https://travis-ci.org/natario1/CameraView.svg?branch=master)](https://travis-ci.org/natario1/CameraView)
[![Code Coverage](https://codecov.io/gh/natario1/CameraView/branch/master/graph/badge.svg)](https://codecov.io/gh/natario1/CameraView)
<p align="center">
<img src="art/icon.png" vspace="10" width="250" height="250">
</p>
@ -409,6 +412,7 @@ Other APIs not mentioned above are provided, and are well documented and comment
|------|-----------|
|`isStarted()`|Returns true if `start()` was called succesfully. This does not mean that camera is open or showing preview.|
|`mapGesture(Gesture, GestureAction)`|Maps a certain gesture to a certain action. No-op if the action is not supported.|
|`getGestureAction(Gesture)`|Returns the action currently mapped to the given gesture.|
|`clearGesture(Gesture)`|Clears any action mapped to the given gesture.|
|`getCameraOptions()`|If camera was started, returns non-null object with information about what is supported.|
|`getExtraProperties()`|If camera was started, returns non-null object with extra information about the camera sensor. Not very useful at the moment.|

@ -6,6 +6,8 @@ apply plugin: 'com.jfrog.bintray'
version = '1.2.0'
group = 'com.otaliastudios'
//region android dependencies
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
@ -15,8 +17,14 @@ android {
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName project.version
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
debug {
testCoverageEnabled true
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
@ -34,10 +42,18 @@ dependencies {
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.10.19'
androidTestCompile 'com.android.support.test:runner:1.0.1'
androidTestCompile 'com.android.support.test:rules:1.0.1'
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
compile "com.android.support:exifinterface:$supportLibVersion"
compile "com.android.support:support-annotations:$supportLibVersion"
}
//endregion
//region bintray
install {
repositories.mavenInstaller {
@ -104,6 +120,10 @@ bintray {
}
}
//endregion
//region javadoc and sources
// From official sample https://github.com/bintray/bintray-examples/blob/master/gradle-aar-example/build.gradle
task sourcesJar(type: Jar) {
classifier = 'sources'
@ -134,6 +154,58 @@ artifacts {
archives sourcesJar
}
//endregion
//region code coverage
// 1. running androidTests with connectedCheck will generate an .ec file
// in build/outputs/code-coverage/connected, plus the XML result in
// in build/reports/coverage/debug/report.xml .
// 2. running unit tests with testDebugUnitTest will just generate the .exec file.
// The JacocoReport task from the jacoco plugin can create the XML report out of it.
// to have a unified report, we just pass both the .exec and the .ec file
// to the jacoco task, so we get a unified XML report with total coverage.
// Reference: https://medium.com/@rafael_toledo/setting-up-an-unified-coverage-report-in-android-with-jacoco-robolectric-and-espresso-ffe239aaf3fa
apply plugin: 'jacoco'
jacoco {
// Using a different version might get 0 coverage reports.
// No time to investigate now.
toolVersion = "0.7.6.201602180812"
reportsDir = file("$buildDir/reports/jacoco/merged/")
}
task coverageReport(type: JacocoReport) {
dependsOn "testDebugUnitTest"
dependsOn "connectedCheck"
def testData = "jacoco/testDebugUnitTest.exec"
def androidTestData = "outputs/code-coverage/connected/*coverage.ec"
executionData = fileTree(dir: "$buildDir", includes: [testData, androidTestData])
// Sources.
sourceDirectories = android.sourceSets.main.java.sourceFiles
// Add BuildConfig and R.
additionalSourceDirs = files([
"$buildDir/generated/source/buildConfig/debug",
"$buildDir/generated/source/r/debug"
])
// Classes.
def debugDir = "$buildDir/intermediates/classes/debug"
def filter = ['**/R.class', '**/R$*.class', '**/*$ViewInjector*.*',
'**/BuildConfig.*', '**/Manifest*.*']
classDirectories = fileTree(dir: debugDir, excludes: filter);
reports.xml.enabled = true
reports.html.enabled = true
}
//endregion
// export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home
// To deploy ./gradlew bintrayUpload

@ -0,0 +1,58 @@
package com.otaliastudios.cameraview;
import android.annotation.TargetApi;
import android.hardware.Camera;
import android.hardware.camera2.CameraCharacteristics;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.SizeF;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class AspectRatioTest {
@Test
public void testConstructor() {
AspectRatio ratio = AspectRatio.of(50, 10);
assertEquals(ratio.getX(), 5f, 0);
assertEquals(ratio.getY(), 1f, 0);
assertEquals(ratio.toString(), "5:1");
}
@Test
public void testEquals() {
AspectRatio ratio = AspectRatio.of(50, 10);
AspectRatio ratio1 = AspectRatio.of(5, 1);
assertTrue(ratio.equals(ratio1));
Size size = new Size(500, 100);
assertTrue(ratio.matches(size));
}
@Test
public void testInverse() {
AspectRatio ratio = AspectRatio.of(50, 10);
AspectRatio inverse = ratio.inverse();
assertEquals(inverse.getX(), 1f, 0);
assertEquals(inverse.getY(), 5f, 0);
}
@Test
public void testParcelable() {
AspectRatio ratio = AspectRatio.of(50, 10);
Parcel parcel = Parcel.obtain();
ratio.writeToParcel(parcel, ratio.describeContents());
parcel.setDataPosition(0);
AspectRatio other = AspectRatio.CREATOR.createFromParcel(parcel);
assertEquals(ratio, other);
}
}

@ -0,0 +1,132 @@
package com.otaliastudios.cameraview;
import android.hardware.Camera;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.test.ActivityInstrumentationTestCase2;
import android.test.InstrumentationTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class CameraOptions1Test {
@Test
public void testEmpty() {
CameraOptions o = new CameraOptions(mock(Camera.Parameters.class));
assertTrue(o.getSupportedWhiteBalance().isEmpty());
assertTrue(o.getSupportedFlash().isEmpty());
assertTrue(o.getSupportedHdr().isEmpty());
assertFalse(o.isAutoFocusSupported());
assertFalse(o.isExposureCorrectionSupported());
assertFalse(o.isVideoSnapshotSupported());
assertFalse(o.isZoomSupported());
assertEquals(o.getExposureCorrectionMaxValue(), 0f, 0);
assertEquals(o.getExposureCorrectionMinValue(), 0f, 0);
}
@Test
public void testFacing() {
Set<Integer> supported = new HashSet<>();
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0, count = Camera.getNumberOfCameras(); i < count; i++) {
Camera.getCameraInfo(i, cameraInfo);
supported.add(cameraInfo.facing);
}
CameraOptions o = new CameraOptions(mock(Camera.Parameters.class));
Mapper m = new Mapper.Mapper1();
Set<Facing> s = o.getSupportedFacing();
assertEquals(o.getSupportedFacing().size(), supported.size());
for (Facing facing : s) {
assertTrue(supported.contains(m.<Integer>map(facing)));
}
}
@Test
public void testWhiteBalance() {
Camera.Parameters params = mock(Camera.Parameters.class);
when(params.getSupportedWhiteBalance()).thenReturn(Arrays.asList(
Camera.Parameters.WHITE_BALANCE_AUTO, // Supported
Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT, // Supported
Camera.Parameters.WHITE_BALANCE_SHADE // Not supported
));
CameraOptions o = new CameraOptions(params);
assertEquals(o.getSupportedWhiteBalance().size(), 2);
assertTrue(o.getSupportedWhiteBalance().contains(WhiteBalance.AUTO));
assertTrue(o.getSupportedWhiteBalance().contains(WhiteBalance.CLOUDY));
assertTrue(o.supports(WhiteBalance.AUTO));
assertTrue(o.supports(WhiteBalance.CLOUDY));
}
@Test
public void testFlash() {
Camera.Parameters params = mock(Camera.Parameters.class);
when(params.getSupportedFlashModes()).thenReturn(Arrays.asList(
Camera.Parameters.FLASH_MODE_AUTO, // Supported
Camera.Parameters.FLASH_MODE_TORCH, // Supported
Camera.Parameters.FLASH_MODE_RED_EYE // Not supported
));
CameraOptions o = new CameraOptions(params);
assertEquals(o.getSupportedFlash().size(), 2);
assertTrue(o.getSupportedFlash().contains(Flash.AUTO));
assertTrue(o.getSupportedFlash().contains(Flash.TORCH));
assertTrue(o.supports(Flash.AUTO));
assertTrue(o.supports(Flash.TORCH));
}
@Test
public void testHdr() {
Camera.Parameters params = mock(Camera.Parameters.class);
when(params.getSupportedSceneModes()).thenReturn(Arrays.asList(
Camera.Parameters.SCENE_MODE_AUTO, // Supported
Camera.Parameters.SCENE_MODE_HDR, // Supported
Camera.Parameters.SCENE_MODE_FIREWORKS // Not supported
));
CameraOptions o = new CameraOptions(params);
assertEquals(o.getSupportedHdr().size(), 2);
assertTrue(o.getSupportedHdr().contains(Hdr.OFF));
assertTrue(o.getSupportedHdr().contains(Hdr.ON));
assertTrue(o.supports(Hdr.OFF));
assertTrue(o.supports(Hdr.ON));
}
@Test
public void testBooleanFlags() {
Camera.Parameters params = mock(Camera.Parameters.class);
when(params.isVideoSnapshotSupported()).thenReturn(true);
when(params.isZoomSupported()).thenReturn(true);
when(params.getSupportedFocusModes()).thenReturn(Arrays.asList(Camera.Parameters.FOCUS_MODE_AUTO));
CameraOptions o = new CameraOptions(params);
assertTrue(o.isVideoSnapshotSupported());
assertTrue(o.isZoomSupported());
assertTrue(o.isAutoFocusSupported());
}
@Test
public void testExposureCorrection() {
Camera.Parameters params = mock(Camera.Parameters.class);
when(params.getMaxExposureCompensation()).thenReturn(10);
when(params.getMinExposureCompensation()).thenReturn(-10);
when(params.getExposureCompensationStep()).thenReturn(0.5f);
CameraOptions o = new CameraOptions(params);
assertTrue(o.isExposureCorrectionSupported());
assertEquals(o.getExposureCorrectionMinValue(), -10f * 0.5f, 0f);
assertEquals(o.getExposureCorrectionMaxValue(), 10f * 0.5f, 0f);
}
}

@ -0,0 +1,279 @@
package com.otaliastudios.cameraview;
import android.app.Instrumentation;
import android.content.Context;
import android.hardware.Camera;
import android.os.Looper;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
import android.view.ViewGroup;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static android.view.View.MeasureSpec.*;
import static android.view.ViewGroup.LayoutParams.*;
@RunWith(AndroidJUnit4.class)
@MediumTest
public class CameraViewTest {
private CameraView cameraView;
private MockCameraController mockController;
private Preview mockPreview;
@Before
public void setUp() {
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
Context context = InstrumentationRegistry.getContext();
cameraView = new CameraView(context) {
@Override
protected CameraController instantiateCameraController(CameraCallbacks callbacks, Preview preview) {
mockController = new MockCameraController(callbacks, preview);
return mockController;
}
@Override
protected Preview instantiatePreview(Context context, ViewGroup container) {
mockPreview = new MockPreview(context, container);
return mockPreview;
}
};
}
});
}
@After
public void tearDown() {
cameraView = null;
mockController = null;
mockPreview = null;
}
//region testDefaults
@Test
public void testNotStarted() {
assertFalse(cameraView.isStarted());
assertNull(cameraView.getCameraOptions());
assertNull(cameraView.getExtraProperties());
assertNull(cameraView.getPreviewSize());
assertNull(cameraView.getCaptureSize());
assertNull(cameraView.getSnapshotSize());
}
@Test
public void testDefaults() {
// CameraController
assertEquals(cameraView.getFlash(), Flash.DEFAULT);
assertEquals(cameraView.getFacing(), Facing.DEFAULT);
assertEquals(cameraView.getGrid(), Grid.DEFAULT);
assertEquals(cameraView.getWhiteBalance(), WhiteBalance.DEFAULT);
assertEquals(cameraView.getSessionType(), SessionType.DEFAULT);
assertEquals(cameraView.getHdr(), Hdr.DEFAULT);
assertEquals(cameraView.getVideoQuality(), VideoQuality.DEFAULT);
// Self managed
assertEquals(cameraView.getExposureCorrection(), 0f, 0f);
assertEquals(cameraView.getZoom(), 0f, 0f);
assertEquals(cameraView.getCropOutput(), CameraView.DEFAULT_CROP_OUTPUT);
assertEquals(cameraView.getJpegQuality(), CameraView.DEFAULT_JPEG_QUALITY);
assertEquals(cameraView.getGestureAction(Gesture.TAP), GestureAction.DEFAULT_TAP);
assertEquals(cameraView.getGestureAction(Gesture.LONG_TAP), GestureAction.DEFAULT_LONG_TAP);
assertEquals(cameraView.getGestureAction(Gesture.PINCH), GestureAction.DEFAULT_PINCH);
assertEquals(cameraView.getGestureAction(Gesture.SCROLL_HORIZONTAL), GestureAction.DEFAULT_SCROLL_HORIZONTAL);
assertEquals(cameraView.getGestureAction(Gesture.SCROLL_VERTICAL), GestureAction.DEFAULT_SCROLL_VERTICAL);
}
//endregion
//region testGesture
@Test
public void testGesture_mapAndClear() {
// Assignable
cameraView.mapGesture(Gesture.PINCH, GestureAction.ZOOM);
assertEquals(cameraView.getGestureAction(Gesture.PINCH), GestureAction.ZOOM);
// Not assignable: This is like clearing
cameraView.mapGesture(Gesture.PINCH, GestureAction.CAPTURE);
assertEquals(cameraView.getGestureAction(Gesture.PINCH), GestureAction.NONE);
// Test clearing
cameraView.mapGesture(Gesture.PINCH, GestureAction.ZOOM);
cameraView.clearGesture(Gesture.PINCH);
assertEquals(cameraView.getGestureAction(Gesture.PINCH), GestureAction.NONE);
}
@Test
public void testGesture_enablingDisablingLayouts() {
cameraView.clearGesture(Gesture.TAP);
cameraView.clearGesture(Gesture.LONG_TAP);
cameraView.clearGesture(Gesture.PINCH);
cameraView.clearGesture(Gesture.SCROLL_HORIZONTAL);
cameraView.clearGesture(Gesture.SCROLL_VERTICAL);
// PinchGestureLayout
cameraView.mapGesture(Gesture.PINCH, GestureAction.ZOOM);
assertTrue(cameraView.mPinchGestureLayout.enabled());
cameraView.clearGesture(Gesture.PINCH);
assertFalse(cameraView.mPinchGestureLayout.enabled());
// TapGestureLayout
cameraView.mapGesture(Gesture.TAP, GestureAction.CAPTURE);
assertTrue(cameraView.mTapGestureLayout.enabled());
cameraView.clearGesture(Gesture.TAP);
assertFalse(cameraView.mPinchGestureLayout.enabled());
// ScrollGestureLayout
cameraView.mapGesture(Gesture.SCROLL_HORIZONTAL, GestureAction.ZOOM);
assertTrue(cameraView.mScrollGestureLayout.enabled());
cameraView.clearGesture(Gesture.SCROLL_HORIZONTAL);
assertFalse(cameraView.mScrollGestureLayout.enabled());
}
//endregion
//region testMeasure
private void mockPreviewSize() {
Size size = new Size(900, 1600);
mockController.setMockPreviewSize(size);
}
@Test
public void testMeasure_matchParentBoth() {
mockPreviewSize();
// Respect parent/layout constraints on both dimensions.
cameraView.setLayoutParams(new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
cameraView.measure(
makeMeasureSpec(500, EXACTLY),
makeMeasureSpec(500, EXACTLY));
assertEquals(cameraView.getMeasuredWidth(), 500);
assertEquals(cameraView.getMeasuredHeight(), 500);
// Even if the parent ViewGroup passes AT_MOST
cameraView.measure(
makeMeasureSpec(500, AT_MOST),
makeMeasureSpec(500, AT_MOST));
assertEquals(cameraView.getMeasuredWidth(), 500);
assertEquals(cameraView.getMeasuredHeight(), 500);
cameraView.measure(
makeMeasureSpec(500, EXACTLY),
makeMeasureSpec(500, AT_MOST));
assertEquals(cameraView.getMeasuredWidth(), 500);
assertEquals(cameraView.getMeasuredHeight(), 500);
}
@Test
public void testMeasure_wrapContentBoth() {
mockPreviewSize();
// Respect parent constraints, but fit aspect ratio.
// Fit into a 160x160 parent so we espect final width to be 90.
cameraView.setLayoutParams(new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
cameraView.measure(
makeMeasureSpec(160, AT_MOST),
makeMeasureSpec(160, AT_MOST));
assertEquals(cameraView.getMeasuredWidth(), 90);
assertEquals(cameraView.getMeasuredHeight(), 160);
}
@Test
public void testMeasure_wrapContentSingle() {
mockPreviewSize();
// Respect MATCH_PARENT on height, change width to fit the aspect ratio.
cameraView.setLayoutParams(new ViewGroup.LayoutParams(WRAP_CONTENT, MATCH_PARENT));
cameraView.measure(
makeMeasureSpec(160, AT_MOST),
makeMeasureSpec(160, AT_MOST));
assertEquals(cameraView.getMeasuredWidth(), 90);
assertEquals(cameraView.getMeasuredHeight(), 160);
// Respect MATCH_PARENT on width. Enlarge height trying to fit aspect ratio as much as possible.
cameraView.setLayoutParams(new ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
cameraView.measure(
makeMeasureSpec(160, AT_MOST),
makeMeasureSpec(160, AT_MOST));
assertEquals(cameraView.getMeasuredWidth(), 160);
assertEquals(cameraView.getMeasuredHeight(), 160);
}
@Test
public void testMeasure_scrollableContainer() {
mockPreviewSize();
// Assume a vertical scroll view. It will pass UNSPECIFIED as height.
// We respect MATCH_PARENT on width (160), and enlarge height to match the aspect ratio.
cameraView.setLayoutParams(new ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
cameraView.measure(
makeMeasureSpec(160, AT_MOST),
makeMeasureSpec(0, UNSPECIFIED));
assertEquals(cameraView.getMeasuredWidth(), 160);
assertEquals(cameraView.getMeasuredHeight(), 160f * (16f / 9f), 1f); // Leave a margin
// Assume a view scrolling in both dimensions. It will pass UNSPECIFIED.
// In this case we must fit the exact preview dimension.
cameraView.setLayoutParams(new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
cameraView.measure(
makeMeasureSpec(0, UNSPECIFIED),
makeMeasureSpec(0, UNSPECIFIED));
assertEquals(cameraView.getMeasuredWidth(), 900);
assertEquals(cameraView.getMeasuredHeight(), 1600);
}
//endregion
//region Zoom, ExposureCorrection
@Test
public void testZoom() {
cameraView.setZoom(0.5f);
assertEquals(cameraView.getZoom(), 0.5f, 0f);
cameraView.setZoom(-10f);
assertEquals(cameraView.getZoom(), 0f, 0f);
cameraView.setZoom(10f);
assertEquals(cameraView.getZoom(), 1f, 0f);
}
@Test
public void testExposureCorrection() {
// This needs a valid CameraOptions value.
CameraOptions o = mock(CameraOptions.class);
when(o.getExposureCorrectionMinValue()).thenReturn(-10f);
when(o.getExposureCorrectionMaxValue()).thenReturn(10f);
mockController.setMockCameraOptions(o);
cameraView.setExposureCorrection(5f);
assertEquals(cameraView.getExposureCorrection(), 5f, 0f);
cameraView.setExposureCorrection(-100f);
assertEquals(cameraView.getExposureCorrection(), -10f, 0f);
cameraView.setExposureCorrection(100f);
assertEquals(cameraView.getExposureCorrection(), 10f, 0f);
}
//endregion
// TODO: test setLocation
// TODO: test touch events
// TODO: test permissions and start() stop() isStarted()
// TODO: test CameraCallbacks
}

@ -4,15 +4,20 @@ package com.otaliastudios.cameraview;
import android.annotation.TargetApi;
import android.hardware.Camera;
import android.hardware.camera2.CameraCharacteristics;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.SizeF;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
public class ExtraPropertiesTest {
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ExtraProperties1Test {
@Test
public void testConstructor1() {

@ -2,11 +2,17 @@ package com.otaliastudios.cameraview;
import android.hardware.Camera;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class Mapper1Test {
private Mapper mapper = new Mapper.Mapper1();

@ -0,0 +1,124 @@
package com.otaliastudios.cameraview;
import android.graphics.PointF;
import android.location.Location;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.io.File;
public class MockCameraController extends CameraController {
MockCameraController(CameraView.CameraCallbacks callback, Preview preview) {
super(callback, preview);
}
void setMockCameraOptions(CameraOptions options) {
mOptions = options;
}
void setMockPreviewSize(Size size) {
mPreviewSize = size;
}
@Override
void onStart() {
}
@Override
void onStop() {
}
@Override
boolean setZoom(float zoom) {
return true;
}
@Override
boolean setExposureCorrection(float EVvalue) {
return true;
}
@Override
void setFacing(Facing facing) {
mFacing = facing;
}
@Override
void setFlash(Flash flash) {
mFlash = flash;
}
@Override
void setWhiteBalance(WhiteBalance whiteBalance) {
mWhiteBalance = whiteBalance;
}
@Override
void setVideoQuality(VideoQuality videoQuality) {
mVideoQuality = videoQuality;
}
@Override
void setSessionType(SessionType sessionType) {
mSessionType = sessionType;
}
@Override
void setHdr(Hdr hdr) {
mHdr = hdr;
}
@Override
void setLocation(Location location) {
}
@Override
boolean capturePicture() {
return true;
}
@Override
boolean captureSnapshot() {
return true;
}
@Override
boolean startVideo(@NonNull File file) {
return true;
}
@Override
boolean endVideo() {
return true;
}
@Override
boolean shouldFlipSizes() {
return false;
}
@Override
boolean isCameraOpened() {
return true;
}
@Override
boolean startAutoFocus(@Nullable Gesture gesture, PointF point) {
return true;
}
@Override
public void onSurfaceChanged() {
}
@Override
public void onSurfaceAvailable() {
}
}

@ -0,0 +1,34 @@
package com.otaliastudios.cameraview;
import android.content.Context;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
public class MockPreview extends Preview {
public MockPreview(Context context, ViewGroup parent) {
super(context, parent);
}
@Override
Surface getSurface() {
return null;
}
@Override
View getView() {
return null;
}
@Override
Class getOutputClass() {
return null;
}
@Override
boolean isReady() {
return true;
}
}

@ -1,6 +1,7 @@
package com.otaliastudios.cameraview;
import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
@ -44,8 +45,8 @@ public class CameraView extends FrameLayout {
private final static String TAG = CameraView.class.getSimpleName();
public final static int PERMISSION_REQUEST_CODE = 16;
private final static int DEFAULT_JPEG_QUALITY = 100;
private final static boolean DEFAULT_CROP_OUTPUT = false;
final static int DEFAULT_JPEG_QUALITY = 100;
final static boolean DEFAULT_CROP_OUTPUT = false;
// Self managed parameters
private int mJpegQuality;
@ -61,10 +62,10 @@ public class CameraView extends FrameLayout {
private Preview mPreviewImpl;
// Views
private GridLinesLayout mGridLinesLayout;
private PinchGestureLayout mPinchGestureLayout;
private TapGestureLayout mTapGestureLayout;
private ScrollGestureLayout mScrollGestureLayout;
GridLinesLayout mGridLinesLayout;
PinchGestureLayout mPinchGestureLayout;
TapGestureLayout mTapGestureLayout;
ScrollGestureLayout mScrollGestureLayout;
private boolean mIsStarted;
private boolean mKeepScreenOn;
@ -98,6 +99,7 @@ public class CameraView extends FrameLayout {
WhiteBalance whiteBalance = WhiteBalance.fromValue(a.getInteger(R.styleable.CameraView_cameraWhiteBalance, WhiteBalance.DEFAULT.value()));
VideoQuality videoQuality = VideoQuality.fromValue(a.getInteger(R.styleable.CameraView_cameraVideoQuality, VideoQuality.DEFAULT.value()));
SessionType sessionType = SessionType.fromValue(a.getInteger(R.styleable.CameraView_cameraSessionType, SessionType.DEFAULT.value()));
Hdr hdr = Hdr.fromValue(a.getInteger(R.styleable.CameraView_cameraHdr, Hdr.DEFAULT.value()));
// Gestures
GestureAction tapGesture = GestureAction.fromValue(a.getInteger(R.styleable.CameraView_cameraGestureTap, GestureAction.DEFAULT_TAP.value()));
@ -109,8 +111,8 @@ public class CameraView extends FrameLayout {
// Components
mCameraCallbacks = new CameraCallbacks();
mPreviewImpl = new TextureViewPreview(context, this);
mCameraController = new Camera1(mCameraCallbacks, mPreviewImpl);
mPreviewImpl = instantiatePreview(context, this);
mCameraController = instantiateCameraController(mCameraCallbacks, mPreviewImpl);
mUiHandler = new Handler(Looper.getMainLooper());
mWorkerHandler = new WorkerHandler("CameraViewWorker");
@ -137,6 +139,7 @@ public class CameraView extends FrameLayout {
setVideoQuality(videoQuality);
setWhiteBalance(whiteBalance);
setGrid(grid);
setHdr(hdr);
// Apply gestures
mapGesture(Gesture.TAP, tapGesture);
@ -151,6 +154,17 @@ public class CameraView extends FrameLayout {
}
}
protected Preview instantiatePreview(Context context, ViewGroup container) {
return new TextureViewPreview(context, container);
}
protected CameraController instantiateCameraController(CameraCallbacks callbacks, Preview preview) {
return new Camera1(callbacks, preview);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@ -364,7 +378,18 @@ public class CameraView extends FrameLayout {
* @param gesture which gesture to clear
*/
public void clearGesture(@NonNull Gesture gesture) {
mGestureMap.put(gesture, GestureAction.NONE);
mapGesture(gesture, GestureAction.NONE);
}
/**
* Returns the action currently mapped to the given gesture.
*
* @param gesture which gesture to inspect
* @return mapped action
*/
public GestureAction getGestureAction(@NonNull Gesture gesture) {
return mGestureMap.get(gesture);
}
@ -472,6 +497,7 @@ public class CameraView extends FrameLayout {
* Throws if session = audio and manifest did not add the microphone permissions.
* @return true if we can go on, false otherwise.
*/
@SuppressLint("NewApi")
private boolean checkPermissions(SessionType sessionType) {
checkPermissionsManifestOrThrow(sessionType);
boolean api23 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
@ -480,9 +506,7 @@ public class CameraView extends FrameLayout {
cameraCheck = PackageManager.PERMISSION_GRANTED;
audioCheck = PackageManager.PERMISSION_GRANTED;
} else {
//noinspection all
cameraCheck = getContext().checkSelfPermission(Manifest.permission.CAMERA);
//noinspection all
audioCheck = getContext().checkSelfPermission(Manifest.permission.RECORD_AUDIO);
}
switch (sessionType) {
@ -922,12 +946,21 @@ public class CameraView extends FrameLayout {
*/
public void setJpegQuality(int jpegQuality) {
if (jpegQuality <= 0 || jpegQuality > 100) {
throw new IllegalArgumentException("JPEG quality should be > 0 and <= 0");
throw new IllegalArgumentException("JPEG quality should be > 0 and <= 100");
}
mJpegQuality = jpegQuality;
}
/**
* Gets the JPEG compression quality for image outputs.
* @return a 0-100 integer
*/
public int getJpegQuality() {
return mJpegQuality;
}
/**
* Whether we should crop the picture output to match CameraView aspect ratio.
* This is only relevant if CameraView dimensions were somehow constrained
@ -942,6 +975,17 @@ public class CameraView extends FrameLayout {
}
/**
* Returns whether we should crop the picture output to match CameraView aspect ratio.
*
* @see #setCropOutput(boolean)
* @return whether we crop
*/
public boolean getCropOutput() {
return mCropOutput;
}
/**
* Sets a {@link CameraListener} instance to be notified of all
* interesting events that will happen during the camera lifecycle.
@ -1158,7 +1202,7 @@ public class CameraView extends FrameLayout {
private MediaActionSound mSound;
private final boolean mUseSounds = Build.VERSION.SDK_INT >= 16;
@SuppressWarnings("all")
@SuppressLint("NewApi")
private void sound(int soundType) {
if (mUseSounds) {
if (mSound == null) mSound = new MediaActionSound();

@ -29,6 +29,10 @@ abstract class GestureLayout extends FrameLayout {
mEnabled = enable;
}
public boolean enabled() {
return mEnabled;
}
public abstract boolean onTouchEvent(MotionEvent event);
public final Gesture getGestureType() {

Loading…
Cancel
Save