com.pyamsoft.zaptorch.service.OriginalCamera.java Source code

Java tutorial

Introduction

Here is the source code for com.pyamsoft.zaptorch.service.OriginalCamera.java

Source

/*
 * Copyright 2016 Peter Kenji Yamanaka
 *
 * 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.pyamsoft.zaptorch.service;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import com.pyamsoft.pydroid.tool.AsyncOffloader;
import com.pyamsoft.pydroid.tool.ExecutedOffloader;
import com.pyamsoft.pydroid.tool.OffloaderHelper;
import java.io.IOException;
import java.util.List;
import timber.log.Timber;

@SuppressWarnings("deprecation")
class OriginalCamera extends CameraCommon implements SurfaceHolder.Callback {

    @SuppressWarnings("WeakerAccess")
    @NonNull
    final WindowManager windowManager;
    @SuppressWarnings("WeakerAccess")
    @NonNull
    final SurfaceView surfaceView;
    @SuppressWarnings("WeakerAccess")
    @NonNull
    final WindowManager.LayoutParams params;
    @SuppressWarnings("WeakerAccess")
    @Nullable
    Camera camera;
    @SuppressWarnings("WeakerAccess")
    boolean opened;
    @NonNull
    private ExecutedOffloader cameraSubscription = new ExecutedOffloader.Empty();

    OriginalCamera(final @NonNull Context context, final @NonNull VolumeServiceInteractor interactor) {
        super(context, interactor);
        Timber.d("OLD CAMERA API");
        opened = false;

        surfaceView = new SurfaceView(getAppContext());
        windowManager = (WindowManager) getAppContext().getSystemService(Context.WINDOW_SERVICE);

        params = new WindowManager.LayoutParams();
        params.width = 1;
        params.height = 1;
        params.gravity = Gravity.TOP | Gravity.START;
        params.format = PixelFormat.TRANSLUCENT;
        params.type = WindowManager.LayoutParams.TYPE_TOAST;
        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
    }

    @SuppressWarnings("WeakerAccess")
    SurfaceHolder getInitializedHolder() {
        final SurfaceHolder holder = surfaceView.getHolder();
        holder.addCallback(this);
        return holder;
    }

    @Override
    public void toggleTorch() {
        if (ActivityCompat.checkSelfPermission(getAppContext(),
                Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
            if (opened) {
                Timber.d("Camera is open, close it");
                release();
            } else {
                connectToCameraService();
            }
        } else {
            Timber.e("Missing camera permission");
            startPermissionExplanationActivity();
        }
    }

    private void connectToCameraService() {
        Timber.d("Camera is closed, open it");
        OffloaderHelper.cancel(cameraSubscription);
        cameraSubscription = AsyncOffloader.newInstance(Camera::open).onError(throwable -> {
            clearCamera(throwable);
            startErrorExplanationActivity();
        }).onResult(item -> {
            final Camera.Parameters parameters = item.getParameters();
            if (parameters.getFlashMode() == null) {
                Timber.e("Null flash mode");
                item.release();
                startErrorExplanationActivity();
                return;
            }

            final List<String> supportedFlashModes = parameters.getSupportedFlashModes();
            if (supportedFlashModes == null || supportedFlashModes.isEmpty()
                    || !supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
                Timber.e("Camera parameters do not include Torch");
                item.release();
                startErrorExplanationActivity();
                return;
            }

            Timber.d("Camera should have torch mode");
            try {
                Timber.d("Camera has flash");
                camera = item;
                windowManager.addView(surfaceView, params);
                assert camera != null;
                Timber.d("set preview");
                final SurfaceHolder holder = getInitializedHolder();
                camera.setPreviewDisplay(holder);
                final Camera.Parameters cameraParameters = camera.getParameters();
                cameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                camera.setParameters(cameraParameters);

                Timber.d("start camera");
                camera.startPreview();
                opened = true;
                notifyCallbackOnOpened();
            } catch (IOException e) {
                clearCamera(e);
                startErrorExplanationActivity();
            }
        }).execute();
    }

    @SuppressWarnings("WeakerAccess")
    void clearCamera(@NonNull Throwable throwable) {
        Timber.e(throwable, "Error opening camera");
        releaseCamera();
    }

    private void releaseCamera() {
        Timber.d("release camera");
        if (camera != null) {
            camera.release();
            camera = null;
            opened = false;
            notifyCallbackOnClosed();
        }
    }

    @Override
    public void release() {
        super.release();
        if (camera != null && opened) {
            final Camera.Parameters params = camera.getParameters();
            params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            camera.setParameters(params);
            camera.stopPreview();
            releaseCamera();
            windowManager.removeView(surfaceView);
        }
        OffloaderHelper.cancel(cameraSubscription);
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        if (surfaceHolder != null && camera != null) {
            try {
                Timber.d("Surface created");
                camera.setPreviewDisplay(surfaceHolder);
            } catch (IOException e) {
                Timber.e(e, "surfaceCreated ERROR");
            }
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        if (surfaceHolder != null && camera != null) {
            Timber.d("Surface destroyed");
            camera.stopPreview();
        }
    }
}