Sound Plays from Smarthpone Speakers instead Android Auto Speakers - android

I am new to Android Auto and still trying to figure it out.
I have successfully played music from my own programmed app but the music is coming out from my smartphone speakers instead of car speakers. Other (sample) apps do it the right way.
Which part of of the Media System is responsible to handle this behaviour? Android documentation says the sound is sent to the car speakers.
#Override
public void onPlayFromMediaId(String mediaId, Bundle extras) {
this.mPlayingQueue.add(item);
session.setActive(true);
session.setQueue(mPlayingQueue);
session.setQueueTitle("My Queue");
session.setPlaybackState(buildState(PlaybackState.ACTION_PLAY));
session.setMetadata(createRammsteinMetaData());
this.mediaPlayer = MediaPlayer.create(getBaseContext(), R.raw.rammstein_sonne);
this.mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
if (tryToGetAudioFocus()) {
this.mediaPlayer.start();
Log.d("AUDIOTAG", "Playing");
} else {
Log.d("AUDIOTAG", "Playing not possible, no focus");
}
}
private boolean tryToGetAudioFocus() {
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
return result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}
Thanks in advance. Orrimp

There seems to be a pretty big bug there! Local music from resources does not play properly using MediaPlayer.create(...);
Thx Reaz Murshed I just tried to use the STREAM_MUSIC as a real stream with Internet Music and it works.
Translate to use setDataSource with Resource URI!
Use the following snippet:
#Override
public void onPlayFromMediaId(String mediaId, Bundle extras) {
/* Set session stuff like queue, metadata and so on*/
Uri myUri = resourceToUri(getBaseContext(), R.raw.rammstein_sonne);
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(getBaseContext(), myUri);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
if (tryToGetAudioFocus()) {
mediaPlayer.start();
Log.d("AUDIOTAG", "Playing");
} else {
Log.d("AUDIOTAG", "Playing not possible, no focus");
}
}
});
} catch (IOException e) {
e.printStackTrace();
Log.d("AUTO", "EERORROR");
}
}
public Uri resourceToUri(Context context, int resID) {
return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
context.getResources().getResourcePackageName(resID) + '/' +
context.getResources().getResourceTypeName(resID) + '/' +
context.getResources().getResourceEntryName(resID));
}

Related

NullPointerException in MediaPlayer after pressing the home button and reopening the app

This is my code, I want to keep music playing when the app is in background. And I want to be able to pause it when I re-open the app. The music should play in the background, but for some reason media player returns null pointer when I re-open it. So, when I pause it, it crashes.
public void play(View view) {
if (status) {
status = false;
requestRecordAudioPermission();//audio permission
startPlay();//start mediaplayer
} else {
status = true;
mediaPlayer.pause();
}
}
public void startPlay() {
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(URL_LINK);
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(HomeActivity.this, "CAN'T PLAY!",Toast.LENGTH_LONG).show();
}
mediaPlayer.start();
}
Why Media Player returns null after pressing the home button and reopening the app?
Thanks for help
If you are streaming audio from an url then try to load the Media Player asynchronously.
String url = "YOUR_URL";
MediaPlayer myMediaPlayer = new MediaPlayer();
myMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
myMediaPlayer.setDataSource(url);
myMediaPlayer.prepareAsync();
} catch (IOException e) {
Toast.makeText(this, "mp3 not found", Toast.LENGTH_SHORT).show();
}
myMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer player) {
player.start();
}
});

Audio Playing But Video not Showing in VideoView Android (Black Screen in Low Internet)

I am Working on Video Streaming in Android. when I want to play video in Low Internet Speed video is not appear in the VideoView show black Screen but Audio is playing fine. i have see these links link1 and link2 . But these link couldn't help me. Here is my code snapshot:-
private void playvideo(String url){
final MediaController mediacontroller;
try {
mediacontroller = new MediaController(MainActivity.this);
mediacontroller.setAnchorView(videoView);
final Uri video = Uri.parse(url);
videoView.setMediaController(mediacontroller);
videoView.setVideoURI(video);
videoView.requestFocus();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
// Close the progress bar and play the video
public void onPrepared(MediaPlayer mp) {
mp.start();
mp.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mediaPlayer, int what, int extra) {
if (extra == MediaPlayer.MEDIA_ERROR_SERVER_DIED
|| extra == MediaPlayer.MEDIA_ERROR_MALFORMED) {
Log.e(TAG , "MEDIA_ERROR_SERVER_DIED && MEDIA_ERROR_MALFORMED");
Toast.makeText(MainActivity.this , "Server Died or Malformed" , Toast.LENGTH_LONG).show();
return true;
} else if (extra == MediaPlayer.MEDIA_ERROR_IO) {
Log.e(TAG , "MediaPlayer.MEDIA_ERROR_IO");
Toast.makeText(MainActivity.this , "Media Error IO" , Toast.LENGTH_LONG).show();
return true;
}else if (extra == MediaPlayer.MEDIA_ERROR_UNKNOWN){
Log.e(TAG , ".MEDIA_ERROR_UNKNOWN");
Toast.makeText(MainActivity.this , "MEDIA ERROR UNKNOWN" , Toast.LENGTH_LONG).show();
return true;
}
return false;
}
});
mp.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
#Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int percentage) {
Log.e(TAG , "onBufferingUpdate :- " + percentage);
}
});
progressBar.setVisibility(View.GONE);
videoView.start();
}
});
} catch (Exception e) {
Log.e("Error", e.getMessage());
progressBar.setVisibility(View.GONE);
Toast.makeText(getApplicationContext() ,"URL is Wrong Test with other URL" , Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
because Audio and Video both are different Streams so in Low Internet somehow it able to download the audio stream but not a video stream, is it ?? so in this case, it is possible to show a message to the user like "you have Low Internet Try Again" and not to play Audio ??
thanks
Try to use Exoplayer which is an alternative to Android’s MediaPlayer API for playing audio and video both locally and over the Internet.
https://github.com/google/ExoPlayer
I recommend you to use SurfaceView.
surfaceView = (SurfavceView) findView.....;
holder = surfaceView.getHolder();
holder.addCallback(this); // implement SurfaceHolder.Callback methods
Then in surfaceCreated method:
mediaPlayer.setDisplay(holder);
mediaPlayer.setDataSource(mVideoUrl);
mediaPlayer.prepareAsync();
You also can use https://github.com/anthorlop/EasyExoPlayer
It use ExoPlayer for Android SDK >= 16 and MediaPlayer for Android < 16.
I hope it works for you.

How can I know if the MediaPlayer is in Stopped state?

I am building an app which plays several videos, and I have two different user scenarios :
Scenario 1. While video 'A' is playing, if user clicks next button, then it stops and play the next video 'B'.
Scenario 2. Play video 'A', and if it's done, user clicks next button and it plays video 'B'.
For the first scenario, I used mediaPlayer.isPlaying() method to detect if it is in Started state and it works fine. However, if I use the same code for the second scenario, isPlaying() throws IllegalStateException.
Here's my code for playing videos :
private void playVideos(SurfaceHolder holder) {
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDisplay(holder);
Uri uri = Uri.parse("android.resource://" + getPackageName() + "/" + video_files[mCounter]);
mediaPlayer.setDataSource(this, uri);
mediaPlayer.prepare();
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
if (mCounter <= 8) {
onVideoCompletion(mediaPlayer);
} else {
mediaPlayer.stop();
mediaPlayer.release();
}
}
});
} catch (IOException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalStateException e) {
}
}
Also, here's my button listener to play next video :
nextBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(mediaPlayer != null) {
if(mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
}
}
mCounter += 1;
if (mCounter <= 8) {
playVideos(holder);
}
}
});
One way that I tried to hack this issue was using a boolean variable instead of isPlaying() method. For example,
boolean mIsPlaying = false;
...
// in button listener
if(mIsPlaying) {
mediaPlayer.stop();
mediaPlayer.release();
}
...
// in playVideos() function
mediaPlayer.start();
mIsPlaying = true;
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
if (mCounter <= 8) {
onVideoCompletion(mediaPlayer);
} else {
mediaPlayer.stop();
mediaPlayer.release();
}
}
});
That works for my both of scenario, but I'm not sure if it's the correct way to do it. Isn't there any way to detect whether mediaPlayer is in Stopped state?
I took a look at Google's Documentation which you can find here. You can only know if the player isPlaying(); or isLooping(); ... So no, there is not an "easy" or "short" way to achieve what you want. Hope it helped.

How to correctly change MediaPlayer audio stream type?

I have a simple mp service to play, pause, resume audio. All works fine.
But, last night I have decided to add a feature for user to route audio to ear-piece or speaker and have been battling with mp.setAudioStreamType().
Problem is that I can't change it while service connected and mp created. I don't want to terminate service and/or unbind and rebind as it would require a lot of refactoring
How do I supposed to change AudioStreamType while playing an audio?
Here is my code:
Player service:
public class PService extends Service {
private MediaPlayer mp = new MediaPlayer();
public static final String PLAYING_FINISHED_MSG = "1";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
mp.stop();
mp.release();
}
private void playSong(String file) {
try {
mp.reset();
mp.setDataSource(file);
mp.setAudioStreamType(MYAPP.getAudioStreamType());
mp.prepare();
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer arg0) {
Intent i = new Intent();
i.setAction(MDService.PLAYING_FINISHED_MSG);
sendBroadcast(i);
}
});
toggle route button onclick
currentlyPlayingFile = file;
currentlyPlayingPhone = phone;
lastDurationBeforePause = mpInterface.getCurrentPosition();
if(MYAPP.getAudioStreamType() == AudioManager.STREAM_MUSIC)
{
MYAPP.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
recording_player_route_button.setImageResource(R.drawable.route_off);
}
else{
MYAPP.setAudioStreamType(AudioManager.STREAM_MUSIC);
recording_player_route_button.setImageResource(R.drawable.route_on);
}
try {
mpInterface.playFile(file);
player_seekbar.setProgress(0);
player_seekbar.setMax(mpInterface.getDuration());
//seekto last millisecond after switching from/to sepaker
if(seekTo>0)
{
mpInterface.seekTo(seekTo);
}
isPauseButtonPressed = false;
handleSeekBarUpdate.postDelayed(handleSeekBarUpdateJob, 1);
} catch (RemoteException e) {
e.printStackTrace();
}
The MODIFY_AUDIO_SETTINGS permission is needed in the Manifest for this to work.
AudioManager am=(AudioManager)getSystemService(Context.AUDIO_SERVICE);
am.setMode(AudioManager.MODE_NORMAL);
MediaPlayer mp=new MediaPlayer();
Uri ringtoneUri=RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
try
{
mp.setDataSource(getApplicationContext(), ringtoneUri);
mp.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
mp.prepare();
mp.start();
}
catch(Exception e)
{
//exception caught in the end zone
}

AudioManager MODE_IN_CALL interferences

I'm using AudioManager to play a sound through earpiece just before a call is placed so I use AudioManager setMode(MODE_IN_CALL).
I'm not having any problems except in Galaxy S3 where after playing the music correctly, ringtone sounds very distorted and very noisy. I've read setMode documentation:
The audio mode encompasses audio routing AND the behavior of the telephony
layer. Therefore this method should only be used by applications that replace
the platform-wide management of audio settings or the main telephony application.
In particular, the MODE_IN_CALL mode should only be used by the telephony
application when it places a phone call, as it will cause signals from the
radio layer to feed the platform mixer.
So I suspect there may be signals from radio layer feeding platform mixer.
So the code I'm using is like this:
am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
speakerWasOn = am.isSpeakerphoneOn();
speakerPrevMode = am.getMode();
bthA2dpWasOn = am.isBluetoothA2dpOn();
bthScoWasOn = am.isBluetoothScoOn();
if (BluetoothBR.bthOn && BluetoothBR.conectarBluetooth()) {
am.setMode(AudioManager.STREAM_VOICE_CALL);
am.setBluetoothA2dpOn(true);
am.setBluetoothScoOn(true);
} else {
am.setSpeakerphoneOn(false);
am.setMode(AudioManager.MODE_IN_CALL);
}
Then I use MediaPlayer to play the .mp3 file in a separated thread:
private OnPreparedListener opl = new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
try {
mp.setVolume(1.0f, 1.0f);
mp.start();
} catch (Throwable e) {
e.printStackTrace();
mp.release();
}
}
};
private OnCompletionListener ocl = new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
stop();
}
};
public void run() {
synchronized (mp) {
FileInputStream fis = null;
try {
fis = new FileInputStream(getMp3FilePath());
mp.setDataSource(fis.getFD());
mp.setOnPreparedListener(opl);
mp.setOnCompletionListener(ocl);
mp.prepare();
fis.close();
} catch (Exception e) {
mp.release();
if (fis != null) {
try {
fis.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
}
public void stop() {
if (mp != null) {
try {
mp.stop();
mp.release();
mp.setVolume(0.5f, 0.5f);
mp.reset();
} catch (Exception ignored) {
}
}
if (BluetoothBR.bthOn) {
BluetoothBR.desconectarBluetooth();
}
}
And when music is done I call:
am.setSpeakerphoneOn(speakerWasOn);
am.setMode(speakerPrevMode);
am.setBluetoothA2dpOn(bthA2dpWasOn);
am.setBluetoothScoOn(bthScoWasOn);
This is only happening on Samsung Galaxy S3 (afaik) and has been tested in S2, Huawei, SonyEricsson, and others and works correctly.
Any Ideas?
Thanks
UPDATE:
I have discovered that all works fine if the thread waits 5 seconds when the music finishes and after setting AudioManager to original state.
am.setSpeakerphoneOn(speakerWasOn);
am.setMode(speakerPrevMode);
am.setBluetoothA2dpOn(bthA2dpWasOn);
am.setBluetoothScoOn(bthScoWasOn);
long ctime = System.currentTimeMillis();
while (System.currentTimeMillis() - ctime < 5000);
I had the same problem. When i commented out this line
am.setMode(AudioManager.MODE_IN_CALL);
All worked fine for me.

Categories

Resources