Playing 2 musics through 2 different sound cards at same time - java

Trying something pretty out of the box... I have a simple app with a button that when pushed, plays music out of the audio jack of my android tablet.
public void btn1 (View view) {
MediaPlayer mp = MediaPlayer.create(this, R.raw.xxx);
mp.start();
}
I've now added a usb audio interface (through a micro usb adapter) and I can hear audio out of it.
I'm able to list the sound cards with this
AudioDeviceInfo[] devices = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
for (AudioDeviceInfo device : devices) {
int b = device.getId();
int d = device.getType();
CharSequence productName = device.getProductName();
}
How do I route music so that I can play 2 different music at once, one through usb and the other through the headphone jack?

According to the MediaPlayer documentation, you can set the audio device using setPreferredDevice which receive an AudioDeviceInfo as a parameter, see https://developer.android.com/reference/android/media/MediaPlayer.html#setPreferredDevice(android.media.AudioDeviceInfo).
You will then have to create one MediaPlayer to play on each device.

it works about like this:
protected void playAudio() {
this.playByDeviceIdx(0, R.raw.xxx);
this.playByDeviceIdx(1, R.raw.yyy);
}
protected void playByDeviceIdx(int deviceIndex, #IdRes int resId) {
/* obtain audio-output device-infos */
deviceInfos[] devices = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
/* check, if the desired index is even within bounds */
if(deviceInfos.length < deviceIndex) {
/* create an instance of MediaPlayer */
MediaPlayer mp = MediaPlayer.create(this, resId);
/* assign a preferred device to the MediaPlayer instance */
mp.setPreferredDevice(deviceInfos[deviceIndex]);
/* start the playback (only if a device exists at the index) */
mp.start();
}
}
you could also filter for the headset jack plug/unplug event:
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
Intent intent = context.registerReceiver(null, intentFilter);
boolean isConnected = intent.getIntExtra("state", 0) == 1;
sources: me, based upon the SDK documentation for the MediaPlayer.

Related

Android Studio Mediaplayer

I am a completely begginer guy in Android Studio and mobile apps in general. I used to create websites on Wordpress and i don't have so much experience on coding. Recently i started experimenting with mobile apps and mostly Android Studio. I bought a template for a Logo Quiz game and i managed to make it run without errors and publish it in Play Store as my first game. The player can see a part of the logo and guess the brand name using the given letters
But i would like to use the same template with new graphics and create a music quiz.
Instead of the logo guess game, the player will be able to listen a part of a song and guess the song's title.
The current project is getting the file names from a database stored in assets/databases folder.
So i managed to add start, pause and stop buttons in my activity_play.xml and succesfully created a mediaplayer in activityPlay.java file like:
public void music(View view) {
switch (view.getId()){
case R.id.button:
// Check if mediaPlayer is null. If true, we'll instantiate the MediaPlayer object
if(mediaPlayer == null){
mediaPlayer = MediaPlayer.create(this, R.raw.music);
}
// Then, register OnCompletionListener that calls a user supplied callback method onCompletion() when
// looping mode was set to false to indicate playback is completed.
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
// Here, call a method to release the MediaPlayer object and to set it to null.
stopMusic();
}
});
// Next, call start() method on mediaPlayer to start playing the music.
mediaPlayer.start();
break;
case R.id.button2:
if(mediaPlayer != null) {
// Here, call pause() method on mediaPlayer to pause the music.
mediaPlayer.pause();
}
break;
case R.id.button3:
if(mediaPlayer != null){
// Here, call stop() method on mediaPlayer to stop the music.
mediaPlayer.stop();
// Call stopMusic() method
stopMusic();
}
break;
}
}
private void stopMusic() {
mediaPlayer.release();
mediaPlayer = null;
}
// Call stopMusic() in onStop() overridden method as well.
#Override
protected void onStop() {
super.onStop();
stopMusic();
}
The above code can succesfully play the music.mp3 file located in raw folder. The app i bought is using the following code to load the images and display them for each level:
String image_a = listDataBase.get(1);
String image_q = listDataBase.get(2);
if (isTrue == 1) {
String imgPath;
if (numImage == 0) {
imgPath = "file:///android_asset/logos/" + image_a;
} else {
imgPath = "file:///android_asset/logos/" + image_q;
}
Picasso.get().load(imgPath).into(imageView);
linearLayoutNullClick.setVisibility(View.VISIBLE);
recyclerViewKeys.setVisibility(View.GONE);
trueLogo = 2;
} else {
String imgPath = "file:///android_asset/logos/" + image_q;
Picasso.get().load(imgPath).into(imageView);
recyclerViewKeys.setVisibility(View.VISIBLE);
recyclerViewLogoKeys.setVisibility(View.VISIBLE);
}
So is it possible to use the same code and load the imgPath into mediaPlayer = MediaPlayer.create(this, R.raw.music);
I tried loading imgPath directly to mediaplayer like this but didn't work:
mediaPlayer = MediaPlayer.create(this, imgPath);
Then i tried:
private String audioPath;
audioPath = imgPath;
mediaPlayer = MediaPlayer.create(this, audioPath);
but also didn't work.
Tried many more methods i found on the web, but always i am missing something
As i said before i am a newbie in coding and programming so the solution probably will be very easy .
Anyone can help please?
Are you sure you are getting a audio path in your imgPath object?
Then you can try getting actual storage path from device using code mentioned
here
If you change the value in the database of pic_1.png with audio_1.mp3
then path will start like:
"file:///android_asset/logos/" + YOUR_AUDIO;
So are you sure audio exists in this path?

mediaPlayer.release() crashes my app java

I have a project where I added a MediaPlayer in a custom Array Adapter and I make it take the Resource ID of the audio file from the Array List the problem is that I want to release the media player after the audio completes but every time I try to add release in OnCompletion and try to press a view while the media player plays a sound the app crashes .. I searched online and found a code but it gives me an error and I can't find the actual reason for such a crash.
that's the code for the on Click Listener and the Media player:
final MediaPlayer mediaPlayer = MediaPlayer.create(getContext(), currentWord.getVoiceResourceID());
// Wait for user's input by his click on the list's item to play the sound.
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
// Storing the return value of getVoiceResourceID() into mVoice.
// I think this line can be ignored so we call the method inside the creation of the Media Player.
// Creating our media player and put our track on it.
mediaPlayer.selectTrack(currentWord.getVoiceResourceID());
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mediaPlayer.release();
}
});
}
};
I hope I could fix that problem.

playing sounds on simultaneous button presses

In my Launchpad Simulator there are a lot of Buttons on the main activity. I want to play sound on each button press. If the buttons are pressed simultaneously, I want to play the sound simultaneously. From what I made uptil now, it seems that Whenever I press buttons it does play the sound, but since the first sound is 3 seconds long (eg. a clap sound file is 3 seconds long in its playtime).
Before any other sound is produced through buttons, it waits 3 seconds and the plays the next sound if any button is pressed after 3 seconds and same with other 32 buttons.
Just like a launchpad as soon as I press buttons I want a sound to be played. In this case the clap sound.
Here is the Java Code:
MainActivity.java
package com.oniichansblog.launchpadify;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.media.MediaPlayer;
public class MainActivity extends AppCompatActivity {
private MediaPlayer clap1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
clap1 = MediaPlayer.create(this, R.raw.clap1);
}
public void clap1(View v){
clap1.start();
}
}
I only have this one function clap1() that is being called over and over everytime I press a button.
if you want to check it for yourself I have a repository:
GitHub Repository for LaunchPadify
I'd recommend to not define the MediaPlayer above.
Just create a new temporary MediaPlayer every ButtonClick
new MediaPlayer.create(this, R.raw.clap).start();
and it will play sounds simultaneously
UPDATE
If you want to destroy a MediaPlayer after it finishes playing the sound, you can do this by using this code
new MediaPlayer.create(getApplicationContext(), R.raw.test)
.start()
.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.release();
}
});
To play several tracks simultaneously you should use AsyncTask and execute it on THREAD_POOL_EXECUTOR.
How to do this:
Thread class:
class PlayThread extends AsyncTask<MediaPlayer, Void, Void>
{
#Override
protected Void doInBackground(MediaPlayer... player) {
player[0].start();
return null;
}
}
Media Players:
MediaPlayer[] players = new MediaPlayer[5];
//Then set source to each player...
//...
//Create objects of Thread class
PlayThread[] playThreads = new PlayThread[5];
for (int i = 0; i < 5; i++)
playThreads[i] = new PlayThread();
//Set Media Players there and start play
for (int i = 0; i < 5; i++)
playThreads[i].executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, players[i]);
AsyncTask can execute only 5 Threads simultaneously, other are going to queue.
SoundPool buffer limit is 1Mb, so it is not a solution at all.
It is very important:
To play simultaneously more audio tracks you should mix them into 1 buffer.
The way to do this: decode mp3 to pcm (to small buffers in stream mode), mix it into one byte buffer and put it to AudioTrack for playing.

Android Wear Communicate With Phone Hardware

Hi I have this simple code on Android Wear I need a bit of help everything works well if I'm using the phone alone the problem I have is that I taught Android wear will use automatically the Phone hardware for sound and all that good stuff.
Here is my test code
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
#Override
public void onLayoutInflated(WatchViewStub stub) {
imageButtonOne = (ImageButton) findViewById(R.id.imageButtonOne);
textviewOne = (TextView) findViewById(R.id.textviewOne);
imageButtonOne.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
textviewOne.setText("Hello World!");
soundOne() ;
}
});
}
public void soundOne() {
try {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone one = RingtoneManager.getRingtone(getApplicationContext(), notification);
one.play();
} catch (Exception e) {
e.printStackTrace();
}
// MediaPlayer media = MediaPlayer.create(this, R.raw.sound_file_1);
// media.start() ;
// Toolkit.getDefaultToolkit().beep() ;
}
});
It call the sound but because watches doesn't have speakers won't sound. I want the phone to make the sound. Please if someone can help me will be appreciated.
While Android Wear devices will play sound if a bluetooth headset is attached, if you need sound to play on the phone you need to use the Wearable Data Layer and probably more specifically the Message API to send a message to your phone app. Your phone app would implement a WearableListenerService which would be triggered by the incoming message and would play the sound on the phone.
Note: it is much more common for Wear apps to vibrate (via the Vibrator to draw attention rather than play sounds on the phone. Many Wear users use the 'Mute connected phone' option to effectively silence their phone so a sound coming from it may be quite unexpected.

Using Videoview or mediaplayer to play http live streaming video is LAG

First,I built a small app using videoview to play hls video with mp4 format on Samsung galaxt S2.With SD quality, video was smooth.But with HD quality,video was lag. Then, I built a larger app to play hls video using same videoview or mediaplayer android. When i played video, video was lag with SD and HD quality.
In small app, I have a string array to store URLs. My app allows user to choose a URL and push a button to throw a activity to play video using videoview:
Code using videoview in the small app :
VideoView vd = (VideoView)findViewById(R.id.videoView1);
MediaController mc = new MediaController(this);
mc.setAnchorView(vd);
Uri uri = Uri.parse(URL_link);
vd.setMediaController(mc);
vd.setVideoURI(uri);
vd.start();
In larger app, I using listfragment to display all URls. User choose a URLs, then throw a activity to playvideo using videoview. Code in the activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_channel_detail);
TextView tv = (TextView) findViewById(R.id.tvVideoPlayer);
Bundle extras = getIntent().getExtras();
if (extras != null) {
channel_id = extras.getInt(ChannelDetailActivity.CHANNEL_ID);
}
tv.setText("Video is playing...");
}
#Override
protected void onStart() {
super.onStart();
getChannelInfo();
}
private void getChannelInfo( ) {
TimeTVApiCaller.getInstance().getChannel(channel_id, this,
new AjaxCallback<ChannelInfo>() {
#Override
public void callback(String url, ChannelInfo object,
AjaxStatus status) {
if (object != null) {
Urlvideo = object.getChannelUrls().get(0).getPath();
getURLfull(Urlvideo);
}
}
});
}
//get a full URL
protected void getURLfull(String url)
{
TimeTVApiCaller.getInstance().getChannelStream(url, this, new AjaxCallback<String>()
{
#Override
public void callback(String url, String object,
AjaxStatus status) {
String Urlfull = object.replace("\"", "");
Urltoken = Urlfull;
//Using the same videoview
VideoView vd = (VideoView) findViewById(R.id.videoView1);
MediaController mc = new MediaController(ChannelDetailActivity.this);
mc.setAnchorView(vd);
Uri uri = Uri.parse(Urltoken);
vd.setMediaController(mc);
vd.setVideoURI(uri);
vd.start();
//vd.requestFocus();
}
});
}
}
I have two questions :
Why videoview or mediaplayer play hls video is lag?
How to custom videoview or mediaplayer to play hls video smoothly?
Each segment in HLS aka HTTP Live Streaming is typically 10 seconds.
The player measures the time it takes to get each segment, if it took too long it will try to pick a bandwidth where it can get a segment or more before it plays it. And the most common error is buffering delays.
You should look in the log file to see what the player is doing when playing content.
If the above is not helpful, this might help.
I assume HD quality is at least 720p and more than 1.5 mbps bit stream with h.264/avc encoding. My best guess is that S2 Hardware doesn't support it.

Categories