Right now I have a native function which sort of does this:
Object o = new Object();
while (!o.done()) { o.compute(); }
return o.result();
This computing can take a while and I would want the UI in Android to be update with some kind of progress bar. So what I need is three different native functions, one for each step above. The problem I'm having is how to save the "native object" inbetween calls. Any tips?
Thanks
Your Android NDK C code statics act like statics do in normal application programming. As long as the current process (app) is running, your data will be preserved. If you have a method that will do a lot of processing, call it from a Java thread to work in the background like this:
new Thread(new Runnable()
{
public void run()
{
<call native method here>
}
}).start();
Related
This is my first Android application and I am finding troubles with while loop, I am trying to use a while loop on my Android application but the application freezes.
What I'm trying to do is track the user location (using onlocationChanged) and keep querying on the location until the query returns a result. It's a GIS application so I am going to describe the application behavior:
the application keeps tracking the user position using a listener "onLocationChangedListener" and store it in a variable "myPosition". I am using a boolean"noResults=true". I will use a method "query(myPosition)" in the while loop, this method has a callback that when a result is found, and changes a boolean "noResults" to false. the loop will keep on until "noResults" is false (that means query's callback changed the boolean's value)
, here's what I did:
while(noResults)
{
//myPosition keeps changing
query(myPosition);
//query has a callback that when a result is found it changes noResults to false
}
I resolved the problem using a "Handler" that query the Feature Layer every 5 seconds, this stops the main thread from generating application not responding error:
Handler m_handler=new Handler();
Runnable m_runnable;
m_runnable = new Runnable(){
public void run() {
//query code here
m_handler.postDelayed(m_runnable, 5000);
}
};
m_handler.postDelayed(m_runnable, 0);
running while loop codes on the main thread freezes the UI, and makes all other processes pause making your app unresponsive use
Threads..
also note that the while loop you are running is running on a default Thread termed as the ui thread so in short run while loops on separate threads..
eg..
new Thread(new Runnable() {
#Override
public void run() {
// Your hard while loop here
//get whatever you want and update your ui with ui communication methods.
}
).start();
for ui communicating methods
View.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(getActivity(), "updated ui", Toast.LENGTH_LONG).show();
}
});
the view could be any views you are updating..
also like #TehCoder said you could use asynctask but asynctask is not meant for long workaflow work there are 3 of them but i can't recall the last one
Maybe you should use an AsyncTask? I'm not quite sure what your problem is tho.
Loop is not a problem in android (or any language).
There are two scenario might be reason for your freezing,
If you run network call in api, android throw error and crashes. You have to do network related calls in Aysnc Task ot threading
Use try throw catch and exception cases to avoid app crashing and better coding skill.
I would like some help regarding Java - Android MultiThreading
While learning to develop my app in a multi-threading way in order to take advantage of the ever-growing multi-core devices market share (most devices are quad core now, some even octo-core), I ran in a situation where my threads are either being calling twice or running twice.
I just don't why and how.
[EDIT 3]
Alright, I narrowed down the issue : I called the AsyncTask from the onResume() method. Although my app did not lost focus (which would mean a call to onPause() then back to onResume() upon return of focus in which case my threads would be run twice) during the tests, I solved the issue by moving away the call to FetchFriendsList to another place.
So far so good, but since in my tests the app did not loose focus or perhaps it did but I could not witness it (!), I think there is another reason behind so I'd say my problem is not entirely solved ... at least for the moment. It does work though. Perhaps I did solve the issue but I do not know how :(
[end of EDIT 3]
I am implementing last Facebook SDK and I am using it to fetch the end-user friends list, which seems to do the work.
Since I am running this operation in an AsyncTask, I am not using request.executeAsync().
Instead I am using request.executeAndWait(). Facebook JavaDoc does state that this method must only be used if I am not in a the Main UI Thread which is my case otherwise I would get a NetworkOnMainThreadException.
Anyway, this is where the weird behavior is happening.
private final ArrayList<GraphUser> userFriendsList = new ArrayList<GraphUser>();
public final void fetchFriendsList() {
if (this.session != null && this.session.isOpened()) {
final Request requestUserFriendsList = Request.newMyFriendsRequest(
this.session, new Request.GraphUserListCallback()
public final void onCompleted(final List<GraphUser> users, final Response response) {
if (users != null && users.size() > 0) {
Log.v("Retrieved Friends List -> ", String.valueOf(users.size()));
userFriendsList.addAll(users);
}
}
}
);
if (this.asyncFlag)
requestUserFriendsList.executeAsync();
else
requestUserFriendsList.executeAndWait();
}
}
In my case, asyncFlag is set to false because I need to do stuff synchronously in that specific order :
Fetch User Friends List (not on the Main (UI) Thread)
Save friends list on device (separate new thread)
Save friends list on a server (separate new thread)
Following this pattern, the line userFriendsList.addAll(users); is called twice.
In the logcat, the Log.vis showed twice as well, and finally looking with the debugger, the content of the user friends list is made of duplicates.
But that's not all ... step 2 and 3 are indeed two separate threads which are both created and spawned within the same method : public final void asyncSaveFacebookFriendsList().
And guess what, this method is even called twice !
just why ?
At the beginning I was calling the method for step 2 and 3 like this :
[...]
userFriendsList.addAll(users);
asyncSaveFacebookFriendsList(); // it was private before
[...]
This is where the issue started as both line were running twice.
So I thought, alright, I'll call it later like this :
[...]
fetchFriendsList();
asyncSaveFacebookFriendsList(); // it is now public
[...]
But the issue remains still.
If I don't call public final void asyncSaveFacebookFriendsList(), then nothing is run twice.
Why does this issue happen ? Is there something I did not get in Java Threads ?
I do not think this is somehow related to the Facebook SDK because following the same pattern (and doing it also at the same time), I have the same issues when fetching and storing the end-user Twitter friends list.
So I do believe I am doing something wrong. Does someone have any idea in what possible case a thread is called twice ?
Note : all threads are started this way : thread.start(). I am not using any ThreadPool nor the ExecutorService.
In case you need more background context :
Content of AsyncTask : (no need to wonder why Void and Long, I remove the irrelevant code related to it)
private final class FetchFriendsLists extends AsyncTask<Long, Integer, Void> {
protected final Void doInBackground(final Long... params) {
if (params[0] != Long.valueOf(-1)) {
[...]
twitterAPI.fetchUserFriendsList();
publishProgress(1, -1);
}
if (params[1] == Long.valueOf(0)) {
[...]
facebookAPI.fetchFriendsList();
publishProgress(-1, 0);
}
return null;
}
protected final void onProgressUpdate(Integer... flags) {
super.onProgressUpdate(flags);
if (flags[0] != -1)
twitterAPI.asyncSaveFacebookFriendsList();
if (flags[1] == 0)
facebookAPI.asyncSaveFacebookFriendsList();
}
}
As you can see, I start step 2 and 3 in onPublishProgress() which runs on the Main UI Thread. Brefore it was in the doInBackground() method : the issue happens in both cases!
[EDIT]
After further test, it would seem any kind of code is in fact running twice.
I created a simple method called test in which in print a counter. The counter incremente twice as well !
Why you use onProgressUpdate?¿?
onProgressUpdate(Progress...), [...]. This method is used to display any form of progress in the
user interface while the background computation is still executing.
For instance, it can be used to animate a progress bar or show logs in
a text field.
This is used not at the finish of the petition, but when progress increased.
Read this:
http://developer.android.com/reference/android/os/AsyncTask.html
You need to use:
protected void onPostExecute(Long result) {
Since Webworkers is only implemented from Android 4.4 onwards, is it possible to have a wrapper in the application code that provides this functionality to the contained WebView?
An example on how to solve this would really help.
Thanks,
Rajath
I guess you are talking about running a javascript code block in the background, i.e. different thread. Had tried doing that using RhinoJS on Android. Tested on Android 2.2 and above
https://github.com/devthon/SilentJSAndroid
The main features are
Execute Javascript code without browser context
Execute Javascript code from a script file
Load other JS files in the same context
Execute a method in the background thread and return a result
Execute a Object.Method() call
Execute a prototype method call
Run long running script in the background after app is closed.
May not be a full fledged Web worker as such, since it doesn't have API to check the status in between. But that can be still added to the interface I believe.
If this is the direction you are looking for, I can explain more on how it is done.
How much of the Worker spec do you need to implement, and how flexible does the implementation need to be? You could probably get basic functionality up and running using a JavaScript interface[1] and spawning threads natively from Java. However this will get complex quite quickly.
Perhaps if you can describe what you are using workers for I might be able to offer a different/better suggestion.
[1] http://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object, java.lang.String)
--
Adding some pseudo code
In JavaScript spawn a Java worker thread:
var worker_id = window.Android.spawnWorker();
In JavaScript, run a task on that worker:
var task_id = window.Android.doAdditionOnWorker(2,2, worker_id);
Handle the result in JavaScript
function onReceiveResultForWorkerTask(task_id, result) {
alert("the answer was " + result);
}
Java side:
public int spawnWorker() {
HandlerThread worker = new HandlerThread();
worker.start();
Handler h = new Handler(worker.getLooper()) {
#Override
handleMessage(Message msg) {
switch(msg.what)
case ADD:
// calculate the answer and send back to JS via UI thread
// Unpack parameters and task id from Message
mWebView.post(new Runnable(
public void run() {
mWebView.loadUrl("javascript:onReceiveResultForWorkerTask(task_id, " + (a+b) +");");
}
)
}
};
mWorkerMap.put(mWorkerId++, h);
return mWorkerId;
}
public int doAdditionOnWorker(int a, int b, int worker_id) {
Handler h = mWorkerMap.get(worker_id);
Bundle b = new Bundle();
int task_id = mTaskId++;
// pack arguments and task_id into the bundle
h.postMessage(Message.obtain(h, ADD, b);
return task_id;
}
Don't forget to go through and tear down all the worker threads that you spawn when the app doesn't need them anymore. Depending on how many workers you need you might also prefer to use a thread pool rather than creating new threads every time.
I am writing the program which processes Android OpenGL at other thread. But it freezes in case of this code. For example, it processes a method directly without calling task.get(), if it's the same thread. Does such a way exist?
public void onSurfaceCreated(GL10 arg0, EGLConfig arg1)
{
Thread t = new Thread(new Runnable(){
#Override
public void run()
{
FutureTask<Object> task = new FutureTask<Object>(new Callable<Object>() {
#Override
public Object call() {
return null;
}
});
gv.queueEvent(task);
try{
task.get();
}catch(Exception e){
}
Log.i("MainActivity", "Done"); // <- Work
}
});
t.start();
FutureTask<Object> task = new FutureTask<Object>(new Callable<Object>() {
#Override
public Object call() {
return null;
}
});
gv.queueEvent(task);
try{ task.get(); }catch(Exception e){} // <- Freeze
Log.i("MainActivity", "Done");
If I interpret your question correctly, there is some code you would like to run in the OpenGL thread without using a FutureTask, Runnable or other asynchronous solution.
First of all, does this code (and any of its data) depend on other threads? Does it need to be synchronized with other code/data? If yes, then you should use queueEvent() from a different thread. Since you want to stay within the OpenGL thread completely, I assume that your code to be executed does not have any relationship with other (non-GL) threads.
Moreover, never call FutureTask.get() from the same thread as the one which is supposed to perform the FutureTask code -- who will perform the job if your thread is waiting for itself? And if you want to send code to the GL thread from another thread, don't use FutureTask; just use the simple Runnable for it (as an argument to queueEvent()).
Back to the main question: to run something from the GL thread without queueEvent(), you should decide how exactly you want to perform that job, i.e. when (where) exactly it should be called. Do you want to get it called each time onDrawFrame() is called? Or each time onSurfaceChanged() or onSurfaceCreated() is called?
Since you used queueEvent(), I assume you want your code to run before the next upcoming onDrawFrame() call. In the Android GL thread, internally, the order of calls is as follows:
Android processes all your queued events (I simplified this a bit, but the main point is OK)
If needed, Android calls onSurfaceCreated()
If needed, Android calls onSurfaceChanged()
Android calls onDrawFrame()
So, to put it simple, the code you add with queueEvent() will get executed before the next render cycle (onDrawFrame()). If you want to run this code on the GL thread in onDrawFrame(), you can add it to the beginning of onDrawFrame(), for example:
#Override
public void onDrawFrame(GL10 gl) {
if (mDoJob) {
mDoJob = false;
// perform code
}
...
}
Here, mDoJob is a volatile variable. You can set it to true from another thread. However, please be warned that this assumes you don't need any additional synchronization with the other thread that uses the mDoJob signal, i.e. all the code that will run in the mDoJob condition block will be fine without any further synchronization with anything else.
Basically, what I presented above is just a simplified (non-synchronized) solution to replace queueEvent(), which assumes you don't need synchronization (including up-to-date variables as well) with other threads.
If you don't need any signalling (any dependence with other threads), and the value of mDoJob can be decided inside the OpenGL thread (inside onDrawFrame(), onSurfaceCreated() or onSurfaceChanged()), then mDoJob does not need to be volatile. In such a case, you're staying inside the OpenGL thread, so there is no need for an asynchronous (and thus synchronized) solution.
To sum up, specifically, if you want to decide in onSurfaceCreated() whether a code should run in onDrawFrame(), just use a (non-volatile) boolean variable, which you set in onSurfaceCreated(), and then check it in onDrawFrame() (as in my code example above).
I'm trying to get my user interface to react to events (like button presses, thread completions, etc.) in real time in Android (obviously).
I have a button layout, and one of the buttons is used to copy an unknown number of files from a remote computer using FTP. The FTP part of all this is working very well, but I just cannot find a way to let the user know the state of things:
The states, as I see them are:
1) Selected "Download Files" from "normal" menu.
2) Pressed Confirm (the download process may be quite lengthy and perhaps I don't want to select it by mistake -- however now it's a separate thread so may need to re-think that.
3) Downloading
4) Download complete, restore normal menu
One of the things I hoped would work would be to run the FTP code in a separate thread, and by using the thread.isAlive() construction, wait for the thread to complete and change the display accordingly.
The only thing I haven't been able to do is display that files are downloading. Regardless of what I try, the display jumps from the "Confirm Download" view to the "Normal Menu" view. (Please note, these are not Views as Android defines them in any way.)
Code follows:
Btn.setOnClickListener (new View.OnClickListener()
{
#Override
public void onClick (View v)
{
hideTempWidgets();
Btn01.setVisibility (View.GONE);
Btn02.setVisibility (View.GONE);
Btn03.setVisibility (View.GONE);
verfBtn.setVisibility (View.VISIBLE);
verfBtn.setText ("Press to Verify");
verfBtn.setOnClickListener (null);
verfBtn.setOnClickListener (new View.OnClickListener()
{
#Override
public void onClick (View v)
{
runOnUiThread (new Runnable()
{
public void run()
{
verfBtn.setText ("Downloading...");
}
});
Thread temp = new Thread (new Runnable()
{
public void run()
{
try
{
FileTransfer.getFiles (getAddr().trim());
}
catch (SQLException e)
{ }
}
}, "ftp");
temp.start();
while (temp.isAlive());
verfBtn.setVisibility (View.GONE);
Btn01.setVisibility (View.VISIBLE);
Btn02.setVisibility (View.VISIBLE);
Btn03.setVisibility (View.VISIBLE);
alert (true, VIBE_BLIP);
}
});
}
});
Has anybody faced this and come up with a decent solution??
What's not happening is the setText to "Downloading...", or at least, if it does, not when I want it to and too fast to see... Finally, what's especially frustrating is that that command does work properly when I remove the code to run the FTP thread.
Thanks,
R.
This task seems to be perfect for Async Task. Basically Async Task is a Thread with a built in, thread safe component to allow you to publish updates to the UI and notify when the task is complete.
A popular idea is to show a spinner or progress bar, until the AsyncTask is complete, then dismiss it.
For more information about Async Task see: http://developer.android.com/reference/android/os/AsyncTask.html
I think your mistake is here:
temp.start();
while (temp.isAlive());
The code inside onClick() is already running on graphical Thread, so there is no need for a runOnUIThread() method and you should not block it with the while() statement, which in fact is blocking the UI thread till the Thread completes.
My advice: you can start an AsyncTask instead and update the UI accordingly.
Since it is a very long file transfer, I'd suggest you consider a service to do the work. If you use thread, user will be bound to keep your application on top of others. Otherwise your thread can be just killed. Worst of all, there is not much you can do to prevent user from going to home screen or other application (some tricks are possible but user will be pissed).
If you use service, you can always use notification to show progress and go back to your application.