gettedID is a public variable and gets a value after onComplete is done. How can I listen to gettedID value in order to execute some code after it is filled up, without using a separate thread?
VKRequest request = VKApi.wall().get(VKParameters.from("domain", "bitcoin", VKApiConst.OFFSET, offset, VKApiConst.COUNT, count));
request.executeWithListener(new VKRequest.VKRequestListener() {
#Override
public void onError(VKError error) {
System.out.println("error: " + error);
}
#Override
public void onComplete(VKResponse response) {
super.onComplete(response);
try {
json = response.json.getJSONObject("response").getJSONArray("items");
for (int i = 0; i < json.length(); i++) {
returnArray.put(json.getJSONObject(i).get("id").toString());
}
gettedID = returnArray;
//Log.d("BTCR", "gettedID: " + returnArray.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
});
Related
I'm trying to do something similar to the answer of this question
I'm using Volley rather than Retrofit, and have adapted my code accordingly. For me the callback handlers never actually fire, although the counDownLatch does timeout after the specified number of seconds. I suspect the handlers never fire because the countDownLatch.awaiting is using all the processing on the current thread. Or am I missing something else?
public void queryUmbrellaServer() {
ArrayList<String> identifiers = getHardwareIdentifiers(context);
VolleyLog.DEBUG = true;
CountDownLatch countDownLatch = new CountDownLatch(identifiers.size());
// creating a new variable for our request queue
final RequestQueue[] queue = {Volley.newRequestQueue(context)};
queue[0].start();
for (int i = 0; i < identifiers.size(); i++) {
String url = umbrellaServerUrl + identifiers.get(i) + "/";
Log.i(LOG_TAG, "Inside Loop " + url);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
countDownLatch.countDown();
String serverName = response.getString("mdm_server_url");
String registrationUrl = response.getString("registration_url");
String isDeviceOwner = response.getString("device_owner");
Toast.makeText(context, "Retrieved server name from umbrella server: " + serverName, Toast.LENGTH_LONG).show();
setMdmInfo(serverName, registrationUrl, isDeviceOwner);
Log.i(LOG_TAG, "Successful response");
//queue[0].stop();
results.add(isDeviceOwner.toString());
} catch (JSONException e) {
e.printStackTrace();
Log.d(LOG_TAG, "Error in parsing response");
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
countDownLatch.countDown();
if(error.networkResponse.data!=null) {
String jsonString = new String(error.networkResponse.data);
//Log.d(LOG_TAG, jsonString);
try {
JSONObject jsonObject = new JSONObject(jsonString);
String msg = jsonObject.getString("message");
if (!msg.equals("Device not found")) {
Log.d(LOG_TAG, "Error in retrieving response from server");
//queue[0].stop();
results.add("false");
}
else {
Log.d(LOG_TAG, "No device found");
results.add("false");
}
} catch (JSONException e) {
e.printStackTrace();
Log.d(LOG_TAG, "Error in retrieving response from server");
//queue[0].stop();
results.add("UNSET");
}
}
else {
Log.d(LOG_TAG, "Error in retrieving response from server");
//queue[0].stop();
results.add("UNSET");
}
}
});
// Add the request to the RequestQueue.
queue[0].add(jsonObjectRequest);
}
try {
countDownLatch.await(1L * identifiers.size(), TimeUnit.SECONDS); // join thread with timeout of second for each item
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(LOG_TAG,"outside loop" + results);
}
I expected the results arrayList should get populated before the countDownLatch countdown completes, but I haven't been able to get any results.
I want to return string value after getting response from web service in Volley and call value in activity.
Below is my code;
Utils.java
public static String getitemCountPrice(String cartId) {
try {
if (Utils.isNetworkAvailable(mContext)) {
HashMap<String, String> params = new HashMap<>();
params.put(CONSTANTS.API_param_cartid, cartId);
params.put(CONSTANTS.API_param_token, Utils.getToken());
JSONObject postdata = new JSONObject(params);
try {
YupITApplication.getJsonWithHTTPPostResponse(params, mContext, 1, (id, jsonResult) -> {
if (jsonResult.getString(mContext.getString(R.string.status)).equalsIgnoreCase(mContext.getString(R.string.success))) {
itemCountPrice = jsonResult.getJSONObject("Data").getString("Count") + ","
+ jsonResult.getJSONObject("Data").getString("TotalPrice");
Log.e("itemCountPrice.............", "" + itemCountPrice);
// Here I get value
} else {
itemCountPrice = "0,0";
}
}, Utils.cartitemcount, postdata);
} catch (Exception e) {
e.printStackTrace();
}
} else {
Toast.makeText(mContext, mContext.getString(R.string.no_server_found), Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
return itemCountPrice;
// Here I get null and this is called before web service call
}
MainActivity.java
Utils.getitemCountPrice(cart_id));
Every time I get null from above method
Your return statement will execute right after the making the API call and wouldn't wait for the response because it is written in synchronous way. You can notify the result with help of an interface
interface APIListener{
public void onResponse(String itemPrice);
}
your method would look like this
public static void getitemCountPrice(String cartId, APIListener apiListener) {
try {
if (Utils.isNetworkAvailable(mContext)) {
HashMap<String, String> params = new HashMap<>();
params.put(CONSTANTS.API_param_cartid, cartId);
params.put(CONSTANTS.API_param_token, Utils.getToken());
JSONObject postdata = new JSONObject(params);
try {
YupITApplication.getJsonWithHTTPPostResponse(params, mContext, 1, (id, jsonResult) -> {
if (jsonResult.getString(mContext.getString(R.string.status)).equalsIgnoreCase(mContext.getString(R.string.success))) {
itemCountPrice = jsonResult.getJSONObject("Data").getString("Count") + ","
+ jsonResult.getJSONObject("Data").getString("TotalPrice");
Log.e("itemCountPrice.............", "" + itemCountPrice);
apiListener.onResponse(itemCountPrice);
// Here I get value
} else {
itemCountPrice = "0,0";
apiListener.onResponse(itemCountPrice);
}
}, Utils.cartitemcount, postdata);
} catch (Exception e) {
e.printStackTrace();
}
} else {
Toast.makeText(mContext, mContext.getString(R.string.no_server_found), Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
You are mixing async call with sync call.
When you call method getItemCountPrice, you will actually receive your value from volley call when it will be available from network.
You need to use callback or some futurecall.
You can do it using callback like mentioned:
public static String getitemCountPrice(String cartId, onDataListener pDataListener) {
// some code
YupITApplication.getJsonWithHTTPPostResponse(params, mContext, 1, (id, jsonResult) -> {
if (jsonResult.getString(mContext.getString(R.string.status)).equalsIgnoreCase(mContext.getString(R.string.success))) {
itemCountPrice = jsonResult.getJSONObject("Data").getString("Count") + ","
+ jsonResult.getJSONObject("Data").getString("TotalPrice");
Log.e("itemCountPrice.............", "" + itemCountPrice);
// Here I get value
} else {
itemCountPrice = "0,0";
}
//pass value through callback
pDataListener.onItemCountPriceReceived(itemCountPrice)
}, Utils.cartitemcount, postdata);
// some code
}
Take one interface to pass data back to calling activity
interface OnDataListener{
void onItemCountPriceReceived(String itemCountPrice);
}
YourActivity code will look like this
Utils.getItemCountPrice(cart_id,new OnDataListener(){
#Override
void onItemCountPriceReceived(String itemCountPrice){
//you will get your value here when received from network call
}
})
I'm trying to make simple telegram bot on Java.
The question is: how can I receive messages in a loop, when the user typed /start? I have already some
#Override
public void onUpdateReceived(Update update) {
Message msg = update.getMessage();
String txt = msg.getText();
if (txt.equals("/start")) {
sendMsg(msg, "Привет, меня зовут бот " + name + "!");
showHelp(msg);
run(msg, update);
} else if (txt.equals("/help")) {
showHelp(msg);
}
}
Here's showhelp:
private void showHelp(Message msg) {
try {
String inAbout = ReadFile.readFileInString(this.about);
sendMsg(msg, inAbout);
} catch (Exception ex) {
ex.printStackTrace();
}
}
sendMsg:
private void sendMsg(Message msg, String text) {
SendMessage s = new SendMessage();
s.setChatId(msg.getChatId());
s.setText(text);
try {
execute(s);
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
In Run I want to read questions from data and wait for users answer, check if correct and do it in loop. In the end show how many he answered correct.
public void run(Message msg, Update update) {
try {
List<String> data = ReadFile.readFileInList(this.getData());
List<String> dataAnswers = ReadFile.readFileInList(this.answers);
this.sizeOfAnswers = data.size();
for (int i = 0; i < data.size(); i++) {
String line = data.get(i);
sendMsg(msg, line);
String inAnswer = update.getMessage().getText();
String rAns = dataAnswers.get(i);
boolean flag = checkAnswer(inAnswer, rAns);
if (flag) {
this.currentUser.incrementScore();
}
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
String finalString = "Поздравляю, ты ответил на " + this.currentUser.getScore() + "/" + this.sizeOfAnswers
+ " вопросов!";
sendMsg(msg, finalString);
}
}
Also here is maybe some multi user problems. How should I do it? Now it's showing all questions in one second without waiting for an answer.
How it's working now
The problem I am having is acquiring all reachable clients on a network.The below method returns some clients when called. In most cases other android clients.However for the PC it fails when firewall is on.Is there a more effective way to get all clients in Java/android purely or will I need to use android NDK?Any help from experts in this domain will be appreciated.Thanks in advance.
/***
* ping_JavaStyle(final int j)
* uses multi threads to enhance performance
* while pinging from 0>j<=255
* #param j
*/
private void ping_JavaStyle(final int j)
{
new Thread(new Runnable() { // new thread for parallel execution
public void run() {
try {
String testIp = prefix + String.valueOf(j);
InetAddress address = InetAddress.getByName(testIp);
String output = address.toString().substring(1);
if (address.isReachable(3000)) {
System.out.println(output + " is on the network");
ipList.add(testIp);
} else {
if (retest(testIp, 139)) {
ipList.add(testIp);
} else {
System.out.println("Not Reachable: " + output);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
After Researching some more, got this working.With help of this repo:https://github.com/stealthcopter/AndroidNetworkTools
Below code solves the problem:
** RunnableTask.Java
* Created by Kirk on 10/29/2017.
*/
public class RunnableTask implements Callable<Boolean> {
private String testIp = "";
private Boolean is_Reachable = false;
public RunnableTask(String testIp) {
this.testIp = testIp;
}
#Override
public Boolean call() throws Exception {
try {
PingResult pingResult = Ping.onAddress(this.testIp).setTimes(1).setTimeOutMillis(1500).doPing();
if (pingResult.isReachable) {
is_Reachable = true;
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
return is_Reachable;
}
}
And use in the caller method:
private static final int NTHREDS = 255;
//.......
ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
List<Future<Boolean>> thread_Values_list = new ArrayList<>();
for (int i = 1; i <= 255; i++) {
final int j = i;
try {
try {
String testIp = prefix + String.valueOf(j);
RunnableTask worker = new RunnableTask(testIp);
Future<Boolean> submit = executor.submit(worker);
thread_Values_list.add(submit);
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
}
}
for (Future<Boolean> finishedThread : thread_Values_list) {
String reachable_Ip = "";
try {
if (finishedThread.get()) {
reachable_Ip = prefix + String.valueOf(finishThread_counter);
ipList.add(reachable_Ip);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
finishThread_counter++;
}
executor.shutdown();
}
I have an onClickListener that uses Okhttp to asynchronously get some stuff in the background. Here's the OnClickListener:
mGetChartButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String companyName = mSymbolValue.getText().toString();
getRequest(companyName, "chart");
Log.i(TAG, mChartProfile.getSizeDates()+""); // Null exception happens here
}
});
And here is the Okhttp snippet:
OkHttpClient client = new OkHttpClient();
Request request = new Request
.Builder()
.url(completeUrl)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
#Override
public void onResponse(Call call, Response response) throws IOException {
try {
String jsonData = response.body().string();
Log.v(TAG, jsonData);
if (response.isSuccessful()) {
if (requestType.equals("quote")) {
isValidSearch = getQuote(jsonData);
runOnUiThread(new Runnable() {
#Override
public void run() {
if (isValidSearch) {
updateDisplay();
}
toggleFacts(isValidSearch);
}
});
}
else{
getChartInfo(jsonData);
}
} else {
alertUserAboutError();
}
} catch (IOException e) {
Log.e(TAG, "Exception caught: ", e);
} catch (JSONException e) {
Log.e(TAG, "JSONException caught: ", e);
Toast.makeText(BuyActivity.this, "oops!", Toast.LENGTH_LONG).show();
}catch (ParseException e){
Log.e(TAG, "Unable to parse", e);
}
}
});
// How do I do a thread.join() here?
private void getChartInfo(String jsonData) throws JSONException, ParseException{
JSONObject wholeChartData = new JSONObject(jsonData);
JSONArray dates = wholeChartData.getJSONArray("Dates");
mChartProfile = new ChartProfile();
// ChartProfile contains ArrayList of ChartDate and ArrayList of ChartValue
for (int i = 0; i < dates.length(); i++){
ChartDate chartDate = new ChartDate(dates.getString(i));
mChartProfile.addToDates(chartDate);
}
JSONArray values = close.getJSONArray("values");
for (int i = 0; i < values.length(); i++){
ChartValue chartValue = new ChartValue(values.getDouble(i));
mChartProfile.addToValues(chartValue);
}
}
Right now, I'm getting an error of thread exiting with uncaught exception. And this is caused by a null exception because when calling mChartProfile.getSizeDates(), the values haven't been written in yet. My intuition is that the call to getChartInfo(jsonData) doesn't finish and the main UI thread is already returning from the getRequest() function. Hence, it will continue next line, and try to access an empty array that has not been initialized. Hence, I get a null exception. My solution is to have the main thread wait on the worker thread by calling thread.join() but I am not sure of how to do this through this Okhttp interface. Any help is deeply appreciated.