Camera Intent not returning to calling Activity
Asked Answered
A

3

8

I have read a lot of questions regarding this problem. Some are similar to what I am experiencing; I have tried the answers with no success. The code works on a HTC Android 4.2 and doesn't work on a Nexus 7 Android 4.4. I have modified the storage directory to work on android 4.4, so this isn't the problem.

The camera intent never returns if I use

takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));

and does return if I use

takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoFile);

but it doesn't save the file.

Here is the full code. Call the intent

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(manager) != null)
{
    try
    {
        final File photoFile = createImageFile();

        if (photoFile != null)
        {
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
            //takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoFile);
            startActivityForResult(takePictureIntent, 1);
        }
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}

The file name

private File createImageFile() throws IOException
{
    if (mStorageDirectory == null)
    {
        createInitialStorageDirectory();
        setupFolders();
        mScrollList.notifyDataSetInvalidated();
    }

    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "slide_" + timeStamp;
    File storageDir = new File(mStorageDirectory);
    File image = File.createTempFile(imageFileName, ".jpg", storageDir);
//        image.setWritable(true, false);

    // Save a path for use with ACTION_VIEW intents
    mCurrentPhotoPath = image.getAbsolutePath();
    return image;
}

The callback function

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 1 && resultCode == -1)
    {

    }
}

The root directory plus the save directory

static String mBasePath = "/slides/";

private String getRootDirectory()
{
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state))
    {
        if (Build.VERSION.SDK_INT >= 19)
            return mView.getContext().getFilesDir() + mBasePath;
        else
            return Environment.getExternalStorageDirectory() + "/Android/data/com.hdms.manager" + mBasePath;
        //return Environment.getExternalStorageDirectory() + mBasePath;
    }

    return mBasePath;
}

Any thoughts would be appreciated.

Alkylation answered 1/7, 2014 at 6:46 Comment(0)
A
6

So I have found a solution to my problem. If a file doesn't exist then the Camera Activity will not return. I guess the reason that it doesn't work on 4.4 is the change to the files system. I am not saving the image to the media gallery and loading the file back into my apps directory. The media file is then deleted. The reason that I don't leave it in the media directory, is when the app is deleted so will the images be deleted.

Here is the new code. First the intent call

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(manager) != null)
{
    ContentValues values = new ContentValues();
    values.put(MediaStore.Images.Media.TITLE, "New Picture");
    values.put(MediaStore.Images.Media.DESCRIPTION,"From your Camera");
    Uri mImageUri = App.mApplication.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

    mCurrentPhotoPath = mImageUri.getPath();

    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
    startActivityForResult(takePictureIntent, 1);
}

Then the callback.

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 1 && resultCode == -1)
    {
        if (data != null)
            mCurrentPhotoPath = String.valueOf(data.getData());

        String[] filePathColumn = {MediaStore.Images.Media.DATA};

        Cursor cursor = App.mApplication.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, filePathColumn, null, null, null);
        if (cursor == null)
            return;
        // find the file in the media area
        cursor.moveToLast();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String filePath = cursor.getString(columnIndex);
        File source  = new File(filePath);
        cursor.close();
        // create the destination file
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "slide_" + timeStamp;
        File destination = new File(mStorageDirectory, imageFileName + ".jpg");

        // copy the data
        if (source.exists())
        {
            try
            {
                FileChannel src = new FileInputStream(source).getChannel();
                FileChannel dst = new FileOutputStream(destination).getChannel();
                dst.transferFrom(src, 0, src.size());
                src.close();
                dst.close();

                source.delete();
            }
            catch (FileNotFoundException e)
            {
                e.printStackTrace();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
}
Alkylation answered 2/7, 2014 at 4:40 Comment(0)
G
7

In my case, it did not return because the output file was inside a folder which I have not created yet.

If it is the case for someone else, do this before starting anintent:

file.getParentFile().mkdirs();
Grogshop answered 15/10, 2014 at 15:59 Comment(1)
Isn't it an android framework bug that in android console there is no IOException (e.g. NoSuchFileOrDirecrtoy) or a log trace to inform us about the reason why the activity is stuck? how are we suppose to understand what happend (apart from opening stackoverflow...)Hustler
A
6

So I have found a solution to my problem. If a file doesn't exist then the Camera Activity will not return. I guess the reason that it doesn't work on 4.4 is the change to the files system. I am not saving the image to the media gallery and loading the file back into my apps directory. The media file is then deleted. The reason that I don't leave it in the media directory, is when the app is deleted so will the images be deleted.

Here is the new code. First the intent call

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(manager) != null)
{
    ContentValues values = new ContentValues();
    values.put(MediaStore.Images.Media.TITLE, "New Picture");
    values.put(MediaStore.Images.Media.DESCRIPTION,"From your Camera");
    Uri mImageUri = App.mApplication.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

    mCurrentPhotoPath = mImageUri.getPath();

    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
    startActivityForResult(takePictureIntent, 1);
}

Then the callback.

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 1 && resultCode == -1)
    {
        if (data != null)
            mCurrentPhotoPath = String.valueOf(data.getData());

        String[] filePathColumn = {MediaStore.Images.Media.DATA};

        Cursor cursor = App.mApplication.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, filePathColumn, null, null, null);
        if (cursor == null)
            return;
        // find the file in the media area
        cursor.moveToLast();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String filePath = cursor.getString(columnIndex);
        File source  = new File(filePath);
        cursor.close();
        // create the destination file
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "slide_" + timeStamp;
        File destination = new File(mStorageDirectory, imageFileName + ".jpg");

        // copy the data
        if (source.exists())
        {
            try
            {
                FileChannel src = new FileInputStream(source).getChannel();
                FileChannel dst = new FileOutputStream(destination).getChannel();
                dst.transferFrom(src, 0, src.size());
                src.close();
                dst.close();

                source.delete();
            }
            catch (FileNotFoundException e)
            {
                e.printStackTrace();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
}
Alkylation answered 2/7, 2014 at 4:40 Comment(0)
A
0

In our scenario our app is able to launch the camera app either via a 'button' click or an 'imageview' click. When using the button route the camera app correctly returned to the calling Activity as expected, however when tapping the imageview the results were inconsistent - sometimes it would return and sometimes the back button had to be tapped several times.

Turns out the solution was my oversight: I was not removing the event handler for the imageview in the OnPause method - once I did then it worked perfectly.

Arminius answered 26/7, 2018 at 18:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.