views:

835

answers:

5

Man, I am still not able to save a picture when I send an intent asking for a photo to be taken. Here's what I am doing:

  1. Make a URI representing the pathname

    android.content.Context c = getApplicationContext();

    String fname = c.getFilesDir().getAbsolutePath()+"/parked.jpg";

    java.io.File file = new java.io.File( fname );

    Uri fileUri = Uri.fromFile(file);

  2. Create the Intent (don't forget the pkg name!) and start the activity

    private static int TAKE_PICTURE = 22;

    Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE );

    intent.putExtra("com.droidstogo.boom1." + MediaStore.EXTRA_OUTPUT, fileUri); startActivityForResult( intent, TAKE_PICTURE );

  3. The camera activity starts, and I can take a picture, and approve it. My onActivityResult() then gets called. But my file doesn't get written. The URI is: file:///data/data/com.droidstogo.boom1/files/parked.jpg

  4. I can create thumbnail OK (by not putting the extra into the Intent), and can write that file OK, and later read it back).

Can anyone see what simple mistake I am making? Nothing obvious shows up in the logcat - the camera is clearly taking the picture. Thanks,

Peter

A: 

I should mention that I have the appropriate permissions set in the AndroidManifest.xml file:

    <uses-permission android:name="android.permission.READ_OWNER_DATA" />
    <uses-permission android:name="android.permission.WRITE_OWNER_DATA" />

    <uses-permission android:name="android.permission.CAMERA" />

    <uses-feature android:name="android.hardware.camera" />
    <uses-library android:name="com.google.android.maps" />



</application>

Any ideas? Any ideas on things to try, to get more info about the problem?

Peter vdL
It's probably a good idea to put this in an edit in your orignial question so people will always see it together with your question
borisCallens
+1  A: 

Perhaps this question can help.

kgiannakakis
+1  A: 

Is it because you've added an extra dot:

 intent.putExtra("com.droidstogo.boom1."

Instead of:

 intent.putExtra("com.droidstogo.boom1"
stealthcopter
+1  A: 

Your problem might be with the directory you're trying to store the file in. To save files to the SD card you don't need any special permissions, but the way you get the folder reference is different to how you've done it. It also depends on whether you want to save the image in a way that can be retrieved by the MediaStore (i.e. things like the gallery or albums application, or any other app that relies on those to find images) or not. Assuming you want it to be listed in the MediaStore, here's the code to do that:

ContentValues newImage = new ContentValues(2);
newImage.put(Media.DISPLAY_NAME, "whatever name you want shown");
newImage.put(Media.MIME_TYPE, "image/png");

Uri uri = contentResolver.insert(Media.EXTERNAL_CONTENT_URI, newImage);

try {
    Bitmap bitmap = //get your bitmap from the Camera, however that's done  
    OutputStream out = contentResolver.openOutputStream(uri);
    boolean success = bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
    out.close();
    if (success){
        Log.d("Image Writer", "Image written successfully.");                   
    } else {
        Log.d("Image Writer", "Image write failed, but without an explanation.");
    }

} catch (Exception e){
    Log.d("Image Writer", "Problem with the image. Stacktrace: ", e);
}

On my emulator running v1.5, that's successfully saves a bitmap onto the SD card in the DCIM/Camera folder with its file name being current time. (The time is saved in milliseconds since 1st Jan 1970, also known as the "Epoch" for some reason.)

Steve H
Just to nitpick... to save files to the SDCard you DO have to have permissions. I think this was changed in api level 4.
fiXedd
@fiXedd: Just to nitpick in return :P Turns out you're right that they introduced the requirement to have the write_external_storage permission to write to the SD card. On v1.5, it worked fine without, but on v2.1 it required the permission. However, to write to the Media Store, on both 2.1 and 1.5 no permissions appeared to be required.
Steve H
+1  A: 
  1. As Steve H said you can't just use file:///data/data/com.droidstogo.boom1/files/parked.jpg for that. It's your application private directory and camera can't write there. You can use some SD card file for example - it's available for all.

  2. As stealthcopter said, intent extra is just MediaStore.EXTRA_OUTPUT without your package name.

  3. Not an issue just FYI. I guess none of the permissions you specified are actually required for this operation.

Here's my code sample:

final int REQUEST_FROM_CAMERA=1;

private File getTempFile()
{
    //it will return /sdcard/image.tmp
    return new File(Environment.getExternalStorageDirectory(),  "image.tmp");
}

private void getPhotoClick()
{
  Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(getTempFile()));
  startActivityForResult(intent, REQUEST_FROM_CAMERA);
}


protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if (requestCode == REQUEST_FROM_CAMERA && resultCode == RESULT_OK) {
    InputStream is=null;

    File file=getTempFile();
    try {
        is=new FileInputStream(file);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

    //On HTC Hero the requested file will not be created. Because HTC Hero has custom camera
    //app implementation and it works another way. It doesn't write to a file but instead
    //it writes to media gallery and returns uri in intent. More info can be found here:
    //http://stackoverflow.com/questions/1910608/android-actionimagecapture-intent
    //http://code.google.com/p/android/issues/detail?id=1480
    //So here's the workaround:
    if(is==null){
        try {
            Uri u = data.getData();
            is=getContentResolver().openInputStream(u);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    //Now "is" stream contains the required photo, you can process it
    DoSomeProcessing(is);

    //don't forget to remove the temp file when it's not required. 
  }

}
Fedor