Android: how return a value from JsonObjectRequest? - android

Let's say I have this Dashboard.java:
public class DashboardActivity extends ActionBarActivity {
private TextView login_response;
private static String TAG = DashboardActivity.class.getSimpleName();
final static String API_URL_ACCOUNT = "http://www.example.com/apiv2/account";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
login_response = (TextView) findViewById(R.id.login_response);
Intent intent = getIntent();
if(intent.hasExtra("TOKEN"))
{
String token = intent.getStringExtra("TOKEN");
getShopName(token);
}
else
{
}
And this is the getShopName method:
private void getShopName(String token) {
JsonObjectRequest req = new JsonObjectRequest(API_URL_ACCOUNT + "?token=" + token, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
VolleyLog.v("Response:%n %s", response.toString(4));
JSONArray account = response.getJSONArray("account");
//Log.d(TAG, "Account: "+account.toString());
JSONObject shop = account.getJSONObject(0);
String name_shop = shop.getString("name_shop");
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("Error: ", error.getMessage());
}
});
// add the request object to the queue to be executed
VolleyController.getInstance().addToRequestQueue(req);
}
My goal is to have
if(intent.hasExtra("TOKEN"))
{
String token = intent.getStringExtra("TOKEN");
String shop_name = getShopName(token);
}
The "shop_name" in variable, to reuse in other part.
So, I know that void doesn't return nothing, but, I tried to edit like this answer, without success:
How can I return value from function onResponse of Volley?
Thank you

The issue is not returning a value from a JsonObjectRequest, but rather that you're trying to do an asynchronous operation in a synchronous way.
Here is a great explanation: Asynchronous vs synchronous execution, what does it really mean?
And to your specific question: I advise using an AsyncTask for your network operation.

Related

Android Async interface to get data obtained fron json request

i am new to Android,here is class Question bank returns list of json obj received from an api
ArrayAsyncResponse in interface containing only one method process complete ,i readed that http request is asynchronous but unable to relate
Question is model class
case 1) when there is no ArrayAsyncResponse interface exist and i return the list to main activity and print it it shows empty list but when i make call to callback.processComplete() and then return list followed by printing ,it shows data
case2 )if i pass null in this function callback.processComplete() then again returned list is empty
so what basically Interface is helping us
public class QuestionBank {
ArrayList questionArrayList = new ArrayList<>();
private String url = "https://raw.githubusercontent.com/curiousily/simple-quiz/master/script/statements-data.json";
public List<Question> getQuestions(final AnswerListAsyncResponse callBack) {
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(
Request.Method.GET,
url,
(JSONArray) null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
for (int i = 0; i < response.length(); i++) {
try {
Question question = new Question();
question.setAnswer(response.getJSONArray(i).get(0).toString());
question.setAnswerTrue(response.getJSONArray(i).getBoolean(1));
//Add question objects to list
questionArrayList.add(question);
//Log.d("Hello", "onResponse: " + question.getAnswer());
// Log.d("JSON", "onResponse: " + response.getJSONArray(i).get(0));
//Log.d("JSON2", "onResponse: " + response.getJSONArray(i).getBoolean(1));
} catch (JSONException e) {
e.printStackTrace();
}
}
if (null != callBack) callBack.processFinished(questionArrayList);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
AppController.getInstance().addToRequestQueue(jsonArrayRequest);
return questionArrayList;
}
public class MainActivity extends AppCompatActivity {
private QuestionBank questionBank;
List<Question> questionList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
questionBank=new QuestionBank();
questionList=questionBank.getQuestions(new AnswerListAsyncResponse() {
#Override
public void processFinished(ArrayList<Question> questionsArrayList) {//this function triggers when response is received from api
Log.d("inside", "processFinished: "+questionsArrayList);
}
});
Log.d("sync response", "questionLIst: "+questionList);
}
}
Sorry I can't write this in comment, but I think I can help you.
I don't understand well your question. but I think you need to get a Listener of the async in your class activity.
You can do that with EventBus, like this : https://github.com/greenrobot/EventBus

How to pass custom class in an intent

I'm using Volley GET method and I successfully got response.Now i try to deserialize response and then i try to pass custom class in another activity
RequestQueue queue = Volley.newRequestQueue(getActivity());
mShowDialog();
String url = "************";
UTF8VolleySupport sr = new UTF8VolleySupport(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e("response", response + "mm");
hideDialog(pDialog);
TrainsMainClass trainsMainClass;
Gson gson = new Gson();
try {
JSONObject jsonObject = new JSONObject(response);
String errorcode = jsonObject.getString("errorcode");
if (errorcode.equals("500")) {
Toast.makeText(getActivity(), jsonObject.getString("message"), Toast.LENGTH_SHORT).show();
}
if (jsonObject.has("data")) {
trainsMainClass = gson.fromJson(jsonObject.getString("data"), TrainsMainClass.class);
if (trainsMainClass != null) {
Intent intent = new Intent(getActivity(), TrainsActivity.class);
Bundle bundle = new Bundle();
bundle.putSerializable("trainsMainClass", trainsMainClass);
intent.putExtras(bundle);
startActivity(intent);
getActivity().overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
hideDialog(pDialog);
NetworkResponse errorRes = error.networkResponse;
String stringData = "";
if (errorRes != null && errorRes.data != null) {
try {
stringData = new String(errorRes.data, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
Log.e("Error", stringData);
}
});
sr.setRetryPolicy(new DefaultRetryPolicy(
30000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
queue.add(sr);
public class TrainsActivity extends AppCompatActivity {
private TrainsMainClass trainsMainClass;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_trains);
trainsMainClass = new TrainsMainClass();
if (getIntent() != null) {
trainsMainClass = (TrainsMainClass) getIntent().getExtras().getSerializable("trainsMainClass");
if (trainsMainClass != null)
Log.e("trainsMainClass", trainsMainClass + "");
}
}
}
public class TrainsMainClass implements Serializable{
#Override
public String toString() {
return "TrainsMainClass{" +
"trainDeparture=" + trainDeparture +
", trainReturn=" + trainReturn +
'}';
}
#SerializedName("departure")
private Timetable trainDeparture;
#SerializedName("return")
private Timetable trainReturn;
}
This is my source,but when I run my app i have exception.
How i can solve my problem?
`Parcelable` encountered `IOException` writing serializable object
Why not just pass the jsonResponse string in intent which can be parsed later in the new activity that you are starting!
intent.putExtraString("jsonResp", jsonObject.getString("data"));
startActivity(intent);
& in your other activity, you can parse the response into object using GSON
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_trains);
trainsMainClass = new TrainsMainClass();
if (getIntent() != null) {
String response = getIntent().getExtraString("jsonResp");
if(response !=null){
trainsMainClass = gson.fromJson(, TrainsMainClass.class);
Log.e("trainsMainClass", trainsMainClass + "");
}
}
Try to avoid passing large amounts of data between Activities, there's an upper limit on the size of data that can be passed with an Intent. Alternatively, what I'd suggest to do is:
Read the data in the first Activity, parse it and store either in DB, or in an in-memory storage. Make sure there's a meaningful ID field in your data.
Pass the ID (which will probably be either int, long or String) with the Intent to the second Activity.
In second Activity, get the data by ID from the storage.
This solution will scale well for any amount of data you're passing between Activities, and additionally, given that you'll be keeping your data in memory, you won't be paying the cost of serializing and deserializing the data from the Intent.

Testing RX java

public void getTerms(boolean showDialog) {
service.getTermsFromServer().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new SingleSubscriber<String>() {
#Override
public void onSuccess(String value) {
try {
JSONObject jsonObject = new JSONObject(value);
JSONObject data = jsonObject.getJSONObject("data");
String content = data.getString("content");
String id = data.getString("id");
if (showDialog) {
***signUpView.showDialog(content, id)***;
} else {
agreeTerms(id);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onError(Throwable error) {
Log.e(getClass().getName(), "Error : " + new Gson().toJson(error.getStackTrace()));
ErrorCheck.processError(error, gson, signUpView);
}
});
}
Please help me in testing this code. I have attached the method which i want to test. Here I want to verify that showDialog method gets called
Attaching the Unit test code also
#Test
public void testGetTermsCalled(){
String terms= "{\"data\":{\"id\":\"67f07c7a482542\",\"content\":\"<h3>Part of the test</h3>\",\"timestamp\":1484768675815,\"timestampFormatted\":\"2017-01-18T19:44:35\"},\"metadata\":null,\"version\":{\"id\":\"v1\",\"versionStatus\":\"candidate\",\"message\":null}}";
TestSubscriber<String> testSubscriber = new TestSubscriber<>();
signUpService.getTermsFromServer().just(terms).subscribe(testSubscriber);
signUpPresenter.getTerms(true);
Mockito.verify(signUpView).showDialog("<h3>Part of the test</h3>","67f07c71-1707-4b7a-a168-d7d05a482542");
}
Thanks!!!
Use RxJavaPlugins.setInitIoSchedulerHandler and RxAndroidPlugins.registerSchedulersHook to specify your own TestScheduler, then use its advanceTimeBy method to make some time pass, then verify that the expected calls happened.

Volley second request return null

The first request done successfully but second request in queue return null , when setting break point and start debugging the second request get it's value successfully
class ListLoader extends AsyncTask<Void,Void,MerchantCategories[]>
{
MerchantCategories[] data;
protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected MerchantCategories[] doInBackground(Void... params) {
Gson g = new Gson();
gcm = GoogleCloudMessaging.getInstance(getApplicationContext());
try {
regid = gcm.register(PROJECT_NUMBER);
String msg="";
msg = "Device registered, registration ID=" + regid;
Log.i("GCM", msg);
EgxServices.getJsonFrom("http://inareg.com/APIs/RegisterAndroidDevice?registrationID="+regid,(Activity) c);
} catch (IOException e) {
e.printStackTrace();
}
MerchantCategories[] categs=g.fromJson(EgxServices.getJsonFrom("http://inareg.com/APIs/ListMerchantCategories",(Activity) c),MerchantCategories[].class);
return categs;
}
protected void onPostExecute(MerchantCategories[] response) {
if(response == null) {
progressBar.setVisibility(View.GONE);
}
else{
progressBar.setVisibility(View.GONE);
MerchantCategoriesAdp adp =new MerchantCategoriesAdp(c,R.layout.lst_merchant_categories,response);
drawerList.setAdapter(adp);
// Log.i("INFO", response);
// responseView.setText(response);
}
}
}
This method which i used to initialize a new request and return JSON String
public static String getJsonFrom(final String urlStr, Activity context) {
final Context c = context;
final SharedValue value = new SharedValue();
String result="";
StringRequest request = new StringRequest(Request.Method.GET,urlStr,new Response.Listener<String>(){
#Override
public void onResponse(String response) {
value.setResult(response);
}
},new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(c, "No Internet Connection",
Toast.LENGTH_LONG).show();
}
});
Volley.newRequestQueue(c).add(request);
return value.getResult();
}
as you can see that first request
EgxServices.getJsonFrom("http://inareg.com/APIs/RegisterAndroidDevice?registrationID="+regid,(Activity) c);
run successfully but the second one ,
EgxServices.getJsonFrom("http://inareg.com/APIs/ListMerchantCategories",(Activity) c);
always return null value ...
i need to know why ?????!!!
Try this :
request.setShouldCache(false);
before Volley.newRequestQueue(c).add(request);

Parse JSON with both sides values

I'm using volley to get response from API but the response consist of STATE_ID:STATE_NAME pair (i.e. value:value pair) and I need both side's values in different Strings. I need these values to put in a spinner so that when user selects a State I can get its corresponding ID also.
// JSON response
{
"1": "West bengal",
"3": "Himachal Pradesh",
"4": "Maharashtra",
"11": "Queensland"
}
My Code
public class MainActivity extends AppCompatActivity {
private static final String STATE = "MY_API";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void login(View v){
loginRequest();
}
private void loginRequest() {
StringRequest stringRequest = new StringRequest(Request.Method.POST, STATE,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(MainActivity.this, response, Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), "VolleyError" + error.toString(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("country_id","2");
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
requestQueue.add(stringRequest);
}
}
You already have the iterate() method as we discussed in comments.
Done some work to give you value :
try {
JSONObject jsonObject = new JSONObject(response);
for (String key : iterate(jsonObject.keys()))
{
Toast.makeText(this, "Key : "+key+" Value: "+jsonObject.optString(key), Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
Please refer the iterate method from this answer. I have posted this as a new answer because OP was unable to make it for the values..!!
I used iterator to find a key. May this will help:
private void parseRespone(String response){
try {
JSONObject MainjsonObject = new JSONObject(response)
Iterator<String> iter= MainjsonObject.keys();
//To get keys of an object
while (iter.hasNext())
{
String key = (String)iter.next();
//Object value = jsonobj.get(key); //To use by object
String valueStr = jsonobj.get.getString(key);
Log.i("Jsonparsing", "key= "+key + "\n Value=" +valueStr );
Toast.makeText(getActivity(),"key= "+ key + "\n value= " + valueStr ,Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
}
I could find an unknown key by this.
Please check in a Log in your android studio...
here I have put Toast also..
And call this function here...
...........
#Override
public void onResponse(String response) {
parseRespone(response); //Function to parse json
}
Thanks..
It will be much better if you consider changing your response to something like this:
[
{"ID":"1","name": "West bengal"},
{"ID":"3","name": "Himachal Pradesh"},
{"ID":"4","name": "Maharashtra"},
{"ID":"11","name": "Queensland"}
]
You can use jsonObject.names() (or keys() for an Iterator) to retrieve all keys.
After that you can iterate through the array using the keys and store your strings.
https://developer.android.com/reference/org/json/JSONObject.html#names()
https://developer.android.com/reference/org/json/JSONObject.html#keys()
I tried this solution and it worked out.`Here, "key" will toast the key_value[1,3,4,11] and value will print the names[West bengal,Himachal Pradesh,Maharashtra,Queensland].
JSONObject list_object = inner_json_object.getJSONObject("");
for (String key : iterate(list_object.keys()))
{
// here key will be containing your OBJECT NAME YOU CAN SET IT IN TEXTVIEW.
Toast.makeText(Activity.this, ""+key, Toast.LENGTH_SHORT).show();
String value = bank_list_object.optString(key);
}`
private <T> Iterable<T> iterate(final Iterator<T> i){
return new Iterable<T>() {
#Override
public Iterator<T> iterator() {
return i;
}
};
}

Categories

Resources