MediaPlayer loading sound from Uri not working - java

I have a simple voice recorder app. When the user records something it gets saved on the external storage and after that it gets played from there.
Everything works fine except on a Huawei P8 Lite smartphone with Android 6.
Here is how I play the sound:
Thread th=new Thread(new Runnable() {
#Override
public void run() {
try {
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(view.getContext(), uri);
mp.prepare();
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//send message to handler
}
});
th.start();
The Uri does exist at this moment and also the file does exist in the destination. Why is my mediaPlayer not playing anything? The permissions are given at this point where it tries to create the MediaPlayer so it should not be a permission issue.
All I get in the logcat is:
W/MediaPlayer-JNI: MediaPlayer finalized without being released
I/MediaPlayer: setDataSource(34, 0, 576460752303423487)
I/MediaPlayer: [HSM] stayAwake true uid: 10255, pid: 22592
E/MediaPlayer: error (-19, 0)
E/MediaPlayer: Error (-19,0)
Like I said it works fine on all other devices I tested (Android 10 & Android 9)
EDIT
Here is what I tried:
I created Emulators with every API level from API 18 to 30 and it works fine on every emulator.
I reseted my Huawei P8 Lite smartphone to factory settings.
I checked if the sound file is saved properly and if I can open and play it manualy when I navigate in the folder where it gets saved (it works perfectly so it has nothing to do with the code that saves the sound)
I really run out of ideas.
Hope someone can help, Thanks!

You need to player prepare asynchronously. player. prepare() replace with below code:
player.prepareAsync()

Related

CameraX Image Analysis app not running the analyze method

I am developing a camerax app for the image analysis use case. I built it and ran on my phone and it worked perfectly. I also tried it on a few other phones and it worked on them too. We actually plan to use the app on our raspberry pi 3B which has lineageOS installed and has necessary cameras attached and we have also tried running other apps that use camera on it and it worked perfectly. But, when I ran our app on it, it started, showed the animation that it was supposed to show and nothing else happened, like the app didn't crash, we also noticed the camera turning on and off a few times, but that's it. From the logs, I could see the app never runs the code in the setAnalyzer() block. Here's the code for the relevant part.
model=new LocalModel.Builder()
.setAssetFilePath("model.tflite")
.build();
CustomImageLabelerOptions customImageLabelerOptions=new CustomImageLabelerOptions.Builder(model)
.setConfidenceThreshold(.98f)
.setMaxResultCount(1)
.build();
labeler= ImageLabeling.getClient(customImageLabelerOptions);
analysis=new ImageAnalysis.Builder().setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.setTargetResolution(new Size(1280, 720))
.build();
Log.i(TAG, "before the analysis starts");
analysis.setAnalyzer(ContextCompat.getMainExecutor(this), image -> {
Log.i(TAG, "Analysis started");
int rotationDegrees = image.getImageInfo().getRotationDegrees();
#SuppressLint("UnsafeOptInUsageError") Image mediaImage=image.getImage();
if(mediaImage!=null){
InputImage i=InputImage.fromMediaImage(mediaImage, rotationDegrees);
labeler.process(i).addOnSuccessListener(new OnSuccessListener<List<ImageLabel>>() {
#Override
public void onSuccess(#NonNull #NotNull List<ImageLabel> imageLabels) {
Log.i(TAG, "successfully started to process the image");
String labels="";
for(ImageLabel label: imageLabels){
Log.i(TAG, label.getText());
labels=label.getText();
Log.i(TAG, labels);
}
if(labels.equalsIgnoreCase("dew")) {
isDetectingBottles=true;
d.stop();
imageView.setBackgroundResource(R.drawable.unnffffamed);
}
else{
if(isDetectingBottles){
isDetectingBottles=false;
imageView.setBackgroundResource(R.drawable.blink_animation);
d= (AnimationDrawable) imageView.getBackground();
d.start();
}
}
image.close();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull #NotNull Exception e) {
Log.i(TAG, "ImageLabeling process failed");
e.printStackTrace();
image.close();
}
});
}
});
CameraSelector selector= CameraSelector.DEFAULT_BACK_CAMERA;
Log.i(TAG, "before binding to lifecycle");
ListenableFuture<ProcessCameraProvider> m=ProcessCameraProvider.getInstance(this);
m.addListener(new Runnable() {
#Override
public void run() {
try {
m.get().bindToLifecycle((LifecycleOwner) MainActivity.this, selector, analysis);
}
catch(InterruptedException e){
e.printStackTrace();
}
catch(ExecutionException e){
e.printStackTrace();
}
}
}, ContextCompat.getMainExecutor(this));
Here are a few thing I tried:
At the beginning I didn't set any target resolution and left it to camerax but it still didn't work back then.
I tried using different cameras with the selector, using the front camera leads to a crash.
Tried calling image.close() at the end of setAnalyzer block, but that's obviously not the issue since it works on other devices.
NOTE: the logs don't show any exceptions as for me to get an idea of what's happening.

SeekTo initially in Android's Mediaplayer makes mediaplayer not work

This is the method where I create my Mediaplayer and set it's source, but directly after I call seekTo it does't play anymore (If I give it some time-depends on the audio, it worksm--> Conclusion after debug).
public void makeAudio(boolean isInit){
try{
if(!isInit){
mediaPlayer = new MediaPlayer();
}
soundSource = episode.getAudio();
mediaPlayer.setDataSource(soundSource);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
soundLength = mediaPlayer.getDuration();
seekBar.setMax(soundLength/1000);
mediaPlayer.seekTo(progress);//the problem I guess
}
});
}catch (Exception e){
e.printStackTrace();
}
}
It shows me this error message:
E/MediaPlayerNative: Attempt to perform seekTo in wrong state: mPlayer=0x706c23ebc0, mCurrentState=0
I would like to have any suggestion about this, because I want to make my mediaplayer go to the progress value(I get it from my intent).
I suggest you to use ExoPlayer, it is an improved version of MediaPlayer and addListener works better for online audio.
You have to add listener until it is prepared and only then you can get the duration:
exoPlayer.addListener(new Player.Listener() {
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == ExoPlayer.STATE_READY) {
long realDurationMillis = exoPlayer.getDuration();
seekBar.setMax((int)realDurationMillis/1000);
dialog.dismiss();
}
if (playbackState == ExoPlayer.STATE_ENDED){
performEndExoPlayer();
}
}
});
Here is an example you can have a look https://developer.android.com/codelabs/exoplayer-intro#5

MediaPlayer delay 0.4 seconds for Bluetooth headset

I'm developing an application with playing audio. In several cases I change the AudioStreamType to AudioManager.STREAM_RING(is mode when music is playing both: speakers and headset). When I use Bluetooth headset, I have a small annoying delay.
So i was reading that Bluetooth has a buffer and and this is logical
, but how I can solve this? Also i tried to change buffer size or delay for mediaPlayer.
So, i create a mediaPlayer like as:
#Override
public void onInit() {
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setLooping(true);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_RING);
songManager = new SongsManager(context);
}
#Override
public void onPrepare() {
// prepare media player
if (mediaPlayer != null) {
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_RING);
absolutePathToPlayingSong = /*some place*/;
mediaPlayer.setDataSource(/*some place*/);
mediaPlayer.prepare();
mediaPlayer.setVolume(volumeLvl, volumeLvl);
}
AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audio.setStreamVolume(AudioManager.STREAM_MUSIC, 20, 0);
}
then i just start player:
mediaPlayer.start();
So, i already tried:
to change a prepare() to prepareAsync() - probably it was tiny help, to may be i had a sound hallucinations. Unfortunately it broke a seekTo() in one place
added onPrepared() and start playing from listener - I not sure that it help
Give me please any advance^ how to fix delay for Bluetooth headset? I checked this device in YouTube application and it work great. So problem in my application. sorry my bad English!)
I have 2 target devices android 7.0(SDK 24) and android 4.2 (SDK 16)

How to start a second media player ..?

I am developing an App where I want to play two mp3 files one is background music and another audio plays after 20 seconds.
mediaPlayer = MediaPlayer.create(this, R.raw.testsong_20_sec);
mediaPlayer1 = MediaPlayer.create(this,R.raw.sound3 );
private void buttonClick(){
if (buttonPlayStop.getText() == getString(R.string.play_str)) {
buttonPlayStop.setText(getString(R.string.pause_str));
try
{
mediaPlayer.start();
mediaPlayer1.start();
startPlayProgressUpdater();
}
catch (IllegalStateException e) {
mediaPlayer.pause();
}
}
Use MediaPlayer to play background music and SoundPool for everything else.
You can play two files in Mediaplayer by using this piece of code in a thread(don't use UI thread for this) :
mediaplayer = new MediaPlayer();
mediaplayer.reset();
//For media file 1
mediaplayer.setDataSource(dataSourceOne);
mediaplayer.prepare();
mediaplayer.start();
Thread.sleep(500);//Set the time as per your need.
//For media file 2
mediaplayer.reset();
mediaplayer.setDataSource(dataSourceTwo);
mediaplayer.setLooping(true);
mediaplayer.prepare();
mediaplayer.start();
As per the better implementation perspective, write an util class with all the common methods (play(),pause(),stop()) and call every method from your class based on the requirement using a thread.

Android media player stop playing while in background

I'm making music player app with simple functionality. But when I listen music on my phone with Android 6, sometimes music stops playing until I turn on display again with power button. Then next song is playing, so it seems like it's problem with loading next song. I tried to write new app just to test it out, for this purpose I used this tutorial:
https://code.tutsplus.com/tutorials/background-audio-in-android-with-mediasessioncompat--cms-27030
To this example I added ArrayList with paths to songs. In mediaPlayer onCompletionListener I increase track counter and load new song to media player.
My code:
private void initMediaPlayer() {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setVolume(1.0f, 1.0f);
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer)
{
onTrackCompletion();
}
});
private void onTrackCompletion()
{
NextTrack();
Play();
}
private void NextTrack()
{
playlistPosition++;
if (playlistPosition == playlists.get(playlistCurrent).size){
playlistPosition = 0;
}
sendAction(ACTION_TRACK_NEXT);
if(mMediaPlayer.isPlaying()){
Pause();
}
loadSong();
Play();
}
private void loadSong()
{
String path = playlists.get(playlistCurrent).getPath(playlistPosition);
if(path == null || path == "")
{
return;
}
try
{
try
{
mMediaPlayer.setDataSource(path);
} catch( IllegalStateException e ) {
mMediaPlayer.release();
initMediaPlayer();
mMediaPlayer.setDataSource(path);
}
initMediaSessionMetadata();
} catch (IOException e) {
return;
}
try {
mMediaPlayer.prepare();
} catch (IOException e) {}
sendTrackData();
}
I don't know anymore why this doesn't work. In manifest I have WAKE_LOCK permission. I also set wake lock for Media player.
Edit:
Today I tried to move loading song into onPlayFromMediaId. I made broadcast from AutoActivity where is Media player to Main Activity and send back onPlayFromMediaId with path to song. But seems like this doesn't work either.I also find out that changing volume with buttons also wake up app.
Edit2:
I made many tests and added debug string in many places in code. And I found out that app stops at mediaplayer.prepare() until I trigger any action on phone (turn on display, volume up/down, click headset button). But I don't know how to fix this bug. I tried to use prepareAsync, but didn't help.
Unless you use foreground service, the system will kill your process and mediaplayer will stop.
below is a part from from a foreground service ( notification example).
builder.setContentTitle(aMessage) // required
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText(this.getString(R.string.app_name)) // required
.setAutoCancel(false)
.setContentIntent(pendingIntent)
.setVibrate(new long[]{0L})
.setPriority(Notification.PRIORITY_HIGH);
int mId = 1489;
startForeground(mId, builder.build());
The above code is tested and working fine.

Categories

Resources