alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Android example source code file (LolcatActivity.java)

This example Android source code file (LolcatActivity.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Android by Example" TM.

Java - Android tags/keywords

alertdialog, android, app, application, button, cancel, caption, dialog_save_progress, edittext, file, intent, io, os, override, photo_picked, save, string, toast, ui, uri

The LolcatActivity.java Android example source code

/*
 * Copyright (C) 2008 Google Inc.
 *
 * 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.android.lolcat;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

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

/**
 * Lolcat builder activity.
 *
 * Instructions:
 * (1) Take photo of cat using Camera
 * (2) Run LolcatActivity
 * (3) Pick photo
 * (4) Add caption(s)
 * (5) Save and share
 *
 * See README.txt for a list of currently-missing features and known bugs.
 */
public class LolcatActivity extends Activity
        implements View.OnClickListener {
    private static final String TAG = "LolcatActivity";

    // Location on the SD card for saving lolcat images
    private static final String LOLCAT_SAVE_DIRECTORY = "lolcats/";

    // Mime type / format / extension we use (must be self-consistent!)
    private static final String SAVED_IMAGE_EXTENSION = ".png";
    private static final Bitmap.CompressFormat SAVED_IMAGE_COMPRESS_FORMAT =
            Bitmap.CompressFormat.PNG;
    private static final String SAVED_IMAGE_MIME_TYPE = "image/png";

    // UI Elements
    private Button mPickButton;
    private Button mCaptionButton;
    private Button mSaveButton;
    private Button mClearCaptionButton;
    private Button mClearPhotoButton;
    private LolcatView mLolcatView;

    private AlertDialog mCaptionDialog;
    private ProgressDialog mSaveProgressDialog;
    private AlertDialog mSaveSuccessDialog;

    private Handler mHandler;

    private Uri mPhotoUri;

    private String mSavedImageFilename;
    private Uri mSavedImageUri;

    private MediaScannerConnection mMediaScannerConnection;

    // Request codes used with startActivityForResult()
    private static final int PHOTO_PICKED = 1;

    // Dialog IDs
    private static final int DIALOG_CAPTION = 1;
    private static final int DIALOG_SAVE_PROGRESS = 2;
    private static final int DIALOG_SAVE_SUCCESS = 3;

    // Keys used with onSaveInstanceState()
    private static final String PHOTO_URI_KEY = "photo_uri";
    private static final String SAVED_IMAGE_FILENAME_KEY = "saved_image_filename";
    private static final String SAVED_IMAGE_URI_KEY = "saved_image_uri";
    private static final String TOP_CAPTION_KEY = "top_caption";
    private static final String BOTTOM_CAPTION_KEY = "bottom_caption";
    private static final String CAPTION_POSITIONS_KEY = "caption_positions";


    @Override
    protected void onCreate(Bundle icicle) {
        Log.i(TAG, "onCreate()...  icicle = " + icicle);

        super.onCreate(icicle);

        setContentView(R.layout.lolcat_activity);

        // Look up various UI elements

        mPickButton = (Button) findViewById(R.id.pick_button);
        mPickButton.setOnClickListener(this);

        mCaptionButton = (Button) findViewById(R.id.caption_button);
        mCaptionButton.setOnClickListener(this);

        mSaveButton = (Button) findViewById(R.id.save_button);
        mSaveButton.setOnClickListener(this);

        mClearCaptionButton = (Button) findViewById(R.id.clear_caption_button);
        // This button doesn't exist in portrait mode.
        if (mClearCaptionButton != null) mClearCaptionButton.setOnClickListener(this);

        mClearPhotoButton = (Button) findViewById(R.id.clear_photo_button);
        mClearPhotoButton.setOnClickListener(this);

        mLolcatView = (LolcatView) findViewById(R.id.main_image);

        // Need one of these to call back to the UI thread
        // (and run AlertDialog.show(), for that matter)
        mHandler = new Handler();

        mMediaScannerConnection = new MediaScannerConnection(this, mMediaScanConnClient);

        if (icicle != null) {
            Log.i(TAG, "- reloading state from icicle!");
            restoreStateFromIcicle(icicle);
        }
    }

    @Override
    protected void onResume() {
        Log.i(TAG, "onResume()...");
        super.onResume();

        updateButtons();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        Log.i(TAG, "onSaveInstanceState()...");
        super.onSaveInstanceState(outState);

        // State from the Activity:
        outState.putParcelable(PHOTO_URI_KEY, mPhotoUri);
        outState.putString(SAVED_IMAGE_FILENAME_KEY, mSavedImageFilename);
        outState.putParcelable(SAVED_IMAGE_URI_KEY, mSavedImageUri);

        // State from the LolcatView:
        // (TODO: Consider making Caption objects, or even the LolcatView
        // itself, Parcelable?  Probably overkill, though...)
        outState.putString(TOP_CAPTION_KEY, mLolcatView.getTopCaption());
        outState.putString(BOTTOM_CAPTION_KEY, mLolcatView.getBottomCaption());
        outState.putIntArray(CAPTION_POSITIONS_KEY, mLolcatView.getCaptionPositions());
    }

    /**
     * Restores the activity state from the specified icicle.
     * @see onCreate()
     * @see onSaveInstanceState()
     */
    private void restoreStateFromIcicle(Bundle icicle) {
        Log.i(TAG, "restoreStateFromIcicle()...");

        // State of the Activity:

        Uri photoUri = icicle.getParcelable(PHOTO_URI_KEY);
        Log.i(TAG, "  - photoUri: " + photoUri);
        if (photoUri != null) {
            loadPhoto(photoUri);
        }

        mSavedImageFilename = icicle.getString(SAVED_IMAGE_FILENAME_KEY);
        mSavedImageUri = icicle.getParcelable(SAVED_IMAGE_URI_KEY);

        // State of the LolcatView:

        String topCaption = icicle.getString(TOP_CAPTION_KEY);
        String bottomCaption = icicle.getString(BOTTOM_CAPTION_KEY);
        int[] captionPositions = icicle.getIntArray(CAPTION_POSITIONS_KEY);
        Log.i(TAG, "  - captions: '" + topCaption + "', '" + bottomCaption + "'");
        if (!TextUtils.isEmpty(topCaption) || !TextUtils.isEmpty(bottomCaption)) {
            mLolcatView.setCaptions(topCaption, bottomCaption);
            mLolcatView.setCaptionPositions(captionPositions);
        }
    }

    @Override
    protected void onDestroy() {
        Log.i(TAG, "onDestroy()...");
        super.onDestroy();
        clearPhoto();  // Free up some resources, and force a GC
    }

    // View.OnClickListener implementation
    public void onClick(View view) {
        int id = view.getId();
        Log.i(TAG, "onClick(View " + view + ", id " + id + ")...");

        switch (id) {
            case R.id.pick_button:
                Log.i(TAG, "onClick: pick_button...");
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
                intent.setType("image/*");

                // Note: we could have the "crop" UI come up here by
                // default by doing this:
                //   intent.putExtra("crop", "true");
                // (But watch out: if you do that, the Intent that comes
                // back to onActivityResult() will have the URI (of the
                // cropped image) in the "action" field, not the "data"
                // field!)

                startActivityForResult(intent, PHOTO_PICKED);
                break;

            case R.id.caption_button:
                Log.i(TAG, "onClick: caption_button...");
                showCaptionDialog();
                break;

            case R.id.save_button:
                Log.i(TAG, "onClick: save_button...");
                saveImage();
                break;

            case R.id.clear_caption_button:
                Log.i(TAG, "onClick: clear_caption_button...");
                clearCaptions();
                updateButtons();
                break;

            case R.id.clear_photo_button:
                Log.i(TAG, "onClick: clear_photo_button...");
                clearPhoto();  // Also does clearCaptions()
                updateButtons();
                break;

            default:
                Log.w(TAG, "Click from unexpected source: " + view + ", id " + id);
                break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.i(TAG, "onActivityResult(request " + requestCode
              + ", result " + resultCode + ", data " + data + ")...");

        if (resultCode != RESULT_OK) {
            Log.i(TAG, "==> result " + resultCode + " from subactivity!  Ignoring...");
            Toast t = Toast.makeText(this, R.string.lolcat_nothing_picked, Toast.LENGTH_SHORT);
            t.show();
            return;
        }

        if (requestCode == PHOTO_PICKED) {
            // "data" is an Intent containing (presumably) a URI like
            // "content://media/external/images/media/3".

            if (data == null) {
                Log.w(TAG, "Null data, but RESULT_OK, from image picker!");
                Toast t = Toast.makeText(this, R.string.lolcat_nothing_picked,
                                         Toast.LENGTH_SHORT);
                t.show();
                return;
            }

            if (data.getData() == null) {
                Log.w(TAG, "'data' intent from image picker contained no data!");
                Toast t = Toast.makeText(this, R.string.lolcat_nothing_picked,
                                         Toast.LENGTH_SHORT);
                t.show();
                return;
            }

            loadPhoto(data.getData());
            updateButtons();
        }
    }

    /**
     * Updates the enabled/disabled state of the onscreen buttons.
     */
    private void updateButtons() {
        Log.i(TAG, "updateButtons()...");

        // mPickButton is always enabled.

        // Do we have a valid photo and/or caption(s) yet?
        Drawable d = mLolcatView.getDrawable();
        // Log.i(TAG, "===> current mLolcatView drawable: " + d);
        boolean validPhoto = (d != null);
        boolean validCaption = mLolcatView.hasValidCaption();

        mCaptionButton.setText(validCaption
                               ? R.string.lolcat_change_captions : R.string.lolcat_add_captions);
        mCaptionButton.setEnabled(validPhoto);

        mSaveButton.setEnabled(validPhoto && validCaption);

        if (mClearCaptionButton != null) {
            mClearCaptionButton.setEnabled(validPhoto && validCaption);
        }

        mClearPhotoButton.setEnabled(validPhoto);
    }

    /**
     * Clears out any already-entered captions for this lolcat.
     */
    private void clearCaptions() {
        mLolcatView.clearCaptions();

        // Clear the text fields in the caption dialog too.
        if (mCaptionDialog != null) {
            EditText topText = (EditText) mCaptionDialog.findViewById(R.id.top_edittext);
            topText.setText("");
            EditText bottomText = (EditText) mCaptionDialog.findViewById(R.id.bottom_edittext);
            bottomText.setText("");
            topText.requestFocus();
        }

        // This also invalidates any image we've previously written to the
        // SD card...
        mSavedImageFilename = null;
        mSavedImageUri = null;
    }

    /**
     * Completely resets the UI to its initial state, with no photo
     * loaded, and no captions.
     */
    private void clearPhoto() {
        mLolcatView.clear();

        mPhotoUri = null;
        mSavedImageFilename = null;
        mSavedImageUri = null;

        clearCaptions();

        // Force a gc (to be sure to reclaim the memory used by our
        // potentially huge bitmap):
        System.gc();
    }

    /**
     * Loads the image with the specified Uri into the UI.
     */
    private void loadPhoto(Uri uri) {
        Log.i(TAG, "loadPhoto: uri = " + uri);

        clearPhoto();  // Be sure to release the previous bitmap
                       // before creating another one
        mPhotoUri = uri;

        // A new photo always starts out uncaptioned.
        clearCaptions();

        // Load the selected photo into our ImageView.
        mLolcatView.loadFromUri(mPhotoUri);
    }

    private void showCaptionDialog() {
        // If the dialog already exists, always reset focus to the top
        // item each time it comes up.
        if (mCaptionDialog != null) {
            EditText topText = (EditText) mCaptionDialog.findViewById(R.id.top_edittext);
            topText.requestFocus();
        }

        showDialog(DIALOG_CAPTION);
    }

    private void showSaveSuccessDialog() {
        // If the dialog already exists, update the body text based on the
        // current values of mSavedImageFilename and mSavedImageUri
        // (otherwise the dialog will still have the body text from when
        // it was first created!)

        if (mSaveSuccessDialog != null) {
            updateSaveSuccessDialogBody();
        }
        showDialog(DIALOG_SAVE_SUCCESS);
    }

    private void updateSaveSuccessDialogBody() {
        if (mSaveSuccessDialog == null) {
            throw new IllegalStateException(
                    "updateSaveSuccessDialogBody: mSaveSuccessDialog hasn't been created yet");
        }
        String dialogBody = String.format(
                getResources().getString(R.string.lolcat_save_succeeded_dialog_body_format),
                mSavedImageFilename, mSavedImageUri);
        mSaveSuccessDialog.setMessage(dialogBody);
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        Log.i(TAG, "onCreateDialog(id " + id + ")...");

        // This is only run once (per dialog), the very first time
        // a given dialog needs to be shown.

        switch (id) {
            case DIALOG_CAPTION:
                LayoutInflater factory = LayoutInflater.from(this);
                final View textEntryView = factory.inflate(R.layout.lolcat_caption_dialog, null);
                mCaptionDialog = new AlertDialog.Builder(this)
                        .setTitle(R.string.lolcat_caption_dialog_title)
                        .setIcon(0)
                        .setView(textEntryView)
                        .setPositiveButton(
                                R.string.lolcat_caption_dialog_ok,
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int whichButton) {
                                        Log.i(TAG, "Caption dialog: OK...");
                                        updateCaptionsFromDialog();
                                    }
                                })
                        .setNegativeButton(
                                R.string.lolcat_caption_dialog_cancel,
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int whichButton) {
                                        Log.i(TAG, "Caption dialog: CANCEL...");
                                        // Nothing to do here (for now at least)
                                    }
                                })
                        .create();
                return mCaptionDialog;

            case DIALOG_SAVE_PROGRESS:
                mSaveProgressDialog = new ProgressDialog(this);
                mSaveProgressDialog.setMessage(getResources().getString(R.string.lolcat_saving));
                mSaveProgressDialog.setIndeterminate(true);
                mSaveProgressDialog.setCancelable(false);
                return mSaveProgressDialog;

            case DIALOG_SAVE_SUCCESS:
                mSaveSuccessDialog = new AlertDialog.Builder(this)
                        .setTitle(R.string.lolcat_save_succeeded_dialog_title)
                        .setIcon(0)
                        .setPositiveButton(
                                R.string.lolcat_save_succeeded_dialog_view,
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int whichButton) {
                                        Log.i(TAG, "Save dialog: View...");
                                        viewSavedImage();
                                    }
                                })
                        .setNeutralButton(
                                R.string.lolcat_save_succeeded_dialog_share,
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int whichButton) {
                                        Log.i(TAG, "Save dialog: Share...");
                                        shareSavedImage();
                                    }
                                })
                        .setNegativeButton(
                                R.string.lolcat_save_succeeded_dialog_cancel,
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int whichButton) {
                                        Log.i(TAG, "Save dialog: CANCEL...");
                                        // Nothing to do here...
                                    }
                                })
                        .create();
                updateSaveSuccessDialogBody();
                return mSaveSuccessDialog;

            default:
                Log.w(TAG, "Request for unexpected dialog id: " + id);
                break;
        }
        return null;
    }

    private void updateCaptionsFromDialog() {
        Log.i(TAG, "updateCaptionsFromDialog()...");

        if (mCaptionDialog == null) {
            Log.w(TAG, "updateCaptionsFromDialog: null mCaptionDialog!");
            return;
        }

        // Get the two caption strings:

        EditText topText = (EditText) mCaptionDialog.findViewById(R.id.top_edittext);
        Log.i(TAG, "- Top editText: " + topText);
        String topString = topText.getText().toString();
        Log.i(TAG, "  - String: '" + topString + "'");

        EditText bottomText = (EditText) mCaptionDialog.findViewById(R.id.bottom_edittext);
        Log.i(TAG, "- Bottom editText: " + bottomText);
        String bottomString = bottomText.getText().toString();
        Log.i(TAG, "  - String: '" + bottomString + "'");

        mLolcatView.setCaptions(topString, bottomString);
        updateButtons();
    }


    /**
     * Kicks off the process of saving the LolcatView's working Bitmap to
     * the SD card, in preparation for viewing it later and/or sharing it.
     */
    private void saveImage() {
        Log.i(TAG, "saveImage()...");

        // First of all, bring up a progress dialog.
        showDialog(DIALOG_SAVE_PROGRESS);

        // We now need to save the bitmap to the SD card, and then ask the
        // MediaScanner to scan it.  Do the actual work of all this in a
        // helper thread, since it's fairly slow (and will occasionally
        // ANR if we do it here in the UI thread.)

        Thread t = new Thread() {
                public void run() {
                    Log.i(TAG, "Running worker thread...");
                    saveImageInternal();
                }
            };
        t.start();
        // Next steps:
        // - saveImageInternal()
        // - onMediaScannerConnected()
        // - onScanCompleted
    }

    /**
     * Saves the LolcatView's working Bitmap to the SD card, in
     * preparation for viewing it later and/or sharing it.
     *
     * The bitmap will be saved as a new file in the directory
     * LOLCAT_SAVE_DIRECTORY, with an automatically-generated filename
     * based on the current time.  It also connects to the
     * MediaScanner service, since we'll need to scan that new file (in
     * order to get a Uri we can then VIEW or share.)
     *
     * This method is run in a worker thread; @see saveImage().
     */
    private void saveImageInternal() {
        Log.i(TAG, "saveImageInternal()...");

        // TODO: Currently we save the bitmap to a file on the sdcard,
        // then ask the MediaScanner to scan it (which gives us a Uri we
        // can then do an ACTION_VIEW on.)  But rather than doing these
        // separate steps, maybe there's some easy way (given an
        // OutputStream) to directly talk to the MediaProvider
        // (i.e. com.android.provider.MediaStore) and say "here's an
        // image, please save it somwhere and return the URI to me"...

        // Save the bitmap to a file on the sdcard.
        // (Based on similar code in MusicUtils.java.)
        // TODO: Make this filename more human-readable?  Maybe "Lolcat-YYYY-MM-DD-HHMMSS.png"?
        String filename = Environment.getExternalStorageDirectory()
                + "/" + LOLCAT_SAVE_DIRECTORY
                + String.valueOf(System.currentTimeMillis() + SAVED_IMAGE_EXTENSION);
        Log.i(TAG, "- filename: '" + filename + "'");

        if (ensureFileExists(filename)) {
            try {
                OutputStream outstream = new FileOutputStream(filename);
                Bitmap bitmap = mLolcatView.getWorkingBitmap();
                boolean success = bitmap.compress(SAVED_IMAGE_COMPRESS_FORMAT,
                                                  100, outstream);
                Log.i(TAG, "- success code from Bitmap.compress: " + success);
                outstream.close();

                if (success) {
                    Log.i(TAG, "- Saved!  filename = " + filename);
                    mSavedImageFilename = filename;

                    // Ok, now we need to get the MediaScanner to scan the
                    // file we just wrote.  Step 1 is to get our
                    // MediaScannerConnection object to connect to the
                    // MediaScanner service.
                    mMediaScannerConnection.connect();
                    // See onMediaScannerConnected() for the next step
                } else {
                    Log.w(TAG, "Bitmap.compress failed: bitmap " + bitmap
                          + ", filename '" + filename + "'");
                    onSaveFailed(R.string.lolcat_save_failed);
                }
            } catch (FileNotFoundException e) {
                Log.w(TAG, "error creating file", e);
                onSaveFailed(R.string.lolcat_save_failed);
            } catch (IOException e) {
                Log.w(TAG, "error creating file", e);
                onSaveFailed(R.string.lolcat_save_failed);
            }
        } else {
            Log.w(TAG, "ensureFileExists failed for filename '" + filename + "'");
            onSaveFailed(R.string.lolcat_save_failed);
        }
    }


    //
    // MediaScanner-related code
    //

    /**
     * android.media.MediaScannerConnection.MediaScannerConnectionClient implementation.
     */
    private MediaScannerConnection.MediaScannerConnectionClient mMediaScanConnClient =
        new MediaScannerConnection.MediaScannerConnectionClient() {
            /**
             * Called when a connection to the MediaScanner service has been established.
             */
            public void onMediaScannerConnected() {
                Log.i(TAG, "MediaScannerConnectionClient.onMediaScannerConnected...");
                // The next step happens in the UI thread:
                mHandler.post(new Runnable() {
                        public void run() {
                            LolcatActivity.this.onMediaScannerConnected();
                        }
                    });
            }

            /**
             * Called when the media scanner has finished scanning a file.
             * @param path the path to the file that has been scanned.
             * @param uri the Uri for the file if the scanning operation succeeded
             *        and the file was added to the media database, or null if scanning failed.
             */
            public void onScanCompleted(final String path, final Uri uri) {
                Log.i(TAG, "MediaScannerConnectionClient.onScanCompleted: path "
                      + path + ", uri " + uri);
                // Just run the "real" onScanCompleted() method in the UI thread:
                mHandler.post(new Runnable() {
                        public void run() {
                            LolcatActivity.this.onScanCompleted(path, uri);
                        }
                    });
            }
        };

    /**
     * This method is called when our MediaScannerConnection successfully
     * connects to the MediaScanner service.  At that point we fire off a
     * request to scan the lolcat image we just saved.
     *
     * This needs to run in the UI thread, so it's called from
     * mMediaScanConnClient's onMediaScannerConnected() method via our Handler.
     */
    private void onMediaScannerConnected() {
        Log.i(TAG, "onMediaScannerConnected()...");

        // Update the message in the progress dialog...
        mSaveProgressDialog.setMessage(getResources().getString(R.string.lolcat_scanning));

        // Fire off a request to the MediaScanner service to scan this
        // file; we'll get notified when the scan completes.
        Log.i(TAG, "- Requesting scan for file: " + mSavedImageFilename);
        mMediaScannerConnection.scanFile(mSavedImageFilename,
                                         null /* mimeType */);

        // Next step: mMediaScanConnClient will get an onScanCompleted() callback,
        // which calls our own onScanCompleted() method via our Handler.
    }

    /**
     * Updates the UI after the media scanner finishes the scanFile()
     * request we issued from onMediaScannerConnected().
     *
     * This needs to run in the UI thread, so it's called from
     * mMediaScanConnClient's onScanCompleted() method via our Handler.
     */
    private void onScanCompleted(String path, final Uri uri) {
        Log.i(TAG, "onScanCompleted: path " + path + ", uri " + uri);
        mMediaScannerConnection.disconnect();

        if (uri == null) {
            Log.w(TAG, "onScanCompleted: scan failed.");
            mSavedImageUri = null;
            onSaveFailed(R.string.lolcat_scan_failed);
            return;
        }

        // Success!

        dismissDialog(DIALOG_SAVE_PROGRESS);

        // We can now access the saved lolcat image using the specified Uri.
        mSavedImageUri = uri;

        // Bring up a success dialog, giving the user the option to go to
        // the pictures app (so you can share the image).
        showSaveSuccessDialog();
    }


    //
    // Other misc utility methods
    //

    /**
     * Ensure that the specified file exists on the SD card, creating it
     * if necessary.
     *
     * Copied from MediaProvider / MusicUtils.
     *
     * @return true if the file already exists, or we
     *         successfully created it.
     */
    private static boolean ensureFileExists(String path) {
        File file = new File(path);
        if (file.exists()) {
            return true;
        } else {
            // we will not attempt to create the first directory in the path
            // (for example, do not create /sdcard if the SD card is not mounted)
            int secondSlash = path.indexOf('/', 1);
            if (secondSlash < 1) return false;
            String directoryPath = path.substring(0, secondSlash);
            File directory = new File(directoryPath);
            if (!directory.exists())
                return false;
            file.getParentFile().mkdirs();
            try {
                return file.createNewFile();
            } catch (IOException ioe) {
                Log.w(TAG, "File creation failed", ioe);
            }
            return false;
        }
    }

    /**
     * Updates the UI after a failure anywhere in the bitmap saving / scanning
     * sequence.
     */
    private void onSaveFailed(int errorMessageResId) {
        dismissDialog(DIALOG_SAVE_PROGRESS);
        Toast.makeText(this, errorMessageResId, Toast.LENGTH_SHORT).show();
    }

    /**
     * Goes to the Pictures app for the specified URI.
     */
    private void viewSavedImage(Uri uri) {
        Log.i(TAG, "viewSavedImage(" + uri + ")...");

        if (uri == null) {
            Log.w(TAG, "viewSavedImage: null uri!");
            return;
        }

        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        Log.i(TAG, "- running startActivity...  Intent = " + intent);
        startActivity(intent);
    }

    private void viewSavedImage() {
        viewSavedImage(mSavedImageUri);
    }

    /**
     * Shares the image with the specified URI.
     */
    private void shareSavedImage(Uri uri) {
        Log.i(TAG, "shareSavedImage(" + uri + ")...");

        if (uri == null) {
            Log.w(TAG, "shareSavedImage: null uri!");
            return;
        }

        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEND);
        intent.setType(SAVED_IMAGE_MIME_TYPE);
        intent.putExtra(Intent.EXTRA_STREAM, uri);
        try {
            startActivity(
                    Intent.createChooser(
                            intent,
                            getResources().getString(R.string.lolcat_sendImage_label)));
        } catch (android.content.ActivityNotFoundException ex) {
            Log.w(TAG, "shareSavedImage: startActivity failed", ex);
            Toast.makeText(this, R.string.lolcat_share_failed, Toast.LENGTH_SHORT).show();
        }
    }

    private void shareSavedImage() {
        shareSavedImage(mSavedImageUri);
    }
}

Other Android examples (source code examples)

Here is a short list of links related to this Android LolcatActivity.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.