I'm quite new to using android studio. My question is, how do i change an asynchronous response into a synchronous response. I am currently using the volleyball library to return data from my database in JSON format.
The problem that I am experiencing is, representing that data into a graph format. You see, due to the structure of my code, the compiler waits for the response (essentially the data that is being sent from my database to android studio) but as its waiting, the compiler moves on to the other parts of the code which involves creating a graph and representing the data from my database into the graph.
But the graph is empty because it has not been fed any data, as we'r waiting for a response.
Here is the code:
private void sendRequest() {
System.out.println("Triggering send Request");
StringRequest stringRequest = new StringRequest(JSON_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
showJSON(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(BillReport.this, error.getMessage(), Toast.LENGTH_LONG).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
System.out.println("Send Request done");
}
The send request method is called before the implementation of the graph in the main method.
Bottom line is, I need to figure out how I can get an immediate response as opposed to waiting for a response.
Thank you for taking your time to read this post!
You will have to wait for the response to show the values in the graph. You can cache the data in volley and use it if the server data is not expected to change. You can have a progress bar that will rotate while the data is being retrieved. This is the standard practice.
Related
I am developing an app in Android Studio (Java) that uses the Google speech recognition API and a certain other API that I am trying to make a POST request to. Here is an excerpt of my code.
String url = MY_URL;
String jsonSpeechResults = "{\"prompt\": \"" + speechResults + "\"}";
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(jsonSpeechResults, MediaType.parse("application/json"));
Request request = new Request.Builder().url(url).addHeader("Authorization", API_KEY).post(body).build();
try {
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NonNull Call call, #NonNull IOException e) {
}
#Override
public void onResponse(#NonNull Call call, #NonNull Response response) throws IOException {
try {
String theResponse = response.body().string();
errorView.setText(theResponse);
} catch(Exception f) {
errorView.setText(f.getMessage());
}
}
});
} catch (Exception g) {
errorView.setText(g.getMessage());
}
Here is how this part of the app is supposed to work. When I speak some words, the speech recognition API picks up my words, and when the speech recognition results are returned, those results get sent to my other API (the one that corresponds to MY_URL) in a POST request, and then that API should return some JSON, which is then supposed to print out in string format in the errorView TextView field. If it is not apparent by this explanation, this excerpt of code is inside of the onResults method of a RecognitionListener object that is defined in the onCreate method.
Whenever I run this on my Android phone, I am expecting the response results to appear in my errorView TextView field, but instead all that appears is a single "{". Furthermore, the request doesn't even seem to get made at all the first time I speak into the phone. I have to speak again for the request to even get made (even though I know for certain that the speech recognition does work the first time; it is just the other API that doesn't seem to receive my request the first time I speak).
I don't understand why, and this is annoying me. Furthermore, I can't use
client.newCall(request).execute()
because this just returns an exception. Even the message from a try catch does not tell me what the problem is.
Can someone please help me?
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
I am an android beginner learner .I want to know why should we use RequestQueue in our codes and pass JsonObjectRequest to RequestQueue as an argument .
enter image description here
The Volley uses two classes, RequestQueue and Request
RequestQueue is where all the requests are queued up that has to be executed,
it also manages the worker threads
and maintain network call in the background
also it handles reading from and writing to the cache
and also parsing the response and delivering the parsed response to mainthread.
Request is where network request is constructed.The request object has 3 major request:
JSON requests
JsonObjectRequest — A request for retrieving a JSONObject response body at a given URL
.
JsonArrayRequest — For retrieving JSON Array from the server.
Request takes 3 parameters that are passed to the constructor.
Request Method Type(GET,POST,PUT...).
Resource URL of the required object.
ResponseListener whose callback method contains the response.
ErrorListener whose callback method has an error has been occurred with request (provided error code and optional user-readable).
The snippet for the implementation of both JsonObjectRequest and JsonArrayRequest is as below:
String mJSONURLString= "json_url";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, mJSONURLString, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
//add JsonObjectRequest request to queue
requestQueue.add(jsonObjectRequest);
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, url, null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
//add JsonArrayRequest to queue
requestQueue.add(jsonArrayRequest);
StringRequest — To retrieve response body as String from the server.
Method Type(GET,POST,...).
The Resource URL.
The Event Listeners.
Code snippet as below:
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// Do something with the response
}
},
ImageRequest-To receive an image from the server,the network call has the similar structure as other network requests.
Code snippet as below:
String mImageURLString= "";
ImageRequest imageRequest = new ImageRequest(mImageURLString= , new Response.Listener<Bitmap>() {
#Override
public void onResponse(Bitmap response) {
// Assign the response to an ImageView
ImageView imageView = (ImageView) findViewById(R.id.imageView);
imageView.setImageBitmap(response);
}
}, 0,0, null);//Image width,Image height
//add request to queue
requestQueue.add(imageRequest);
When you're using Volley, RequestQueue will queue your requests on worker thread and then delivers the response to main thread. The reason why you need it is that you are not allowed to perform network operations on the main thread if your application targeting the Honeycomb SDK or higher. Thus you will not get NetworkOnMainThreadException.
i am trying to send json using postman to Lavavel but i facing this error.
enter image description here
this is my json code:
{
"email":"test#test.com",
"password":"testtest"
}
and this is Laravel codes :
Route::get('/r','test#store');
and
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use DB;
use Log;
class test extends Controller
{
public function store(Request $request)
{
$email = $request->input('email');
$password = $request->input('password');
Log::info('test');
Log::info($email);
Log::info($password);
DB::table('login')->insert([
['email' => $email],
['password' => $password]
]);
}
}
also i trying using android for send data using volley and so checked Laravel logs :
Column 'email' cannot be null (this is Laravel logs)
and on android Logs:
E/Volley: [299] BasicNetwork.performRequest: Unexpected response code 500 for http://192.168.1.4:8000/r
D/error: com.android.volley.ServerErro
my android code is :
public class ApiService {
private final Context context;
public ApiService(Context context){
this.context=context;
}
public void loginUser(String email, String password, final OnLoginResponse onLoginResponse){
JSONObject requestJsonObject=new JSONObject();
try {
requestJsonObject.put("email",email);
requestJsonObject.put("password",password);
JsonObjectRequest request=new JsonObjectRequest(Request.Method.GET, "http://192.168.1.4:8000/r",requestJsonObject , new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("response",response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("error",error.toString());
}
}) {
#Override
public Map getHeaders() throws AuthFailureError {
HashMap headers = new HashMap();
headers.put("Content-Type", "application/json");
return headers;
}
};
request.setRetryPolicy(new DefaultRetryPolicy(18000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
Volley.newRequestQueue(context).add(request);
} catch (JSONException e) {
Log.e(TAG, "loginUser: "+e.toString());
}
}
public interface OnLoginResponse{
void onResponse(boolean success);
}
}
I hope this helps people trying to search on how to send JSON data to laravel not only specific to android applications but to all. The goal of this solution is to identify whether you can send a JSON data to laravel or not.
First of all you have to download postman from https://www.getpostman.com/ to test if your API is really working or not.
Create a post request using postman. Be sure that you follow the example data below
Be sure that you set your Routes that would associate to the controller
This is the controller part that will show the JSON data you sent if it was successfully accepted or not.
And also, if ever you are trying to send POST data to laravel, by default they provided a CSRF Token which is applicable for the forms if you are going to use the MVC of laravel. For the meantime, we are going to take this down and comment it out. Just go to app/http/kernel.php
and now you'll get the following result from the code earlier
$json = json_decode($request['json']);
echo $json->{'email'};
echo "\n";
echo $json->{'password'};
We tested that we were able to send data to laravel. I hope this truly helps.
Wen you want to send data, you will want to use POST or PUT method on your postman, specially if you are sending a body, that means that you are sending data. Get method is used to retrieve data from a service.
Take a look into CRUD functions for more information.
Your postman should look something like this
Last in your android code try to change this line
JsonObjectRequest request=new JsonObjectRequest(Request.Method.GET, "http://192.168.1.4:8000/r",requestJsonObject , new Response.Listener<JSONObject>() {
to use Request.Method.POST
I am attempting to get a user's Reddit front page. I have successfully received an Auth Token via the Token Retrieval (code flow). I have managed to get the expected JSON response via Postman, but cannot produce the same results with Retrofit. The request seems to be timing out as onFailure() is being triggered in the callback. I am using the scopes: identity, mysubreddits, and read.
Additional note: I have got a 401 and 403 response with the code below when using insufficient scopes and using an expired Auth Token respectively.
Relevant constants:
redditToken = (actual auth token String)
RedditConstants.REDDIT_BASE_URL_OAUTH2 = "https://oauth.reddit.com"
Relevant method Section:
if (redditToken != null) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(RedditConstants.REDDIT_BASE_URL_OAUTH2)
.addConverterFactory(GsonConverterFactory.create())
.build();
Api api = retrofit.create(Api.class);
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "bearer " + redditToken);
headers.put("User-Agent", RedditConstants.REDDIT_USER_AGENT);
Call<RedditFeed> call = api.getFeed(headers);
call.enqueue(new Callback<RedditFeed>() {
#Override
public void onResponse(Call<RedditFeed> call, Response<RedditFeed> response) {
Log.d("FINDME", "response "+ response.toString());
if (response.isSuccessful()) {
Log.d("FINDME", "response was a success! we got the feed!");
} else {
Log.d("FINDME", "responce was not successfull triggered");
}
}
#Override
public void onFailure(Call<RedditFeed> call, Throwable t) {
Log.d("FINDME", "onFailure called from populateRedditFeed");
}
});
} else {
Toast.makeText(this, "Please Login with Reddit", Toast.LENGTH_SHORT).show();
}
Retrofit Interface:
public interface Api {
#GET(".")
Call<RedditFeed> getFeed (
#HeaderMap Map<String, String> headers
);
}
Log Results:
D/NetworkSecurityConfig: No Network Security Config specified, using
platform default
I/zygote: Do full code cache collection, code=123KB, data=105KB
After code cache collection, code=111KB, data=79KB
D/FINDME: onFailure called from populateRedditFeed
Postman Success:
After many starts and stops, seemingly randomly getting either a 200 or calling onFailure() I discovered the problem in one of my Retrofit model classes. The JSON response from Reddit contains a field that can either be a long or boolean. I had it defined as a boolean in my java class which threw an llegalStateException when it was returned as a long.
type name description
special edited false if not edited, edit date in UTC epoch-seconds
otherwise. NOTE: for some old edited comments on reddit.com, this will
be set to true instead of edit date.
*I'm unsure how to deal with this duality of types in java so for now I've commented out the field and the code works as expected.
Below is my class for handling http requests. I have tried the Volley Request in a new Android Project with no other code and the request is handled properly and I receive the result I expected. But for some reason when I use this code in my working project as a class, it doesn't return any response.
The way I call the request is:
HttpRequest request = new HttpRequest();
String url = "some-url";
String urlReturn = request.getFromURL(url, <ACTIVITY>.this);
where <ACTIVITY> is the activity I am calling the request from and "some-url" is a url that returns a string of data.
public class HttpRequest {
String response_test = "";
public String getFromURL (String url, Context context) {
RequestQueue requestQueue = Volley.newRequestQueue(context);
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e("response1", response);
response_test = "1";
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
Log.d("log2=", error.toString());
//requestQueue.stop();
}
});
// Add the request to the RequestQueue.
requestQueue.add(stringRequest);
requestQueue.start();
return response_test;
}
response_test never changes, so onResponse is never called. I thought there may be a timing issue, but when I add loop for it to wait until response_test is changed, it waits forever. Any idea what may be the issue? Anything I may have overlooked in how I'm calling this class?
Any help appreciated.
Volley is async library. It does work on another thread and when the call is ready it executes the code in onResponse. In the example you are returning imideately. Check your logcat for the messages they should be there