I'm using this library: https://github.com/alxrm/audiowave-progressbar to give an audio wave effect like Soundcloud music player.
This is how I implemented:
byte[] data = convert(songsList.get(currentSongIndex).get("songPath"));
final AudioWaveView waveView = (AudioWaveView) findViewById(R.id.wave);
waveView.setScaledData(data);
waveView.setRawData(data, new OnSamplingListener() {
@Override
public void onComplete() {
}
});
waveView.setOnProgressListener(new OnProgressListener() {
@Override
public void onStartTracking(float progress) {
}
@Override
public void onStopTracking(float progress) {
}
@Override
public void onProgressChanged(float progress, boolean byUser) {
}
});
This is the method that converts the file to byte array using the said file's path
public byte[] convert(String path) throws IOException {
FileInputStream fis = new FileInputStream(path);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
for (int readNum; (readNum = fis.read(b)) != -1;) {
bos.write(b, 0, readNum);
}
byte[] bytes = bos.toByteArray();
return bytes;
}
Maybe the problem is due to not getting the array asynchronously, but I'm not sure.
Can anyone help me with this?
EDIT: As @commonsware suggested correctly, I did this:
class AudioWave extends AsyncTask<String,Integer,String>{
private Context mContext;
private View rootView;
public MusicPlayerActivity m;
final AudioWaveView waveView = (AudioWaveView) m.findViewById(R.id.wave);
public AudioWave(MusicPlayerActivity m1){
m = m1;
}
// Runs in UI before background thread is called
@Override
protected void onPreExecute() {
super.onPreExecute();
// Do something like display a progress bar
}
byte[] b2;
// This is run in a background thread
@Override
protected String doInBackground(String... params){
// get the string from params, which is an array
String path = params[0];
try {
FileInputStream fis = new FileInputStream(path);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
try {
for (int readNum; (readNum = fis.read(b)) != -1; ) {
bos.write(b, 0, readNum);
}
}catch(IOException e){
}
byte[] bytes = bos.toByteArray();
b2=bytes;
new MusicPlayerActivity().setData(b2);
}
catch (FileNotFoundException e){
}
return "lol";
}
// This is called from background thread but runs in UI
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// Do things like update the progress bar
}
// This runs in UI when background thread finishes
@Override
protected void onPostExecute(String result) {
waveView.setScaledData(b2);
waveView.setRawData(b2, new OnSamplingListener() {
@Override
public void onComplete() {
}
});
waveView.setOnProgressListener(new OnProgressListener() {
@Override
public void onStartTracking(float progress) {
}
@Override
public void onStopTracking(float progress) {
}
@Override
public void onProgressChanged(float progress, boolean byUser) {
}
});
super.onPostExecute(result);
// Do things like hide the progress bar or change a TextView
}
}
Doing I/O on the main application thread will freeze your UI for the duration of that I/O, meaning that your UI will be unresponsive. Moving I/O to a background thread is necessary for a well-behaved UI.
Android's insistence that we can only safely update the UI from the main application thread means that you need to use an AsyncTask
, a Thread
and stuff like runOnUiThread()
, RxJava/RxAndroid, or other approaches to arrange both the background work and updating the UI when that background work is done.
In your case, doing the convert()
logic on a background thread, and updating the waveView
on the main application thread, should help.