I get a small problem: I need using async task in cocos2d-x on Android.
private void parseJSONJava() throws ClientProtocolException, IOException, JSONException
{
STAJSONParser jPars = new STAJSONParser();
jPars.makeHttpRequest(String.format("%s/app/%s/json",STA_URL,STA_APP_UID));
}
But this code crash application with error Can't create handler inside thread that has not called Looper.prepare(). I solve this by adding runOnUiThread:
me.runOnUiThread(new Runnable(){
public void run(){
STAJSONParser jPars = new STAJSONParser();
jPars.makeHttpRequest(String.format("%s/app/%s/json",STA_URL,STA_APP_UID));
}
});
Where "me" is my Activity.
Code from STAJSONParser:
public JSONObject makeHttpRequest(String url) {
AsyncGetJson Task= new AsyncGetJson(url);
try {
return Task.execute().get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
AsyncGetJson task its a simple AsyncTask that get JSON from server.
So, my question: is this solution is right/wrong? Or you can give me other solution?
I don't see why you couldn't do that. You could also use libcurl like m.ding mentioned, along with pthreads and a json parser. But the problem there is that you'd need to manage the pthreads yourself. It's "messier" than just doing it the way you're doing it now. Then again, using the JNI isn't exactly pretty either. It's one big giant trade-off, probably leaning in favor of the JNI & Android Java SDK.
On iOS and Android, pthreads are the underlying threading mechanism, which are already managed for you when you use things like iOS's NSOperation and Android's AsyncTask (I'm assuming..)
Related
I am trying to save data into a Firebase RealtimeDatabase.
The process of saving is fine and works just well, but I was curious about an idea I had: To force the .setValue operation into a synchronous structure. I know, that that way isn't the best one, but I wanted to try it regardless of that fact.
So I came up with this code:
Thread t1 = new Thread(){
public void run(){
try {
Tasks.await(databaseReference.child("someChild").setValue(someObject));
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("finished");
}
In theory, that code snippet is intended to first set the value in the Database, then wait for the completion of that (through the Tasks.await()), and then print out **after that* the line "finished".
I wrapped the Tasks.await()-command in a second thread because when I don't, I get an exception which says something like "Tasks.await() must not be called in the main application thread".
But when I run the whole thing, it just gets stuck at t1.join();.
When I delete the t1.join();-statement, everything works just fine, but the second Thread (t1) isn't finished before the "finished"-output is there. I know why this is like that, but I am nontheless interested in a solution to that problem.
I am working on an Android app which will need to parse a fair amount of XML and/or JSON.
Every file takes 3-4 seconds to parse and this is done in a AsyncTask. The parsed data is then inserted into my SQlite database.
My problem is that the UI gets very slow and unresponsive during the parsing.
I have verified, using DDMS that almost all of the CPU is spend parsing and this happens in another (AsyncTask) thread.
I'm primarily testing on a galaxy nexus which is slow but has two cores. I therefore do not understand why I am experiencing this UI slowdown. I can still feel the slowdown on my Nexus 7 2013 but it is much less of an issue
Do you have any idea how of I could progress to fix find the cause of this issue? Shouldn't it be possible to have a heavy load on a AsyncTask without getting a laggy UI when having two cores available?
Code example
The first piece below initiates Volley and requests a number of XML files.
public static void start_update(final Context context,
Subscription subscription) {
if (updateConnectStatus(context) == NO_CONNECT)
return;
mContext = context;
RequestManager.initIfNeeded(context);
RequestQueue requestQueue = RequestManager.getRequestQueue();
Cursor subscriptionCursor = Subscription.allAsCursor(context
.getContentResolver());
while (subscriptionCursor.moveToNext()) {
Subscription sub = Subscription.getByCursor(subscriptionCursor);
if (subscription == null || sub.equals(subscription)) {
StringRequest jr = new StringRequest(sub.getUrl(),
new MyStringResponseListener(context
.getContentResolver(), sub),
createGetFailureListener());
int MY_SOCKET_TIMEOUT_MS = 300000;
DefaultRetryPolicy retryPolicy = new DefaultRetryPolicy(
MY_SOCKET_TIMEOUT_MS,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
jr.setRetryPolicy(retryPolicy);
// Add the request to Volley
requestQueue.add(jr);
processCounts.incrementAndGet();
}
}
requestQueue.start();
}
When Volley has fetced an XML file the following callback is called:
static class MyStringResponseListener implements Listener<String> {
static FeedHandler feedHandler = new FeedHandler();
Subscription subscription;
ContentResolver contentResolver;
final JSONFeedParserWrapper feedParser = null;
public MyStringResponseListener(ContentResolver contentResolver,
Subscription subscription) {
this.subscription = subscription;
this.contentResolver = contentResolver;
}
#Override
public void onResponse(String response) {
new ParseFeedTask().execute(response); // Execute the parsing as a AsyncTask
}
private class ParseFeedTask extends AsyncTask<String, Void, Void> {
protected Void doInBackground(String... responses) {
Subscription sub = null;
String response = responses[0];
try {
sub = feedHandler.parseFeed(contentResolver, subscription,
response.replace("", "")); // Remove the Byte Order Mark
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedFeedtypeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Long result) {
decrementProcessCount();
}
}
}
It is common for Android devices to have poor storage I/O performance and if the main thread needs to access the drive for whatever reason things could get sluggish. The storage is the bottleneck, not the number of cores.
Use the profiler to see exactly what methods are slow. You may find that the UI is stuck loading data from the drive. For instance, it is common to load bitmaps on the UI thread and never notice the lag under normal conditions. In this sort of situation, move all I/O operations off the UI thread as you already have with your background data processor.
I am using the Drive API v2 for android, and when I execute the following method my app seems to pause or wait, and no data is returned.
public About getAbout() throws InterruptedException, ExecutionException {
FutureTask<About> future = new FutureTask<About>(new Callable<About>() {
public About call() throws IOException {
About about = null;
try {
about = _driveService.about().get().execute();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return about;
}
});
About about = future.get();
return about;
}
Does anyone have any idea what I'm doing wrong?
You are creating a FutureTask, but you are never executing it (not on the current thread and not on any other). Then you call future.get() which will block until the operation is completed. Since you never actually perform the operation, it will wait forever.
To execute an operation on a background thread you could for example use http://developer.android.com/reference/android/os/AsyncTask.html
I must use Thread in an Android project. Sometimes, it works corectly, however sometimes does not; it does not start (does not call SendToServer() method)or it starts but return to another function suddenly (return updated; line)before the thread does not finish.
Note: affected value is bigger than 0, it gives condition and it goes to if statement.
Here is the my code sample;
public static Boolean MyUpdateFunction(MyObject myobject){
Boolean updated=false;
//Code for updating local database
int affected= SqliteDb.update(....);
if(affected>0)
{
//Send updated data to server
//For this I must use Thread(I can't use AsyncThread)
updated=true;
SendToServer();
}
return updated;
}
public static void SendToServer()
{
try{
;
Thread th=new Thread(new Runnable() {
public void run() {
try {
//Create data and send it to server
//.......
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
th.start();
th.join();
}
catch(SQLException e)
{
Toast.makeText(myContext,"ERROR: "+e.getMessage(), Toast.LENGTH_LONG).show();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Other people are correct in that an AsyncTask is the way forward, but the direct problem due to what you're experiencing is this (and as such, I would recommend reading up on how Threading works):
When you start the thread, it begins a new process. The UI thread (which is generally where the majority of your code is) continues. So your code will fire the thread with SendToServer(), and then by definition will immediately return updated, as the UI thread immediately goes to the next line.
What you need is a callback from your Thread, which is handled in the onPostExecute() method of an AsyncTask. There's a good tutorial on how to use them and what they do here
Edit:
I've just seen from a comment above that you can't use Asynctasks, fair enough, but you still need a callback/event fired from your Thread to return any results
Instead of using threads and your variables (updated and affected), you can use AsyncTasks: see: http://developer.android.com/reference/android/os/AsyncTask.html
With AsyncTask, you have some methods which are doing exactly what you want:
onPreExecute
doInBackground
onPostExecute
So, what you can do is to check your condition in onPreExecute, then do your SendToServer in the doInBackground and onPostExecute do what you need.
Working with facebook in Android. Sometimes my application is cashing in real time device when I tried to authorize Facebook in Android.not in emulator. I used the Android Facebook SDK. So I thought threading might stop that.First tried the asynctask
Activity act=this;
private class fbwork extends AsyncTask<Facebook, Integer, String>
{
#Override
protected String doInBackground(Facebook... para)
{
// TODO Auto-generated method stub
Log.d(tagg, "Entered async");
if(loginflag==0)
{
try
{
para[0].authorize(act, PERMISSIONS, new LoginDialogListener());
}catch(Exception ex)
{
Log.d(tagg,ex.getMessage());
}
Log.d(tagg, tagg.toString());
}
else
{
try {
logout();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return "0";
}
calling code:
new fbwork().execute(facebook);
produce error: Can't create handler inside thread that has not called Looper.Prepare()
So tried the normal threading way.
public void loginprocesure() throws MalformedURLException, IOException
{
final Activity ac=this;
if(loginflag==0)
{
new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
facebook.authorize(ac, PERMISSIONS, new LoginDialogListener());
}
}).start();
}
else
{
logout();
}
}
Again same result. any way to fix this!!!! How to stop that crashing of application in real device. Please help.
I faced the same issue.You must try to put this method in loop
Looper.prepare();
new fbwork().execute(facebook);
Looper.loop();
Facebook authorize uses methods which access event thread, so you dont need to execute this method into another thread, than event thread.
If you face issue in execution of this method in normal event thread, specifythat issue.
I'm having this problem too. I couldn't get the AsyncTask code working.
So I ended up using runOnUiThread. It works on the emulator, but not on the device, I'm using HTC Desire Android SDK 2.2.2. Unfortunately, I can't even login to Facebook using Hackbook (Facebook's sample project).
Here's code that uses runOnUiThread:
Android App Crashes after Sharing using Facebook Dialogs