I am using the Google Distance Matrix API to compute distance between different lat longs. I am calling the respective API as mentioned below
public void computeDistanceAndTime()
{
try
{
DistanceMatrixApiRequest req = DistanceMatrixApi.newRequest(Context.getContext()).origins(src)
.destinations(dst).mode(TravelMode.WALKING);
DistanceMatrix matrix = req.await();
}
catch (OverQueryLimitException o)
{
System.out.println(o.getMessage());
}
catch (Exception e) {
e.printStackTrace();
}
}
Actually I want to set a callback using setCallback function DistanceMatrixApiRequest. So I am assuming rather catching the excepetion the callback would be get called and could avoid the
com.google.maps.internal.OkHttpPendingResult retry
exception from google.
Now I am not aware how to set the callback like
what is the signature of the call back?
Do we need to inherit any class to set the callback
What would be the parameters of that function?
I am assuming that needs to called before calling the await function, am I correct?
I could see one example for Geocoding as like below,
req.setCallback(new PendingResult.Callback<GeocodingResult[]>() {
#Override
public void onResult(GeocodingResult[] result) {
// Handle successful request.
}
#Override
public void onFailure(Throwable e) {
// Handle error.
}
});
I am not successfull even if I follow in similar manner for Distance Matrix.
req.setCallback(new PendingResult.Callback<DistanceMatrix[]>() {
#Override
public void onResult(DistanceMatrix[] result) {
// Handle successful request.
}
#Override
public void onFailure(Throwable e) {
System.out.println("There is a failure in Distance function");
}
});
Here is an example of using DistanceMatrixApi with a callback instead of await(). Note, I need to use a CountDownLatch due to OkHTTP invoking the callback on a background thread.
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.maps.DistanceMatrixApi;
import com.google.maps.DistanceMatrixApiRequest;
import com.google.maps.GeoApiContext;
import com.google.maps.PendingResult;
import com.google.maps.model.DistanceMatrix;
import java.util.concurrent.CountDownLatch;
public class DistanceMatrixApp {
public static void main(String[] args) throws InterruptedException {
GeoApiContext context = new GeoApiContext();
context.setApiKey("[API KEY]");
DistanceMatrixApiRequest req = DistanceMatrixApi.getDistanceMatrix(context,
new String[]{"Sydney Town Hall"},
new String[]{"Parramatta Station"});
final CountDownLatch latch = new CountDownLatch(1);
req.setCallback(new PendingResult.Callback<DistanceMatrix>() {
#Override
public void onResult(DistanceMatrix result) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
System.out.println(gson.toJson(result));
latch.countDown();
}
#Override
public void onFailure(Throwable e) {
System.out.println("Exception thrown: "+e);
latch.countDown();
}
});
// We have to hold the main thread open until callback is called by OkHTTP.
latch.await();
}
}
Related
How can I change this code to get rid of thread blocking? Here .get() blocks the thread to receive the result from the future. But can I absolutely avoid blocking? Something like - one thread sends the requests, and the other one receives responses and implements some code. To make it fully asynchronous.
I tried to use CompletableFuture, but couldn't really understand it.
Tried to make a callback method, but wasn't successful as well.
byte[] sendRequest(JSONObject jsonObject, String username, String password) throws IOException, ExecutionException, InterruptedException {
try (AsyncHttpClient client = new AsyncHttpClient()) {
String userPassword;
if (username != null && password != null) {
userPassword = username + ":" + password;
} else {
throw new NullPointerException("Нет логина и/или пароля.");
}
Future future = client.preparePost(apiUrl)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Basic " + DatatypeConverter.printBase64Binary(userPassword.getBytes()))
.setBody(jsonObject.toString().getBytes())
.execute(getHandler());
String response = (String) future.get();
return response.getBytes();
}
}
private AsyncCompletionHandler<String> getHandler() throws IOException {
return new AsyncCompletionHandler<String>() {
#Override
public String onCompleted(Response response) throws IOException {
return response.getResponseBody();
}
#Override
public void onThrowable(Throwable t) {
}
};
}
What I expect:
The program sends a request in the main thread.
Then there is a kind of a callback that waits for a response in an
alternative thread.
Still, the program continues working in the main thread - it goes on with sending more requests.
When the response from the server comes, the callback from the
alternative thread catches it and processes in some way, but it
doesn't correspond with the main thread
You should run your async task in new thread (preferably using ExecutorService or CompletableFuture). Pass CallbackHandler to the Runnable/Callable tasks and once the invocation is complete invoke handler methods.
Alternatively, if all you're worried about is handling async http requests, I'd suggest to not reinvent the wheel and instead use existing solutions. Example of async http client
For other use cases, you can follow the following example.
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone {
public static void main (String[] args) throws java.lang.Exception {
for (int i=0; i<10; i++) {
new Thread(new MyRunnable(new CallbackHandler())).start();
}
}
static class MyRunnable implements Runnable {
CallbackHandler handler;
public MyRunnable(CallbackHandler handler) {
this.handler = handler;
}
public void run() {
try {
Thread.sleep(100);
} catch(Exception e) {
} finally {
Random r = new Random();
if (r.nextBoolean()) {
handler.onSuccess();
} else {
handler.onError();
}
}
}
}
static class CallbackHandler {
public void onSuccess() {
System.out.println("Success");
}
public void onError() {
System.out.println("Error");
}
}
}
I have a basic class which has a static method with a following call of another helper method.
MsBandHelper.connectToSelectedBand(bandClient);
The helper method:
public static void connectToSelectedBand(BandClient bandClient) {
try {
MsBandConnectHelperAssync asyncTask = new MsBandConnectHelperAssync(new AsyncResponse() {
#Override
public void processFinish(Boolean output) {
try {
Logger.d("HELPER METHOD RETURNED " + output);
} catch (Exception e) {
Logger.e(e.getMessage());
}
}
});
asyncTask.execute(bandClient);
} catch (Exception e) {
Logger.e(e.getMessage());
}
}
I am able to get result in processFinish of this method, but I don't know how I should pass the returned value back to the calling because it is an async method.
If I tried to implement interface which i'm using in MsBandConnectHelperAssync class no interface event was triggered.
Should i create a new interface on can i broadcast result into all bound classes?
How can i do it in the right way please?
Many thanks for any advice.
If you look at the code I have two ArrayLists that are called, pressed and released that are global. What I have to do is update those arrays with the keys that are to be pressed, then pass these updated arrays to my Thread, or update the thread.. this is the part where I'm a little lost on what I have to do.
The currently example(untested if runs), is a basic example of what I had in my actual program. When I ran it it would press the buttons once, then it would throw and error, I can't remember the error as I can't test it right now, but it had to do with the way I was using the thread.
QUESTION
How do I pass the arrays to my Thread, once the thread has been started.
Code Example:
import oscP5.OscEventListener;
import oscP5.OscMessage;
import oscP5.OscP5;
import oscP5.OscStatus;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Main implements OscEventListener {
protected BlockingQueue<Integer> _KeyQue = new ArrayBlockingQueue<>(1024);
Producer producer = new Producer(this._KeyQue);
Consumer consumer = new Consumer(this._KeyQue);
ThreadTest threadTest = new ThreadTest(this._KeyQue);
Thread prod;
Thread con;
Thread threadT;
OscP5 osc = new OscP5(this, 22556);
public static void main(String[] argv) {
Main main = new Main();
main.setup();
}
public void setup() {
prod = new Thread(producer);
con = new Thread(consumer);
threadT = new Thread(threadTest);
prod.start();
con.start();
threadT.start();
}
#Override
public void oscEvent(OscMessage theMessage) {
float val = Float.parseFloat(theMessage.arguments()[0].toString());
if (val == 1.0) {
producer.addKey(KeyEvent.VK_W);
producer.addKey(KeyEvent.VK_S);
} else {
consumer.removeKey(KeyEvent.VK_S);
}
threadTest.run();
}
#Override
public void oscStatus(OscStatus theStatus) {}
public class Producer implements Runnable {
protected BlockingQueue<Integer> _KeyQue = null;
public void addKey(int key) {
try {
this._KeyQue.put(key);
System.out.println("Key " + key +" added to queue");
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
public Producer(BlockingQueue<Integer> _KeyQue) {
this._KeyQue = _KeyQue;
}
public void run() {
}
}
public class Consumer implements Runnable {
protected BlockingQueue<Integer> _KeyQue = null;
public void removeKey(int key) {
try {
this._KeyQue.remove(key);
System.out.println("key " + key + " removed from queue");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public Consumer(BlockingQueue<Integer> _KeyQue) {
this._KeyQue = _KeyQue;
}
public void run() {
}
}
public class ThreadTest implements Runnable {
protected BlockingQueue<Integer> _KeyQue = null;
public ThreadTest(BlockingQueue<Integer> _KeyQue) {
this._KeyQue = _KeyQue;
}
public void run() {
try {
Robot robot = new Robot();
while(!this._KeyQue.isEmpty()) {
for (Integer x : this._KeyQue) {
System.out.println("Keys in que: " + x);
Thread.sleep(500);
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
Edit:
Ok, so I've taken a look at threads and BlockingQueue's, but the thing I still can't figure out is how to continue to run the ThreadTest's run() method without locking the program. In this example it doesn't run at all. When I directly call threadTest.run() it locks the program within it and doesn't allow for adding or removing elements.
So what I need to do is be able to run a thread in the background that is constantly running, looping through *_KeysQueue()* and, in this example, printout the number associated with the keys. This should all happen while allowing me to add and remove keys.
You can have a BlockingQueue and a method to add elements that would be called from every other thread. You can have a static method addKey that could be accessed from every other thread and that would look for adding the new key to the BlockingQueue.
You can use there the producer-consumer pattern and you can see the book Java Concurrency In Practice or the link that led me to the book, in the blog The Java Specialists. The book has examples of all queues, concurrent or synchronized lists, ways to implement code to do several things, and all without having to stop to read 50 pages about something. An example and a few paragraphs of every issue.
Have a setter method in your class
public class ThreadTest implements Runnable {
....
public void setPressedList(ArrayList<Integer> e) {
this.pressed = e;
}
public void setReleasedList(ArrayList<Integer> f)
{
this.released = f
}
}
ArrayList are not thread-safe so you should not used them this way : it could work or it could fail.
Moreover you should use some kind of synchronization mechanism instead of busy-waiting which consume resources for nothing.
So have a look at the BlockingQueue collection which will give you a simple data-passing mechanism between your threads.
Let's imagine we have a simple Android application, which connects to a remote service via IPC, schedules a relatively long task, then continues working while awaiting for callback with some results. AIDL interfaces:
IRemoteService.aidl
package com.var.testservice;
import com.var.testservice.IServCallback;
interface IRemoteService {
void scheduleHeavyTask(IServCallback callback);
}
IRemoteService.aidl
package com.var.testservice;
interface IServCallback {
void onResult(int result);
}
Code for activity:
package com.var.testclient;
import com.var.testservice.IServCallback;
import com.var.testservice.IRemoteService;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
public class MainActivity extends Activity {
private static final String TAG = "TestClientActivity";
private IServCallback.Stub servCallbackListener = new IServCallback.Stub(){
#Override
public void onResult(int result) throws RemoteException {
Log.d(TAG, "Got value: " + result);
}
};
private ServiceConnection servConnection = new ServiceConnection(){
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
service = IRemoteService.Stub.asInterface(binder);
}
#Override
public void onServiceDisconnected(ComponentName name) {
service = null;
}
};
private IRemoteService service;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(!bindService(new Intent(IRemoteService.class.getName()), servConnection, Context.BIND_AUTO_CREATE)){
Log.d(TAG, "Service binding failed");
} else {
Log.d(TAG, "Service binding successful");
}
}
#Override
protected void onDestroy() {
if(service != null) {
unbindService(servConnection);
}
super.onDestroy();
}
public void onButtonClick(View view){
Log.d(TAG, "Button click");
if(service != null){
try {
service.scheduleHeavyTask(servCallbackListener);
} catch (RemoteException e) {
Log.d(TAG, "Oops! Can't schedule task!");
e.printStackTrace();
}
}
}
}
Code for service:
package com.var.testservice;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
public class TestService extends Service {
private static final String TAG = "TestService";
class TestServiceStub extends IRemoteService.Stub {
private IServCallback servCallback;
//These 2 fields will be used a bit later
private Handler handler;
private int result;
//The simpliest implementation. In next snippets I will replace it with
//other version
#Override
public void scheduleHeavyTask(IServCallback callback)
throws RemoteException {
servCallback = callback;
result = doSomethingLong();
callback.onResult(result);
}
private int doSomethingLong(){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
return 42;
}
}
}
#Override
public IBinder onBind(Intent intent) {
return new TestServiceStub();
}
}
This version, while being really dumb (it makes UI thread from application hang for 5 seconds, causing ANR), it successfully executes all calls via IPC, delivering result to activity.
Problems start if I try to put calculations into separate thread:
#Override
public void scheduleHeavyTask(IServCallback callback)
throws RemoteException {
servCallback = callback;
Runnable task = new Runnable(){
#Override
public void run() {
result = doSomethingLong();
try {
Log.d(TAG, "Sending result!");
servCallback.onResult(result);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
new Thread(task).start();
}
In this case the callback is just not delivered to activity: service successfully calls servCallback.onResult(result);, but nothing is called within activity. No exceptions, no clues, no survivors: perfect invocation murder. I couldn't find any information about possible cause of such behavior, so I'd be grateful if someone could clarify what happens here. My suggestion's that there's some kind of security mechanism, tracking which exact threads were bound, and ignoring "unsafe" calls from other threads (something similar happens when we try to mess with UI elements from non-UI thread), but I can't be sure.
The most obvious solution is to post callback invocation to the bound thread, so I made this:
#Override
public void scheduleHeavyTask(IServCallback callback)
throws RemoteException {
Log.d(TAG, "Schedule request received.");
servCallback = callback;
if(Looper.myLooper() == null) {
Looper.prepare();
}
handler = new Handler();
Runnable task = new Runnable(){
#Override
public void run() {
result = doSomethingLong();
Log.d(TAG, "Posting result sender");
handler.post(new Runnable(){
#Override
public void run() {
try {
Log.d(TAG, "Sending result!");
servCallback.onResult(result);
} catch (RemoteException e) {
e.printStackTrace();
}
Looper.myLooper().quit();
Log.d(TAG, "Looper stopped");
}
});
}
};
new Thread(task).start();
Looper.loop();
}
Here I faced 2 more problems:
I had to call Looper.loop() to enable processing of callback runnables, but it blocks IPC, so I have the same result as in the beginning - no actual multithreading;
Registering for callback second time (after first cycle finished and returned value) results in exception:
java.lang.RuntimeException: Handler (android.os.Handler) sending message to a Handler on a dead thread
at android.os.MessageQueue.enqueueMessage
at android.os.Handler.sendMessageAtTime
at android.os.Handler.sendMessageDelayed
at android.os.Handler.post
at com.var.testservice.TestService$TestServiceStub$1.run
at java.lang.Thread.run
This lefts me completely puzzled: I make a fresh instance from actual Looper, how can it point to dead thread?
The whole idea of service being able of queueing tasks and making callbacks when they finish doesn't sound insane to me, so I hope someone more experienced could explain me:
Why can't I actually make IPC calls from different threads?
What's wrong with my Handler?
What instruments/architecture should I use to make a clean, proper queue mechanism, so it could call IPC methods on the right thread without constantly calling Looper.loop()/Looper.quit()?
Thank you.
I can't explain why your program isn't working. But the version involving threads and an asynchronous callback:
#Override
public void scheduleHeavyTask(IServCallback callback)
throws RemoteException {
servCallback = callback;
Runnable task = new Runnable(){
#Override
public void run() {
result = doSomethingLong();
try {
Log.d(TAG, "Sending result!");
servCallback.onResult(result);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
new Thread(task).start();
}
should work just fine.
Here's how Android arranges threads for AIDL and other types of Binder transaction.
If the caller and the callee are in the same process, it becomes a simple method call. So, you should fine that scheduleHeavyTask is called from the very same thread as onButtonClick. Similarly, you should fine that the call to onResult should be a simple method call, from the thread running the task.
If the caller and callee are in different processes, Android will run the Binder transactions from a pool of threads within the callee process (they are called Binder #1 etc.) Even here it's quite clever - so if onButtonClick called scheduleHeavyTask which called back to onResult from the same thread, then onButtonClick would appear directly to call onResult within the caller process.
There are absolutely no mechanisms to avoid calls from "unsafe" or "unbound" threads - so this simple approach you posted should work. As you say, it's a common pattern, and I've used it lots of times. I'd therefore recommend proceeding with this rather than fiddling with extra loopers and handlers.
Here are some ideas:
Run it in a debugger. Assuming your service and activity are in the same process, you should be able to set breakpoints and see sensible method calls taking place.
Even if you can't, fire up ddms from the command line, or show the Devices and Threads views within Eclipse. This will give you a view of exactly what each thread is doing - you can get a callstack. It's normally possible to use this even in cases where a full-on debugger would be inconvenient.
Do you have the word synchronized anywhere? What could be happening is that onResult wants to go ahead and run, but it's blocked on some monitor. As soon as it becomes unblocked, it might well run.
My requirement is to have a thread that maintains a socket connection between a BlackBerry device and a server and exchanges commands, similar to request and response.
My problem is that I need to have this thread running in the background all the time and keep the UI available to the user. So, when there is a command from the server, this thread parses it and updates the UI and also if there's an action from the BlackBerry user, it sends it to the server and the server in turn handles it.
I developed the same application in Android using AsyncTask and it's working well. But in BlackBerry, as there's no such class, I used the invokeLater() option. The communication works fine between the server and the BB device, but the UI is frozen on the BlackBerry.
Anyone have any idea how to get this right?
Vishal is on the right track, but a little more is needed to match Android's AsyncTask. Since enums and generics aren't available with Java 1.3 on BlackBerry, you can't match the Android API perfectly.
But, you could do something like this (not tested ... this is just a starting point for you):
import net.rim.device.api.ui.UiApplication;
public abstract class AsyncTask {
public static final int FINISHED = 0;
public static final int PENDING = 1;
public static final int RUNNING = 2;
private int _status = PENDING;
private boolean _cancelled = false;
private Thread _worker;
/** subclasses MUST implement this method */
public abstract Object doInBackground(Object[] params);
protected void onPreExecute() {
// default implementation does nothing
}
protected void onPostExecute(Object result) {
// default implementation does nothing
}
protected void onProgressUpdate(Object[] values) {
// default implementation does nothing
}
protected void onCancelled() {
// default implementation does nothing
}
protected void onCancelled(Object result) {
onCancelled();
}
public final int getStatus() {
return _status;
}
public final boolean isCancelled() {
return _cancelled;
}
public final boolean cancel(boolean mayInterruptIfRunning) {
if (_status == FINISHED || _cancelled) {
return false;
} else {
_cancelled = true;
if (mayInterruptIfRunning && _status == RUNNING) {
// NOTE: calling Thread.interrupt() usually doesn't work
// well, unless you don't care what state the background
// processing is left in. I'm not 100% sure that this is how
// Android's AsyncTask implements cancel(true), but I
// normally just cancel background tasks by letting the
// doInBackground() method check isCancelled() at multiple
// points in its processing.
_worker.interrupt();
}
return true;
}
}
protected final void publishProgress(final Object[] values) {
// call back onProgressUpdate on the UI thread
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
onProgressUpdate(values);
}
});
}
private void completeTask(final Object result) {
// transmit the result back to the UI thread
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
// TODO: not sure if status should be FINISHED before or after onPostExecute()
_status = FINISHED;
}
});
}
public AsyncTask execute(final Object[] params) throws IllegalStateException {
if (getStatus() != PENDING) {
throw new IllegalStateException("An AsyncTask can only be executed once!");
} else {
try {
onPreExecute();
_worker = new Thread(new Runnable() {
public void run() {
try {
// run background work on this worker thread
final Object result = doInBackground(params);
completeTask(result);
} catch (Exception e) {
// I believe if Thread.interrupt() is called, we'll arrive here
completeTask(null);
}
}
});
_status = RUNNING;
_worker.start();
} catch (Exception e) {
// TODO: handle this exception
}
}
return this;
}
}
Also, it's important to keep in mind the Threading Rules for Android's AsyncTask, which apply to the above implementation, too:
Threading rules
There are a few threading rules that must be followed
for this class to work properly:
The AsyncTask class must be loaded on the UI thread. This is done
automatically as of JELLY_BEAN.
The task instance must be created on
the UI thread.
execute(Params...) must be invoked on the UI thread.
Do not call onPreExecute(), onPostExecute(Result),
doInBackground(Params...), onProgressUpdate(Progress...) manually.
The task can be executed only once (an exception will be thrown if a
second execution is attempted.)
You can create a Class that extends my implementation of class AsyncTask. Good Luck :)
Here the methods onPreExecute, onPostExecute are executed on UI thread and doInBackground is called on worker thread. Since onPreExecute, onPostExecute are abstract you can override them and provide your implementation like showing and dismissing progress dialog.
The sequence in which methods get's executed is
1) onPreExecute
2) doInBackground
3) onPostExecute
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
public abstract class AsyncTask {
Runnable runnable;
Thread threadToRun;
public abstract void onPreExecute();
public abstract void onPostExecute();
public abstract void doInBackground();
public void execute() {
try {
runnable = new Runnable() {
public void run() {
// TODO Auto-generated method stub
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
// TODO Auto-generated method stub
onPreExecute();
}
});
doInBackground();
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
// TODO Auto-generated method stub
onPostExecute();
}
});
}
};
threadToRun = new Thread(runnable);
threadToRun.start();
} catch (Exception e) {
// TODO: handle exception
Dialog.alert("Async Error Occured. " + e.toString());
}
}
}