Kamera Problem

  • 15 Antworten
  • Letztes Antwortdatum
D

Daaaaniel

App-Anbieter (kostenlos)
3
Hallo,

ich entwickle im Moment eine App, die selbstständig Bilder mit der Kamera aufnimmt und speichert.

Ich habe das Problem, dass die App auf meinem Galaxy S2 mit Cyanogenmod (Android 4.2.2) sofort abstürzt, wenn ich auf die Kamera zugreifen möchte.
Auf meinem Note 3 mit Android 4.3 dagegen funktioniert alles problemlos. Deshalb bin ich im Moment etwas ratlos, woran es liegen könnte.


Hier der Programmcode:

Code:
public class TakePictureThread2 implements Runnable {

	private Context mycontext;
	private ServerThread2 serverThread;
	private final Matrix matrix = new Matrix();
	private boolean readyForNewPicture = true;

	
	public TakePictureThread2(Context activity, ServerThread2 serverThread) {
		this.mycontext = activity;
		this.serverThread = serverThread;
		matrix.postRotate(90);
	}

	public void run() {
		while(true){
			do{
				sleep(1000);
			}while(!readyForNewPicture);
			
			takePicture();			
		}
	}
	
	private void takePicture() {
		readyForNewPicture = false;

		final Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
			public void onPictureTaken(byte[] data, Camera c) {
				if (data != null) {
					CameraHelper.camera.startPreview();

					// Bild dekodieren
					//Bitmap bmp = BitmapFactory.decodeByteArray(data, 0,	data.length);
					
					//bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);

					// Datum als Bildname setzen und speichern
					final String imageFileName = "JPEG_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + "_.jpg";
					UtilsSD.saveBitmapToSD(mycontext, BitmapFactory.decodeByteArray(data, 0, data.length), imageFileName);
					
					// Dateinamen an ServerThread übergeben
					serverThread.setPicture(imageFileName);
					
					readyForNewPicture = true;
				}
			}

		};

		// Abfrage nötig, sonst NullPointerException
//		do {
//			System.out.println("Fehler: Kamera nicht gefunden!");
//			sleep(1000);
//		}while (CameraHelper.camera == null);

		// Bild machen
		CameraHelper.camera.autoFocus(new AutoFocusCallback() {

			@Override
			public void onAutoFocus(boolean arg0, Camera arg1) {
				CameraHelper.camera.takePicture(null, null, mPictureCallback);
				System.out.println("new picture taken!");
			}
		});
	}
	
	public void stop(){
		if(CameraHelper.camera != null){
			CameraHelper.camera.stopPreview();
			CameraHelper.camera.release();
		}
	}
	
	private void sleep(int s){
		try {
			Thread.sleep(s);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}




Code:
public class UtilsSD {
	
	final static String SAVE_PATH = Environment.getExternalStorageDirectory() + "/DCIM/Pictures";
	
	static boolean isSDCardPrepared() {
    	String state = android.os.Environment.getExternalStorageState();
	    if (!state.equals(android.os.Environment.MEDIA_MOUNTED)) return false; else return true;
	}

	public static void saveBitmapToSD(Context mycontext, Bitmap bmp, String filename) {
		if (isSDCardPrepared()) {
			File directory = new File(SAVE_PATH);
		    directory.mkdirs();		    
		    
		    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
		    bmp.compress(Bitmap.CompressFormat.JPEG, 100, bytes);

		    File f = new File(SAVE_PATH+File.separator+filename);
		    
		    try {
			    f.createNewFile();
			    
			    FileOutputStream fo = new FileOutputStream(f);
			    fo.write(bytes.toByteArray());
			    fo.flush();
			    fo.close();
			    
		    } catch (Exception ex) {
		    	Log.e("ex saveBitmapToSD", ex+"");
		    }

		    try {
				bytes.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		    
		    bmp.recycle();
		    bmp = null;
		    System.gc();

		} else {
			System.out.println("Saving Bitmap Failed: SDCard not prepared!");		
		}
	}
	public static InputStream loadBitmapFromSD(Context mycontext, String filename) {
		if (isSDCardPrepared()) {
		    
		    File f = new File(SAVE_PATH+File.separator+filename);
		    
		    try {
			    if (f.exists()) return new FileInputStream(f);	    
		    } catch (Exception ex) {
		    	Log.e("ex loadBitmapFromSD", ex+"");
		    }

		} else {
			System.out.println("Loading Bitmap Failed: SDCard not prepared!");
		}
		
		return null;
	}
	
	public static boolean isBitmapExistOnSD(String filename) {
		return new File(SAVE_PATH+File.separator+filename).exists();
	}
	
	public static String getBitmapPath(String filename) {
		return SAVE_PATH+File.separator+filename;
	}
	
	
}



Hier der Fehler aus der Logcat:

05-01 19:54:40.862: E/AndroidRuntime(5029): FATAL EXCEPTION: Thread-222
05-01 19:54:40.862: E/AndroidRuntime(5029): java.lang.RuntimeException: autoFocus failed
05-01 19:54:40.862: E/AndroidRuntime(5029): at android.hardware.Camera.native_autoFocus(Native Method)
05-01 19:54:40.862: E/AndroidRuntime(5029): at android.hardware.Camera.autoFocus(Camera.java:931)
05-01 19:54:40.862: E/AndroidRuntime(5029): at de.daniel17903.mycamera.TakePictureThread2.takePicture(TakePictureThread2.java:70)
05-01 19:54:40.862: E/AndroidRuntime(5029): at de.daniel17903.mycamera.TakePictureThread2.run(TakePictureThread2.java:30)
05-01 19:54:40.862: E/AndroidRuntime(5029): at java.lang.Thread.run(Thread.java:856)




Die App stürzt ab, sobald ich den autofocus verwenden möchte. Wenn ich es ohne autofoucs probiere stürzt es ab, wenn ich das Bild machen möchte. Das Problem liegt anscheinend irgendwie an der Kamera.

Hat jemand eine Idee was ich noch ausprobieren könnte?
 
Zuletzt bearbeitet:
Such mal nach mobilewebcam android auf google code. Macht das und ist open source.

Android Camera ist Horror ... instabil und unterschiedlich auf vielen Geräten.

Gesendet von meinem dL1 mit der Android-Hilfe.de App
 
miha schrieb:
Such mal nach mobilewebcam android auf google code. Macht das und ist open source.

Android Camera ist Horror ... instabil und unterschiedlich auf vielen Geräten.

Gesendet von meinem dL1 mit der Android-Hilfe.de App

Danke, werd ich mal machen :)

Ja, die Camera ist wirklich Horror.
Hab die App bisher auf 3 Geräten getestet. Auf einem funktioniert sie und auf den anderen beiden stürzt sie mit jeweils verschiedenen Fehlern ab, obwohl alle Android 4.x haben^^
 
Den ursprünglichen Fehler konnte ich jetzt beheben, musste dazu nur etwas an im Manifest ändern :)


Allerdings bekomme ich jetzt nach einigen Bildern einen outofmemory error:

05-02 18:25:23.387: E/AndroidRuntime(9547): FATAL EXCEPTION: main
05-02 18:25:23.387: E/AndroidRuntime(9547): java.lang.OutOfMemoryError
05-02 18:25:23.387: E/AndroidRuntime(9547): at java.io.ByteArrayOutputStream.toByteArray(ByteArrayOutputStream.java:122)
05-02 18:25:23.387: E/AndroidRuntime(9547): at de.daniel17903.mycamera.utils.UtilsSD.saveBitmapToSD(UtilsSD.java:40)
05-02 18:25:23.387: E/AndroidRuntime(9547): at de.daniel17903.mycamera.TakePictureThread2$1.onPictureTaken(TakePictureThread2.java:48)
05-02 18:25:23.387: E/AndroidRuntime(9547): at android.hardware.Camera$EventHandler.handleMessage(Camera.java:768)
05-02 18:25:23.387: E/AndroidRuntime(9547): at android.os.Handler.dispatchMessage(Handler.java:99)
05-02 18:25:23.387: E/AndroidRuntime(9547): at android.os.Looper.loop(Looper.java:137)
05-02 18:25:23.387: E/AndroidRuntime(9547): at android.app.ActivityThread.main(ActivityThread.java:5227)
05-02 18:25:23.387: E/AndroidRuntime(9547): at java.lang.reflect.Method.invokeNative(Native Method)
05-02 18:25:23.387: E/AndroidRuntime(9547): at java.lang.reflect.Method.invoke(Method.java:511)
05-02 18:25:23.387: E/AndroidRuntime(9547): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
05-02 18:25:23.387: E/AndroidRuntime(9547): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
05-02 18:25:23.387: E/AndroidRuntime(9547): at dalvik.system.NativeStart.main(Native Method)


Ich verstehe noch nicht so ganz warum dieser Fehler auftritt, der kommt auch nur bei meinem Galaxy S2, auf dem Note 3 stürzt es nicht ab.

Code ist noch der gleiche wie oben. Wegen diesem Fehler habe ich auch das mit dem recyclen des Bitmaps eingebaut, ich hab das Gefühl dass es seitdem länger dauert bis der Fehler kommt.
 
05-02 18:25:23.387: E/AndroidRuntime(9547): java.lang.OutOfMemoryError
Sieht so aus als würdest du dir den Arbeitsspeicher voll laden
 
kosmus schrieb:
05-02 18:25:23.387: E/AndroidRuntime(9547): java.lang.OutOfMemoryError
Sieht so aus als würdest du dir den Arbeitsspeicher voll laden

danke, was outofmemoryerror bedeutet weiss ich^^

mein problem ist, dass ich nicht weiss warum der arbeitsspeicher voll wird, also wo der fehler in meinem code ist
 
könnte jetzt auch völlig falsch sein aber
ByteArrayOutputStream bytes = new ByteArrayOutputStream();

dieser Outputstream wird doch öfter erzeugt, aber nie geschlossen, könnte es daran liegen?

Der ursprüngliche Beitrag von 19:54 Uhr wurde um 19:56 Uhr ergänzt:

ok sry braucht man wohl nicht...
 
kosmus schrieb:
könnte jetzt auch völlig falsch sein aber
ByteArrayOutputStream bytes = new ByteArrayOutputStream();

dieser Outputstream wird doch öfter erzeugt, aber nie geschlossen, könnte es daran liegen?

Der ursprüngliche Beitrag von 19:54 Uhr wurde um 19:56 Uhr ergänzt:

ok sry braucht man wohl nicht...

Ah, danke. Das war auf jeden Fall ein Fehler, hab den mal behoben und den Code oben geupdatet. :)

Daran hätte es liegen können, stürzt aber leider immernoch mit dem gleichen Fehler ab :/
Vllt ist irgendwo noch ein ähnlicher Fehler
 
Die VM deiner App ist zu klein, bzw nicht schnell genug mit gewachsen.

Meistens hilft es, den Garbage Collector vorher selber anzustossen.

Code:
System.gc();
 
Code:
		    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
		    bmp.compress(Bitmap.CompressFormat.JPEG, 100, bytes);

		    File f = new File(SAVE_PATH+File.separator+filename);
		    
		    try {
			    f.createNewFile();
			    
			    FileOutputStream fo = new FileOutputStream(f);
			    fo.write(bytes.toByteArray());
			    fo.flush();
			    fo.close();
			    
		    } catch (Exception ex) {
		    	Log.e("ex saveBitmapToSD", ex+"");
		    }

		    try {
				bytes.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		    
		    bmp.recycle();
		    bmp = null;
		    System.gc();
macht er ja... bei der Fehlermeldung sieht es so aus, als würde es an folgender Zeile scheitern:
fo.write(bytes.toByteArray());

aber ich glaube, ich bin zu unerfahren um dafür eine lösung zu finden...
 
kosmus schrieb:
Code:
		    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
		    bmp.compress(Bitmap.CompressFormat.JPEG, 100, bytes);

		    File f = new File(SAVE_PATH+File.separator+filename);
		    
		    try {
			    f.createNewFile();
			    
			    FileOutputStream fo = new FileOutputStream(f);
			    fo.write(bytes.toByteArray());
			    fo.flush();
			    fo.close();
			    
		    } catch (Exception ex) {
		    	Log.e("ex saveBitmapToSD", ex+"");
		    }

		    try {
				bytes.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		    
		    bmp.recycle();
		    bmp = null;
		    System.gc();
macht er ja... bei der Fehlermeldung sieht es so aus, als würde es an folgender Zeile scheitern:
fo.write(bytes.toByteArray());

aber ich glaube, ich bin zu unerfahren um dafür eine lösung zu finden...

ja, auf die idee mit system.gc bin ich auch schon gekommen, bringt aber leider nix...

Das heisst dass es gerade an der Zeile abgesürzt ist. Sieht aber leider so aus als wäre der Fehler nicht in der Zeile.
Theoretisch kann es denke ich in jeder Zeile abstürzen, in der neuer Arbeitsspeicher belegt wird. Der Arbeitsspeicher wird ja wegen irgendeinem Fehler langsam immer voller. Die Zeile, die ihn dann zum überlaufen bringt wirft den Fehler.

Ich verstehe aber überhaupt nicht, warum es auf dem Note 3 dann nicht abstürzt. Das hat vllt mehr Arbeitsspeicher, aber nach längerer Zeit müsste es dann theoretisch auch da abstürzen was es aber nicht tut :/
 
Zuletzt bearbeitet:
naja es kann viele gründe haben, z. B. das der Garbage Collector auf dem Note 3 schneller arbeitet. Hattest du das System.gc() von Anfang an drinne? Ich habe mal gelesen, dass das nicht wirklich etwas bringt, da die VM den Garbage Collector sowieso aufrufen würde, bevor sie eine Out of Memory Exception schmeißt.
 
Das meinte ich vorhin, du muss den Speicher aufräumen, bevor du die Bilder bearbeitet.
 
Also ich meine auch mal gelernt zu haben dass der garbage collector normalerweise automatisch ausgeführt wird, das aber manchmal nicht richtig funktioniert.
nein ich hatte das System.gc nicht von Anfang an drin, macht bei dem Fehler garkein unterschied ob mit oder ohne.
 
Das ist so nicht ganz richtig, der funktioniert schon richtig. Fast immer liegt es an der Implementierung des Programmierer. Der GC räumt nur den Code weg, der nicht mehr benötigt wird, und nicht mehr referenziert wird.

Der ursprüngliche Beitrag von 21:14 Uhr wurde um 21:19 Uhr ergänzt:

Das ist so nicht ganz richtig, der funktioniert schon richtig. Fast immer liegt es an der Implementierung des Programmierer. Der GC räumt nur den Code weg, der nicht mehr benötigt wird, und nicht mehr referenziert wird.


Aufgeben gilt nicht, da muss du jetzt durch.
 
markus.tullius schrieb:
Das ist so nicht ganz richtig, der funktioniert schon richtig. Fast immer liegt es an der Implementierung des Programmierer. Der GC räumt nur den Code weg, der nicht mehr benötigt wird, und nicht mehr referenziert wird.

Der ursprüngliche Beitrag von 21:14 Uhr wurde um 21:19 Uhr ergänzt:

Das ist so nicht ganz richtig, der funktioniert schon richtig. Fast immer liegt es an der Implementierung des Programmierer. Der GC räumt nur den Code weg, der nicht mehr benötigt wird, und nicht mehr referenziert wird.


Aufgeben gilt nicht, da muss du jetzt durch.


ja gut, dann hilf mir mal^^
 
Zurück
Oben Unten