Skip to content

Commit

Permalink
Add takePicture
Browse files Browse the repository at this point in the history
Change-Id: I5a185904708305b6affeb148743582063ca76e44
  • Loading branch information
yaraki committed Jun 1, 2016
1 parent 9609fac commit a4fe117
Show file tree
Hide file tree
Showing 16 changed files with 458 additions and 79 deletions.
3 changes: 2 additions & 1 deletion demo/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ android {
versionCode 1
versionName '1.0'
testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
Expand All @@ -37,7 +38,7 @@ android {

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile "com.android.support:appcompat-v7:$supportLibraryVersion"
compile "com.android.support:design:$supportLibraryVersion"
compile project(':library')

// Tests
Expand Down
1 change: 1 addition & 0 deletions demo/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<manifest package="com.google.android.cameraview.demo"
xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
Expand Down
169 changes: 157 additions & 12 deletions demo/src/main/java/com/google/android/cameraview/demo/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,72 @@
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.DialogFragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;


public class MainActivity extends AppCompatActivity implements
ActivityCompat.OnRequestPermissionsResultCallback {

private static final String TAG = "MainActivity";

private static final int REQUEST_CAMERA_PERMISSION = 1;
private static final int REQUEST_STORAGE_PERMISSION = 2;

private static final String FRAGMENT_DIALOG = "dialog";

private CameraView mCameraView;

private Handler mBackgroundHandler;

private View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.take_picture:
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
if (mCameraView != null) {
mCameraView.takePicture();
}
} else if (ActivityCompat.shouldShowRequestPermissionRationale(
MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
ConfirmationDialogFragment
.newInstance(R.string.storage_permission_confirmation,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_STORAGE_PERMISSION,
R.string.storage_permission_not_granted)
.show(getSupportFragmentManager(), FRAGMENT_DIALOG);
} else {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_STORAGE_PERMISSION);
}
break;
}
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand All @@ -49,6 +96,10 @@ protected void onCreate(Bundle savedInstanceState) {
if (mCameraView != null) {
mCameraView.addCallback(mCallback);
}
FloatingActionButton takePicture = (FloatingActionButton) findViewById(R.id.take_picture);
if (takePicture != null) {
takePicture.setOnClickListener(mOnClickListener);
}
}

@Override
Expand All @@ -59,7 +110,12 @@ protected void onResume() {
mCameraView.start();
} else if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
new ConfirmationDialogFragment().show(getSupportFragmentManager(), FRAGMENT_DIALOG);
ConfirmationDialogFragment
.newInstance(R.string.camera_permission_confirmation,
new String[]{Manifest.permission.CAMERA},
REQUEST_CAMERA_PERMISSION,
R.string.camera_permission_not_granted)
.show(getSupportFragmentManager(), FRAGMENT_DIALOG);
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
REQUEST_CAMERA_PERMISSION);
Expand All @@ -72,18 +128,52 @@ protected void onPause() {
super.onPause();
}

@Override
protected void onDestroy() {
super.onDestroy();
if (mBackgroundHandler != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
mBackgroundHandler.getLooper().quitSafely();
} else {
mBackgroundHandler.getLooper().quit();
}
mBackgroundHandler = null;
}
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_CAMERA_PERMISSION) {
if (permissions.length != 1 || grantResults.length != 1) {
throw new RuntimeException("Error on requesting permission.");
}
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, R.string.permission_not_granted, Toast.LENGTH_SHORT).show();
switch (requestCode) {
case REQUEST_CAMERA_PERMISSION:
if (permissions.length != 1 || grantResults.length != 1) {
throw new RuntimeException("Error on requesting camera permission.");
}
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, R.string.camera_permission_not_granted,
Toast.LENGTH_SHORT).show();
}
// No need to start camera here; it is handled by onResume
}
break;
case REQUEST_STORAGE_PERMISSION:
if (permissions.length != 1 || grantResults.length != 1) {
throw new RuntimeException("Error on requesting storage permission.");
}
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, R.string.storage_permission_not_granted,
Toast.LENGTH_SHORT).show();
}
break;
}
}

private Handler getBackgroundHandler() {
if (mBackgroundHandler == null) {
HandlerThread thread = new HandlerThread("background");
thread.start();
mBackgroundHandler = new Handler(thread.getLooper());
}
return mBackgroundHandler;
}

private CameraView.Callback mCallback
Expand All @@ -99,29 +189,84 @@ public void onCameraClosed(CameraView cameraView) {
Log.d(TAG, "onCameraClosed");
}

@Override
public void onPictureTaken(CameraView cameraView, final byte[] data) {
Log.d(TAG, "onPictureTaken " + data.length);
Toast.makeText(cameraView.getContext(), R.string.picture_taken, Toast.LENGTH_SHORT)
.show();
getBackgroundHandler().post(new Runnable() {
@Override
public void run() {
// This demo app saves the taken picture to a constant file.
// $ adb pull /sdcard/Android/data/com.google.android.cameraview.demo/files/Pictures/picture.jpg
File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES),
"picture.jpg");
OutputStream os = null;
try {
os = new FileOutputStream(file);
os.write(data);
os.close();
} catch (IOException e) {
Log.w(TAG, "Cannot write to " + file, e);
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
// Ignore
}
}
}
}
});
}

};

public static class ConfirmationDialogFragment extends DialogFragment {

private static final String ARG_MESSAGE = "message";
private static final String ARG_PERMISSIONS = "permissions";
private static final String ARG_REQUEST_CODE = "request_code";
private static final String ARG_NOT_GRANTED_MESSAGE = "not_granted_message";

public static ConfirmationDialogFragment newInstance(@StringRes int message,
String[] permissions, int requestCode,
@StringRes int notGrantedMessage) {
ConfirmationDialogFragment fragment = new ConfirmationDialogFragment();
Bundle args = new Bundle();
args.putInt(ARG_MESSAGE, message);
args.putStringArray(ARG_PERMISSIONS, permissions);
args.putInt(ARG_REQUEST_CODE, requestCode);
args.putInt(ARG_NOT_GRANTED_MESSAGE, notGrantedMessage);
fragment.setArguments(args);
return fragment;
}

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Bundle args = getArguments();
return new AlertDialog.Builder(getActivity())
.setMessage(R.string.permission_confirmation)
.setMessage(args.getInt(ARG_MESSAGE))
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String[] permissions = args.getStringArray(ARG_PERMISSIONS);
if (permissions == null) {
throw new IllegalArgumentException();
}
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.CAMERA},
REQUEST_CAMERA_PERMISSION);
permissions, args.getInt(ARG_REQUEST_CODE));
}
})
.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getActivity(), R.string.permission_not_granted,
Toast.makeText(getActivity(),
args.getInt(ARG_NOT_GRANTED_MESSAGE),
Toast.LENGTH_SHORT).show();
}
})
Expand Down
25 changes: 25 additions & 0 deletions demo/src/main/res/drawable/ic_camera.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
<path
android:fillColor="#FFFFFFFF"
android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
</vector>
20 changes: 12 additions & 8 deletions demo/src/main/res/layout-land/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,24 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<FrameLayout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="horizontal"
tools:context=".MainActivity">

<com.google.android.cameraview.CameraView
android:id="@+id/camera"
<include
layout="@layout/include_camera"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>

<include
layout="@layout/include_control"
android:layout_width="0dp"
android:layout_height="match_parent"
android:adjustViewBounds="true"
app:focusMode="continuousPicture"
app:facing="back"/>
android:layout_weight="1"/>

</FrameLayout>
</LinearLayout>
21 changes: 12 additions & 9 deletions demo/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,23 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<FrameLayout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">

<com.google.android.cameraview.CameraView
android:id="@+id/camera"
<include
layout="@layout/include_camera"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
app:focusMode="continuousPicture"
app:facing="back"/>
android:layout_height="wrap_content"/>

</FrameLayout>
<include
layout="@layout/include_control"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>

</LinearLayout>
22 changes: 22 additions & 0 deletions demo/src/main/res/layout/include_camera.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<com.google.android.cameraview.CameraView
android:id="@+id/camera"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
app:facing="back"
app:focusMode="continuousPicture"/>
Loading

0 comments on commit a4fe117

Please sign in to comment.