Steady sound playing in Android with Mediaplayer - android

I'm developing my application but i came across a problem.
When starting my app it retrieves information from database . Then It draws notes on the screen according to the information from database , it draws hi hat, snare and kick notes , if it has to be played the note is black when not it is gray.
The next step is that im using rx java to call a method called highLightNotes() .
Observable.interval(400, TimeUnit.MILLISECONDS).subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Long>() { #Override
public void onNext(#NonNull Long aLong) {
highLightNotes(aLong);
}
the next step is that it is looking for black notes, and when the note is black it calls this method :
public void playSnare(){
snarePlayer.seekTo(0);
snarePlayer.start();
}
snarePlayer is a mediaplayer.
My first problem here is that it takes way too much time to hear the note. The rhytm is becoming unsteady as sometimes it takes more time to get through sometimes less.
The second problem is that im kind of rxjava noob obviously and i'm wondering why by clicking for the first time to play the rhytm it takes a couple of seconds to get it started and then it is played really fast and after that i becomes steady .
Please provide me with some more information to keep working on it , im stuck.

You're starting up a new thread the first time. See where you're telling it to subscribe on a new thread?
If you need tight control over timing like this, RxJava is NOT the way to go. You do not want a giant codebase swapping you between threads. You're just asking for pain.

Related

Android cold app start: How to optimise time to Application.onCreate?

My current app takes for a cold start ~8 seconds and I want to optimize that.
For that reason I added a log entry in my Application onCreate (Application, not Activity)
override fun onCreate() {
Log.d("myTag", "Calling Application onCreate()")
....
}
When looking in the logs and measuring the time, I found out that the above mentioned 8 seconds consist of the following:
Tapping app icon => Application.onCreate = 4 seconds
Application.onCreate => my Activity visible = 4 seconds
I know I can optimize the time from Application.onCreate() onward. It's my code and I can speed this part up.
But how can I optimize the time the system needs until my Application.onCreate is called?
Thanks!
Sounds like a great usecase for systrace. I usually use (at least) the gfx, input, view, wm, am, res, dalvik, bionic, and sched categories. A -b 10000 to ensure a sufficient buffer size doesn't hurt.
You'll get an html file which can be loaded in a browser, or opened through Chrome/Chromium's built-in chrome://tracing page.
At the top, you'll see CPU details like usage% and which thread is running at which time. Then, you'll see all the processes on the device, containing nested colored blocks ("segments") with information about what's currently going on. At the top of each thread, there is a small colored bar: white is "sleeping" (this includes waiting on a mutex), blue is "waiting for CPU", green is "running on CPU".
If there is a segment that seems interesting but you don't understand the exact meaning of, a search for the text at https://cs.android.com/ can be useful.
In any case, my guess is that you either have some library linking or ContentProviders that take time before Application.onCreate. Both of those would be visible in a systrace. And if my guess is wrong, you'll likely find something else. Good luck! :)
(it could also be class initialization... it'll be interesting to hear what you find!)

Unexpected behavior of same methods in different threads

My initial question was: Android GraphView project get freeze with real time updates. In this one I was asking about possible concurrency in UI thread of 3 plots. On memory allocation plot it looks like this:
I was receiving data directly from my ProcessThread in main activity and pass it using onEventMainThread from EventBus library back to the GraphFragment. All the data that is passed comes from ProcessThread which gathers data from Bluetooth listening service and then proceeds it to get meaningful numbers.
My idea was to test if this same will happen with test thread that only generates data and sends it to onEventMainThread. Because this also produces some errors I was forced to ask another question: Difficulty in understanding complex multi threading in Android app. After some time I've received great answer from #AsifMujteba explaining that my test thread is simply too fast.
Knowing that I was able to return to my main problem and my real thread to check if all the timings are correct. As I've said there is a lot going on so being to fast is not a problem (however, I've added this same mechanize to test if data isn't send to fast). I would be more concern about to slow work of this thread.
My current onEventMainThread looks like that:
public void onEventMainThread(float[] data) {
mSeries1.appendData(new DataPoint(counter,data[0]),true,100);
mSeries1.appendData(new DataPoint(counter,data[1]),true,100);
mSeries1.appendData(new DataPoint(counter,data[2]),true,100);
counter++;
}
Unfortunately when I've returned to the beginning the problem emerged again. After a lot of testing I am able to say that data looks like is being send correctly. I've checked it with two markers:
public void onEventMainThread(float[] data) {
Log.d("LOG","marker1");
mSeries1.appendData(new DataPoint(counter,data[0]),true,100);
mSeries1.appendData(new DataPoint(counter,data[1]),true,100);
mSeries1.appendData(new DataPoint(counter,data[2]),true,100);
counter++;
Log.d("LOG","marker2");
}
Logcat messages are appearing correctly. Unfortunately the error appears even though the sending looks this same as in my test thread:
if((System.currentTimeMillis()-start)>10) {
values[0] = (float) getRandom();
values[1] = (float) getRandom();
values[2] = (float) getRandom();
EventBus.getDefault().post(values);
start = System.currentTimeMillis();
}
What's more I am sure that the data is correctly send all the time because when I've tested another fragment with OpenGL visualization everything works.
So to sum everything up:
When sending values to the fragment using EventBus from one (very simple) thread everything works great, while sending from another (more complex) thread ends in freezing of display and showed memory allocation graph. It is important to know, that if one thread is running the second one is commented out.
Can someone please advice me what might be a problem here? Or what should I check more?
EDIT
I have done one more test with commenting out everything regarding Series data append leaving only Log.d() and no error appeared. What is interesting is that the blocking (or freezing) of graph updates doesn't affect UI itself so I can still press all the buttons and so on.
Have you tried using a Custom eventbus and not the default one?
I had a similiar problem today and i fixed that by creating a custom evenbus with a seperate ThreadPool and it worked like a charm.

Android GraphView project get freeze with real time updates

I am trying to incorporate Android GraphView project into my app and all the time I have some strange problem with it.
My app requires drawing graph from real time data. I have thread with all the communication that is providing the data. In main thread I am reading this data and simply use mSeries1.appendData(new DataPoint(counter,data[0]),true,100); where counter is int that is incremented after each update.
Unfortunately at some point it freeze. I've tried putting it in synchronized block or changing the line of code to mSeries1.appendData(new DataPoint(counter,counter),true,100); and still this same result.
This is how the memory looks like during app running and when it freezes:
Does anyone have any idea what might be wrong in here?
EDIT:
This is my current method for updating my graph view:
public void onEventMainThread(ReadingsUpdateData data) {
mSeries1.appendData(new DataPoint(counter,data.getData()[0]),true,100);
counter++;
}
Maybe it's too late, but I had the similar problem and finally I found that when GraphView is appended a new data of "NaN" freezes.
So check the situation in which the result will be NaN such as divide by zero or something like that.
Although you do not specify the rate at which you add points, and how long for the app runs without crashing, you should expect things to go wrong at some point (you're potentially generating an infinite number of point objects, while the memory is indeed limited).
Do you need to have all the points the app has received from the beginning drawn ? If not, you could implement a sort of circular buffer that only keeps the X last values generated by your "provider thread", and update the graph each time you receive a new value with the method
your_series.resetData( dataPoint[] my_circular_buffer_of_data_points );
This thread is quite similar to your problem, have a look at it !

Android Rubik's Cube Kociemba optimal solver memory shortage

I'd like to ask for some help about the following problem I have.
I'd like to create an application that solves the Rubik's cube with an optimal solution. I downloaded the following library, whitch supposedly does just that using the Kociemba's Algorithm.
http://kociemba.org/twophase.jar
Apparently it can solve the cube in under 0.5 sec, but in my app it never returned the solution due to memory problems. I know it works, I tested it with wrong inputs and it returns the documented error codes.
I call it in my onCreate method like this:
resultTxt = Search.solution(data, 21, 10, true);
resultTxt is a String variable and it should contain the solution.
It quickly eats up the memory.
I tried it with IntentService without success. By this I mean it didn't really changed anything.
As i didn't find any evidence of anyone using this library in any android application, I thought I would ask someone who is more experienced than me.
Is there any way I could make this work on Android, or is this as impossible as I thought?
It may be a bit late, but I was also facing this issue quite recently when I was working on a Rubik's-Cube-solving-robot using an Android-Smartphone for scanning the cube and computing the solution, so I'll put here what I have found out.
What is the problem?
Let's start off by discussing where the problem causing that performance issue actually is located.
The reason for that being so slow is the class CoordCube, which looks (very simplified) like this:
class CoordCube {
short[] pruneTables;
static {
/* compute and save ~50MB data in `pruneTables` */
}
}
Basically what it does, is to load a pretty big amount of data into lookup-tables which are required for a fast solving procedure. This loading is automatically executed by the JVM once this class is first instantiated. That happens on line 159 in Search.solution():
/* simplified code of solution() */
if (cube.isValid()) {
CoordCube c = new CoordCube(); // pruning tables will be loaded on this line
That is also the reason why this method executes in negligible time as long as the passed cube is invalid, since it never gets to load the tables.
Possible Solutions:
Now that we have identified where the problem is located, let's focus on how to solve it.
I have come up with 3 different approaches, where the first one is probably the easiest (but also the slowest execution wise ...) and is also used in my App. The other two are just ideas on how to improve the performance even more.
Approach 1:
The first and most simple approach is to just manually preload the lookup tables in a kind of LoadingActivity with a ProgressBar showing our current progress. For that we first want to be able to manually control exactly when which tables are loaded (when the class is first instantiated is not precise enough), like this:
loadTable1() {
/* load pruning table number 1 */
}
For that I have written some simple utility here (code is too long to paste). Make sure to check out my instructions there on how to properly import that code in your App.
Also we will probably want to do the loading in the background, namely in an AsyncTask. This is how I have done it in my application (PruneTableLoader is included in the previous link):
private class LoadPruningTablesTask extends AsyncTask<Void, Void, Void> {
private PruneTableLoader tableLoader = new PruneTableLoader();
#Override
protected Void doInBackground(Void... params) {
/* load all tables if they are not already in RAM */
while (!tableLoader.loadingFinished()) { // while tables are left to load
tableLoader.loadNext(); // load next pruning table
publishProgress(); // increment `ProgressBar` by one
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
/* increment `ProgressBar` by 1 */
}
}
When using my PruneTableLoader, the loading of all tables needs about 40s on my Samsung Galaxy S3 with 250 MB RAM free. (in contrast it needs well over 2min when loading them automatically and in addition often results in a crash ...)
That may still sound quite slow considering it needs < 1s on PC, but at least you must only do that once, since Android caches the static-variables and you so don't have to load them on every startup of your App.
Approach 2: (untested)
I assume it would be faster to save the pruning tables in a file or a database and load them from there instead of always recomputing them. I have not yet tested that though and it will probably require quite some work getting the saving and loading to work properly. (also maybe it's not even faster because of access times)
Approach 3: (untested)
Well, the hardest and also by decades most work expensive solution would be, to simply rewrite the whole algorithm in C or C++ and invoke it in the App via JNI. (Herbert Kociemba has not published his C-sourcecode yet as far as I know ...)
This is going to be the performance wise fastest solution for sure. (also for the solving procedure itself)
All in all approach 1 is probably the effort/benefit-wise best approach for the beginning (and also was for me), so I would recommend you to go with that, in case the loading time is not such a huge issue for your Application.
I'm not completely satisfied with the performance of that myself though, so I may try out approach 2 and maybe even approach 3 some time in the future. In case I do that, I will update this post with my results then.

Seeker For Media Player

I would assume that someone would have found an easy solution to this but I haven't found a straight-forward method. I want to build a seeker bar for playing back audio through the MediaPlayer. I haven't been able to find something like an onSeekChanged listener in the MediaPlayer object so I've built an AsyncTask that just keeps refreshing through a while(playing) loop and updates the duration and bar. This doesn't seem to be the best way, however, since this while loop causes the app to run very slowly (the audio doesn't lag, but buttons like pause are delayed). So I want to know what the best implementation is for building a seeker that is efficient. This isn't a difficult question since so many apps use it, I just want to know what the proper way of doing this should be. Thanks!
First of all you need put sleep at least 1 millisecond in your cycle whit:
Thread.sleep(1);
Second you can calculate needed time for next recheck:
Thread.sleep(1000 - currentPos % 1000);
This algorithm is used in standard MediaController.

Categories

Resources