Brauche Hilfe beim Programmieren - Video mit MediaRecorder aufnehmen

  • Antworten:14
Sam Browder
  • Forum-Beiträge: 236

28.12.2013, 20:41:03 via Website

Hallo!
Ich versuche eine kleine App mit Videoaufnahmefunktion zu schreiben, bekomme aber immer einen Absturz und eine IOException. Ich weiss mittlerweile einfach nicht weiter, und weiss auch nicht, was ich da jetzt falsch mache. Villeicht könnt Ihr mir ja weiterhelfen?
Hier ist mein Code:
Manifest Berechtigungen
1<uses-permission android:name="android.permission.CAMERA" />
2 <uses-permission
3 android:name="android.permission.FLASHLIGHT"
4 android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
5 android:protectionLevel="normal" />
6 <uses-permission android:name="android.hardware.camera.autofocus" />
7 <uses-permission android:name="android.hardware.camera" />
8 <uses-permission android:name="android.hardware.camera.flash" />
9 <uses-permission android:name="android.hardware.Camera.setParameters" />
10 <uses-permission android:name="android.permission.WRITE_SETTINGS" />
11 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
12 <uses-permission android:name="android.permission.RECORD_AUDIO"/>
13 <uses-permission android:name="android.permission.RECORD_VIDEO"/>

Code für den MediaRecorder und den SurfaceHolder
1surface = (SurfaceView) findViewById(R.id.surfaceView1);
2 SurfaceHolder holder = surface.getHolder();
3 holder.addCallback(this);
4 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
5 holder.setSizeFromLayout();
6 }
7 private void initMediaRecorder() {
8 isRecording = false;
9 recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
10 recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
11 CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
12 recorder.setProfile(profile);
13 File dir = new File(Environment.getExternalStorageDirectory(),
14 this.getClass().getPackage().getName());
15 dir.mkdirs();
16 videofile = new File(dir.getAbsolutePath(), new SimpleDateFormat(
17 "'IMG_'yyyyMMddHHmmss'.mp4'").format(new Date()));
18 recorder.setOutputFile(videofile.getAbsolutePath());
19 }
20 public void recStart(final View View) {
21 if (isRecording) {
22 recorder.stop();
23 initMediaRecorder();
24 prepareMediaRecorder();
25 } else {
26 recorder.start();
27 isRecording = true;
28 }
29 }
30 private void prepareMediaRecorder() {
31 recorder.setPreviewDisplay(holder.getSurface());
32 try {
33 recorder.prepare();
34 } catch (IllegalStateException e) {
35 e.printStackTrace();
36 } catch (IOException e) {
37 e.printStackTrace();
38 }
39 }

Hier die Fehlermeldungen
112-28 20:25:06.314: E/AndroidRuntime(30563): FATAL EXCEPTION: main
212-28 20:25:06.314: E/AndroidRuntime(30563): java.lang.IllegalStateException: Could not execute method of the activity
312-28 20:25:06.314: E/AndroidRuntime(30563): at android.view.View$1.onClick(View.java:3600)
412-28 20:25:06.314: E/AndroidRuntime(30563): at android.view.View.performClick(View.java:4106)
512-28 20:25:06.314: E/AndroidRuntime(30563): at android.view.View$PerformClick.run(View.java:17052)
612-28 20:25:06.314: E/AndroidRuntime(30563): at android.os.Handler.handleCallback(Handler.java:615)
712-28 20:25:06.314: E/AndroidRuntime(30563): at android.os.Handler.dispatchMessage(Handler.java:92)
812-28 20:25:06.314: E/AndroidRuntime(30563): at android.os.Looper.loop(Looper.java:137)
912-28 20:25:06.314: E/AndroidRuntime(30563): at android.app.ActivityThread.main(ActivityThread.java:5118)
1012-28 20:25:06.314: E/AndroidRuntime(30563): at java.lang.reflect.Method.invokeNative(Native Method)
1112-28 20:25:06.314: E/AndroidRuntime(30563): at java.lang.reflect.Method.invoke(Method.java:511)
1212-28 20:25:06.314: E/AndroidRuntime(30563): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
1312-28 20:25:06.314: E/AndroidRuntime(30563): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
1412-28 20:25:06.314: E/AndroidRuntime(30563): at dalvik.system.NativeStart.main(Native Method)
1512-28 20:25:06.314: E/AndroidRuntime(30563): Caused by: java.lang.reflect.InvocationTargetException
1612-28 20:25:06.314: E/AndroidRuntime(30563): at java.lang.reflect.Method.invokeNative(Native Method)
1712-28 20:25:06.314: E/AndroidRuntime(30563): at java.lang.reflect.Method.invoke(Method.java:511)
1812-28 20:25:06.314: E/AndroidRuntime(30563): at android.view.View$1.onClick(View.java:3595)
1912-28 20:25:06.314: E/AndroidRuntime(30563): ... 11 more
2012-28 20:25:06.314: E/AndroidRuntime(30563): Caused by: java.lang.IllegalStateException
2112-28 20:25:06.314: E/AndroidRuntime(30563): at android.media.MediaRecorder.start(Native Method)
2212-28 20:25:06.314: E/AndroidRuntime(30563): at de.aleks.camera.MainActivity.recStart(MainActivity.java:247)
2312-28 20:25:06.314: E/AndroidRuntime(30563): ... 14 more

Ich wäre für jede Hilfe sehr Dankbar!
MfG
Sam

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

28.12.2013, 23:31:10 via Website

Der Fehler ligt bei :
Caused by: java.lang.IllegalStateException at de.aleks.camera.MainActivity.recStart(MainActivity.java:247)

Bitte Lerne LogCat richtig auszuwerten..
PS: Wo ist deine Zeile 247?
Poste mal deinen ganzen Code.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Sam Browder
  • Forum-Beiträge: 236

28.12.2013, 23:41:04 via Website

Ja, da hast du wohl Recht... :D
Das ist die Zeile 247:
1recorder.start();
aus diesem Codeabsnitt:
1public void recStart(final View View) {
2 if (isRecording) {
3 recorder.stop();
4 initMediaRecorder();
5 prepareMediaRecorder();
6
7 rec.getResources().getColor(android.R.color.white);
8 rec.setTextColor(Color.rgb(254, 254, 254));
9 } else {
10 recorder.start();
11 isRecording = true;
12
13 rec.setTextColor(Color.rgb(253, 3, 3));
14 }
15 }

Hin und wieder zeig er mir auch Zeile 249 an, welche komplett leer ist... :mellow:
Ich habe jetzt alle Manipulationen mit dem Button selbst rausgenommen, auch die Button Deklaration. Jetzt zeig er mir nur die Zeile 247, also
1recorder.start();
an.
Deswegen weiß ich auch nicht weiter...

— geändert am 28.12.2013, 23:50:18

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

29.12.2013, 00:29:16 via App

Was macht den die Methode Start()?

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Sam Browder
  • Forum-Beiträge: 236

29.12.2013, 00:35:46 via Website

Die soll den Recorder starten, also die Aufzeichnung beginnen.
Oder habe ich jetzt die Frage falsche verstanden?

P. S. Ich habe auch schon Teile initMediaRecorder() überprüft - also am Pfad gibt es keine Probleme: der Ordner wurde erstellt...

P.S. 2 Also der Fehler ist definitiv im MediaRecorder, also im o. g. Code. Denn ich habe jetz diesen komplett in eine neue App ausgelagert - nur ein sehr einfache SurfaceView und ein Button. Dort habe ich dann den Code getestet - das selbe Problem! Deswegen poste ich hier jetzt den ganzen code davon:
1public class MainActivity extends Activity implements SurfaceHolder.Callback {
2
3 File videofile;
4 private static final String CAMERA = null;
5 private Camera camera;
6 SurfaceView surface;
7 SurfaceHolder holder;
8 private MediaRecorder recorder;
9 private boolean isRecording;
10
11 @Override
12 protected void onCreate(Bundle savedInstanceState) {
13 super.onCreate(savedInstanceState);
14 recorder = new MediaRecorder();
15 initMediaRecorder();
16 setContentView(R.layout.main);
17 surface = (SurfaceView) findViewById(R.id.surfaceView1);
18 SurfaceHolder holder = surface.getHolder();
19 holder.addCallback(this);
20 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
21 holder.setSizeFromLayout();
22 }
23 private void initMediaRecorder() {
24 isRecording = false;
25 recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
26 recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
27 CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
28 recorder.setProfile(profile);
29 File dir = new File(Environment.getExternalStorageDirectory(),
30 this.getClass().getPackage().getName());
31 dir.mkdirs();
32 videofile = new File(dir.getAbsolutePath(), new SimpleDateFormat(
33 "'IMG_'yyyyMMddHHmmss'.mp4'").format(new Date()));
34 recorder.setOutputFile(videofile.getAbsolutePath());
35 }
36 public void recStart(final View View) {
37 if (isRecording) {
38 recorder.stop();
39 isRecording = false;
40 initMediaRecorder();
41 prepareMediaRecorder();
42 } else {
43 isRecording = true;
44 recorder.start();
45 }
46 }
47 private void prepareMediaRecorder() {
48 recorder.setPreviewDisplay(holder.getSurface());
49 try {
50 recorder.prepare();
51 } catch (IllegalStateException e) {
52 e.printStackTrace();
53 } catch (IOException e) {
54 e.printStackTrace();
55 }
56 }
57 @Override
58 public void surfaceChanged(SurfaceHolder holder, int format, int width,
59 int height) {
60 if (camera == null) {
61 camera = camera.open();
62 Camera.Parameters parameters = camera.getParameters();
63 parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
64 camera.setParameters(parameters);
65 try {
66 camera.setPreviewDisplay(holder);
67 camera.startPreview();
68 } catch (IOException e) {
69 e.printStackTrace();
70 }
71 try {
72 recorder.prepare();
73 } catch (IllegalStateException e1) {
74 e1.printStackTrace();
75 } catch (IOException e1) {
76 e1.printStackTrace();
77 }
78 }
79 }
80 @Override
81 public void surfaceCreated(SurfaceHolder holder) {
82 // TODO Auto-generated method stub
83 }
84 @Override
85 public void surfaceDestroyed(SurfaceHolder holder) {
86 // TODO Auto-generated method stub
87 }
88}

— geändert am 29.12.2013, 10:18:35

Antworten
Sam Browder
  • Forum-Beiträge: 236

29.12.2013, 11:40:51 via Website

Nein. Wo denn genau dort?

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

29.12.2013, 12:44:54 via Website

Und wieso wolltest du die videw bei recStart Übergeben?
1public void recStart(final View View) {
Hat das irgendeinen Zweck?
Den die View benutzt du in der Funktion sowieso nicht.

— geändert am 29.12.2013, 12:45:05

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Sam Browder
  • Forum-Beiträge: 236

29.12.2013, 12:47:55 via Website

Ja, und zwar ist das der Zugrif auf einen Button über android:onClick=""
Hier ist dieser Button in XML:
1<Button
2 android:id="@+id/recButton"
3 android:layout_width="wrap_content"
4 android:layout_height="wrap_content"
5 android:layout_alignParentRight="true"
6 android:layout_centerVertical="true"
7 android:background="@drawable/backgroud_rec"
8 android:text="R E C"
9 android:textColor="@color/weiss"
10 android:textSize="30sp"
11 android:textStyle="bold"
12 android:onClick="recStart" />

Das alles spielt aber überhaupt keine Rolle: ich habe auch schon über einen OnClickListener versucht (wo man die SurfaceView antippen muss), aber das Ergebnis ist das selbe,

— geändert am 29.12.2013, 12:49:50

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

29.12.2013, 12:49:28 via Website

ok, solange die Funktion recStart auch wirklich aufgerufen wird, sonst solltest de einen OnCklickListener Benutzen

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Sam Browder
  • Forum-Beiträge: 236

29.12.2013, 12:50:49 via Website

Wie gesagt, das alles spielt aber überhaupt keine Rolle: ich habe auch schon über einen OnClickListener versucht (wo man die SurfaceView antippen muss), aber das Ergebnis ist das selbe - Absturz.

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

29.12.2013, 12:55:15 via Website

Ich empfehle das ganze Projekt mal zu debuggen um damit herauszufinden wo der Fehler liegt.
Wie ist der Media Recorder denn in das Projekt eingebunden?
Als lib oder?
Dann mal die Build Einstellungen überprüfen, ob sie auch wirklich integriert wir.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Sam Browder
  • Forum-Beiträge: 236

29.12.2013, 12:58:56 via Website

Den folgenden Code habe ich aus einem Buch - sollte ja eigentlich funktionieren:
1public class MainActivity extends Activity implements SurfaceHolder.Callback {
2
3 private MediaRecorder recorder;
4 private SurfaceHolder surfaceHolder;
5 private boolean isRecording;
6
7@Override
8public void onCreate(Bundle savedInstanceState) {
9 super.onCreate(savedInstanceState);
10
11 recorder = new MediaRecorder();
12 initMediaRecorder();
13
14 setContentView(R.layout.main);
15 final SurfaceView view = (SurfaceView) findViewById(R.id.surfaceView);
16
17 view.setOnClickListener(new OnClickListener() {
18
19 @Override
20 public void onClick(View view) {
21 if (isRecording) {
22 recorder.stop();
23 initMediaRecorder();
24 prepareMediaRecorder();
25 } else {
26 recorder.start();
27 isRecording = true;
28 }
29 }
30
31 });
32
33 surfaceHolder = view.getHolder();
34 surfaceHolder.addCallback(this);
35 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
36}
37
38private void initMediaRecorder() {
39 isRecording = false;
40 recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
41 recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
42 CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
43 recorder.setProfile(profile);
44 File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
45 dir.mkdirs();
46 File file = new File(dir, "video.mp4");
47 recorder.setOutputFile(file.getAbsolutePath());
48 recorder.setMaxDuration(60000);
49}
50private void prepareMediaRecorder() {
51 recorder.setPreviewDisplay(surfaceHolder.getSurface());
52 try {
53 recorder.prepare();
54 } catch (IllegalStateException e) {
55 e.printStackTrace();
56 } catch (IOException e) {
57 e.printStackTrace();
58 }
59}
60
61@Override
62public void surfaceChanged(SurfaceHolder holder, int format, int width,
63 int height) {
64 // TODO Auto-generated method stub
65
66}
67
68@Override
69public void surfaceCreated(SurfaceHolder holder) {
70 prepareMediaRecorder();
71
72}
73
74@Override
75public void surfaceDestroyed(SurfaceHolder holder) {
76 if (isRecording) {
77 recorder.stop();
78 isRecording = false;
79 }
80 recorder.release();
81 finish();
82}

Beim ersten Start hat dieser auch TEILWEISE funktioniert: es gab zwar kienen Absturz, aber der Videofile lag nach 3 Minuten Aufzeichnung bei 0kb. Aber beim 2en Start - Absturz, und danach funktioniert es gar nicht mehr.

Antworten
Sam Browder
  • Forum-Beiträge: 236

29.12.2013, 13:08:12 via Website

Und hier ist das Ergebnus vom Debuggen:

Antworten