public class BtcPaymentQR extends AppCompatActivity {
ImageView QrCode;
RequestQueue mQueue;
public static String btcAddress = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_btc_payment_qr);
QrCode = findViewById(R.id.imageViewQR);
mQueue = Volley.newRequestQueue(this);
getAddress();
Log.i("test", "onCreate: " + btcAddress);
}
public void getAddress(){
String url = "xxx"
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONObject jsonObject = response.getJSONObject("address");
String a = jsonObject.getString("extkey_next_receiving_address");
BtcPaymentQR.btcAddress=a;
Log.i("test", "onResponse: " + btcAddress);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
mQueue.add(request);
}
Logcat
My Question is, How do I get the value of "a" from the method. I've tried everything to save it in another global variable, with return, with get and set.
I need the value to use it in a other Method
Your problem is solved by using static variable to save response,and static variables are part of class not object so you can use static variable with class name like MainActivity.myValue in my example.
Your Activity or Fragment Class:
MainActivity Extends AppCompatActivity{
public static String myValue="";
//define this in your classs where you run the web service
}
your response method
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONObject jsonObject = response.getJSONObject("address");
String a = jsonObject.getString("extkey_next_receiving_address");
MainActivity.myValue=a;
Log.i("test", "onResponse: " + MainActivity.myValue);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i("test2", "onErrorResponse: error");
}
});
mQueue.add(request);
}
Simple way is using static variable. define a static variable for class and assign the value of 'a' to this static variable and use it every where.
Related
I am trying to retrieve a JsonObject via GET request. When I set Breakpoints in my code I see that the count() method returns nothing. After that the onResponse method from the inner class gets called and the desired value gets retrieved.
I am calling the count() method inside the save() method. In order to create a JSONObject. The code creates the JSONObject before it retrieves the correct customer count.
I am using a custom requesQueue called AppController to queue the network request. I hope someone understands this strange behaviour.
#Override
public void save(Customer customer) throws JSONException {
int zw = count();
JSONObject obj = new JSONObject();
obj.put("customernumber", count + 1);
obj.put("name", customer.getName());
obj.put("lastname", customer.getLastname());
obj.put("phonenumber", customer.getPhonenumber());
obj.put("addressid", customer.getAdressID());
obj.put("password", customer.getPassword());
String urlJsonObj = URL;
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
urlJsonObj, obj,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("Error: " + error.getMessage());
}
});
AppController.getInstance().addToRequestQueue(jsonObjReq);
}
#Override
public int count() {
String countURL = URL + "/count";
JsonObjectRequest jsonObjReq = new JsonObjectRequest
(Request.Method.GET, countURL, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
// Parsing json object response
// response will be a json object
count = response.getInt("count");
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d( "Error: " + error.getMessage());
}
});
AppController.getInstance().addToRequestQueue(jsonObjReq);
return count;
The AppController network queue
public class AppController extends Application {
public static final String TAG = AppController.class
.getSimpleName();
private RequestQueue mRequestQueue;
private static AppController mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
What's Happening?
This is happening due to incorrect thread usage. count() function performs the network request in the background thread, so it won't return the count immediately when we call it from save() function.
Solution
Wait for the response from count API and then perform a save operation. Replace the above implementation with the following
#Override
public void save(Customer customer) throws JSONException {
count();
}
private void performSave(Customer customer, int count) throws JSONException {
int zw = count; // Finally received the count
JSONObject obj = new JSONObject();
obj.put("customernumber", count + 1);
obj.put("name", customer.getName());
obj.put("lastname", customer.getLastname());
obj.put("phonenumber", customer.getPhonenumber());
obj.put("addressid", customer.getAdressID());
obj.put("password", customer.getPassword());
String urlJsonObj = URL;
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
urlJsonObj, obj,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("Error: " + error.getMessage());
}
});
AppController.getInstance().addToRequestQueue(jsonObjReq);
}
#Override
public int count(Customer customer) {
String countURL = URL + "/count";
JsonObjectRequest jsonObjReq = new JsonObjectRequest
(Request.Method.GET, countURL, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
// Parsing json object response
// response will be a json object
count = response.getInt("count");
performSave(customer, count);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d( "Error: " + error.getMessage());
}
});
AppController.getInstance().addToRequestQueue(jsonObjReq);
return 0; // Remove this return type as we will not use it anymore
}
I Want to Store the response of Volley in a Public variable but when I Toast it out the volley request that returns null
public JSONArray array ;
String URL = "http://192.168.1.104/json.php";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_json);
array = new JSONArray();
JsonArrayRequest request = new JsonArrayRequest( URL,new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
try {
array = response;
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
Volley.newRequestQueue(this).add(request);
Toast.makeText(json.this, array.toString(),Toast.LENGTH_LONG).show();
As people have said, calling the Toast initiation within onResponse() works, but the best way to handle this is to create a small listener interface or method that is called in onResponse and implemented where you need it.
I'd also strongly suggest only passing the data you need and saving that in a model class, rather than just saving the response outright.
a very simple example would be
String URL = "http://192.168.1.104/json.php";
// make sure your class implements this
public interface ResponseListener {
public gotResponse(JSONArray array);
}
// implementation of ResponseListener
public gotResponse(JSONArray array) {
// eventually do more with this data
Toast.makeText(json.this, array.toString(),Toast.LENGTH_LONG).show();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_json);
ResponseListener listener = this;
JsonArrayRequest request = new JsonArrayRequest( URL,new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
try {
listener.gotResponse(response);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
Volley.newRequestQueue(this).add(request);
One way could be moving the line:
Toast.makeText(json.this, array.toString(),Toast.LENGTH_LONG).show();
exactly to the line after: array = response;
I use JsonArrayRequest inside a method(function), that return number.I use function JsonArrayRequest when I need it.
But some issue: function return wrong number, in code below function have to return variable lastNumber, i.e last number of variable i. Sorry if my qustion stupid, couse I am new in java and android. Note, function return the lastNumber when it used a second time. I suggest that the program in first time is not implement JsonArrayRequest.
I following this tutorial http://www.androidhive.info/2014/05/android-working-with-volley-library-1/ .Any help appreciate!
public int lastNumber = 0;
private int makeJsonObjectRequest(int startList,int endList) {
JsonArrayRequest movieReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
i = startLsit;
while(i < endList) {
try {
JSONObject obj = response.getJSONObject(i);
Movie movie = new Movie();
/***** TONS OF CODE *****/
movieList.add(movie);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
i++;
lastNumber = i;
}
mAdapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
}
});
AppController.getInstance().addToRequestQueue(movieReq);
return lastNumber
}
you use incorrect way. you must return lastNumber after the network back answer. so I suggest that define your function output 'void'. Then you must use Interface for network. I explain it by code. like below:
this is your interface:
public interface JsonObjectListener {
public void onDone(int lastNumber);
public void onError(String error);
}
in your function do it:
private void makeJsonObjectRequest(int startList, int endList, JsonObjectListener listener) {
JsonArrayRequest movieReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
i = startLsit;
while(i < endList) {
try {
JSONObject obj = response.getJSONObject(i);
Movie movie = new Movie();
/***** TONS OF CODE *****/
movieList.add(movie);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
i++;
lastNumber = i;
}
mAdapter.notifyDataSetChanged();
if(listener!=null)
listener.onDone(lastNumber);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (listener != null)
listener.onError(error.getMessage());
}
});
AppController.getInstance().addToRequestQueue(movieReq);
}
Then when you want use it, call it like below:
makeJsonObjectRequest(your_startList, your_endList, new JsonObjectListener() {
#Override
public void onDone(int lastNumber) {
/// Do every thing you want with lastNumber
}
#Override
public void onError(String error) {
hidePDialog();
}
});
}
You want to use callback interface:
public interface VolleyCallback{
void onSuccess(int result);
}
// Method:
public void getResult(VolleyCallback callback) {
JsonArrayRequest movieReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
i = startLsit;
while(i < endList) {
try {
JSONObject obj = response.getJSONObject(i);
Movie movie = new Movie();
/***** TONS OF CODE *****/
movieList.add(movie);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
i++;
lastNumber = i;
}
mAdapter.notifyDataSetChanged();
callback.onSuccess(lastNumber);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
callback.onSuccess(lastNumber);
}
});
}}
Example code in activity:
public void onResume(){
super.onResume();
getResult(new VolleyCallback(){
#Override
public void onSuccess(int result){
... //do stuff here result is your lastNumber
}
});
}
I hope it work.
You need to do in below way:
Add method for fetching server response from server:
public void makeWebServiceRequest(String tag, final String url, int method, JSONObject jPassedObject, final VolleyResponseListener listener){
JsonObjectRequest jsObjRequest = new JsonObjectRequest(method,url,jPassedObject,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
CustomProgressbar.hideProgressBar();
}catch (Exception e){
e.printStackTrace();
}
listener.onVolleySuccess(url, response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
try {
NetworkResponse networkResponse = error.networkResponse;
if (networkResponse != null && networkResponse.statusCode == HttpStatus.SC_UNAUTHORIZED) {
// HTTP Status Code: 401 Unauthorized
}
CustomProgressbar.hideProgressBar();
}catch (Exception e){
e.printStackTrace();
}
listener.onVolleyFailure(url);
}
});
AppController.getInstance().addToRequestQueue(movieReq);
}
Add interfece to pass data to any Activity/Fragment:
public interface VolleyResponseListener {
void onVolleySuccess(String url, String serverResponse);
void onVolleyFailure(String url);
}
How to call this method ?
makeWebServiceRequest("Get Request", "URL HERE", Request.Method.GET, null, new VolleyResponseListener() {
#Override
public void onVolleySuccess(String url, String serverResponse) {
}
#Override
public void onVolleyFailure(String url) {
}
});
Note: You should write your logic in your Activity/Fragment instead of common webservice calling code.
You would get your server response in onVolleySuccess override method.
I have the following class which I want to change a bit so as to make it more "object oriented" and easy to read.
public class CreateLeague extends AppCompatActivity {
....
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.activity_create_league);
createLeague(...);
}
public void createLeague(final String leagueName, final String username, final String password,final String start,final String end,final String openLeague) {
HttpsTrustManager.allowAllSSL();
String tag_json_obj = "json_obj_req";
final HashMap<String, String> postParams = new HashMap<String, String>();
postParams.put("league_name",leagueName);
postParams.put("username",username);
postParams.put("password",password);
postParams.put("league_start",start);
postParams.put("league_finish",end);
postParams.put("open_league",openLeague);
Response.Listener<JSONObject> listener;
Response.ErrorListener errorListener;
final JSONObject jsonObject = new JSONObject(postParams);
JsonObjectRequest jsonObjReq = new JsonObjectRequest(AppConfig.URL_CREATE_LEAGUE, jsonObject,
new com.android.volley.Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("TAG", response.toString());
try {
if (response.getString("status").equals("success")){
Intent i = new Intent(CreateLeague.this, League.class);
startActivity(i);
finish();
}
} catch (JSONException e) {
Log.e("TAG", e.toString());
}
//pDialog.dismiss();
}
}, new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//VolleyLog.d("TAG", "Error: " + error.getMessage());
//pDialog.dismiss();
}
}) {
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonObjReq, tag_json_obj);
}
}
In other words I want to create the createLeague(...) to another class i.e. CreateLeagueClass and instantiate that object inside the onCreate() method of the above class. So here is what I do.
public class CreateLeagueClass extends AppCompatActivity{
private void createLeague(final String leagueName, final String username, final String password,final String start,final String end,final String openLeague) {
HttpsTrustManager.allowAllSSL();
String tag_json_obj = "json_obj_req";
final HashMap<String, String> postParams = new HashMap<String, String>();
postParams.put("league_name",leagueName);
postParams.put("username",username);
postParams.put("password",password);
postParams.put("league_start",start);
postParams.put("league_finish",end);
postParams.put("open_league",openLeague);
Response.Listener<JSONObject> listener;
Response.ErrorListener errorListener;
final JSONObject jsonObject = new JSONObject(postParams);
JsonObjectRequest jsonObjReq = new JsonObjectRequest(AppConfig.URL_CREATE_LEAGUE, jsonObject,
new com.android.volley.Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("TAG", response.toString());
try {
if (response.getString("status").equals("success")){
Intent i = new Intent(CreateLeague.this, League.class);
startActivity(i);
finish();
}
} catch (JSONException e) {
Log.e("TAG", e.toString());
}
//pDialog.dismiss();
}
}, new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//VolleyLog.d("TAG", "Error: " + error.getMessage());
//pDialog.dismiss();
}
}) {
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonObjReq, tag_json_obj);
}
}
The problem is that compiler is giving me an error in this line.
Intent i = new Intent(CreateLeague.this, League.class);
of the CreateLeagueClass
The error is like this.
app....CreateLeague is not an enclosing class
Any suggestions?
Thank you.
CreateLeague.this is the current instance of CreateLeague. It only works inside that class, When you move that code to another class, you have to pass that instance e.g. add a parameter CreateLeague cL to the Method createLeague and use CreateLeague.this when you call that method.
I'm trying to use Volley as a DBA layer to call a webservice that hadles JSON objects. Because this layer is below the activity and another service layer, it doesn't seem to be working properly. I'll try to explain my setup:
MainActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ProductService productService = new ProductService();
productService.getProduct();
}
ProductService.java:
public void getProduct() {
JsonObjectRequest req = new JsonObjectRequest("http://echo.jsontest.com/name/Milk/price/1.23/", null, createMyReqSuccessListener(), createMyReqErrorListener());
ApplicationController.getInstance().addToRequestQueue(req);
}
private Response.Listener<JSONObject> createMyReqSuccessListener() {
return new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.v("response", response.toString());
}
};
}
private Response.ErrorListener createMyReqErrorListener() {
return new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
return;
}
};
}
I hope that is clear enough.
In the end, I would like to use the ProductService::getProduct() from an activity and the the actual JSON response from the webservice in a variable which I can later use.
However, at the moment, the line
Log.v("response", response.toString());
doesn't even execute. What am I doing wrong?
What I would try is this:
Declare getProduct as
public void getProduct(Response.Listener<JSONObject> listener,
Response.ErrorListener errlsn) {
JsonObjectRequest req = new JsonObjectRequest("http://echo.jsontest.com/name/Milk/price/1.23/",null, listener, errlsn);
ApplicationController.getInstance().addToRequestQueue(req);
}
And than call in your activity like this:
productService.getProduct(
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
variableFromActivity = response;
//Or call a function from the activity, or whatever...
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//Show error or whatever...
}
});
Create an abstract class AppActivity
import androidx.appcompat.app.AppCompatActivity;
public abstract class AppActivity extends AppCompatActivity
{
abstract void callback(String data);
}
Extend all your Activities using AppActivity
public class MainActivity extends AppActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String url = "Your URL";
JSONObject jsonBody = new JSONObject();
try {
jsonBody.put("Title", "Android Volley Demo");
jsonBody.put("Author", "BNK");
}
catch (JSONException e) {
System.out.println(e);
}
final String requestBody = jsonBody.toString();
Messenger messenger = new Messenger(MainActivity.this);
messenger.sendMessage(this, url, requestBody);
}
public void callback(String data)
{
System.out.println(data);
}
}
Create Messenger class as below:
public class Messenger
{
private AppActivity myActivity;
public Messenger(AppActivity activity)
{
myActivity = activity;
}
public void sendMessage(Context context, String url, final String requestBody)
{
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(context);
// Request a string response from the provided URL.
StringRequest stringRequest =
new StringRequest(
Request.Method.POST,
url,
null,
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println(error);
}
}
) {
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
return requestBody == null ? null : requestBody.getBytes("utf-8");
}
catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
return null;
}
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response)
{
myActivity.callback(new String(response.data));
String responseString = "";
if (response != null) {
responseString = String.valueOf(response.statusCode);
// can get more details such as response.headers
}
return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
}
};
queue.add(stringRequest);
}
}
Hope it helps.