0

I'd like to create an application to record a video or a picture, process it and then display it. Following the instructions of official guide of How to use camera, I just invoke existing applications for recording videos and pictures. There are two buttons to switch the main activity to video capture or picture capture. Most of the code is copied from the guide (features and permissions have been added). However, it doesn't work. The code is tested on Samsung galaxy 3 Mini, Android 4.1.2.

1, When taking a picture and press "save", it shows "Unfortunately ..." and then quits. The error is in onActivityResult(int requestCode, int resultCode, Intent data), data seems to be null;

2, When taking a video, I can open the camera view but there is a dialog "Failed to record".

3, I deleted onActivityResult function and tested again, I could take photos but cannot store it into SD card; I could take videos but I cannot return to my application activity.

Most code is from above mentioned guide, and I just added two buttons. Any suggestions will be helpful, thanks!

public class MainActivity extends Activity {

private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;

private Uri fileUri;
private Button bPic;
private Button bVideo;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    bPic = (Button) findViewById(R.id.picture);
    bPic.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name
            startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);    
        }
        
    });
    
    bVideo = (Button) findViewById(R.id.video);
    bVideo.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
            fileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the video file name
            intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
            startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);    
        }
        
    });
    
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            // Image captured and saved to fileUri specified in the Intent
            Toast.makeText(this, "Image saved to:\n" +
                     data.getData(), Toast.LENGTH_LONG).show();
        } else if (resultCode == RESULT_CANCELED) {
            // User cancelled the image capture
        } else {
            // Image capture failed, advise user
        }
    }

    if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            // Video captured and saved to fileUri specified in the Intent
            Toast.makeText(this, "Video saved to:\n" +
                     data.getData(), Toast.LENGTH_LONG).show();
        } else if (resultCode == RESULT_CANCELED) {
            // User cancelled the video capture
        } else {
            // Video capture failed, advise user
        }
    }
}

/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
    return Uri.fromFile(getOutputMediaFile(type));
}

private static File getOutputMediaFile(int type){
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
              Environment.DIRECTORY_PICTURES), "MyCameraApp");
    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            Log.d("MyCameraApp", "failed to create directory");
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE){
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "IMG_"+ timeStamp + ".jpg");
    } else if(type == MEDIA_TYPE_VIDEO) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "VID_"+ timeStamp + ".mp4");
    } else {
        return null;
    }

    return mediaFile;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}
}

The manifest is shown below:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mycameratest"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="15"
    android:targetSdkVersion="16" />

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

Someone says that I need , so I added but it still has problems.

Update 03/17: I use another phone, Lenovo, Android 4.0.3, and the video record function is correct. However, when taking a photo and press "save", still quit and display "Unfortunately ...".

Update 03/17: The error is in Toast.makeText(this, "Image saved to:\n"+data.getData(), Toast.LENGTH_LONG).show() and it seems that data is null here. It is quite weird because data has been put into the intent. However, I just make a toast of "Image has been saved" instead of the original one and it works correctly now.

Community
  • 1
  • 1
Sentimental
  • 187
  • 2
  • 13

1 Answers1

0

As Gabe mentioned in the comments, adding

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

to your AndroidManifest.xml should remedy your problem.

As for the crash when you are taking a picture, it seems that the image exists in the file location you specified in the Intent See Android Camera : data intent returns null for a more detailed explanation.

Community
  • 1
  • 1
puj
  • 770
  • 5
  • 9
  • Thanks for your help! But I still cannot take photos; also I cannot switch from video view to my activity view. – Sentimental Mar 16 '15 at 21:36