org.opendatakit.survey.activities.MediaCaptureAudioActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.opendatakit.survey.activities.MediaCaptureAudioActivity.java

Source

/*
 * Copyright (C) 2012-2013 University of Washington
 *
 * 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 org.opendatakit.survey.activities;

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.opendatakit.demoAndroidlibraryClasses.consts.IntentConsts;
import org.opendatakit.demoAndroidCommonClasses.activities.BaseActivity;
import org.opendatakit.demoAndroidlibraryClasses.utilities.MediaUtils;
import org.opendatakit.demoAndroidlibraryClasses.utilities.ODKFileUtils;
import org.opendatakit.demoAndroidlibraryClasses.logging.WebLogger;
import org.opendatakit.survey.R;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentValues;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore.Audio;
import android.widget.Toast;

/**
 * Simple shim for media interactions.
 *
 * @author mitchellsundt@gmail.com
 *
 */
public class MediaCaptureAudioActivity extends BaseActivity {
    private static final String t = "MediaCaptureAudioActivity";

    private static final int ACTION_CODE = 1;
    private static final String MEDIA_CLASS = "audio/";

    private static final String URI_FRAGMENT_NEW_FILE_BASE = "uriFragmentNewFileBase";
    private static final String HAS_LAUNCHED = "hasLaunched";
    private static final String AFTER_RESULT = "afterResult";
    private static final String ERROR_NO_FILE = "Media file does not exist! ";
    private static final String ERROR_COPY_FILE = "Media file copy failed! ";

    private String appName = null;
    private String tableId = null;
    private String instanceId = null;
    private String uriFragmentNewFileBase = null;
    private String uriFragmentToMedia = null;
    private boolean afterResult = false;
    private boolean hasLaunched = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            appName = extras.getString(IntentConsts.INTENT_KEY_APP_NAME);
            tableId = extras.getString(IntentConsts.INTENT_KEY_TABLE_ID);
            instanceId = extras.getString(IntentConsts.INTENT_KEY_INSTANCE_ID);
            uriFragmentToMedia = extras.getString(IntentConsts.INTENT_KEY_URI_FRAGMENT);
            hasLaunched = extras.getBoolean(HAS_LAUNCHED);
            afterResult = extras.getBoolean(AFTER_RESULT);
            uriFragmentNewFileBase = extras.getString(URI_FRAGMENT_NEW_FILE_BASE);
        }

        if (savedInstanceState != null) {
            appName = savedInstanceState.getString(IntentConsts.INTENT_KEY_APP_NAME);
            tableId = savedInstanceState.getString(IntentConsts.INTENT_KEY_TABLE_ID);
            instanceId = savedInstanceState.getString(IntentConsts.INTENT_KEY_INSTANCE_ID);
            uriFragmentToMedia = savedInstanceState.getString(IntentConsts.INTENT_KEY_URI_FRAGMENT);
            hasLaunched = savedInstanceState.getBoolean(HAS_LAUNCHED);
            afterResult = savedInstanceState.getBoolean(AFTER_RESULT);
            uriFragmentNewFileBase = savedInstanceState.getString(URI_FRAGMENT_NEW_FILE_BASE);
        }

        if (appName == null) {
            throw new IllegalArgumentException(
                    "Expected " + IntentConsts.INTENT_KEY_APP_NAME + " key in intent bundle. Not found.");
        }

        if (tableId == null) {
            throw new IllegalArgumentException(
                    "Expected " + IntentConsts.INTENT_KEY_TABLE_ID + " key in intent bundle. Not found.");
        }
        if (instanceId == null) {
            throw new IllegalArgumentException(
                    "Expected " + IntentConsts.INTENT_KEY_INSTANCE_ID + " key in intent bundle. Not found.");
        }

        if (uriFragmentToMedia == null) {
            if (uriFragmentNewFileBase == null) {
                throw new IllegalArgumentException(
                        "Expected " + URI_FRAGMENT_NEW_FILE_BASE + " key in intent bundle. Not found.");
            }
            afterResult = false;
            hasLaunched = false;
        }
    }

    @Override
    public String getAppName() {
        return appName;
    }

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

        if (afterResult) {
            // this occurs if we re-orient the phone during the save-recording
            // action
            returnResult();
        } else if (!hasLaunched && !afterResult) {
            Intent i = new Intent(Audio.Media.RECORD_SOUND_ACTION);
            // to make the name unique...
            File f = ODKFileUtils.getRowpathFile(appName, tableId, instanceId,
                    (uriFragmentToMedia == null ? uriFragmentNewFileBase : uriFragmentToMedia));
            int idx = f.getName().lastIndexOf('.');
            if (idx == -1) {
                i.putExtra(Audio.Media.DISPLAY_NAME, f.getName());
            } else {
                i.putExtra(Audio.Media.DISPLAY_NAME, f.getName().substring(0, idx));
            }

            try {
                hasLaunched = true;
                startActivityForResult(i, ACTION_CODE);
            } catch (ActivityNotFoundException e) {
                String err = getString(R.string.activity_not_found, Audio.Media.RECORD_SOUND_ACTION);
                WebLogger.getLogger(appName).e(t, err);
                Toast.makeText(this, err, Toast.LENGTH_SHORT).show();
                setResult(Activity.RESULT_CANCELED);
                finish();
            }
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(IntentConsts.INTENT_KEY_APP_NAME, appName);
        outState.putString(IntentConsts.INTENT_KEY_TABLE_ID, tableId);
        outState.putString(IntentConsts.INTENT_KEY_INSTANCE_ID, instanceId);
        outState.putString(IntentConsts.INTENT_KEY_URI_FRAGMENT, uriFragmentToMedia);
        outState.putString(URI_FRAGMENT_NEW_FILE_BASE, uriFragmentNewFileBase);
        outState.putBoolean(HAS_LAUNCHED, hasLaunched);
        outState.putBoolean(AFTER_RESULT, afterResult);
    }

    private void deleteMedia() {
        if (uriFragmentToMedia == null) {
            return;
        }
        // get the file path and delete the file
        File f = ODKFileUtils.getRowpathFile(appName, tableId, instanceId, uriFragmentToMedia);
        String path = f.getAbsolutePath();
        // delete from media provider
        int del = MediaUtils.deleteAudioFileFromMediaProvider(this, appName, path);
        WebLogger.getLogger(appName).i(t, "Deleted " + del + " rows from audio media content provider");
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {

        if (resultCode == Activity.RESULT_CANCELED) {
            // request was canceled -- propagate
            setResult(Activity.RESULT_CANCELED);
            finish();
            return;
        }

        Uri mediaUri = intent.getData();

        // it is unclear whether getData() always returns a value or if
        // getDataString() does...
        String str = intent.getDataString();
        if (mediaUri == null && str != null) {
            WebLogger.getLogger(appName).w(t, "Attempting to work around null mediaUri");
            mediaUri = Uri.parse(str);
        }

        if (mediaUri == null) {
            // we are in trouble
            WebLogger.getLogger(appName).e(t, "No uri returned from RECORD_SOUND_ACTION!");
            setResult(Activity.RESULT_CANCELED);
            finish();
            return;
        }

        // Remove the current media.
        deleteMedia();

        // get the file path and create a copy in the instance folder
        String binaryPath = MediaUtils.getPathFromUri(this, (Uri) mediaUri, Audio.Media.DATA);
        File source = new File(binaryPath);
        String extension = binaryPath.substring(binaryPath.lastIndexOf("."));

        if (uriFragmentToMedia == null) {
            // use the newFileBase as a starting point...
            uriFragmentToMedia = uriFragmentNewFileBase + extension;
        }

        // adjust the mediaPath (destination) to have the same extension
        // and delete any existing file.
        File f = ODKFileUtils.getRowpathFile(appName, tableId, instanceId, uriFragmentToMedia);
        File sourceMedia = new File(f.getParentFile(),
                f.getName().substring(0, f.getName().lastIndexOf('.')) + extension);
        uriFragmentToMedia = ODKFileUtils.asRowpathUri(appName, tableId, instanceId, sourceMedia);
        deleteMedia();

        try {
            FileUtils.copyFile(source, sourceMedia);
        } catch (IOException e) {
            WebLogger.getLogger(appName).e(t, ERROR_COPY_FILE + sourceMedia.getAbsolutePath());
            Toast.makeText(this, R.string.media_save_failed, Toast.LENGTH_SHORT).show();
            deleteMedia();
            setResult(Activity.RESULT_CANCELED);
            finish();
            return;
        }

        if (sourceMedia.exists()) {
            // Add the copy to the content provier
            ContentValues values = new ContentValues(6);
            values.put(Audio.Media.TITLE, sourceMedia.getName());
            values.put(Audio.Media.DISPLAY_NAME, sourceMedia.getName());
            values.put(Audio.Media.DATE_ADDED, System.currentTimeMillis());
            values.put(Audio.Media.DATA, sourceMedia.getAbsolutePath());

            Uri MediaURI = getApplicationContext().getContentResolver().insert(Audio.Media.EXTERNAL_CONTENT_URI,
                    values);
            WebLogger.getLogger(appName).i(t, "Inserting AUDIO returned uri = " + MediaURI.toString());
            uriFragmentToMedia = ODKFileUtils.asRowpathUri(appName, tableId, instanceId, sourceMedia);
            WebLogger.getLogger(appName).i(t, "Setting current answer to " + sourceMedia.getAbsolutePath());

            int delCount = getApplicationContext().getContentResolver().delete(mediaUri, null, null);
            WebLogger.getLogger(appName).i(t,
                    "Deleting original capture of file: " + mediaUri.toString() + " count: " + delCount);
        } else {
            WebLogger.getLogger(appName).e(t, "Inserting Audio file FAILED");
        }

        /*
         * We saved the audio to the instance directory. Verify that it is there...
         */
        returnResult();
        return;
    }

    private void returnResult() {
        File sourceMedia = (uriFragmentToMedia != null)
                ? ODKFileUtils.getRowpathFile(appName, tableId, instanceId, uriFragmentToMedia)
                : null;
        if (sourceMedia != null && sourceMedia.exists()) {
            Intent i = new Intent();
            i.putExtra(IntentConsts.INTENT_KEY_URI_FRAGMENT,
                    ODKFileUtils.asRowpathUri(appName, tableId, instanceId, sourceMedia));
            String name = sourceMedia.getName();
            i.putExtra(IntentConsts.INTENT_KEY_CONTENT_TYPE,
                    MEDIA_CLASS + name.substring(name.lastIndexOf(".") + 1));
            setResult(Activity.RESULT_OK, i);
            finish();
        } else {
            WebLogger.getLogger(appName).e(t, ERROR_NO_FILE
                    + ((uriFragmentToMedia != null) ? sourceMedia.getAbsolutePath() : "null mediaPath"));
            Toast.makeText(this, R.string.media_save_failed, Toast.LENGTH_SHORT).show();
            setResult(Activity.RESULT_CANCELED);
            finish();
        }
    }

    @Override
    public void finish() {
        hasLaunched = false;
        afterResult = true;
        super.finish();
    }

    @Override
    public void databaseAvailable() {
    }

    @Override
    public void databaseUnavailable() {
    }

}