I have been struggling to understand the logic of the Android JSON Parsing with volley libraries.I am trying to get JSON Array and parse with Volley Libraries.I understand how JSON data is extracted from PHP file but I have big problems. makeJsonArrayRequest() function runs correctly and parse JSON Array from get_data.php file and add users ArrayList from User class in each iteration.I called this function in onCreate and userLogin function individually.Size of users ArrayList equals to 0 when I call makeJsonArrayRequest() function in onCreate method .However,Size of users ArrayList equals to nonzero number when I call makeJsonArrayRequest() function in userLogin method(This method called when clicked on Login Button).This is my problem.Why makeJsonArrayRequest() doesn't run on Create() method ?
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ET_NAME = (EditText) findViewById(R.id.user_name);
ET_PASS = (EditText) findViewById(R.id.user_pass);
pDialog = new ProgressDialog(this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
makeJsonArrayRequest();
Toast.makeText(getApplicationContext(),"Size:" + users.size(),Toast.LENGTH_LONG).show();
}
public void userLogin(View view) {
login_name = ET_NAME.getText().toString();
login_pass = ET_PASS.getText().toString();
String method = "login";
String status = "1";
BackgroundTask backgroundTask = new BackgroundTask(this);
backgroundTask.execute(method, login_name, login_pass, status);
Intent i = new Intent(this,MapsActivity.class);
i.putExtra("username",login_name);
i.putExtra("userpass", login_pass);
makeJsonArrayRequest();
startActivity(i);
Toast.makeText(getApplicationContext(),"Size:" + users.size(),Toast.LENGTH_LONG).show();
}
private void makeJsonArrayRequest() {
showpDialog();
JsonArrayRequest req = new JsonArrayRequest(JSON_URL,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
try {
// Parsing json array response
// loop through each json object
jsonResponse ="";
for (int i = 0; i < response.length(); i++) {
JSONObject person = (JSONObject) response.get(i);
String name = person.getString("name");
String username = person.getString("username");
String password = person.getString("password");
double latitude = Double.parseDouble(person.getString("latitude"));
double longitude = Double.parseDouble(person.getString("longitude"));
String status = person.getString("status");
User user = new User(name,username,password,latitude,longitude,status);
users.add(user);
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),
"Error: " + e.getMessage(),
Toast.LENGTH_LONG).show();
}
hidepDialog();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
Toast.makeText(getApplicationContext(),
error.getMessage(), Toast.LENGTH_SHORT).show();
hidepDialog();
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(req);
}
If what you're saying is :
I run the request in onCreate() and check - it's empty.
and then:
I run it again LATER, and Check - it's full.
then have you considered the request latency? it takes time (albeit - not much time) for the request to return, you might be checking before it does
EDIT:
Run what you want inside the onResponse(), that's only called when the request returns.
Hope this helps.
Related
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RequestQueue requestQueue;
requestQueue = Volley.newRequestQueue(this);
List<news_Objects> newsList = new ArrayList<>();
//url for News API
String url="https://newsapi.org/v2/everything?q=apple&from=2021-08-31&to=2021-08-31&sortBy=popularity&apiKey=ca3d6c89eff24db2a8ef78868f0af555";
//making json object request
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArr = response.getJSONArray("articles");
for (int i = 0; i < jsonArr.length(); i++) {
JSONObject newsDetail = jsonArr.getJSONObject(i);
//class name news_Objects created
news_Objects news = new news_Objects();
String imtUrl = newsDetail.getString("urlToImage");
String title = newsDetail.getString("title");
String detail = newsDetail.getString("description");
String newsUrl = newsDetail.getString("url");
String content = newsDetail.getString("content");
news.setNewsImageUrl(imtUrl);
news.setNewsTitle(title);
news.setNewsDetail(detail);
news.setNewsUrl(newsUrl);
news.setContent(content);
newsList.add(news);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("fine", "Something Wrong"+error);
Toast.makeText(MainActivity.this, "Something Wrong "+error, Toast.LENGTH_SHORT).show();
error.printStackTrace();
}
});
requestQueue.add(request);
}
}
Your API Key is Invalid please check your API key. Getting this response:
{"status":"error","code":"apiKeyInvalid","message":"Your API key is invalid or incorrect. Check your key, or go to https://newsapi.org to create a free API key."}
Maybe Your API key is not live, please check your API key status than again hit the api.
I have a method that call a api and fill a ArrayList with data. The method is in a fragment, when I open the App it adds data to the arrayList, but when I go to another fragment or activity and come back it doesnt show any in the recyclerview from the ArrayList as if nothing is there, but when I toast the size of array, it returns the number of elements that should be there
but it doesnt show/populate the recyclerview with the elements.
I call the method in onCreateView()
CALLING API
private void getDataFromUAPI(String gist_json_url){
requestQueue = MySingleton.getInstance(this.getContext()).getRequestQueue();
request = new JsonArrayRequest(Method.GET, gist_json_url, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
JSONObject jsonObject = null;
for (int i = 0; i < response.length(); i ++){
try {
jsonObject = response.getJSONObject(i);
User user = new User();
// if this user Id is not user Id of the user and
// if user are already been followed, than don't add
if (!jsonObject.getString("id").equals(firebaseUser.getUid()) && !sharedPreferences.contains(jsonObject.getString("id"))) {
user.setPhoto(jsonObject.getString("photo"));
user.setName(jsonObject.getString("name"));
user.setFnumber(jsonObject.getString("fnumber"));
user.setId(jsonObject.getString("id"));
responseList.add(user);
}
//Toast.makeText(getContext(), user.getId(), Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
Toast.makeText(getContext(), String.valueOf(responseList.size()), Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getContext(), "ERROR \n" + error.toString(), Toast.LENGTH_LONG).show();
}
});
requestQueue.add(request);
I read this article https://www.androidhive.info/2012/01/android-json-parsing-tutorial/ and in this article
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url);
Log.e(TAG, "Response from url: " + jsonStr);
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
JSONArray contacts = jsonObj.getJSONArray("contacts");
// looping through All Contacts
for (int i = 0; i < contacts.length(); i++) {
JSONObject c = contacts.getJSONObject(i);
String id = c.getString("id");
String name = c.getString("name");
String email = c.getString("email");
String address = c.getString("address");
String gender = c.getString("gender");
// Phone node is JSON Object
JSONObject phone = c.getJSONObject("phone");
String mobile = phone.getString("mobile");
String home = phone.getString("home");
String office = phone.getString("office");
// tmp hash map for single contact
HashMap<String, String> contact = new HashMap<>();
// adding each child node to HashMap key => value
contact.put("id", id);
contact.put("name", name);
contact.put("email", email);
contact.put("mobile", mobile);
// adding contact to contact list
contactList.add(contact);
}
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Json parsing error: " + e.getMessage(),
Toast.LENGTH_LONG)
.show();
}
});
}
} else {
Log.e(TAG, "Couldn't get json from server.");
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Couldn't get json from server. Check LogCat for possible errors!",
Toast.LENGTH_LONG)
.show();
}
});
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
/**
* Updating parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(
MainActivity.this, contactList,
R.layout.list_item, new String[]{"name", "email",
"mobile"}, new int[]{R.id.name,
R.id.email, R.id.mobile});
lv.setAdapter(adapter);
}
He/she has retrieved all the values before inflating it to the listview.
I am new to JSon.I tried to retrieve only names but it is not running. So, is it necessary to retrieve all the value before using any of it.
Thank you
The simple answer is: it depends.
When you are the one defining what comes in your JSON data, then you make sure to design it in a "minimalistic" way: you only want to include information that has value for you (or your users). Meaning: in such a world, you only transport the data that you want to display. Then, most likely, your backend code will want to access all data in your JSON strings. Because you designed all these JSON objects to hold only relevant information.
But very often, your code just consumes something. You don't own/define the JSON structure, you just know "there should be fields X, Y, Z in there, which my code will use". Then, obviously, you only extract X, Y, Z. And you leave other data in that JSON alone. There is no point in touching and processing information that isn't relevant for your use case.
In other words: in the real world, you don't do things because you can. You do things, because doing so results in value to you respectively to users of your product.
This question already has answers here:
How can i check whether an android device is connected to the web?
(4 answers)
Closed 5 years ago.
Android AsyncTask processing and found no internet connection system give warning "user please connect internet". How can I do this in my code?
Another problem is when internet not connected its show loading but I don't go back page. How to solve this problem?
I don't understand how to do this inside this code.
public class data extends AppCompatActivity {
private String TAG = MainActivity.class.getSimpleName();
private ProgressDialog pDialog;
private ListView lv;
// URL to get contacts JSON
private static String url = "http://orangehostbd.com/app/bpl2/index.php";
ArrayList<HashMap<String, String>> contactList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_data);
contactList = new ArrayList<>();
lv = (ListView) findViewById(R.id.list);
new GetContacts().execute();
}
/**
* Async task class to get json by making HTTP call
*/
private class GetContacts extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(data.this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url);
Log.e(TAG, "Response from url: " + jsonStr);
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
JSONArray contacts = jsonObj.getJSONArray("contacts");
// looping through All Contacts
for (int i = 0; i < contacts.length(); i++) {
JSONObject c = contacts.getJSONObject(i);
String id = c.getString("id");
String name = c.getString("name");
String email = c.getString("email");
String address = c.getString("address");
String gender = c.getString("gender");
// Phone node is JSON Object
JSONObject phone = c.getJSONObject("phone");
String mobile = phone.getString("mobile");
String home = phone.getString("home");
String office = phone.getString("office");
// tmp hash map for single contact
HashMap<String, String> contact = new HashMap<>();
// adding each child node to HashMap key => value
contact.put("id", id);
contact.put("name", name);
contact.put("email", email);
contact.put("mobile", mobile);
// adding contact to contact list
contactList.add(contact);
}
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Json parsing error: " + e.getMessage(),
Toast.LENGTH_LONG)
.show();
}
});
}
} else {
Log.e(TAG, "Couldn't get json from server.");
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Couldn't get json from server. Check LogCat for possible errors!",
Toast.LENGTH_LONG)
.show();
}
});
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
/**
* Updating parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(
data.this, contactList,
R.layout.list_item, new String[]{"name", "email",
"mobile"}, new int[]{R.id.name,
R.id.email, R.id.mobile});
lv.setAdapter(adapter);
}
}
}
Create a Helper class.
Inside this class, create a method to check internet connection.
public static boolean isNetworkConnected(Context context) {
final ConnectivityManager connectivityManager = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
return connectivityManager.getActiveNetworkInfo() != null && connectivityManager.getActiveNetworkInfo().isConnected();
}
Inside your activity class, use above isNetworkConnected() method in doInBackground.
if (Helper.isNetworkConnected(this)) {
// do your stuff
} else{
Toast.makeText(YourActivity.this, "Your internet connection is lost.", Toast.LENGTH_SHORT).show();
}
Use this permission in Manifest file.
<uses-permission android:name="android.permission.INTERNET" />
If the question is "how to display warning inside doInBackground" because you are not allowed to access the gui inside doInBackground technically you can use the progress indicator of asynctask to transfer a message to the gui.
However i would recommond a differen aproach: either
check for problems before starting the async task
or let the async task stop and return with an error as described by #Muthukrishnan Rajendran
I just cant see what is wrong with my code even after following all the other answers here. Can someone please look at my code and tell me why the list view only displays the last item in the loop
Here is my code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_appointments);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
pDialog = new ProgressDialog(this);
pDialog.setCancelable(false);
db = new SQLiteHandler(getApplicationContext());
listview = (ListView)findViewById(R.id.appointmentList);
// cancel request tag
String tag_string_req = "req_appointments";
pDialog.setMessage("fetching appointments...");
showDialog();
StringRequest strReq = new StringRequest(Request.Method.POST,
AppConfig.URL_FETCH_APPOINTMENTS, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Appointment fetch response: " + response.toString());
hideDialog();
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
if (!error) {
JSONArray appointments = jObj.getJSONArray("appointments");
//Log.d(TAG, String.valueOf(appointments.length()));
int count=appointments.length();
String fullAppointment="";
for (int i=0;i<count;i++){
JSONObject jsonObj2 = appointments.getJSONObject(i);
String date = jsonObj2.getString("date");
String status=jsonObj2.getString("status");
String timestamp=jsonObj2.getString("timestamp");
String appointmentStatus="";
if (status.matches("PENDING")){
appointmentStatus="This appointment is still pending and has not been confirmed by the doctor";
}else{
appointmentStatus="This appointment has already been confirmed by the doctor";
}
//Log.d(TAG,date+":"+status+":"+timestamp);
fullAppointment="Date of consultation: "+date +"\n"+ appointmentStatus +"\n"+ "Booked on date :"+timestamp;
//myList.add(fullAppointment);
adapter.add(fullAppointment);
adapter.notifyDataSetChanged();
}
} else {
String errorMsg = jObj.getString("error_msg");
Toast.makeText(getApplicationContext(),
errorMsg, Toast.LENGTH_LONG).show();
Intent intent = new Intent(
MyAppointments.this,
HomeActivity.class);
startActivity(intent);
finish();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Appointment Error: " + error.getMessage());
Toast.makeText(getApplicationContext(),
error.getMessage(), Toast.LENGTH_LONG).show();
hideDialog();
}
}) {
#Override
protected Map<String, String> getParams() {
HashMap<String, String> user = db.getUserDetails();
String userID = user.get("uid");
// Posting params to register url
Map<String, String> params = new HashMap<String, String>();
params.put("userID", userID);
return params;
}
};
// Adding request to request queue
myConnection.getInstance().addToRequestQueue(strReq, tag_string_req);
adapter= new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,0);
listview.setAdapter(adapter);
}
This is what i get when i print the arrayList in console
enter image description here
Print all your List elements in console! If all of the elements were same then you have to take care of the String object that you're adding to your list, it may be because of all elements in list may point to a single object, you can avoid it by moving the "String fullappointment;" inside the for loop. If error continues then post your adapter class!