Android media player returns IllegalStateException - android

I have following code to play small audio files
private void playVoice() {
if (mPlayVoice != null) {
if (mPlayVoice.isPlaying()) {
mPlayVoice.release();
mPlayVoice = null;
}
}
mPlayVoice =
MediaPlayer.create(BirdsActivity.this, mSoundIds[getCurrentIndex()]);
mPlayVoice.start();
}
It works fine in Samsung galaxy tab but gives below error in small device(I Checked in Sony xperia mini pro my project)
08-17 12:45:45.232: ERROR/AndroidRuntime(6639): java.lang.IllegalStateException
08-17 12:45:45.232: ERROR/AndroidRuntime(6639): at android.media.MediaPlayer.isPlaying(Native Method)
08-17 12:45:45.232: ERROR/AndroidRuntime(6639): at com.android.mds.kidsapps.alphakids.BirdsActivity.playVoice(BirdsActivity.java:146)

You're doing this:
PlayVoice.release();
Do you not mean
mPlayVoice.release();
If you have other issues this is the best document to consult:
Android MediaPlayer
EDIT
Ok if you are here: isPlaying() Invalid States it show's you're trying to call isPlaying() while the player is in the error state. So you need to work out why it is already in the error state.
In general, some playback control operation may fail due to various reasons, such as unsupported audio/video format, poorly interleaved audio/video, resolution too high, streaming timeout, and the like.
Have a look at adding an error listener: setOnErrorListener()

Use the following code as i was facing the same exception.
try {
if(mPlayVoice!=null && mPlayVoice.isPlaying()) {
Log.d("TAG------->", "player is running");
mPlayVoice.stop();
Log.d("Tag------->", "player is stopped");
mPlayVoice.release();
Log.d("TAG------->", "player is released");
}
} catch(Exception e){
}
Here write whatever you want to do. Actually the condition checking like isPlaying() or checking for null generates the IllegalStateException.....

You may have to clear the audioGroup joined with audioStream. Mine worked with the following code:
public static void audioPlayCaptureStop()
{
try
{
if(audioStream.isBusy())
{
audioGroup.clear();
audioStream.release();
System.out.println("audioStream released");
}
} catch (Exception e) {
System.out.println("audioStream release exception: "+e.toString());
}
}

Related

IllegalStateException on MediaRecorder.start()

Morning!
I have a weird problem with a production app. Some users get an IllegalStateException on a MediaRecorder start. I cannot reproduce the problem on the few devices I own or even on an emulator. This error occurs on different versions and devices, (Android 5 to 10 and every kind of devices), and has many occurrences.
Here is the code
if (mRecorder == null) {
mRecorder = new MediaRecorder();
} else {
try {
mRecorder.stop();
} catch (Exception e) {}
}
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mRecorder.setAudioSamplingRate(44100);
mRecorder.setAudioEncodingBitRate(128000);
mRecorder.setOutputFile(mSoundFile.getAbsolutePath());
mRecorder.setAudioChannels(1);
mRecorder.setMaxDuration(mMaxDurationInMs);
mRecorder.prepare();
mRecorder.start();
And the stacktrace
java.lang.IllegalStateException: null
at android.media.MediaRecorder.native_start(MediaRecorder.java)
at android.media.MediaRecorder.start(MediaRecorder.java:1603)
at de.boxine.someapp.util.media.VoiceRecorder.start(VoiceRecorder.java:115)
at de.boxine.someapp.recording.audio.RecordAudioPresenter.startRecording(RecordAudioPresenter.java:186)
at de.boxine.someapp.recording.audio.RecordAudioPresenter.startRecordingByAvailableSource(RecordAudioPresenter.java:204)
at de.boxine.someapp.recording.audio.RecordAudioPresenter.access$500(RecordAudioPresenter.java:27)
at de.boxine.someapp.recording.audio.RecordAudioPresenter$2.onPermissionGranted(RecordAudioPresenter.java:116)
at de.boxine.someapp.mvp.AbstractPresenter.checkPermissionBeforeRun(AbstractPresenter.java:67)
at de.boxine.someapp.recording.audio.RecordAudioPresenter.onRecordButtonClicked(RecordAudioPresenter.java:108)
at de.boxine.someapp.recording.audio.RecordAudioFragment.lambda$onCreateView$0$RecordAudioFragment(RecordAudioFragment.java:112)
at de.boxine.someapp.recording.audio.-$$Lambda$RecordAudioFragment$9H7EZrHdPKO0BFbM_UTVYf_SFBU.onClick
at android.view.View.performClick(View.java:6659)
at android.view.View.performClickInternal(View.java:6631)
at android.view.View.access$3100(View.java:790)
at android.view.View$PerformClick.run(View.java:26187)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
I also have these permissions in my manifest (I ask them realtime on the recent Android versions)
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Thanks for the help.
Thanks guys for the help. I think the problem in my case was that the phone was in a call (or other communication app).
To prevent this I added this check before
public static boolean isMicrophoneAvailable() {
AudioManager audioManager = (AudioManager) MyApp.getAppContext().getSystemService(Context.AUDIO_SERVICE);
return audioManager.getMode() == MODE_NORMAL;
}
The use case I generally use is, I create the instance of the media recorder and start when the user presses the button. once the recording is finished and the user presses the stop button then I release the media recorder.
Here is my piece of code:
private fun startRecording() {
mRecorder = MediaRecorder()
try {
mRecorder.prepare()
mRecorder.start()
} catch (e: IOException) {
e.printStackTrace()
}
}
When the user presses the stop button then invoke the stopRecording method.
private fun stopRecording() {
mRecorder.stop()
mRecorder.release()
}
The same this you can apply in your application.
Note: The code is in Kotlin.

Method called after release

these days i was try to code a custom camera, but there's many bugs i can't figure out. the most serious error log as below.
at android.hardware.Camera.setHasPreviewCallback(Native Method)
at android.hardware.Camera.setPreviewCallback(Camera.java:600)
java.lang.RuntimeException: Method called after release()
at android.hardware.Camera.setHasPreviewCallback(Native Method)
at android.hardware.Camera.setPreviewCallback(Camera.java:600)
at com.baitian.wenta.customcamera.CameraActivity.cameraRelease(SourceFile:210)
at com.baitian.wenta.customcamera.CameraActivity.runExceptionHandle(SourceFile:526)
at com.baitian.wenta.customcamera.CameraActivity.updateFlashStatus(SourceFile:859)
at com.baitian.wenta.customcamera.CameraActivity.onResume(SourceFile:152)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1199)
at com.qihoo360.mobilesafe.loader.b.callActivityOnResume(SourceFile:123)
at android.app.Activity.performResume(Activity.java:5280)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2629)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2667)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2140)
at android.app.ActivityThread.access$700(ActivityThread.java:140)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4921)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
it seems the Method wouldn't called after release. i make the camera null everytime when i try to release it, and there is no multithread call.
here is the camera release code:
private void cameraRelease() {
try {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCameraExceptionLog.addLog("Camera release() After", "");
mCamera = null;
}
} catch (Throwable e) {
}
}
here is the camera init code
private void initCamera() {
try {
if (mCamera == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
mCamera = Camera.open(0);
} else {
mCamera = Camera.open();
}
mCamera.setErrorCallback(new ErrorCallback() {
#Override
public void onError(int error, Camera camera) {
isCanAutoFouce = false;
CameraActivity.this.setResult(ERROR_KEY);
CameraActivity.this.finish();
}
});
setFocusAreaDefault();
}
} catch (Throwable e) {
runExceptionHandle(e);
}
}
Can you help me,thank you .
You need to add mCamera.setPreviewCallback(null) in between mCamera.stopPreview() and mCamera.release(). This way you cancel any callbacks coming.
I provided a complete cameraRelease method here
I see at least three possible problems with the log and posted code:
You might want to call mCamera.setPreviewCallback(null) after mCamera.stopPreview(); and before mCamera.release().
The log seems to refer to a Camera#setPreviewCallback() being called from the cameraRelease() method, which is not being shown on the posted code. Maybe the actual running code log was of an older version of the posted code.
It seems that you reach the cameraRelease() code from some sort of error handling. It might be the case that the error that happened to trigger the cameraRelease() code could have already released the camera because of some illegal state, hence any call inside this method, such as the mCamera.stopPreview() or mCamera.setPreviewCallback(null) calls would likely fail if the camera was already released at this point.
I had the similar issue. This line is the key line.
com.qihoo360.mobilesafe.loader.b.callActivityOnResume
From the log above, the camera permission is disabled by Qihoo 360 mobilesafe. After Camera.open(), although it return normally, the camera is released immediately. So you should check and catch the error after Camera.open().
try {
Camera camera = Camera.open();
if (camera != null) {
cmaera.getParamters(); // empty operation
}
} catch (Exception e) {
e.printStackTrack()
// oops, finish activity
}
As a third-party app, how Qihoo 360 mobilesafe can do like this? How it can perform permission management? This problem confuses me. Does it utilize unknown bug in system to do this?

hasSystemFeature(PackageManager.FEATURE_CAMERA) returns true for device with no camera

I have a application which uses camera functionality in it but part of its functionality can also run without camera feature. SO I have put this in my manifest.
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false"/>
and in my code I check whether the device has camera or not using this
final boolean deviceHasCameraFlag = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
Now I am testing my code on a tablet which runs Android 4.0(ICS) and has no camera. But still I get True value for the deviceHasCameraFlag. Is this weird or am I missing something.
I tried different things and even tried the same thing on Bluetooth feature as Tablet even doesn't have Bluetooth feature. It works fine for Bluetooth but gives me true for camera.
Which device is it? The answer you get is a bug, and 4.0 is very old nowadays. Many tablets that still run this version were not crafted correctly, both hardware and software featuring multiple problems.
Regardless, you should always be prepared to handle failure on Camera.open() or Camera.open(0): for example, in some cases other software on your device will not release the camera gracefully.
So, in your case you have a false positive, you try to open the camera, it fails, and you continue as if there is no camera on the device, even if PackageManager thinks that PackageManager.FEATURE_CAMERA is availabe.
Though I have accepted Alex's answer I still want to put this one collectively as what can be the best solution in such condition.
What I found was in case of some low standard android devices
pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)
returns true even if camera doesn't exist and that seems to be a device bug for me which in unchecked.
So whenever there is scenario that you need to check if camera exists for a device or not best practice is something that I am putting below (best practice as per my knowledge if there is something more interesting and best solution that this you are welcome to put it here on this post)
int numberOfCameras = Camera.getNumberOfCameras();
context = this;
PackageManager pm = context.getPackageManager();
final boolean deviceHasCameraFlag = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
if( !deviceHasCameraFlag || numberOfCameras==0 )
{
Log.e(TAG, "Device has no camera" + numberOfCameras);
Toast.makeText(getApplicationContext(), "Device has no camera", Toast.LENGTH_SHORT).show();
captureButton.setEnabled(false);
}
else
{
Log.e(TAG, "Device has camera" + deviceHasCameraFlag + numberOfCameras);
}
In this I am checking both number of cameras as well as device has camera feature Boolean , so in any case it would not fail my condition.
In my case I had this code:
public boolean hasCameraSupport() {
boolean hasSupport = false;
if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) { //<- this constant caused problems
hasSupport = true;
}
return hasSupport;
}
and it kept returning false on a Genymotion device running Android 4.1.1 (API 16). Once I changed the constant PackageManager.FEATURE_CAMERA_ANY to PackageManager.FEATURE_CAMERA, my problems went away. I am guessing that not all devices/API levels support PackageManager.FEATURE_CAMERA_ANY.
I got it you will try this one definitely it will work....
import android.hardware.Camera;
int numCameras = Camera.getNumberOfCameras();
if (numCameras > 0) {
System.out.println("camera");
} else {
System.out.println("No Camera");
}
For CameraX, if the FEATURE_CAMERA_ANY method is still returning true when there is no Camera on device, you can add the below method. So whether FEATURE_CAMERA_ANY returns true or false when CameraX is getting initialized, Below method will make sure to do what you want if a camera is actually not available on device.
private CameraSelector cameraSelector;
private ProcessCameraProvider cameraAvailableCheck;
private ListenableFuture<ProcessCameraProvider> cameraAvailableCheckFuture;
private void checkIfAnyCameraExist()
{
cameraAvailableCheckFuture = ProcessCameraProvider.getInstance(context);
cameraAvailableCheckFuture.addListener(new Runnable() {
#Override
public void run() {
try {
cameraAvailableCheck = cameraAvailableCheckFuture.get();
if ((cameraAvailableCheck.hasCamera(cameraSelector.DEFAULT_BACK_CAMERA) || cameraAvailableCheck.hasCamera(cameraSelector.DEFAULT_FRONT_CAMERA) ))
{
//Do what you want if at least back OR front camera exist
}
else
{
//Do what you want if any camera does not exist
}
}
catch (ExecutionException | InterruptedException | CameraInfoUnavailableException e)
{
// No errors need to be handled for this Future.
// This should never be reached.
}
}
}, ContextCompat.getMainExecutor(this));
}
Please try this code:
private boolean isDeviceSupportCamera() {
if (getApplicationContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
Still it does't work then please let me know

chromecast "failed to start application: no application is running" after called startSession()

I'm testing playing online video using chromecast.
After onRouteSelected(), I create the ApplicationSession and attach a MediaProtocalMessageStream;
Then I called mSession.startSession(); with no APP_ID, so I assume the build-in app inside chromecast play the video for me. This code works perfect and I can play online mp4 videos without writing my own receiver.
But, When I try to leave the video play app, I can't go back anymore, there is always an error message comes from onSessionStartFailed() which says
StartSessionTask failed with error: failed to start application: no
application is running
I don't remember how the first time I got into the video play app, which I don't leave for few day.
But I do know how I leave it, Here is what I did before I can never startSession again:
open Youtube app, get a deviced connected
play some youtube videos
disconnected from a chormecast, then the chromecast return to the starting page
So, doesn't anybody know what's going on here? How to open the build-in video app again?
By the way, My chromecast get a system update just after I return to the starting page, I don't know if google update something cause startSession() fail.
Below is the code I startSession and attach a mediaStream.
mSession = new ApplicationSession(mCastContext, mSelectedDevice);
ApplicationSession.Listener listener = new ApplicationSession.Listener() {
#Override
public void onSessionStarted(ApplicationMetadata appMetadata) {
mChannel = mSession.getChannel();
mStream = new MediaProtocolMessageStream();
mChannel.attachMessageStream(mStream);
if (mStream.getPlayerState() == null) {
ContentMetadata metaData = new ContentMetadata();
metaData.setTitle("Test Video");
String url = "http://www.auby.no/files/video_tests/h264_720p_hp_5.1_6mbps_ac3_planet.mp4";
try {
mCommand = mStream.loadMedia(url, metaData, true);
mCommand.setListener(new MediaProtocolCommand.Listener() {
#Override
public void onCompleted(MediaProtocolCommand arg0) {
onSetVolume(0.5);
}
#Override
public void onCancelled(MediaProtocolCommand arg0) {
}
});
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onSessionStartFailed(SessionError error) {
Log.d("TEST", "Session Started failed");
}
#Override
public void onSessionEnded(SessionError error) {
Log.d("TEST", "Session Started end");
}
};
mSession.setListener(listener);
try {
mSession.startSession();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
You will have to use your own app id and own receiver. Google's default receiver doesn't play video streams anymore (it used to). It only handles Chrome tab mirroring now.

Exception when trying to call(SIP)

I'm developping a SIP application, and when i want to call someone(with its identifier configured in the server) i have a NullPointerException => "Error when trying to close manager."
Here is the code:
public void initiateCall() {
updateStatus(sipAddress);
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};
call = manager.makeAudioCall(me.getUriString(), sipAddress, listener, 30);
}
catch (Exception e) {
Log.i("WalkieTalkieActivity/InitiateCall", "Error when trying to close manager.", e);
if (me != null) {
try {
manager.close(me.getUriString());
} catch (Exception ee) {
Log.i("WalkieTalkieActivity/InitiateCall",
"Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
Thank you for your help.
The VOIP/SIP libary is not supported by default on Android emulator. The problem is that the manager == null - thats why you are getting the NullPointerException.
Luckily, there is a work-a-round. Download this link and copy it into ...\.android\avd\.avd folder.
Start your emulator and
Boolean voipSupported = SipManager.isVoipSupported(this);
Boolean apiSupported = SipManager.isApiSupported(this);
should now return true.
Source: http://xilard.hu/
Android.net.sip (Sip API) only works on G711 over Android 2.3+.
Also the phones supplied by carriers may have the SIP stack (android.net.sip) blocked or cripple. SipManager.isVoipSupported(this) && SipManager.isApiSupported(this) will return false for most of the devices is your ie. your SipManager object will always be null in such case.You should use third party library to implement SIP.
There are different open source sip stack libraries as well as projects are available on internet. You can download the source code of that projects.
Here is the List of some popular open source sip stack libraries which allows to voice call over internet.
1.Jain sip (I think the best option):
2.Pjsip
3.Mjsip
4.Doubango
There are different open source projects which have used these libraries in their projects.
1.Jain sip: Not used in a "famous" app.
2. Sipdroid uses MjSip
3. Csipsimple uses PjSip
4. Imsdroid uses doubango.
Check the bridge connection in Android and the SIP server in your application to obtain the SIP key of your application.

Categories

Resources