Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

After configuration change in Camera, returns to app with empty ImageView

I have not found anything online that addresses this particular issue. I have an activity that takes a photo or video using the Android camera app. It then returns from the camera with the image or video, and shows it in a view. Both my video and image, capture and show, work fine when I am in the same configuration. But if I start the camera from my app in say, portrait, then when I am in the camera app I decide to change it to landscape, then once I come back from the camera app, my image shows a blank ImageView. It works fine if I stay in the same configuration. Like when I start in portrait, and use the camera app also in portrait, then my ImageView shows the image upon returning. Since I cannot write code for the camera app, not sure how to handle this.

However, my video has no trouble if I change orientation during use of the camera video. It displays fine when it comes back into my app, no matter which orientation I am in in either the app or the camera app.

But why does the image have problems? I've tried to save state in onSaveInstanceState and onRestoreInstanceState, but this does not affect anything. I get null values for all my variables in those methods, when I log them (for video too). I think because it might have more to do with my Intent data? But that's just a guess. I looked over the Intent and see nothing missing. The image intent is a little different from the video intent, so maybe I'm missing something.

I do have 2 different xml files for the portrait and landscape layout, but they are identical and in the right folders. Android auto-chooses them when I do a configuration change.

If anyone has tips, thanks very much.

UPDATE:

I tried to add a line of code in my manifest: android:configChanges="keyboardHidden|orientation|screenSize"

and I overrode onConfigurationChanged(), but now my image comes back as a black screen. Both layout files are in my layout folder.

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        setContentView(R.layout.activity_make_photo_video_land);
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        setContentView(R.layout.activity_make_photo_video);
    }
}

UPDATE 2:

I undid everything I tried in UPDATE 1. Since that gave me a black screen and other unfixable bugs.

This time, I have added a configuration selector in onCreate to manually change the view:

// Checks the orientation of the screen
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
            setContentView(R.layout.activity_make_photo_video_land);
            mImageView = (ImageView) findViewById(R.id.taken_photo_land);
        } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            setContentView(R.layout.activity_make_photo_video);
            mImageView = (ImageView) findViewById(R.id.taken_photo);
        }

After more logging, I have realized when I change the configuration in the camera app, the following methods execute in this order (listed from 1st activity start):

  1. onCreate()

  2. onSavedInstanceState() - I leave my app to go to the camera

  3. onCreate() - I return from app with a photo, a log on mImageBitmap is null.

  4. onRestoreInstanceState()

  5. inActivityResult() - then it processes the photo that is captured from camera.

The only thing I persist in onSavedInstanceState() is the mCurrentPhotoPath, which is needed to run the setPic() method in inActivityResult().

In onSavedInstanceState(): outState.putString("FILE_PATH", mCurrentPhotoPath);

In onCreate():

if (savedInstanceState != null) {
            mCurrentPhotoPath = savedInstanceState.getString("FILE_PATH");
   }

This processes fine, and a log on the bitmap value is not null. So why doesn't the image post still??

MakePhotoVideo.java

package org.azurespot.makecute;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Gravity;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;

import org.azurespot.R;
import org.azurespot.cutecollection.CuteCollection;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Random;

public class MakePhotoVideo extends ActionBarActivity {

    private static final int ACTION_TAKE_PHOTO = 1;
    private static final int ACTION_TAKE_VIDEO = 2;
    private static final String BITMAP_STORAGE_KEY = "viewbitmap";
    private static final String IMAGEVIEW_VISIBILITY_STORAGE_KEY = "imageviewvisibility";
    private ImageView mImageView;
    private Bitmap mImageBitmap;

    private static final String VIDEO_STORAGE_KEY = "viewvideo";
    private static final String VIDEOVIEW_VISIBILITY_STORAGE_KEY = "videoviewvisibility";
    private VideoView mVideoView;
    private Uri mVideoUri;
    private File fileVideo;

    private String mCurrentPhotoPath;
    String videoPath;
    private int position = 0;

    private static final String JPEG_FILE_PREFIX = "IMG_";
    private static final String JPEG_FILE_SUFFIX = ".jpg";

    private PhotoStorageDirFactory mPhotoStorageDirFactory = null;



    /* Photo album for this application */
    private String getAlbumName() {
        return getString(R.string.album_name);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_make_photo_video);

        mImageView = (ImageView) findViewById(R.id.taken_photo);
        mVideoView = (VideoView) findViewById(R.id.video_view);
        mVideoView.setVisibility(View.INVISIBLE);
        mImageView.setSaveEnabled(true);

        Button photoBtn = (Button) findViewById(R.id.click);
        setBtnListenerOrDisable(photoBtn, mTakePicOnClickListener, MediaStore.ACTION_IMAGE_CAPTURE);

        Button videoBtn = (Button) findViewById(R.id.record_video);
        setBtnListenerOrDisable(videoBtn,mTakeVidOnClickListener, MediaStore.ACTION_VIDEO_CAPTURE);

        mPhotoStorageDirFactory = new BasePhotoDirFactory();

        // Shows the up carat near app icon in ActionBar
        getSupportActionBar().setDisplayUseLogoEnabled(false);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    }


    public void viewCollection(View v){

        // finishes/restarts the activity so the unsaved video does not corrupt
        Intent intent = getIntent();
        finish();
        startActivity(intent);

        // goes to Cute Collection activity
        Intent i = new Intent(this, CuteCollection.class);
        startActivity(i);
    }

    private File getAlbumDir() {
        File storageDir = null;

        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {

            storageDir = mPhotoStorageDirFactory.getAlbumStorageDir(getAlbumName());

            if (storageDir != null) {
                if (! storageDir.mkdirs()) {
                    if (! storageDir.exists()){
                        Log.d("Camera", "failed to create directory");
                        return null;
                    }
                }
            }

        } else {
            Log.v(getString(R.string.app_name), "External storage is not mounted READ/WRITE.");
        }

        return storageDir;
    }

    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = JPEG_FILE_PREFIX + timeStamp + "_";
        File albumF = getAlbumDir();
        File imageF = File.createTempFile(imageFileName, JPEG_FILE_SUFFIX, albumF);
        return imageF;
    }

    private File setUpPhotoFile() throws IOException {

        File f = createImageFile();
        mCurrentPhotoPath = f.getAbsolutePath();

        return f;
    }

    private void setPic() {

        /* There isn't enough memory to open up more than a couple camera photos */
        /* So pre-scale the target bitmap into which the file is decoded */

        /* Get the size of the ImageView */
        int targetW = mImageView.getWidth();
        int targetH = mImageView.getHeight();

        /* Get the size of the image */
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
        int photoW = bmOptions.outWidth;
        int photoH = bmOptions.outHeight;

        /* Figure out which way needs to be reduced less */
        int scaleFactor = 1;
        if ((targetW > 0) || (targetH > 0)) {
            scaleFactor = Math.min(photoW/targetW, photoH/targetH);
        }

        /* Set bitmap options to scale the image decode target */
        bmOptions.inJustDecodeBounds = false;
        bmOptions.inSampleSize = scaleFactor;
        bmOptions.inPurgeable = true;

        /* Decode the JPEG file into a Bitmap */
        mImageBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);


        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            mImageBitmap = rotateBitmap(mImageBitmap, 90);
        }

        savePhoto(mImageBitmap);

        /* Associate the Bitmap to the ImageView, make sure the VideoView
         * is cleared to replace with ImageView */
        mImageView.setImageBitmap(mImageBitmap);

        Log.d("TAG", "Value of mImageBitmap inside setPic(): " + mImageBitmap);
        mVideoUri = null;
        mImageView.setVisibility(View.VISIBLE);
        mVideoView.setVisibility(View.INVISIBLE);

    }

    // save your photo to SD card
    private void savePhoto(final Bitmap bitmapPhoto){
        // set OnClickListener to save the photo
        mImageView.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                boolean success = false;

                File photoDir = new File(Environment.getExternalStoragePublicDirectory
                        (Environment.DIRECTORY_PICTURES) + "/Cute Photos");
                photoDir.mkdirs();
                Random generator = new Random();
                int n = 10000;
                n = generator.nextInt(n);
                String photoName = "Photo"+ n +".jpg";
                File filePhoto = new File (photoDir, photoName);
//                if (filePhoto.exists ()) filePhoto.delete ();
                try {
                    FileOutputStream out = new FileOutputStream(filePhoto);
                    bitmapPhoto.compress(Bitmap.CompressFormat.JPEG, 100, out);
                    out.flush();
                    out.close();
                    success = true;
                } catch (Exception e) {
                    e.printStackTrace();
                }

                if (success) {
                    Toast toast = Toast.makeText(getApplicationContext(), "Cute photo saved!",
                            Toast.LENGTH_LONG);
                    LinearLayout toastLayout = (LinearLayout) toast.getView();
                    toastLayout.setBackgroundColor(getResources().getColor(R.color.toast_color));
                    TextView toastTV = (TextView) toastLayout.getChildAt(0);
                    toastTV.setTextSize(30);
                    toast.setGravity(Gravity.CENTER_VERTICAL, 0, 80);
                    toast.show();
                } else {
                    Toast.makeText(getApplicationContext(),
                            "Error during image saving", Toast.LENGTH_SHORT).show();
                }

            }
        });
    }


    // save your video to SD card
    protected void saveVideo(final Uri uriVideo){

        // click the video to save it
        mVideoView.setOnTouchListener(new View.OnTouchListener() {

            public boolean onTouch(View v, MotionEvent event) {

                boolean success = false;

                if(event.getAction() == MotionEvent.ACTION_UP) {

                    try {
                        // make the directory
                        File vidDir = new File(android.os.Environment.getExternalStoragePublicDirectory
                                (Environment.DIRECTORY_MOVIES) + File.separator + "Cute Videos");
                        vidDir.mkdirs();

                        // create unique identifier
                        Random generator = new Random();
                        int n = 100;
                        n = generator.nextInt(n);
                        // create file name
                        String videoName = "Video" + n + ".mp4";

                        fileVideo = new File(vidDir.getAbsolutePath(), videoName);

                        videoPath = fileVideo.getAbsolutePath();

                        Log.d("TAG", "Value of videoPath:" + videoPath);

                        fileVideo.setWritable(true, false);

                        OutputStream out = new FileOutputStream(fileVideo);
                        InputStream in = getContentResolver().openInputStream(uriVideo);

                        byte buffer[] = new byte[1024];
                        int length = 0;
                        while ((length = in.read(buffer)) > 0) {
                            out.write(buffer, 0, length);
                        }

                        out.close();
                        in.close();

                        success = true;

                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    if (success) {
                        Toast toast = Toast.makeText(getApplicationContext(), "Cute video saved!",
                                Toast.LENGTH_SHORT);
                        LinearLayout toastLayout = (LinearLayout) toast.getView();
                        toastLayout.setBackgroundColor(getResources().getColor(R.color.toast_color));
                        TextView toastTV = (TextView) toastLayout.getChildAt(0);
                        toastTV.setTextSize(30);
                        toast.setGravity(Gravity.CENTER_VERTICAL, 0, 80);
                        toast.show();
                    } else {
                        Toast.makeText(getApplicationContext(),
                                "Error during video saving", Toast.LENGTH_SHORT).show();
                    }
                }

                return true;
            }
        });
    }


    public Bitmap rotateBitmap(Bitmap source, int angle)
    {
        Matrix matrix = new Matrix();
        matrix.set(matrix);
        matrix.setRotate(angle);
        return Bitmap.createBitmap(source, 0, 0, source.getWidth(),
                source.getHeight(), matrix, false);
    }

    private void galleryAddPic() {
        Intent mediaScanIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
        File f = new File(mCurrentPhotoPath);
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
    }

    private void dispatchTakePictureIntent(int actionCode) {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

        switch(actionCode) {
            case ACTION_TAKE_PHOTO:
                File f;

                try {
                    f = setUpPhotoFile();
                    mCurrentPhotoPath = f.getAbsolutePath();
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
                } catch (IOException e) {
                    e.printStackTrace();
                    f = null;
                    mCurrentPhotoPath = null;
                }
                break;

            default:
                break;
        } // switch

        startActivityForResult(takePictureIntent, actionCode);
    }

    // Captures video from Android camera component
    protected void dispatchTakeVideoIntent() {
        Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        if (takeVideoIntent.resolveActivity(getPackageManager()) != null) {
            // set the video image quality to high
            takeVideoIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
            startActivityForResult(takeVideoIntent, ACTION_TAKE_VIDEO);
        }
    }

    private void handleCameraPhoto() {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);

        Log.d("TAG", "Value of mCurrentPhotoPath: " + mCurrentPhotoPath);


        if (mCurrentPhotoPath != null) {
            setPic();
            galleryAddPic();
            mCurrentPhotoPath = null;
        }

    }
    // Post recorded video into VideoView
    private Uri handleCameraVideo(Intent intent) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);

        mVideoUri = intent.getData();
        mVideoView.setVideoURI(mVideoUri);
//        mImageBitmap = null;
        mVideoView.setVisibility(View.VISIBLE);
        mImageView.setVisibility(View.INVISIBLE);
        mVideoView.start();
        // saves video to file
        saveVideo(mVideoUri);

        return mVideoUri;

    }

    // click listener for the Android Camera button (not my app's button)
    Button.OnClickListener mTakePicOnClickListener =
            new Button.OnClickListener() {
                @Override
                public void onClick(View v) {
//                    mImageBitmap = null;
                    dispatchTakePictureIntent(ACTION_TAKE_PHOTO);
                    // releases the orientation lock
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
                }
            };
    Button.OnClickListener mTakeVidOnClickListener =
            new Button.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dispatchTakeVideoIntent();
                    // releases the orientation lock
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
                }
            };


    // Intent data is how the photo and video transfer into their views
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case ACTION_TAKE_PHOTO: {
                if (resultCode == RESULT_OK) {
                    handleCameraPhoto();
                } else {
                    Log.d("TAG", "Result of photo not work.");
                }
                break;
            } // ACTION_TAKE_PHOTO

            case ACTION_TAKE_VIDEO: {
                if (resultCode == RESULT_OK) {
                    handleCameraVideo(data);
                }
                break;
            } // ACTION_TAKE_VIDEO
        } // switch
    }


    // Some lifecycle callbacks so that the image can survive orientation change
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putParcelable(BITMAP_STORAGE_KEY, mImageBitmap);
        outState.putParcelable(VIDEO_STORAGE_KEY, mVideoUri);
        outState.putBoolean(IMAGEVIEW_VISIBILITY_STORAGE_KEY, (mImageBitmap != null) );
        outState.putBoolean(VIDEOVIEW_VISIBILITY_STORAGE_KEY, (mVideoUri != null) );
        outState.putString("FILE_PATH", mCurrentPhotoPath);


        if (mVideoUri != null) {
            // use onSaveInstanceState in order to store the video or photo
            outState.putInt("PositionVideo", mVideoView.getCurrentPosition());
            // playback position for orientation change
            mVideoView.pause();
        }

        // super should be last in this method
        super.onSaveInstanceState(outState);

    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {


        mCurrentPhotoPath = savedInstanceState.getString("FILE_PATH");

        mImageView.setImageBitmap(mImageBitmap);
        mImageView.setVisibility(
                savedInstanceState.getBoolean(IMAGEVIEW_VISIBILITY_STORAGE_KEY) ?
                        ImageView.VISIBLE : ImageView.INVISIBLE
        );


        mVideoUri = savedInstanceState.getParcelable(VIDEO_STORAGE_KEY);


        mVideoView.setVideoURI(mVideoUri);
        mVideoView.setVisibility(
                savedInstanceState.getBoolean(VIDEOVIEW_VISIBILITY_STORAGE_KEY) ?
                        ImageView.VISIBLE : ImageView.INVISIBLE
        );


        if (mVideoUri != null) {
            // for video, restores position it was playing
            position = savedInstanceState.getInt("PositionVideo");
            mVideoView.seekTo(position);
        }


        super.onRestoreInstanceState(savedInstanceState);


    }

    /**
     * Indicates whether the specified action can be used as an intent. This
     * method queries the package manager for installed packages that can
     * respond to an intent with the specified action. If no suitable package is
     * found, this method returns false.
     * http://android-developers.blogspot.com/2009/01/can-i-use-this-intent.html
     *
     * @param context The application's environment.
     * @param action The Intent action to check for availability.
     *
     * @return True if an Intent with the specified action can be sent and
     *         responded to, false otherwise.
     */
    public static boolean isIntentAvailable(Context context, String action) {
        final PackageManager packageManager = context.getPackageManager();
        final Intent intent = new Intent(action);
        List<ResolveInfo> list =
                packageManager.queryIntentActivities(intent,
                        PackageManager.MATCH_DEFAULT_ONLY);
        return list.size() > 0;
    }

    private void setBtnListenerOrDisable(Button btn, Button.OnClickListener onClickListener,
                                                                        String intentName) {
        if (isIntentAvailable(this, intentName)) {
            btn.setOnClickListener(onClickListener);

        } else {
            btn.setClickable(false);
        }
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        // Makes the UP caret go back to the previous fragment MakeCuteFragment
        switch (item.getItemId()) {
            case android.R.id.home:
                android.app.FragmentManager fm= getFragmentManager();
                fm.popBackStack();
                finish();

                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

}
like image 288
Azurespot Avatar asked Feb 03 '26 20:02

Azurespot


1 Answers

After all of my trial and error, I finally found the problem. My 2nd update was very close, the only fault was in the

mImageView.setVisibility(
           savedInstanceState.getBoolean(IMAGEVIEW_VISIBILITY_STORAGE_KEY) ?
                    ImageView.VISIBLE : ImageView.INVISIBLE
    );

method. I had this in onCreate, only executed if it passed the null check, but what I forgot is that the image bitmap does come back null when the configuration changes in the camera app, so the visibility will always be set to invisible. The IMAGEVIEW_VISIBILITY_STORAGE_KEY was set up to be true if the bitmap is not null, and false if it is null. So once I got rid of this, my other saving state code worked really well. Below is the final working code.

MakePhotoVideo.java

package org.azurespot.makecute;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Gravity;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;

import org.azurespot.R;
import org.azurespot.cutecollection.CuteCollection;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Random;

public class MakePhotoVideo extends ActionBarActivity {

    private static final int ACTION_TAKE_PHOTO = 1;
    private static final int ACTION_TAKE_VIDEO = 2;
    private static final String BITMAP_STORAGE_KEY = "viewbitmap";
    private static final String IMAGEVIEW_VISIBILITY_STORAGE_KEY = "imageviewvisibility";
    private ImageView mImageView;
    private Bitmap mImageBitmap;

    private static final String VIDEO_STORAGE_KEY = "viewvideo";
    private static final String VIDEOVIEW_VISIBILITY_STORAGE_KEY = "videoviewvisibility";
    private VideoView mVideoView;
    private Uri mVideoUri;
    private File fileVideo;

    private String mCurrentPhotoPath;
    String videoPath;
    private int position = 0;
    int targetH;
    int targetW;

    private static final String JPEG_FILE_PREFIX = "IMG_";
    private static final String JPEG_FILE_SUFFIX = ".jpg";

    private PhotoStorageDirFactory mPhotoStorageDirFactory = null;


    /* Photo album for this application */
    private String getAlbumName() {
        return getString(R.string.album_name);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_make_photo_video);

        mImageView = (ImageView) findViewById(R.id.taken_photo);
        mVideoView = (VideoView) findViewById(R.id.video_view);
        mImageView.setVisibility(View.VISIBLE);
        mVideoView.setVisibility(View.INVISIBLE);
        mImageView.setSaveEnabled(true);

        Button photoBtn = (Button) findViewById(R.id.click);
        setBtnListenerOrDisable(photoBtn, mTakePicOnClickListener, MediaStore.ACTION_IMAGE_CAPTURE);

        Button videoBtn = (Button) findViewById(R.id.record_video);
        setBtnListenerOrDisable(videoBtn, mTakeVidOnClickListener, MediaStore.ACTION_VIDEO_CAPTURE);

        mPhotoStorageDirFactory = new BasePhotoDirFactory();

        // Shows the up carat near app icon in ActionBar
        getSupportActionBar().setDisplayUseLogoEnabled(false);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    }


    public void viewCollection(View v){

        // finishes/restarts the activity so the unsaved video does not corrupt
        Intent intent = getIntent();
        finish();
        startActivity(intent);

        // goes to Cute Collection activity
        Intent i = new Intent(this, CuteCollection.class);
        startActivity(i);
    }

    private File getAlbumDir() {
        File storageDir = null;

        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {

            storageDir = mPhotoStorageDirFactory.getAlbumStorageDir(getAlbumName());

            if (storageDir != null) {
                if (! storageDir.mkdirs()) {
                    if (! storageDir.exists()){
                        Log.d("Camera", "failed to create directory");
                        return null;
                    }
                }
            }

        } else {
            Log.v(getString(R.string.app_name), "External storage is not mounted READ/WRITE.");
        }

        return storageDir;
    }

    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = JPEG_FILE_PREFIX + timeStamp + "_";
        File albumF = getAlbumDir();
        File imageF = File.createTempFile(imageFileName, JPEG_FILE_SUFFIX, albumF);
        return imageF;
    }

    private File setUpPhotoFile() throws IOException {

        File f = createImageFile();
        mCurrentPhotoPath = f.getAbsolutePath();

        return f;
    }


    private void setPic() {

        mImageView.setVisibility(View.VISIBLE);
        mVideoView.setVisibility(View.INVISIBLE);

        /* There isn't enough memory to open up more than a couple camera photos */
        /* So pre-scale the target bitmap into which the file is decoded */

        /* Get the size of the image */
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inJustDecodeBounds = true;

        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
            targetH = 570;
            targetW = 960;
        } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
            targetH = 960;
            targetW = 570;
        }

        BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
        int photoW = bmOptions.outWidth;
        int photoH = bmOptions.outHeight;

        /* Figure out which way needs to be reduced less */
        int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

        /* Set bitmap options to scale the image decode target */
        bmOptions.inJustDecodeBounds = false;
        bmOptions.inPreferredConfig = Bitmap.Config.RGB_565;
        bmOptions.inSampleSize = scaleFactor;
        bmOptions.inBitmap = mImageBitmap;
        bmOptions.inPurgeable = true;


        /* Decode the JPEG file into a Bitmap */
        mImageBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);


        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            mImageBitmap = rotateBitmap(mImageBitmap, 90);
        }

        savePhoto(mImageBitmap);

        /* Associate the Bitmap to the ImageView, make sure the VideoView
         * is cleared to replace with ImageView */
        mImageView.setImageBitmap(mImageBitmap);
        mVideoUri = null;
    }

    // save your photo to SD card
    private void savePhoto(final Bitmap bitmapPhoto){
        // set OnClickListener to save the photo
        mImageView.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                boolean success = false;

                File photoDir = new File(Environment.getExternalStoragePublicDirectory
                        (Environment.DIRECTORY_PICTURES) + "/Cute Photos");
                photoDir.mkdirs();
                Random generator = new Random();
                int n = 10000;
                n = generator.nextInt(n);
                String photoName = "Photo"+ n +".jpg";
                File filePhoto = new File (photoDir, photoName);

                try {
                    FileOutputStream out = new FileOutputStream(filePhoto);
                    bitmapPhoto.compress(Bitmap.CompressFormat.JPEG, 100, out);
                    out.flush();
                    out.close();
                    success = true;
                } catch (Exception e) {
                    e.printStackTrace();
                }

                if (success) {
                    Toast toast = Toast.makeText(getApplicationContext(), "Cute photo saved!",
                            Toast.LENGTH_LONG);
                    LinearLayout toastLayout = (LinearLayout) toast.getView();
                    toastLayout.setBackgroundColor(getResources().getColor(R.color.toast_color));
                    TextView toastTV = (TextView) toastLayout.getChildAt(0);
                    toastTV.setTextSize(30);
                    toast.setGravity(Gravity.CENTER_VERTICAL, 0, 80);
                    toast.show();
                } else {
                    Toast.makeText(getApplicationContext(),
                            "Error during image saving", Toast.LENGTH_SHORT).show();
                }

            }
        });
    }


    // save your video to SD card
    protected void saveVideo(final Uri uriVideo){

        // click the video to save it
        mVideoView.setOnTouchListener(new View.OnTouchListener() {

            public boolean onTouch(View v, MotionEvent event) {

                boolean success = false;

                if(event.getAction() == MotionEvent.ACTION_UP) {

                    try {
                        // make the directory
                        File vidDir = new File(android.os.Environment.getExternalStoragePublicDirectory
                                (Environment.DIRECTORY_MOVIES) + File.separator + "Cute Videos");
                        vidDir.mkdirs();

                        // create unique identifier
                        Random generator = new Random();
                        int n = 100;
                        n = generator.nextInt(n);
                        // create file name
                        String videoName = "Video" + n + ".mp4";

                        fileVideo = new File(vidDir.getAbsolutePath(), videoName);

                        videoPath = fileVideo.getAbsolutePath();

                        Log.d("TAG", "Value of videoPath:" + videoPath);

                        fileVideo.setWritable(true, false);

                        OutputStream out = new FileOutputStream(fileVideo);
                        InputStream in = getContentResolver().openInputStream(uriVideo);

                        byte buffer[] = new byte[1024];
                        int length = 0;
                        while ((length = in.read(buffer)) > 0) {
                            out.write(buffer, 0, length);
                        }

                        out.close();
                        in.close();

                        success = true;

                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    if (success) {
                        Toast toast = Toast.makeText(getApplicationContext(), "Cute video saved!",
                                Toast.LENGTH_SHORT);
                        LinearLayout toastLayout = (LinearLayout) toast.getView();
                        toastLayout.setBackgroundColor(getResources().getColor(R.color.toast_color));
                        TextView toastTV = (TextView) toastLayout.getChildAt(0);
                        toastTV.setTextSize(30);
                        toast.setGravity(Gravity.CENTER_VERTICAL, 0, 80);
                        toast.show();
                    } else {
                        Toast.makeText(getApplicationContext(),
                                "Error during video saving", Toast.LENGTH_SHORT).show();
                    }
                }

                return true;
            }
        });
    }


    public Bitmap rotateBitmap(Bitmap source, int angle)
    {
        Matrix matrix = new Matrix();
        matrix.set(matrix);
        matrix.setRotate(angle);
        return Bitmap.createBitmap(source, 0, 0, source.getWidth(),
                source.getHeight(), matrix, false);
    }

    private void galleryAddPic() {
        Intent mediaScanIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
        File f = new File(mCurrentPhotoPath);
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
    }

    private void dispatchTakePictureIntent(int actionCode) {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

        switch(actionCode) {
            case ACTION_TAKE_PHOTO:
                File f;

                try {
                    f = setUpPhotoFile();
                    Log.d("TAG", "Value of f in picture intent: " + f);
                    mCurrentPhotoPath = f.getAbsolutePath();
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
                } catch (IOException e) {
                    e.printStackTrace();
                    f = null;
                    mCurrentPhotoPath = null;
                }
                break;

            default:
                break;
        } // switch

        startActivityForResult(takePictureIntent, actionCode);
    }

    // Captures video from Android camera component
    protected void dispatchTakeVideoIntent() {
        Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        if (takeVideoIntent.resolveActivity(getPackageManager()) != null) {
            // set the video image quality to high
            takeVideoIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
            startActivityForResult(takeVideoIntent, ACTION_TAKE_VIDEO);
        }
    }

    private void handleCameraPhoto() {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);

        if (mCurrentPhotoPath != null) {
            setPic();
            galleryAddPic();
            mCurrentPhotoPath = null;
        }

    }
    // Post recorded video into VideoView
    private Uri handleCameraVideo(Intent intent) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);

        mVideoUri = intent.getData();
        mVideoView.setVideoURI(mVideoUri);
        mImageBitmap = null;
        mVideoView.setVisibility(View.VISIBLE);
        mImageView.setVisibility(View.INVISIBLE);
        mVideoView.start();
        // saves video to file
        saveVideo(mVideoUri);

        return mVideoUri;

    }

    // click listener for the Android Camera button (not my app's button)
    Button.OnClickListener mTakePicOnClickListener =
            new Button.OnClickListener() {
                @Override
                public void onClick(View v) {
//                    mImageBitmap = null;
                    dispatchTakePictureIntent(ACTION_TAKE_PHOTO);
                    // releases the orientation lock
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
                }
            };
    Button.OnClickListener mTakeVidOnClickListener =
            new Button.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dispatchTakeVideoIntent();
                    // releases the orientation lock
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
                }
            };

    // Intent data is how the photo and video transfer into their views
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case ACTION_TAKE_PHOTO: {
                if (resultCode == RESULT_OK) {
                    handleCameraPhoto();
                }
                break;
            }
            case ACTION_TAKE_VIDEO: {
                if (resultCode == RESULT_OK) {
                    handleCameraVideo(data);
                }
                break;
            }
        }
    }


    // Some lifecycle callbacks so that the image can survive orientation change
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putParcelable(BITMAP_STORAGE_KEY, mImageBitmap);
        outState.putParcelable(VIDEO_STORAGE_KEY, mVideoUri);

        outState.putBoolean(IMAGEVIEW_VISIBILITY_STORAGE_KEY, (mImageBitmap != null) );
        outState.putBoolean(VIDEOVIEW_VISIBILITY_STORAGE_KEY, (mVideoUri != null) );

        outState.putString("FILE_PATH", mCurrentPhotoPath);

        if (mVideoUri != null) {
            // use onSaveInstanceState in order to store the video or photo
            outState.putInt("PositionVideo", mVideoView.getCurrentPosition());
            // playback position for orientation change
            mVideoView.pause();
        }

        // super should be last in this method
        super.onSaveInstanceState(outState);

    }

    // this is called after onCreate (when returning from camera app),
    // so br careful what you put here
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        mCurrentPhotoPath = savedInstanceState.getString("FILE_PATH");

        mVideoUri = savedInstanceState.getParcelable(VIDEO_STORAGE_KEY);
        mVideoView.setVideoURI(mVideoUri);
        mVideoView.setVisibility(
                savedInstanceState.getBoolean(VIDEOVIEW_VISIBILITY_STORAGE_KEY) ?
                        ImageView.VISIBLE : ImageView.INVISIBLE
        );

        if (mVideoUri != null) {
            // for video, restores position it was playing
            position = savedInstanceState.getInt("PositionVideo");
            mVideoView.seekTo(position);
        }

        super.onRestoreInstanceState(savedInstanceState);
    }

    /**
     * Indicates whether the specified action can be used as an intent. This
     * method queries the package manager for installed packages that can
     * respond to an intent with the specified action. If no suitable package is
     * found, this method returns false.
     * http://android-developers.blogspot.com/2009/01/can-i-use-this-intent.html
     *
     * @param context The application's environment.
     * @param action The Intent action to check for availability.
     *
     * @return True if an Intent with the specified action can be sent and
     *         responded to, false otherwise.
     */
    public static boolean isIntentAvailable(Context context, String action) {
        final PackageManager packageManager = context.getPackageManager();
        final Intent intent = new Intent(action);
        List<ResolveInfo> list =
                packageManager.queryIntentActivities(intent,
                        PackageManager.MATCH_DEFAULT_ONLY);
        return list.size() > 0;
    }

    private void setBtnListenerOrDisable(Button btn, Button.OnClickListener onClickListener,
                                                                        String intentName) {
        if (isIntentAvailable(this, intentName)) {
            btn.setOnClickListener(onClickListener);

        } else {
            btn.setClickable(false);
        }
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        // Makes the UP caret go back to the previous fragment MakeCuteFragment
        switch (item.getItemId()) {
            case android.R.id.home:
                android.app.FragmentManager fm= getFragmentManager();
                fm.popBackStack();
                finish();

                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

}
like image 136
Azurespot Avatar answered Feb 06 '26 08:02

Azurespot



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!