Good afeternoon
First of all, this is my first android project.
In my project I have an audio recorder and it works fine, the problem is when I switch the screen rotation gives an error and the app turns off.
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile("/dev/null");
try {
recorder.prepare();
recorder.start();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Error appears when Android Studio reads the line recorder.start(), after rotating the screen.
The error description is Unable to start activity ComponentInfo{com.example.duarte.mediaplayerandroid/com.example.duarte.mediaplayerandroid.MainActivity}: java.lang.RuntimeException: start failed.
To handle screen rotation, Add (Override) the method onConfigurationChanged() in your Activity . As you just want to avoid config. changes,don't put any code into it. Following is the example:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//Nothing here...
}
Related
My photo taking algorithm works perfectly the first time, but if I call the method the second time, I get java.lang.RuntimeException: Fail to connect to camera service on camera.open()
takePhoto(this, 0);//back camera.
takePhoto(this, 1);//selfie. No matter what, the second line crashes. Even if I switch the two lines.
Here is the method that only works the first time:
private void takePhoto(final Context context, final int frontorback) {
Log.v("myTag", "In takePhoto()");
final SurfaceView preview = new SurfaceView(context);
SurfaceHolder holder = preview.getHolder();
// deprecated setting, but required on Android versions prior to 3.0
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.addCallback(new SurfaceHolder.Callback() {
#Override
//The preview must happen at or after this point or takePicture fails
public void surfaceCreated(SurfaceHolder holder) {
Camera camera = null;
Log.v("myTag", "Surface created ");
try {
camera = Camera.open(frontorback); //** THIS IS WHERE IT CRASHES THE SECOND TIME **
Log.v("myTag", "Opened camera");
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
Log.v("myTag", "Can't assign preview to Surfaceview holder" + e.toString());
}
try {
camera.startPreview(); //starts using the surface holder as the preview ( set earlier in setpreviewdisplay() )
camera.autoFocus(new Camera.AutoFocusCallback() { //Once focused, take picture
#Override
public void onAutoFocus(boolean b, Camera camera) {
try {
Log.v("myTag", "Started focusing");
camera.takePicture(null, null, mPictureCallback);
Log.v("myTag", "Took picture!");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
} catch (Exception e) {
Log.v("myTag", "Can't start camera preview " + e.toString());
if (camera != null)
camera.release();
throw new RuntimeException(e);
}
}catch(Exception e){
Log.v("myTag", "can't open camera " +e.toString());
e.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
});
addPreviewToSurfaceView(); //Irrelavent here
}
//CALLBACK WHERE I RELEASE:
android.hardware.Camera.PictureCallback mPictureCallback = new android.hardware.Camera.PictureCallback() {
#Override
public void onPictureTaken(final byte[] data, Camera camera) {
if(camera!=null){
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
downloadPicture(data);
sendPicture(data);
Log.v("myTag","Picture downloaded and sent");
}
};
It's odd, because takePhoto(context, int) only works the first time no matter what. Even if I switch the second parameter, only the first takePhoto() works.
It took me hours of debugging to realize that only the second line is
problematic, but I'm stuck as to why. Any feedback is much
appreciated!
EDIT:
Even after removing the code in my onPictureTaken callback, the problem continues to persist. I suspect the camera may need time to reopen immediately, but I can't sleep the thread since I'm performing UI interactions on it. This bug is like a puzzle right now!
You cannot call takePhoto() one after another, because this call takes long time (and two callbacks) to complete. You should start the second call after the first picture is finished. Here is an example, based on your code:
private void takePhoto(final Context context, final int frontorback) {
...
android.hardware.Camera.PictureCallback mPictureCallback = new android.hardware.Camera.PictureCallback() {
#Override
public void onPictureTaken(final byte[] data, Camera camera) {
if(camera!=null){
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
if (frontorback == 0) {
takePhoto(context, 1);
}
}
downloadPicture(data);
sendPicture(data);
Log.v("myTag","Picture downloaded and sent");
}
};
This will start the first photo and start the second photo only when the first is complete.
Here might be problem.
After you take photo, the picture taken callback get called.
if(camera!=null){
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
And the camera has been released, so the second time won't work. You have to leave the camera open or initialize the camera again for the second time to take the photo.
I wrote an Android Flash Light application but that seems to show some strange behavior.
The code that is invoked on clicking the "Turn On" button is
public void flashLightOn(View view){
try {
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH))
cam = Camera.open(0);
Camera.Parameters p = cam.getParameters();
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.startPreview();
}catch (Exception e){
e.printStackTrace();
}
}
Now , the strange thing is that this app works fine on some phones and doesn't work on others.
I have tried it on my OnePlus One and Motorola Droid Mini and on both of them it works fine, but when I ran it on a Motorola Droid RAZR and Moto E it didn't work.
I am not able to understand the problem here. Can anyone help?
Replace your code with:
public void flashLightOn(View view){
try {
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH))
{ // you don't added this
cam = Camera.open(0);
Camera.Parameters p = cam.getParameters();
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.startPreview();
} // and this
}catch (Exception e){
e.printStackTrace();
}
}
im making a music app just for fun. I can read all my music files from sd card but MediaPlayer wont play the sound. I have the path to the file which i pass to the media player with setDataSource but nothing happens and i get no exceptions. Here is the code im using.
Uri songUri;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
setUpViews();
MediaPlayer mp = new MediaPlayer();
try {
mp.setDataSource(songUri.toString());
mp.prepare();
} catch (IllegalArgumentException e) {
Toast.makeText(this, "ILLEGAL ARGUMENT EXCEPTION", Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (SecurityException e) {
Toast.makeText(this, "SECURITY EXCEPTION", Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (IllegalStateException e) {
Toast.makeText(this, "ILLEGAL STATE EXCEPTION", Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (IOException e) {
Toast.makeText(this, "IO EXCEPTION", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
mp.start();
Log.d("URI AFTER SET UP", songUri.toString());
}
As i said before nothing happens when i open this activity but i still get all the Log.d in the console. Is there any more configurations for the media player to play the music? Thanks in advance.
setDataSource() requires a path argument . You are passing the entire uri as string. Try this :
mp.setDataSource(songUri.getPath());
mp.prepare();
mp.start();
Moreover, if you are trying to access a file with content:// uri, it won't work. You'll have to find the real path to the file, i.e file:// uri.
I think you have to add setAudioStreamType to your MediaPlayer Object. You can add this before mp.setDataSource(your_URI); like below
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
There other types, you can choose AudioManager.STREAM_MUSIC for Music Player
I just solved the problem, and i just dont know why it works. What i did was to put a button to stop the music being played. I dont understand why it works so if someone could explain why it does i'd be thanksfull.
get the path of song by querying MEDIASTORE-EXTERNAL_URI.And this field MEDIASTORE.AUDIO.MEDIA.DATA will give u the path of the song(which is string). U can set it directly to mediaplayer.setDataSource(Your_path_from_mediastore) .It will work fine than.
I'm a Beginner in android programming and I want to programming mp3 app to call some mp3 files from URL, so when I show "Media Player" in android developer I put the URL in the setDataSource and it's work fine, but the problem is the Activity take a lot of time to display it and in the sometimes app will be crashed. This is the part of my code :
file_url = Mp3_Linkes[num];
//Set Source
try {
mp.setDataSource(file_url);
} catch (Exception e) {
Toast.makeText(this, "Source Error !!", Toast.LENGTH_LONG).show();
}
//Prepare
try {
mp.prepare();
}catch(Exception e)
{
Toast.makeText(this, "Prepare Error !!", Toast.LENGTH_LONG).show();
}
//Start
mp.start();
Your activity is blocking because you are calling prepare on your Main Thread (UI thread)
Instead You can use prepareAsynch and OnPreparedListener to start specially when loading from remote source:
code :
try {
mp.setDataSource(file_url);
mp.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer player) {
player.start();
}
});
mp.prepareAsync();
I had my camera set to this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); and it works fine but if I change it to PORTRAIT instead of LANDSCAPE then it crashes with the following error...
07-30 12:51:37.655: ERROR/AndroidRuntime(22069): FATAL EXCEPTION: main
07-30 12:51:37.655: ERROR/AndroidRuntime(22069): java.lang.RuntimeException: Fail to connect to camera service
07-30 12:51:37.655: ERROR/AndroidRuntime(22069): at android.hardware.Camera.native_setup(Native Method)
07-30 12:51:37.655: ERROR/AndroidRuntime(22069): at android.hardware.Camera.<init>(Camera.java:110)
07-30 12:51:37.655: ERROR/AndroidRuntime(22069): at android.hardware.Camera.open(Camera.java:90)
07-30 12:51:37.655: ERROR/AndroidRuntime(22069): at org.digital.com.CamLayer.surfaceCreated(CamLayer.java:3
The method it crashes in is..
public void surfaceCreated(SurfaceHolder holder) {
synchronized(this) {
mCamera = Camera.open();
Camera.Parameters p = mCamera.getParameters();
p.setPreviewSize(800, 480);
mCamera.setParameters(p);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
Log.e("Camera", "mCamera.setPreviewDisplay(holder);");
}
mCamera.startPreview();
mCamera.setPreviewCallback(this);
}
}
It crashes at mCamera = Camera.open();
My Manifest file has <uses-permission android:name="android.permission.CAMERA"></uses-permission>
How do I fix this so I can view my app in Portrait?
There is some concurrency problem in platform: http://code.google.com/p/android/issues/detail?id=6201
The workaround is to clear callback before releasing cam, that is I would recommend following clean-up code:
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCam != null) {
mCam.stopPreview();
mCam.setPreviewCallback(null);
mCam.release();
mCam = null;
}
}
For your reference, this is the SurfaceHolderCallBack inner class that I'm using in my app and which works fine on Nexus One 2.2 in portrait mode - hope it helps.
Edit: "which works" = "which doesn't crash". Although I haven't figured out how to rotate the preview image correctly (see my first comment above). That's why I actually had to use landscape and 'convert' UI stuff that's surrounding the preview surface into landscape mode.
Afaik preview (with correct rotation of the preview image) only works in landscape mode. Rotation & orientation params that I tried didn't help at all.
class SurfaceHolderCallback implements SurfaceHolder.Callback {
private static final int IMAGE_WIDTH = 512;
private static final int IMAGE_HEIGHT = 384;
private static final String ORIENTATION = "orientation";
private static final String ROTATION = "rotation";
private static final String PORTRAIT = "portrait";
private static final String LANDSCAPE = "landscape";
public void surfaceCreated(SurfaceHolder holder) {
try {
// This case can actually happen if the user opens and closes the camera too frequently.
// The problem is that we cannot really prevent this from happening as the user can easily
// get into a chain of activites and tries to escape using the back button.
// The most sensible solution would be to quit the entire EPostcard flow once the picture is sent.
camera = Camera.open();
} catch(Exception e) {
finish();
return;
}
//Surface.setOrientation(Display.DEFAULT_DISPLAY,Surface.ROTATION_90);
Parameters p = camera.getParameters();
p.setPictureSize(IMAGE_WIDTH, IMAGE_HEIGHT);
camera.getParameters().setRotation(90);
Camera.Size s = p.getSupportedPreviewSizes().get(0);
p.setPreviewSize( s.width, s.height );
p.setPictureFormat(PixelFormat.JPEG);
p.set("flash-mode", "auto");
camera.setParameters(p);
try {
camera.setPreviewDisplay(surfaceHolder);
} catch (Throwable ignored) {
Log.e(APP, "set preview error.", ignored);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (isPreviewRunning) {
camera.stopPreview();
}
try {
camera.startPreview();
} catch(Exception e) {
Log.d(APP, "Cannot start preview", e);
}
isPreviewRunning = true;
}
public void surfaceDestroyed(SurfaceHolder arg0) {
if(isPreviewRunning && camera != null) {
if(camera!=null) {
camera.stopPreview();
camera.release();
camera = null;
}
isPreviewRunning = false;
}
}
}
Do you have this set in AndroidManifest.xml ?
uses-permission android:name="android.permission.CAMERA"
Instead of using :
<uses-permission
android:name="android.permission.FLASHLIGHT"/>
Try to use:
<uses-permission
android:name="android.permission.FLASHLIGHT"
android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
android:protectionLevel="normal" />
and don't forget to add the permission for camera:
<uses-permission android:name="android.permission.CAMERA" />
Another possibility if you're using an Android Emulator may be that the front and back cameras are defined as "none" in the Android Virtual Device settings.
I think your problem is that when you rotate the camera it is not released correctly or at all. If you switch from landscape to portrait the Intent is launched again. If then the camera is not released and reopend you try to open an already open camera, which throws an error.
this might work...
#Override public void surfaceDestroyed(SurfaceHolder holder) {
Log.d("surfaceDestroyed", "");
cameraSource.stop(); //check if you have this line
}
I see you have set your preview area set as 800 x 480. In portrait mode, this size is invalid and there might be a bug in the API which makes it crash.
Try setting a preview area of 200x200