I have a wav file called 'new.wav' and I want to play it via MediaPlayer and AudioTrack in android:
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "new.wav";
File f = new File(baseDir + File.separator + fileName);
byte[] b = null;
try {
b=this.readFile(f);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.i("123"," "+"length is "+b.length);
truncated=new byte[b.length-44];
truncated=Arrays.copyOf(b, b.length-44);
at=new AudioTrack(AudioManager.STREAM_MUSIC, 48000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, truncated.length /* 1 second buffer */, AudioTrack.MODE_STREAM);
at.write(truncated, 0, truncated.length);
at.play();
mp = new MediaPlayer();
try {
mp.setDataSource(baseDir + File.separator + fileName);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
After having tried both methods, I found that their sound is not the same, the AudioTrack is not outputing the original sound in the wav file. I think my sample rate is fine, can someone help me with this issue? THank you!
As I said in the comments above, the problem is the choice of channels.
Related
I have an App that is receiving a video file from another App that is working as a Server. While the App is saving the file received on the socket, the video stream starts playing the file (which is under construction). In the code sample, after I press the btnStream, I press the btnPlay and App runs successfully. However, if the playing rate is greater than the download rate, an error will occur. I want to avoid this case. So I need to have a listener on the Video Playing that will pause the videoview when it predicts that this error will occur. I know a solution where if I know the video size, I can counter the bytes received and monitor how many seconds have been buffered and see if the videoview should pause or not. However, is it possible to do it without knowing the video file size? Or having two threads that depends on each other? Thanks.
Note: the VideoView used is a custom one where it can play FileDescriptor.
btnStream.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
String s = etURL.getText().toString();
String ip = "10.0.0.24";
int port = 7878;
mct= new VideoDownloadTask(ip,port);
mct.execute();
}});
final MediaController mediaController = new MediaController(this);
mediaController.setAnchorView(mVideoView);
Button btnPlay = (Button) findViewById(R.id.button2);
btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
mVideoView.setVideoFD((new FileInputStream(new File("/sdcard/tempVideo.mp4")).getFD()));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mVideoView.seekTo(0);
mVideoView.start();
}
});
}
public class VideoDownloadTask extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String response = "";
Socket socket=null;
VideoDownloadTask(String addr, int port){
dstAddress = addr;
dstPort = port;
}
#Override
protected Void doInBackground(Void... arg0) {
try {
socket = new Socket(InetAddress.getByName(dstAddress), dstPort);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
try {
if(socket!=null)socket.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
File f = new File("/sdcard/tempVideo.mp4");
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DataInputStream in=null;
try {
in = new DataInputStream (socket.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FileOutputStream videoFile = null;
try {
videoFile = new FileOutputStream(f);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int len;
byte buffer[] = new byte[8192];
try {
while((len = in.read(buffer)) != -1) {
videoFile.write(buffer, 0, len);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
videoFile.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
Toast.makeText(getApplicationContext(), "Done Downloading File",
Toast.LENGTH_LONG).show();
super.onPostExecute(result);
}
}
}
I applied a simple solution that resolved the problem. I am sharing it if anyone is having the same problem. The solution was simply to add an error listener to the videoView that will block the error popups and pauses the video.
mVideoView.setOnErrorListener(new OnErrorListener(){
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub
statusText.setText("ERROR PLAYING VIDEO");
mVideoView.pause();
return true;
}
});
pDialog = new ProgressDialog(PlayVideoActivity.this);
pDialog.setTitle("Gajacharitra");
pDialog.setMessage("Buffering video...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
try {
// Start the MediaController
mediacontroller.setAnchorView(mVideoView);
// Get the URL from String VideoURL
Uri video = Uri.parse(mVideoURL);
mVideoView.setMediaController(mediacontroller);
mVideoView.setVideoURI(video);
mVideoView.requestFocus();
mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
// Close the progress bar and play the video
public void onPrepared(MediaPlayer mp) {
pDialog.dismiss();
mVideoView.start();
}
});
mVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
mVideoView.pause();
pDialog.dismiss();
Toast.makeText(PlayVideoActivity.this, "Can't play this video.", Toast.LENGTH_LONG).show();
finish();
return true;
}
});
} catch (Exception e) {
/*Log.e("Error", e.getMessage());
e.printStackTrace();*/
pDialog.dismiss();
Toast.makeText(PlayVideoActivity.this, "Can't play this video.", Toast.LENGTH_LONG).show();
finish();
}
External storage works, but not internal storage. Am I missing out on something fundamentally from the android storage mechanism?
thanks
public static void playSound()
{
//String path = internalPath + "/www/sounds/" + "SIREN.WAV"; // doesnt work
//String path = "file:///data/data/com.myproject.d08062014f/files/www/sounds/SIREN.WAV"; // doesnt work
//String path = "/data/data/com.myproject.d08062014f/files/www/sounds/SIREN.WAV"; // doesnt work
// all above does not work
Log.d("command", "command:" + path); // to check path string
String path = "file:///mnt/sdcard/media/audio/notifications/facebook_ringtone_pop.m4a"; // This one works!
MediaPlayer mMediaPlayer = new MediaPlayer();
try {
mMediaPlayer.setDataSource(path);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
mMediaPlayer.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mMediaPlayer.start();
}
Update on 09-10-2014
stackoverflow.com/a/4955915/856007 – Abdullah Shoaib Aug 12 at 7:49
thank you for the reference link below, I was able to get it working with
File file = new File(path); // acquire the file from path string
FileInputStream inputStream = new FileInputStream(file);
mMediaPlayer.setDataSource(inputStream.getFD());
inputStream.close();
I have a ListView with some items and each item plays a certain sound. This is the code:
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
try {
player.setDataSource(externalStoragePath + "/Android/data/com.whizzappseasyvoicenotepad/" + recordedFilesArray.get(arg2) + ".mp3");
player.prepare();
player.start();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
If I click an item and it starts playing and then click another item before the one I clicked before has finished playing, the MediaPlayer will just play both sounds at the same time. How do I get my MediaPlayer to stop() playing the previous sound and start playing the new sound if I have clicked the item before it stopped playing?
I tried adding player.Stop() before try, so that everytime I click an item, the MediaPlayer stops before setting a new source and starting again, but that just stops the previous sound and won't play the new sound.
I also tried adding IF statement, like this:
if (!player.isPlaying()){
//normally start the player
}
else if (player.isPlaying()){
//stop it before starting it again
}
I'd copy my actual code but I already deleted it since it didn't work. It also just stopped the previous sound and didn't play the new one.
Reset your player after stopping song.
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
try {
if (player!=null && player.isPlaying())
{
player.stop();
player.reset();
}
player.setDataSource(externalStoragePath + "/Android/data/com.whizzappseasyvoicenotepad/" + recordedFilesArray.get(arg2) + ".mp3");
player.prepare();
player.start();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
You have to call setDataSource() in the idle state. So you have to call reset() before calling setDateSource()
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
try {
player.reset();
player.setDataSource(externalStoragePath + "/Android/data/com.whizzappseasyvoicenotepad/" + recordedFilesArray.get(arg2) + ".mp3");
player.prepare();
player.start();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
try {
stopPlaying();
initializeMediaPlayer(externalStoragePath + "/Android/data/com.whizzappseasyvoicenotepad/" + recordedFilesArray.get(arg2) + ".mp3");
startPlaying();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
private void stopPlaying() {
if (player!=null && player.isPlaying()) {
player.stop();
player.release();
}
}
private void initializeMediaPlayer(String path) {
player = new MediaPlayer();
try {
player.setDataSource(path);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void startPlaying() {
try {
player.prepareAsync();
player.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
if(player!=null)
player.start();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
to reuse MediaPlayer, you must call reset() before setting new dataSource. One more thing, you should not call prepare() in UI thread, it may cause ANR error. You would rather call prepareAsync() function.
I'm developing an Android application and I do this to save a bitmap into internal storage:
protected void onPostExecute(Bitmap profilePicture)
{
FileOutputStream fOut = null;
try
{
fOut = openFileOutput(Constants.FB_PROFILE_IMAGE_FILE_NAME, Context.MODE_PRIVATE);
profilePicture.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
fOut.flush();
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try
{
fOut.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
loadingDialog.dismiss();
}
How can I do to open it and show it into an ImageView?
This code doesn't work because imgFile doesn't exist:
private void loadAndShowUserProfileImage()
{
File imgFile = new File(Constants.FB_PROFILE_IMAGE_FILE_NAME);
if(imgFile.exists())
{
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
userImageProfile.setImageBitmap(myBitmap);
}
}
FileInputStream fIn = openFileInput(Constants.FB_PROFILE_IMAGE_FILE_NAME);
Bitmap myBitmap = BitmapFactory.decodeStream(fIn);
openFileOutput/openFileInput should be always used in pair
got my code working. Just having a little trouble with one part.
public void picksound(){
Intent mIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(mIntent, 1);
}
public void onActivityResult(int requestCode, int resultCode, Intent mIntent) {
if (resultCode == RESULT_OK && null != mIntent) {
if (requestCode == 1) {
Uri selectedRing = mIntent.getData();
}
}}
private void playSong(String selectedRing){
MediaPlayer mp = new MediaPlayer();
try {
mp.setDataSource(selectedRing);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.start();
}
public void alarmmsg(){
//ringtone player
playSong(selectedRing);
//
So that's the code I am working with. When I try to call the playSong function, I am asked for a string, and the only string it seems to accept is "null". Can someone help to see what I've done wrong?
Try changing this line :
MediaPlayer mp = new MediaPlayer();
To this:
MediaPlayer player = MediaPlayer.create(this, Uri.parse("http://www.urltofile.com/file.mp3"));