com.visenze.visearch.camerademo.fragments.CameraFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.visenze.visearch.camerademo.fragments.CameraFragment.java

Source

/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 ViSenze Pte. Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.visenze.visearch.camerademo.fragments;

import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;

import com.visenze.visearch.android.ResultList;
import com.visenze.visearch.android.UploadSearchParams;
import com.visenze.visearch.android.ViSearch;
import com.visenze.visearch.android.model.Image;
import com.visenze.visearch.camerademo.EditPhotoActivity;
import com.visenze.visearch.camerademo.R;
import com.visenze.visearch.camerademo.http.SearchAPI;
import com.visenze.visearch.camerademo.util.Config;
import com.visenze.visearch.camerademo.util.DataHelper;
import com.visenze.visearch.camerademo.util.ImageHelper;
import com.visenze.visearch.camerademo.util.IntentHelper;
import com.visenze.visearch.camerademo.views.CameraPreview;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.InjectViews;
import butterknife.OnClick;

/**
 * Created by yulu on 2/17/15.
 *
 * camera view and search actions control is implemented in this fragment 
 */
public class CameraFragment extends Fragment
        implements ViSearch.ResultListener, CameraPreview.ImageCapturedCallback {

    /**
     * UI action: enable a group of UIs---------------------------------------------------------
     */
    static final ButterKnife.Action<View> ENABLE = new ButterKnife.Action<View>() {
        @Override
        public void apply(View view, int index) {
            view.setEnabled(true);
        }
    };
    /**
     * UI action: disable a group of UIs
     */
    static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() {
        @Override
        public void apply(View view, int index) {
            view.setEnabled(false);
        }
    };
    /**
     * UI action: show a group of UIs
     */
    static final ButterKnife.Action<View> SHOW = new ButterKnife.Action<View>() {
        @Override
        public void apply(View view, int index) {
            view.setVisibility(View.VISIBLE);
        }
    };
    /**
     * UI action: hide a group of UIs
     */
    static final ButterKnife.Action<View> HIDE = new ButterKnife.Action<View>() {
        @Override
        public void apply(View view, int index) {
            view.setVisibility(View.GONE);
        }
    };
    private static final int RESULT_LOAD_IMAGE_FROM_GALLERY = 0x00;
    //Inject UIs
    @InjectView(R.id.camera_preview)
    CameraPreview cameraPreview;
    @InjectView(R.id.camera_image_preview)
    ImageView imagePreview;
    @InjectView(R.id.camera_loading)
    ImageView loadingImage;
    @InjectView(R.id.camera_flash_button)
    ImageView lightButton;
    @InjectViews({ R.id.camera_cancel_button, R.id.camera_loading_background, R.id.camera_loading })
    List<View> searchUIs;
    @InjectViews({ R.id.camera_flash_button, R.id.camera_album_button, R.id.camera_switch_button,
            R.id.camera_shutter_button, R.id.camera_close_button })
    List<ImageView> cameraUIs;
    //ViSearch and Search parameters
    private ViSearch viSearch;
    private String imagePath;
    private UploadSearchParams uploadSearchParams;
    //photo loading and process runnable
    private ImageProcessRunnable imageProcessRunnable;

    /**
     * Constructor
     *
     * @return new instance of CameraFragment
     */
    public static CameraFragment newInstance() {
        CameraFragment fragment = new CameraFragment();
        //can set some properties for the fragment
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.camera_main, container, false);
        ButterKnife.inject(this, view);

        try {
            viSearch = SearchAPI.getInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        viSearch.setListener(this);
        return view;
    }

    @Override
    public void onStop() {
        super.onStop();
        cameraPreview.stopPreview();
        Log.i("CAMERA", "camera fragment stop");
    }

    /**
     * Image selection activity callback:
     *
     * get the image Uri from intent and pass to upload search params to start search
     */
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == RESULT_LOAD_IMAGE_FROM_GALLERY && resultCode == Activity.RESULT_OK && null != data) {
            Uri uri = data.getData();

            changeUploadUI();
            cameraPreview.setVisibility(View.GONE);
            imagePreview.setVisibility(View.VISIBLE);

            int rot = ImageHelper.getRotation(uri, getActivity());
            imagePreview.setRotation(rot);
            imagePreview.setImageURI(uri);

            imageProcessRunnable = new ImageProcessRunnable(uri);
            imageProcessRunnable.start();
        }
    }

    /**
     * Camera preview captured callback:
     *
     * Pass the byte array to upload search params and start search
     */
    @Override
    public void OnImageCaptured(Image image, String imagePath) {
        changeUploadUI();

        this.imagePath = imagePath;

        uploadSearchParams = new UploadSearchParams(image);
        DataHelper.setSearchParams(uploadSearchParams, "all");

        viSearch.uploadSearch(uploadSearchParams);
    }

    /**
     * search result callback:
     *
     * get the list of result image and do something
     * check if the result if from camera or photo gallery by checking
     * imagePath and uri are null or not
     *
     * Change the UI back to searching mode
     */
    @Override
    public void onSearchResult(ResultList resultList) {
        IntentHelper.addObjectForKey(resultList, IntentHelper.SEARCH_RESULT_EXTRA);
        IntentHelper.addObjectForKey(imagePath, IntentHelper.SEARCH_THUMBNAIL_PATH_EXTRA);
        IntentHelper.addObjectForKey(imagePath, IntentHelper.SEARCH_IMAGE_PATH_EXTRA);

        Intent intent = new Intent(getActivity(), EditPhotoActivity.class);
        startActivity(intent);

        Intent thisIntent = new Intent();
        getActivity().setResult(Activity.RESULT_OK, thisIntent);
        getActivity().finish();
    }

    /**
     * search error callback:
     *
     * called when there is an error after upload search
     * display the error and change the UI to camera mode
     */
    @Override
    public void onSearchError(String errorMessage) {
        if (isAdded()) {
            changeUploadUIBack();
            Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * search cancel callback:
     *
     * change the UI to camera mode when search is canceled
     */
    @Override
    public void onSearchCanceled() {
        if (isAdded()) {
            changeUploadUIBack();
        }
    }

    /**
     * Belows are button click action implementations and UI change handling-----------------------
     */
    @OnClick(R.id.camera_close_button)
    public void close() {
        if (imageProcessRunnable != null) {
            try {
                imageProcessRunnable.stop();
                Log.d("Camera Fragment: ", "stop photo loading and processing thread");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        viSearch.cancelSearch();

        getActivity().finish();
    }

    @OnClick(R.id.camera_album_button)
    public void openGallery() {
        Intent openAlbumIntent = new Intent(Intent.ACTION_GET_CONTENT);
        openAlbumIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
        startActivityForResult(openAlbumIntent, RESULT_LOAD_IMAGE_FROM_GALLERY);
    }

    @OnClick(R.id.camera_flash_button)
    public void startFlashLight() {
        lightButton.setSelected(cameraPreview.turnOnTorch());
    }

    @OnClick(R.id.camera_switch_button)
    public void switchCamera() {
        lightButton.setSelected(false);
        cameraPreview.switchCamera();
    }

    @OnClick(R.id.camera_shutter_button)
    public void shutterClicked() {
        disableUploadUI();
        cameraPreview.takePhoto(this);
    }

    @OnClick(R.id.camera_cancel_button)
    public void cancelSearch() {
        if (imageProcessRunnable != null) {
            try {
                imageProcessRunnable.stop();
                Log.d("Camera Fragment: ", "stop photo loading and processing thread");
            } catch (InterruptedException e) {
                Log.d("Interruption exception ", e.getMessage());
            }
        }

        viSearch.cancelSearch();
    }

    //change UI when uploading starts
    private void disableUploadUI() {
        //disable
        ButterKnife.apply(cameraUIs, DISABLE);
    }

    private void changeUploadUI() {
        ButterKnife.apply(cameraUIs, HIDE);
        ButterKnife.apply(searchUIs, SHOW);

        //start scan
        AnimationDrawable anim = (AnimationDrawable) loadingImage.getDrawable();
        anim.start();
    }

    //When cancel button is clicked, bring UI back and enable
    private void changeUploadUIBack() {
        ButterKnife.apply(cameraUIs, SHOW);
        ButterKnife.apply(cameraUIs, ENABLE);
        ButterKnife.apply(searchUIs, HIDE);

        //set light to turn off state
        lightButton.setSelected(false);

        //hide cancel UI and preview image
        imagePreview.setVisibility(View.GONE);

        //stop animation and hide
        loadingImage.setVisibility(View.GONE);

        //restart camera preview
        cameraPreview.setVisibility(View.VISIBLE);

        cameraPreview.startCameraPreview();
    }

    private class ImageProcessRunnable implements Runnable {
        private Thread thread;
        private Uri _uri;

        public ImageProcessRunnable(Uri uri) {
            this._uri = uri;
        }

        @Override
        public void run() {
            try {
                byte[] bytes = ImageHelper.readBytes(_uri, getActivity(), Config.IMAGE_QUALITY);
                CameraFragment.this.imagePath = ImageHelper.saveImageByteTmp(getActivity(), bytes);
                Image image = new Image(bytes, Config.IMAGE_QUALITY);

                uploadSearchParams = new UploadSearchParams(image);
                DataHelper.setSearchParams(uploadSearchParams, "all");

                viSearch.uploadSearch(uploadSearchParams);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void start() {
            if (thread == null) {
                thread = new Thread(this, "photo load from gallery in worker thread");
                thread.start();
            }
        }

        public void stop() throws InterruptedException {
            if (thread != null && thread.isAlive())
                thread.join();
        }
    }
}