[Android] Camera App crashes when run

AI Thread Summary
The discussion revolves around troubleshooting an Android application that crashes upon startup when attempting to access the camera. The developer, familiar with Java but not the Android APIs, initially included camera functions based on the Android developer documentation. However, the app fails to run, displaying a "Permission Denial" error related to camera access. Key issues identified include a typo in the manifest file where the permission for camera access is incorrectly specified as "android.permissions.CAMERA" instead of the correct "android.permission.CAMERA". This oversight leads to a failure in connecting to the camera service, resulting in a runtime exception. The conversation also highlights the importance of checking permissions and suggests using copy-paste for accuracy in manifest strings. Additionally, there are recommendations for using Eclipse to run the application on a physical device, which can provide more useful debugging information compared to the AIDE IDE. The developer plans to correct the permission issue and test the app again in Eclipse to obtain a clearer stack trace for further debugging.
Yoyo_Guru
Messages
32
Reaction score
0
I am working on an android application that will need to take and store pictures. I'm familiar with java but not with the Android APIs. I tried to start by just including the functions for taking and saving an image using the information on the android developers page(Camera | Android Developers) however when I attempt to run the program it says it had to close. Install is successful though. My activity, preview class and manifest.xml are below. I do not want to use an intent because I will be displaying images and buttons over the preview and be adding buttons to interact wiht the camera. I would really appreciate it if anyone could point out where the problem is or anything like that.

Activity:

Code:
import android.hardware.*;
import android.os.*;
import android.app.*;
import android.widget.*;
import android.view.*;
import android.net.*;
import java.io.*;
import android.util.*;
import java.text.*;
import java.util.*;
import android.hardware.Camera.*;
public class ConverterActivity extends Activity 
{
    private Camera mCamera;
    private CameraPreview mPreview;
private PictureCallback mPicture = new PictureCallback() {
private String TAG;
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
// Log.d(TAG, "Error creating media file, check storage permissions: " +
//  e.getMessage());
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
 
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);
        // Create an instance of Camera
        mCamera = Camera.open(this.getBackCamera());
        // Create our Preview view and set it as the content of our activity.
        mPreview = new CameraPreview(this, mCamera);
        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(mPreview);
}
@Override
    protected void onPause()
    {
        super.onPause();
        releaseCamera();              // release the camera immediately on pause event
    }
    private void releaseCamera(){
        if (mCamera != null){
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        }
    }
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
return Uri.fromFile(getOutputMediaFile(type));
}
/** Create a File for saving an image or video */
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;
}
public int getBackCamera()
{
int numCameras = Camera.getNumberOfCameras();
CameraInfo cInfo = new CameraInfo();
for (int i = 0; i < numCameras; i++)
{
Camera.getCameraInfo(i, cInfo);
if (cInfo.facing == CameraInfo.CAMERA_FACING_BACK)
{
return i;
}
}
return -1;
}
}



Camera Preview:

Code:
import android.view.*;
import android.hardware.Camera.*;
import android.hardware.*; 
import android.content.*;
import java.io.*;  
 
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;
 
    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;
 
        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
 
    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }
 
    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }
 
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.
 
        if (mHolder.getSurface() == null){
          // preview surface does not exist
          return;
        }
 
        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
          // ignore: tried to stop a non-existent preview
        }
 
        // set preview size and make any resize, rotate or
        // reformatting changes here
 
        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();
 
        } catch (Exception e){
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }
}



Manifest.xml

PHP:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="[PLAIN]http://schemas.android.com/apk/res/android"[/PLAIN] 
          package="your.Converter"
          android:versionCode="1"
          android:versionName="1.0" >
     <uses-sdk android:minSdkVersion="10" />
   <uses-permission android:name="android.permissions.CAMERA" />
   <uses-feature android:name="android.hardware.camera" />
   <uses-feature android:name="android.hardware.camera.autofocus" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
   <application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
     <activity
      android:name=".ConverterActivity"
      android:label="@string/app_name"
      android:screenOrientation="landscape">
                <intent-filter>
         <action android:name="android.intent.action.MAIN" />
         <category android:name="android.intent.category.LAUNCHER" />
       </intent-filter>
     </activity>
   </application>
   </manifest>
 
Last edited by a moderator:
Technology news on Phys.org
You haven't posted a stack trace, so I'm going to guess that you're having a problem on start-up. The Eclipse plugin (at least for me) doesn't seem to display a useful stack trace in that case - it's all Android internals. However, if you tell it to resume execution (there's a button in the Eclipse toolbar, from memory) your program finishes crashing, and the useful bit of the stack trace appears in the logcat window. You may need to scroll up a bit.
 
Ibix said:
You haven't posted a stack trace, so I'm going to guess that you're having a problem on start-up. The Eclipse plugin (at least for me) doesn't seem to display a useful stack trace in that case - it's all Android internals. However, if you tell it to resume execution (there's a button in the Eclipse toolbar, from memory) your program finishes crashing, and the useful bit of the stack trace appears in the logcat window. You may need to scroll up a bit.

Actually I was using AIDE, and ide on the android, it shows logcat but does not have a way of exporting it. I will run app in eclipse when I get home tonight and add stack trace. I was testing on my phone because I did not know how the virtual device in eclipse would deal with the camera.
 
Ibix said:
You haven't posted a stack trace, so I'm going to guess that you're having a problem on start-up. The Eclipse plugin (at least for me) doesn't seem to display a useful stack trace in that case - it's all Android internals. However, if you tell it to resume execution (there's a button in the Eclipse toolbar, from memory) your program finishes crashing, and the useful bit of the stack trace appears in the logcat window. You may need to scroll up a bit.

Here is logcat errors.
Code:
E(  167) Permission Denial: can't use the camera pid=9354, uid=10009  (CameraService)
E( 9354) FATAL EXCEPTION: main  (AndroidRuntime)
E( 9354) java.lang.RuntimeException: Unable to start activity ComponentInfo{your.Converter/your.Converter.ConverterActivity}: java.lang.RuntimeException: Fail to connect to camera service  (AndroidRuntime)
E( 9354) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2049)  (AndroidRuntime)
E( 9354) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2083)  (AndroidRuntime)
E( 9354) at android.app.ActivityThread.access$600(ActivityThread.java:134)  (AndroidRuntime)
E( 9354) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1233)  (AndroidRuntime)
E( 9354) at android.os.Handler.dispatchMessage(Handler.java:99)  (AndroidRuntime)
E( 9354) at android.os.Looper.loop(Looper.java:137)  (AndroidRuntime)
E( 9354) at android.app.ActivityThread.main(ActivityThread.java:4697)  (AndroidRuntime)
E( 9354) at java.lang.reflect.Method.invokeNative(Native Method)  (AndroidRuntime)
E( 9354) at java.lang.reflect.Method.invoke(Method.java:511)  (AndroidRuntime)
E( 9354) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787)  (AndroidRuntime)
E( 9354) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554)  (AndroidRuntime)
E( 9354) at dalvik.system.NativeStart.main(Native Method)  (AndroidRuntime)
E( 9354) Caused by: java.lang.RuntimeException: Fail to connect to camera service  (AndroidRuntime)
E( 9354) at android.hardware.Camera.native_setup(Native Method)  (AndroidRuntime)
E( 9354) at android.hardware.Camera.<init>(Camera.java:317)  (AndroidRuntime)
E( 9354) at android.hardware.Camera.open(Camera.java:274)  (AndroidRuntime)
E( 9354) at your.Converter.ConverterActivity.onCreate(ConverterActivity.java)  (AndroidRuntime)
E( 9354) at android.app.Activity.performCreate(Activity.java:4539)  (AndroidRuntime)
E( 9354) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)  (AndroidRuntime)
E( 9354) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2013)  (AndroidRuntime)
E( 9354) ... 11 more  (AndroidRuntime)
 
Ok, I found the problem. I said in the manifest,
<uses-permission android:name="android.permissions.CAMERA" />
it should say android.permission, not android.permissions.
 
Ah. I did wonder if it was permissions, although I was just guessing because the browser on my Android phone isn't rendering the page properly, ironically enough. I always find those strings a risk because they aren't checked or auto-completed by the IDE. I recommend cut-and-paste where possible.

As a side note, you can deploy to a phone from Eclipse just like the emulator. Turn on USB debugging on the phone, plug in and click run in Eclipse. Works on my phone, anyway.
 
Ibix said:
Ah. I did wonder if it was permissions, although I was just guessing because the browser on my Android phone isn't rendering the page properly, ironically enough. I always find those strings a risk because they aren't checked or auto-completed by the IDE. I recommend cut-and-paste where possible.

As a side note, you can deploy to a phone from Eclipse just like the emulator. Turn on USB debugging on the phone, plug in and click run in Eclipse. Works on my phone, anyway.

Yeah thanks, I had read about that before. Never got around to setting it up though. And I'm away from my desktop a lot, so it's just easier to do it in AIDE and transfer the files to my desktop or dropbox when I work in Eclipse.
 
Back
Top