se.droidgiro.scanner.CaptureActivity.java Source code

Java tutorial

Introduction

Here is the source code for se.droidgiro.scanner.CaptureActivity.java

Source

/*
 * Copyright (C) 2008 ZXing authors
 * Copyright (C) 2011 DroidGiro authors
 *
 * This file is mostly based on
 * com.google.zxing.client.android.CaptureActivity
 * by ZXing Authors
 *
 * 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 se.droidgiro.scanner;

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

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import se.droidgiro.About;
import se.droidgiro.PreferencesActivity;
import se.droidgiro.R;
import se.droidgiro.scanner.camera.CameraManager;
import se.droidgiro.scanner.resultlist.ResultListAdapter;
import se.droidgiro.scanner.resultlist.ResultListHandler;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.AssetFileDescriptor;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;

/**
 * The main activity. Draws the views and shows the results in them.
 */
public final class CaptureActivity extends ListActivity implements SurfaceHolder.Callback {

    private static final String TAG = "DroidGiro.CaptureActivity";

    private static final float BEEP_VOLUME = 0.10f;
    private static final long VIBRATE_DURATION = 200L;
    private static final long SCAN_DELAY_MS = 1000L;

    private CaptureActivityHandler handler;
    private MediaPlayer mediaPlayer;
    private ResultListHandler resultListHandler;
    private ViewfinderView viewfinderView;

    private boolean hasSurface;
    private boolean paused = false;
    private boolean playBeep;
    private boolean vibrate;

    private static Invoice currentInvoice = new Invoice();

    private Button eraseButton;
    private Button scanButton;

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

    /**
     * When the beep has finished playing, rewind to queue up another one.
     */
    private final OnCompletionListener beepListener = new OnCompletionListener() {
        public void onCompletion(MediaPlayer mediaPlayer) {
            mediaPlayer.seekTo(0);
        }
    };

    private String channel;

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        if (currentInvoice != null) {
            super.onListItemClick(l, v, position, id);
            if (position == 0) {
                resultListHandler.setReference(null);
                currentInvoice.initReference();
            } else if (position == 1) {
                resultListHandler.setAmount(null);
                currentInvoice.initAmount();
            } else {
                resultListHandler.setAccount(null);
                currentInvoice.initGiroAccount();
            }
            onContentChanged();
        }
    }

    ViewfinderView getViewfinderView() {
        return viewfinderView;
    }

    public Handler getHandler() {
        return handler;
    }

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        currentInvoice = new Invoice();
        channel = getIntent().getStringExtra("channel");
        if (channel == null)
            finish();

        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.capture);

        this.eraseButton = (Button) this.findViewById(R.id.send_erase);
        this.eraseButton.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (currentInvoice != null)
                    sendInvoice(CaptureActivity.this, currentInvoice);

                // if (currentInvoice != null && currentInvoice.isComplete()) {
                scanButton.setText(getString(R.string.scan_state_scan));
                handler.sendEmptyMessage(R.id.pause);
                paused = true;
                // }
                if (currentInvoice != null)
                    currentInvoice.initFields();
                resultListHandler.clear();
                //            handler.sendEmptyMessage(R.id.new_invoice);
                onContentChanged();
            }
        });

        this.scanButton = (Button) this.findViewById(R.id.pause);
        this.scanButton.setText(getString(R.string.scan_state_pause));
        this.scanButton.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (paused) {
                    paused = false;
                    handler.sendEmptyMessage(R.id.resume);
                    scanButton.setText(getString(R.string.scan_state_pause));
                } else {
                    paused = true;
                    handler.sendEmptyMessage(R.id.pause);
                    scanButton.setText(getString(R.string.scan_state_scan));
                }
            }
        });

        resultListHandler = new ResultListHandler(this);
        List<ResultListHandler.ListItem> resultList = resultListHandler.getList();
        ResultListAdapter adapter = new ResultListAdapter(this, R.layout.result_list_item, resultList);
        setListAdapter(adapter);

        CameraManager.init(getApplication());
        viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
        handler = null;
        hasSurface = false;
    }

    @Override
    protected void onResume() {
        super.onResume();
        resetStatusView();

        SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
        SurfaceHolder surfaceHolder = surfaceView.getHolder();
        if (hasSurface) {
            // The activity was paused but not stopped, so the surface still
            // exists. Therefore
            // surfaceCreated() won't be called, so init the camera here.
            initCamera(surfaceHolder);
        } else {
            // Install the callback and wait for surfaceCreated() to init the
            // camera.
            surfaceHolder.addCallback(this);
            surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        playBeep = prefs.getBoolean(PreferencesActivity.KEY_PLAY_BEEP, true);
        if (playBeep) {
            // See if sound settings overrides this
            AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
            if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
                playBeep = false;
            }
        }
        vibrate = prefs.getBoolean(PreferencesActivity.KEY_VIBRATE, false);
        initBeepSound();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (handler != null) {
            handler.quitSynchronously();
            handler = null;
        }
        CameraManager.get().closeDriver();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.options_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.about: {
            Intent intent = new Intent(this, About.class);
            startActivity(intent);
            break;
        }
        case R.id.settings: {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
            intent.setClassName(this, PreferencesActivity.class.getName());
            startActivity(intent);
            break;
        }
        }
        return super.onOptionsItemSelected(item);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        if (!hasSurface) {
            hasSurface = true;
            initCamera(holder);
        }
    }

    public boolean isPaused() {
        return paused;
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        hasSurface = false;
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    }

    public void handleDecode(final Invoice invoice, int fieldsFound, Bitmap debugBmp) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        ImageView debugImageView = (ImageView) findViewById(R.id.debug_image_view);
        if (prefs.getBoolean(PreferencesActivity.KEY_DEBUG_IMAGE, false) && (debugBmp != null)) {
            debugImageView.setVisibility(View.VISIBLE);
            debugImageView.setImageBitmap(debugBmp);
        } else if (debugImageView.getVisibility() != View.GONE) {
            debugImageView.setVisibility(View.GONE);
        }
        int fieldsScanned = invoice.getLastFieldsDecoded();
        if (fieldsScanned > 0) {
            boolean scanContainsNewData = false;

            /*
             * The following segment will copy data from scanned invoice object
             * into our currentInvoice and keep track of new data read.
             * Beep/Vibrate will only occur if scan contains new data.
             */

            if ((fieldsScanned & Invoice.AMOUNT_FIELD) == Invoice.AMOUNT_FIELD) {
                if (!(currentInvoice.getAmount() == invoice.getAmount()
                        && currentInvoice.getAmountFractional() == invoice.getAmountFractional())) {
                    currentInvoice.setAmount(invoice.getAmount(), invoice.getAmountFractional());
                    scanContainsNewData = true;
                }
            }

            if ((fieldsScanned & Invoice.DOCUMENT_TYPE_FIELD) == Invoice.DOCUMENT_TYPE_FIELD) {
                if (currentInvoice.getInternalDocumentType() != invoice.getInternalDocumentType()) {
                    currentInvoice.setDocumentType(invoice.getInternalDocumentType());
                    scanContainsNewData = true;
                }
            }

            if ((fieldsScanned & Invoice.GIRO_ACCOUNT_FIELD) == Invoice.GIRO_ACCOUNT_FIELD) {
                Log.v(TAG, "Giro accout scanned. Current account = " + currentInvoice.getGiroAccount()
                        + ". New invoice giro account = " + invoice.getGiroAccount());
                if (!invoice.getGiroAccount().equals(currentInvoice.getGiroAccount())) {
                    currentInvoice.setRawGiroAccount(invoice.getRawGiroAccount());
                    Log.v(TAG, "Copied giro account = " + invoice.getGiroAccount());
                    scanContainsNewData = true;
                }
            }

            if ((fieldsScanned & Invoice.REFERENCE_FIELD) == Invoice.REFERENCE_FIELD) {
                if (!invoice.getReference().equals(currentInvoice.getReference())) {
                    currentInvoice.setReference(invoice.getReference());
                    scanContainsNewData = true;
                }
            }

            if (scanContainsNewData)
                playBeepSoundAndVibrate();

        }
        Log.v(TAG, "CurrentInvoice = " + currentInvoice);
        if (currentInvoice.isReferenceDefined())
            resultListHandler.setReference(currentInvoice.getReference());
        if (currentInvoice.isAmountDefined())
            resultListHandler.setAmount(currentInvoice.getCompleteAmount());
        if (currentInvoice.isGiroAccountDefined())
            resultListHandler.setAccount(currentInvoice.getGiroAccount());
        if (resultListHandler.hasNewData()) {
            resultListHandler.setNewData(false);
        }

        Log.v(TAG, "Got invoice " + invoice);

        /* If scan on every hit */

        // int fieldsScanned = invoice.getLastFieldsDecoded();
        // if (fieldsScanned > 0) {
        // playBeepSoundAndVibrate();
        // final List<NameValuePair> params = new ArrayList<NameValuePair>();
        // if ((fieldsScanned & Invoice.AMOUNT_FIELD) == Invoice.AMOUNT_FIELD)
        // params.add(new BasicNameValuePair("amount", invoice
        // .getCompleteAmount()));
        // if ((fieldsScanned & Invoice.DOCUMENT_TYPE_FIELD) ==
        // Invoice.DOCUMENT_TYPE_FIELD)
        // params.add(new BasicNameValuePair("type", invoice.getType()));
        // if ((fieldsScanned & Invoice.GIRO_ACCOUNT_FIELD) ==
        // Invoice.GIRO_ACCOUNT_FIELD)
        // params.add(new BasicNameValuePair("account", invoice
        // .getGiroAccount()));
        // if ((fieldsScanned & Invoice.REFERENCE_FIELD) ==
        // Invoice.REFERENCE_FIELD)
        // params.add(new BasicNameValuePair("reference", invoice
        // .getReference()));
        // // sendFields(params);
        //
        // }

        // if (invoice.isComplete()) {
        // resultListHandler.setSent(true);
        // this.scanButton.setText(getString(R.string.scan_state_scan));
        // onContentChanged();
        // } else
        if (!paused) {
            handler.sendEmptyMessageDelayed(R.id.restart_preview, SCAN_DELAY_MS);
        }
        onContentChanged();
    }

    private void sendInvoice(final Context context, final Invoice invoice) {
        List<NameValuePair> fields = new ArrayList<NameValuePair>();
        if (invoice.isAmountDefined())
            fields.add(new BasicNameValuePair("amount", invoice.getCompleteAmount()));
        if (invoice.isDocumentTypeDefined())
            fields.add(new BasicNameValuePair("type", invoice.getType()));
        if (invoice.isGiroAccountDefined())
            fields.add(new BasicNameValuePair("account", invoice.getGiroAccount()));
        if (invoice.isReferenceDefined())
            fields.add(new BasicNameValuePair("reference", invoice.getReference()));

        if (fields.size() > 0)
            sendFields(context, fields);
    }

    private void sendFields(final Context context, final List<NameValuePair> fields) {
        new Thread(new Runnable() {
            public void run() {
                fields.add(new BasicNameValuePair("channel", CaptureActivity.this.channel));
                try {
                    boolean res = CloudClient.postFields(fields);
                    Log.v(TAG, "Result from posting invoice " + fields + " to channel " + channel + ": " + res);
                    final String msg = (res ? "Flt har skickats till webblsaren"
                            : "Kunde inte skicka flt till webblsaren");

                    handler.post(new Runnable() {

                        public void run() {
                            Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
                        }
                    });

                } catch (Exception e) {
                    Log.e(TAG, e.getMessage(), e);
                }

            }
        }).start();
    }

    /**
     * Creates the beep MediaPlayer in advance so that the sound can be
     * triggered with the least latency possible.
     */
    private void initBeepSound() {
        if (playBeep && mediaPlayer == null) {
            // The volume on STREAM_SYSTEM is not adjustable, and users found it
            // too loud,
            // so we now play on the music stream.
            setVolumeControlStream(AudioManager.STREAM_MUSIC);
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.setOnCompletionListener(beepListener);

            AssetFileDescriptor file = getResources().openRawResourceFd(R.raw.beep);
            try {
                mediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength());
                file.close();
                mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
                mediaPlayer.prepare();
            } catch (IOException e) {
                mediaPlayer = null;
            }
        }
    }

    private void playBeepSoundAndVibrate() {
        if (playBeep && mediaPlayer != null) {
            mediaPlayer.start();
        }
        if (vibrate) {
            Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
            vibrator.vibrate(VIBRATE_DURATION);
        }
    }

    private void initCamera(SurfaceHolder surfaceHolder) {
        try {
            CameraManager.get().openDriver(surfaceHolder);
        } catch (IOException ioe) {
            Log.w(TAG, ioe);
            return;
        } catch (RuntimeException e) {
            // Barcode Scanner has seen crashes in the wild of this variety:
            // java.?lang.?RuntimeException: Fail to connect to camera service
            Log.w(TAG, "Unexpected error initializating camera", e);
            return;
        }
        if (handler == null) {
            handler = new CaptureActivityHandler(this);
        }
    }

    private void resetStatusView() {
        viewfinderView.setVisibility(View.VISIBLE);
    }

    public void drawViewfinder() {
        viewfinderView.drawViewfinder();
    }

}