Error code (1, -2147483648) in Android MediaPlayer - java

I'm trying to implement a simple alarm in android by using the
MediaPlayer. However, every time I try to prepare() it, I get an error.
Here's my code. I'm a total beginner concerning Java and Android so
perhaps I'm doing something inherently wrong.
private void playDiscreteAlarm()
{
alarmSound = new MediaPlayer();
alarmSound.setAudioStreamType(AudioManager.STREAM_RING);
Resources res=context.getResources();
AssetFileDescriptor fd = res.openRawResourceFd(R.raw.discrete_alarm);
try {
alarmSound.setDataSource(fd.getFileDescriptor());
fd.close();
alarmSound.setLooping(true);
alarmSound.prepare();
alarmSound.start();
}
catch (IOException e)
{
Log.d("error\n");
}
}
The weird thing is that this worked once and after that stopped working.
It works when I use MediaPlayer.create() however I need to use the ringer volume instead of the media volume, and I believe this is the way to do it.

I fixed the problem, though I'm not sure what caused it. I just used a different and maybe slightly simpler method.
Here's what I did:
private void playDiscreteAlarm()
{
String filename = "android.resource://" + context.getPackageName() + "/raw/discrete_alarm";
alarmSound = new MediaPlayer();
alarmSound.setAudioStreamType(AudioManager.STREAM_RING);
try {
alarmSound.setDataSource(context, Uri.parse(filename));
alarmSound.setLooping(true);
alarmSound.prepare();
alarmSound.start();
}
catch (Exception e)
{
System.out.println(e);
}
}
Thanks !

Related

Attempt to call getDuration in wrong state: mPlayer=0x0, mCurrentState=1 How can I solve it?

I am a novice developer trying to make an audio player on android.
On Youtube (https://www.youtube.com/watch?v=hNbXrlrWzGY&list=PL9vy4y29rrd4x5pAbowit8gpjsXAai0yF&index=8),
I did the same way I implemented it at 18:19, but it was played in Youtube video, but I didn't.
I also tried applying the content here Media Player called in state 0, error (-38,0),
but the music still doesn't play.
Here is my code.
musicPlayer = new MediaPlayer();
MediaController controller = new MediaController(this);
try {
musicPlayer.setDataSource(song.getPath());
musicPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
String duration = millisecondsToString(musicPlayer.getDuration());`
What's the difference between that YouTube and the way I did it?
Thank you.
++I invoke start() in onClick()
public void onClick(View v) {
switch(v.getId()) {
case R.id.playbtn :
if(musicPlayer.isPlaying()) {
musicPlayer.pause();
playbtn.setBackgroundResource(R.drawable.resume);
} else {
musicPlayer.start();
playbtn.setBackgroundResource(R.drawable.play);
}
break;
Firstly sorry for my English.
Are you have invoked the method: player.start() ? .
If not,You need invoked it when player prepare successed.
It may be have a listener for when prepare Ready callback.
Invoke the player.start() when received the event.
Or invoke the player.autoStart() like it.
The method name maybe not to exit but maybe similar

PixelCopy android implementation

I am new to android development so I think this may be a teething issue on my part, but I am currently trying to use the PixelCopy function in android studio. I have code as shown below, and it matches what the base class is expecting although it is returning an error. Would anyone be able to assist me with this issue?
The code I currently have is as follows:
final HandlerThread handlerThread = new HandlerThread("PixelCopier");
handlerThread.start();
SurfaceView current = new SurfaceView(view.getContext());
PixelCopy.OnPixelCopyFinishedListener copyResult;
// Make the request to copy.
PixelCopy.request(current, bitmap, copyResult, handlerThread);
if (copyResult. == PixelCopy.SUCCESS) {
//If successful do tasks in here
}
Try crating extracting finish listener as shown below in class.
private static void onPixelCopyFinished(int result) {
if (result != PixelCopy.SUCCESS) {
Log.e("err", "errMsg");
return;
}
}
You can pass the listener as below and also you'll also need to wrap it in try catch as it might throw an exception.
try {
PixelCopy.request(current, bitmap, <YOUR CLASS>::onPixelCopyFinished, this.getHandler());
} catch (IllegalArgumentException e) {
// PixelCopy may throw IllegalArgumentException, make sure to handle it
e.printStackTrace();
}

Jitsi - Playing a WAV file during call - If possible, mix with audio

I am customizing Jitsi to play a Wav file when a call is in progress.
I am facing trouble doing it, and would appreciate if you can help me out.
I can switch the data source before the call starts, by using a custom AudioFileMediaDevice and switching it on in CallPeerMediaHandler.
But I am having problems in replacing the datasource when the call is in progress.
=============================================================
I've tried the following but couldn't make it work.
1) I tried getting the device's output datasource and added a URLDatasource of the wav file using addInDataSource method. Didn't work.
DataSource dataSource = device.createOutputDataSource();
DataSource fileDataSource = Manager.createDataSource(new URL("file://resources/sounds/Sample.wav"));
((AudioMixingPushBufferDataSource)dataSource).addInDataSource(fileDataSource);
2) I tried adding a custom Capture device and switch it, but its not working too:
CaptureDeviceInfo2 fileDevice =
new CaptureDeviceInfo2("Recorded Audio 1",
fileDataSource.getLocator(), null, null, null, null);
((MediaServiceImpl) LibJitsi.getMediaService())
.getDeviceConfiguration().getAudioSystem().setDevice(AudioSystem.DataFlow.CAPTURE, fileDevice, false);
This is working for playback though, not as a capture device.
3) I even tried adding a new Audio system with the playback device as the file data source, but thats not working too.
=============================================================
I am new to libjitsi, so I'm having tough time trying to decode what is happening.
Any directions on how to resolve this would be great.
I made playback sound in call with this code:
public void startPlaying(CallPeer callPeer, DataSource soundDataSource) throws OperationFailedException {
assert callPeer instanceof CallPeerSipImpl;
CallPeerSipImpl cp = (CallPeerSipImpl) callPeer;
AudioMediaStreamImpl audioMediaStream = (AudioMediaStreamImpl) cp.getMediaHandler().getStream(MediaType.AUDIO);
AudioMediaDeviceSession deviceSession = audioMediaStream.getDeviceSession();
assert deviceSession != null;
assert deviceSession.getDevice() instanceof AudioMixerMediaDevice;
AudioMixerMediaDevice dev = (AudioMixerMediaDevice) deviceSession.getDevice();
dev.getAudioMixer().addInDataSource(soundDataSource);
}
Note that AudioMixerMediaDevice.getAudioMixer() has private access in libjitsi, so I made it public and recompiled.
I needed to play an audio file during a call, but only on the remote side of the call. So I played around a little bit with stokitos example and modified it for my needs. In case somebody ever needs it, here is what I did:
private void playAudioFromDataSource(final CallPeerSipImpl callPeer, final DataSource audioDataSource, final MediaDirection direction) {
final CallPeerMediaHandlerSipImpl mediaHandler = callPeer.getMediaHandler();
final AudioMediaStreamImpl audioMediaStream = (AudioMediaStreamImpl) mediaHandler.getStream(AUDIO);
final AudioMediaDeviceSession deviceSession = audioMediaStream.getDeviceSession();
if (null != deviceSession) {
if (RECVONLY == direction) {
// plays audio local only:
deviceSession.addPlaybackDataSource(audioDataSource);
} else {
final AudioMixerMediaDevice mediaDevice = (AudioMixerMediaDevice) deviceSession.getDevice();
final AudioMixer audioMixer = getAudioMixer(mediaDevice);
if (null != audioMixer) {
if (SENDONLY == direction) {
// plays audio remote only:
audioMixer.getLocalOutDataSource().addInDataSource(audioDataSource);
} else if (SENDRECV == direction) {
// plays audio on both sides of call (local and remote):
audioMixer.addInDataSource(audioDataSource);
}
}
}
}
}
private AudioMixer getAudioMixer(final AudioMixerMediaDevice device) {
try {
final Method privateGetAudioMixerMethod = device.getClass().getDeclaredMethod("getAudioMixer");
privateGetAudioMixerMethod.setAccessible(true);
final Object audioMixerObject = privateGetAudioMixerMethod.invoke(device, (Object[]) null);
return (AudioMixer) audioMixerObject;
} catch (final Exception e) {
log.error("Could not get AudioMixer", e);
}
return null;
}
NOTE: I sued reflection to get the private AudioMixer object. I admit it's not the cleanest approach, but it works. :)

Android MediaPlayer reset freezes UI

I have a problem with the Android MediaPlayer when changing the dataSource of the player. According the specification of the MediaPlayer (http://developer.android.com/reference/android/media/MediaPlayer.html) I have to reset the player when changing the dataSource. This works fine, but as soon as the channelChanged method is called twice in quick succession the MediaPlayer.reset freezes the UI. I profile the code as seen here:
public void channelChanged(String streamingUrl)
{
long m1 = System.currentTimeMillis();
mMediaPlayer.reset();
long m2 = System.currentTimeMillis();
try
{
mMediaPlayer.setDataSource(streamingUrl);
}
catch (IOException e)
{
e.printStackTrace();
}
long m3 = System.currentTimeMillis();
mMediaPlayer.prepareAsync();
long m4 = System.currentTimeMillis();
Log.d("MEDIAPLAYER", "reset: " + (m2 - m1));
Log.d("MEDIAPLAYER", "setDataSource: " + (m3 - m2));
Log.d("MEDIAPLAYER", "preparing: " + (m4 - m3));
}
reset: 3
setDataSource: 1
preparing: 0
reset: 3119
setDataSource: 2
preparing: 1
So apparently the reset is blocked by the asynchronous preparing of the first call (when I wait until the first stream starts and then call channelChanged() again, everything is fine).
Any ideas how to solve the problems? Should I execute the whole method in a separate thread? Basically I want to avoid that, because it seems not to be a good coding style and can possibly cause some further issues, e.g. when the user tries to start the player again, but the player is still in the reset method, which on the other hand seems to wait for the asyncPrepare method. It is not clear how the player would behave...
Is there any other good solution?
MediaPlayer is a tricky bastard. I recommend you take a look at the sample app where the MediaPlayer bad design is made evident by looking at the mess of code you have to write around it to have a consistent media playback experience.
If anything, after looking at the sample, you see that when they want to skip a track, they essentially reset and release…
mPlayer.reset();
mPlayer.release();
…and later when they are ready to load a new track…
try {
mPlayer.reset();
mPlayer.setDataSource(someUrl);
mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
//bam!
}
});
mPlayer.prepareAsync();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
I have added the try/catch because on some devices/OS versions, the MediaPlayer is worse than others and sometimes it just does weird stuff. You should have an Interface/Listener that is capable of reacting to these situations
UPDATE:
This is a method I use when I stop (or pause) my Music Playback (mostly taken from the sample app, this is running in a service and it has been modified to suit my own app but still).
The first method is used by both stop and pause, the former passes true, the later false
/**
* Releases resources used by the service for playback. This includes the "foreground service"
* status and notification, the wake locks and possibly the MediaPlayer.
*
* #param releaseMediaPlayer Indicates whether the Media Player should also be released or not
*/
void relaxResources(boolean releaseMediaPlayer) {
stopForeground(true);
stopMonitoringPlaybackProgress();
// stop and release the Media Player, if it's available
if (releaseMediaPlayer && mPlayer != null) {
mPlayer.reset();
mPlayer.release();
mPlayer = null;
}
// we can also release the Wifi lock, if we're holding it
if (mWifiLock.isHeld()) {
mWifiLock.release();
}
}
This is part of the processPauseRequest():
if (mState == State.Playing) {
// Pause media player and cancel the 'foreground service' state.
mState = State.Paused;
mPlayer.pause();
dispatchBroadcastEvent(ServiceConstants.EVENT_AUDIO_PAUSE);//notify broadcast receivers
relaxResources(false); // while paused, we always retain the mp and notification
And this is part of the processStopRequest() (simplified):
void processStopRequest(boolean force, final boolean stopSelf) {
if (mState == State.Playing || mState == State.Paused || force) {
mState = State.Stopped;
// let go of all resources...
relaxResources(true);
currentTrackNotification = null;
giveUpAudioFocus();
}
}
Now the core part is the next/skip…
This is what I do…
void processNextRequest(final boolean isSkipping) {
processStopRequest(true, false); // THIS IS IMPORTANT, WE RELEASE THE MP HERE
mState = State.Retrieving;
dispatchBroadcastEvent(ServiceConstants.EVENT_TRACK_INFO_LOAD_START);
// snipped but here you retrieve your next track and when it's ready…
// you just processPlayRequest() and "start from scratch"
This is how the MediaPlayer sample does it (found in the samples folder) and I haven't had problems with it.
That being said, i know what you mean when you say you get the whole thing blocked, I've seen it and it's the MP buggyness. If you get an ANR I'd like to see the log for it.
For the record here's how I "begin playing" (a lot of custom code has been omited but you get to see the MP stuff):"
/**
* Starts playing the next song.
*/
void beginPlaying(Track track) {
mState = State.Stopped;
relaxResources(false); // release everything except MediaPlayer
try {
if (track != null) {
createMediaPlayerIfNeeded();
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mPlayer.setDataSource(track.audioUrl);
} else {
processStopRequest(true, false); // stop everything!
return;
}
mState = State.Preparing;
setUpAsForeground(); //service
/* STRIPPED ALL CODE FROM REMOTECONTROLCLIENT, AS IT ADDS A LOT OF NOISE :) */
// starts preparing the media player in the background. When it's done, it will call
// our OnPreparedListener (that is, the onPrepared() method on this class, since we set
// the listener to 'this').
// Until the media player is prepared, we *cannot* call start() on it!
mPlayer.prepareAsync();
// We are streaming from the internet, we want to hold a Wifi lock, which prevents
// the Wifi radio from going to sleep while the song is playing.
if (!mWifiLock.isHeld()) {
mWifiLock.acquire();
}
} catch (IOException ex) {
Log.e("MusicService", "IOException playing next song: " + ex.getMessage());
ex.printStackTrace();
}
}
As a final note, I've noticed that the "media player blocking everything" happens when the audio stream or source is unavailable or unreliable.
Good luck! Let me know if there's anything specific you'd like to see.
The newest phones and Android API works much butter, reset method takes only 5-20 ms when fast switching between songs (next or prev)
So there is no solution for older phones, it just how it works

System.err when fetching an image in Android

I'm using a messenger service to asynchronously fetch an image from a URL but LogCat is throwing a strange error message:
W/System.err(26180): Error reading from ./org/apache/harmony/awt/www/content/image/png.class
- or -
W/System.err(26180): Error reading from ./org/apache/harmony/awt/www/content/image/jpeg.class
The funny thing is that everything works. The image is successfully being decoded into a Bitmap on the first try.
Here is my code:
#Override
public void onHandleIntent(Intent i) {
int position = (Integer)i.getExtras().get(EXTRA_POSITION);
String imageUrl = (String)i.getExtras().get(EXTRA_URL);
Messenger messenger = (Messenger)i.getExtras().get(EXTRA_MESSENGER);
Message msg = Message.obtain();
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream((InputStream)new URL(imageUrl).getContent());
msg.arg1 = Activity.RESULT_OK;
msg.arg2 = position;
msg.obj = bitmap;
} catch(Exception e) {
Log.e("RSSForHC", "Exception getting image", e);
msg.arg1 = Activity.RESULT_CANCELED;
msg.obj = e;
}
try {
messenger.send(msg);
} catch (Exception e) {
Log.w("RSSForHC","Exception sending results to activity", e);
}
}
The error is definently being thrown on this line:
bitmap = BitmapFactory.decodeStream((InputStream)new URL(imageUrl).getContent());
Since everything works my question is whether or not it's acceptable to ignore this error? Does anyone know why this error is being thrown and how I can possibly correct it or handle it?
This worked for me to get rid of those messages. Of course Michael may still be right that ignoring them is okay.
I replaced
Drawable.createFromStream(((InputStream)new URL(urlString).getContent()), "name");
with
Drawable.createFromStream((new URL(url)).openConnection().getInputStream(), "name");
Of course this isn't exactly your code, but I suspect that replacing getContent() with openConnection().getInputStream() would work for you too.
It's obviously an error in the Apache/Harmony framework.
I think you may ignore it, you can't change the code there, even if you want :)
It's kinda a logging stuff for the apache/harmony developers, you don't have to care about this.

Categories

Resources