diff --git a/demo/src/main/java/com/google/android/cameraview/demo/AspectRatioFragment.java b/demo/src/main/java/com/google/android/cameraview/demo/AspectRatioFragment.java new file mode 100644 index 00000000..650d30f9 --- /dev/null +++ b/demo/src/main/java/com/google/android/cameraview/demo/AspectRatioFragment.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.cameraview.demo; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import com.google.android.cameraview.AspectRatio; + +import java.util.Set; + + +/** + * A simple dialog that allows user to pick an aspect ratio. + */ +public class AspectRatioFragment extends DialogFragment { + + private static final String ARG_ASPECT_RATIOS = "aspect_ratios"; + private static final String ARG_CURRENT_ASPECT_RATIO = "current_aspect_ratio"; + + private Listener mListener; + + public static AspectRatioFragment newInstance(Set ratios, + AspectRatio currentRatio) { + final AspectRatioFragment fragment = new AspectRatioFragment(); + final Bundle args = new Bundle(); + args.putParcelableArray(ARG_ASPECT_RATIOS, + ratios.toArray(new AspectRatio[ratios.size()])); + args.putParcelable(ARG_CURRENT_ASPECT_RATIO, currentRatio); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + mListener = (Listener) context; + } + + @Override + public void onDetach() { + mListener = null; + super.onDetach(); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Bundle args = getArguments(); + final AspectRatio[] ratios = (AspectRatio[]) args.getParcelableArray(ARG_ASPECT_RATIOS); + if (ratios == null) { + throw new RuntimeException("No ratios"); + } + final AspectRatio current = args.getParcelable(ARG_CURRENT_ASPECT_RATIO); + final AspectRatioAdapter adapter = new AspectRatioAdapter(ratios, current); + return new AlertDialog.Builder(getActivity()) + .setAdapter(adapter, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int position) { + mListener.onAspectRatioSelected(ratios[position]); + } + }) + .create(); + } + + private static class AspectRatioAdapter extends BaseAdapter { + + private final AspectRatio[] mRatios; + private final AspectRatio mCurrentRatio; + + AspectRatioAdapter(AspectRatio[] ratios, AspectRatio current) { + mRatios = ratios; + mCurrentRatio = current; + } + + @Override + public int getCount() { + return mRatios.length; + } + + @Override + public AspectRatio getItem(int position) { + return mRatios[position]; + } + + @Override + public long getItemId(int position) { + return getItem(position).hashCode(); + } + + @Override + public View getView(int position, View view, ViewGroup parent) { + AspectRatioAdapter.ViewHolder holder; + if (view == null) { + view = LayoutInflater.from(parent.getContext()) + .inflate(android.R.layout.simple_list_item_1, parent, false); + holder = new AspectRatioAdapter.ViewHolder(); + holder.text = (TextView) view.findViewById(android.R.id.text1); + view.setTag(holder); + } else { + holder = (AspectRatioAdapter.ViewHolder) view.getTag(); + } + AspectRatio ratio = getItem(position); + StringBuilder sb = new StringBuilder(ratio.toString()); + if (ratio.equals(mCurrentRatio)) { + sb.append(" *"); + } + holder.text.setText(sb); + return view; + } + + private static class ViewHolder { + TextView text; + } + + } + + public interface Listener { + void onAspectRatioSelected(@NonNull AspectRatio ratio); + } + +} diff --git a/demo/src/main/java/com/google/android/cameraview/demo/MainActivity.java b/demo/src/main/java/com/google/android/cameraview/demo/MainActivity.java index 00cb4ed3..eeda56af 100644 --- a/demo/src/main/java/com/google/android/cameraview/demo/MainActivity.java +++ b/demo/src/main/java/com/google/android/cameraview/demo/MainActivity.java @@ -41,12 +41,14 @@ import android.view.View; import android.widget.Toast; +import com.google.android.cameraview.AspectRatio; import com.google.android.cameraview.CameraView; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.Set; /** @@ -54,7 +56,8 @@ * $ adb pull /sdcard/Android/data/com.google.android.cameraview.demo/files/Pictures/picture.jpg */ public class MainActivity extends AppCompatActivity implements - ActivityCompat.OnRequestPermissionsResultCallback { + ActivityCompat.OnRequestPermissionsResultCallback, + AspectRatioFragment.Listener { private static final String TAG = "MainActivity"; @@ -184,6 +187,14 @@ public boolean onCreateOptionsMenu(Menu menu) { @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.aspect_ratio: + if (mCameraView != null) { + final Set ratios = mCameraView.getSupportedAspectRatios(); + final AspectRatio currentRatio = mCameraView.getAspectRatio(); + AspectRatioFragment.newInstance(ratios, currentRatio) + .show(getSupportFragmentManager(), FRAGMENT_DIALOG); + } + break; case R.id.switch_flash: if (mCameraView != null) { mCurrentFlash = (mCurrentFlash + 1) % FLASH_OPTIONS.length; @@ -203,6 +214,14 @@ public boolean onOptionsItemSelected(MenuItem item) { return false; } + @Override + public void onAspectRatioSelected(@NonNull AspectRatio ratio) { + if (mCameraView != null) { + Toast.makeText(this, ratio.toString(), Toast.LENGTH_SHORT).show(); + mCameraView.setAspectRatio(ratio); + } + } + private Handler getBackgroundHandler() { if (mBackgroundHandler == null) { HandlerThread thread = new HandlerThread("background"); diff --git a/demo/src/main/res/drawable/ic_aspect_ratio.xml b/demo/src/main/res/drawable/ic_aspect_ratio.xml new file mode 100644 index 00000000..2c39cace --- /dev/null +++ b/demo/src/main/res/drawable/ic_aspect_ratio.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/demo/src/main/res/menu/main.xml b/demo/src/main/res/menu/main.xml index 8aceb716..e92a242d 100644 --- a/demo/src/main/res/menu/main.xml +++ b/demo/src/main/res/menu/main.xml @@ -15,6 +15,12 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> + + This app demonstrates the usage of CameraView. In order to do that, it needs permission to access camera. Camera app cannot do anything without camera permission. Picture taken + Aspect ratio Switch flash Switch camera Flash auto diff --git a/library/src/androidTest/java/com/google/android/cameraview/CameraViewActions.java b/library/src/androidTest/java/com/google/android/cameraview/CameraViewActions.java new file mode 100644 index 00000000..a7abc596 --- /dev/null +++ b/library/src/androidTest/java/com/google/android/cameraview/CameraViewActions.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.cameraview; + +import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; + +import android.support.annotation.NonNull; +import android.support.test.espresso.UiController; +import android.support.test.espresso.ViewAction; +import android.view.View; + +import org.hamcrest.Matcher; + +class CameraViewActions { + + static ViewAction setAspectRatio(@NonNull final AspectRatio ratio) { + return new ViewAction() { + + @Override + public Matcher getConstraints() { + return isAssignableFrom(CameraView.class); + } + + @Override + public String getDescription() { + return "Set aspect ratio to " + ratio; + } + + @Override + public void perform(UiController controller, View view) { + ((CameraView) view).setAspectRatio(ratio); + } + }; + } + +} diff --git a/library/src/androidTest/java/com/google/android/cameraview/CameraViewMatchers.java b/library/src/androidTest/java/com/google/android/cameraview/CameraViewMatchers.java new file mode 100644 index 00000000..4bd7d005 --- /dev/null +++ b/library/src/androidTest/java/com/google/android/cameraview/CameraViewMatchers.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.cameraview; + +import android.support.annotation.NonNull; +import android.view.View; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +class CameraViewMatchers { + + static Matcher hasAspectRatio(@NonNull final AspectRatio ratio) { + return new TypeSafeMatcher() { + @Override + public void describeTo(Description description) { + description.appendText("has aspect ratio of " + ratio); + } + + @Override + protected boolean matchesSafely(View view) { + return ratio.equals(((CameraView) view).getAspectRatio()); + } + }; + } + +} diff --git a/library/src/androidTest/java/com/google/android/cameraview/CameraViewTest.java b/library/src/androidTest/java/com/google/android/cameraview/CameraViewTest.java index d8f7f997..83599982 100644 --- a/library/src/androidTest/java/com/google/android/cameraview/CameraViewTest.java +++ b/library/src/androidTest/java/com/google/android/cameraview/CameraViewTest.java @@ -25,6 +25,8 @@ import static android.support.test.espresso.matcher.ViewMatchers.withId; import static com.google.android.cameraview.AspectRatioIsCloseTo.closeToOrInverse; +import static com.google.android.cameraview.CameraViewActions.setAspectRatio; +import static com.google.android.cameraview.CameraViewMatchers.hasAspectRatio; import static junit.framework.Assert.assertFalse; @@ -110,31 +112,13 @@ public void preview_isShowing() throws Exception { @Test public void testAspectRatio() { - onView(withId(R.id.camera)) - .check(new ViewAssertion() { - @Override - public void check(View view, NoMatchingViewException noViewFoundException) { - CameraView cameraView = (CameraView) view; - AspectRatio ratio = cameraView.getAspectRatio(); - assertThat(ratio, is(notNullValue())); - Set ratios = cameraView.getSupportedAspectRatios(); - assertThat(ratios.size(), is(greaterThanOrEqualTo(1))); - assertThat(ratios, hasItem(ratio)); - if (ratios.size() == 1) { - return; - } - // Pick one ratio to change to - for (AspectRatio r : ratios) { - if (!r.equals(ratio)) { - ratio = r; - break; - } - } - assert ratio != null; - cameraView.setAspectRatio(ratio); - assertThat(cameraView.getAspectRatio(), is(equalTo(ratio))); - } - }); + final CameraView cameraView = (CameraView) rule.getActivity().findViewById(R.id.camera); + final Set ratios = cameraView.getSupportedAspectRatios(); + for (AspectRatio ratio : ratios) { + onView(withId(R.id.camera)) + .perform(setAspectRatio(ratio)) + .check(matches(hasAspectRatio(ratio))); + } } @Test