i'm trying to get the data from the database to fill the activity with them but i'm not getting anything this is the db code i have 2 Textvies 1 image view i'm trying to fill with the data i'm new to mobile programming so need help:
public void gettypedet(final int tid, final TextView ttitle, final ImageView timg, final TextView desc) {
String url = "http://192.168.0.114/mobileshop/product_typrbyid.php?id="+tid;
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(context);
// Request a json response from the provided URL.
JsonObjectRequest jsonRequest = new JsonObjectRequest(Request.Method.GET, url,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject prt) {
try {
String type=prt.getString("type");
int imgname=Integer.parseInt(prt.getString("imagename"));
String des=prt.getString("description");
ttitle.setText(type);
timg.setImageResource(imgname);
desc.setText(des);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i("error", error.toString());
}
});
// Add the request to the RequestQueue.
queue.add(jsonRequest);
}
this is my php code i tested it and it's working so shouldn't be the problem:
<?php
require_once("connection.php");
$id=$_GET["id"];
$q="Select * from product_type where id='$id'";
$res=mysqli_query($con,$q);
while($row=mysqli_fetch_assoc($res)){
$types[]=$row;
}
echo (json_encode($types));
mysqli_free_result($res);
?>
this is the activity code here not sure if i did something wrong:
public class ptype_detail extends Activity {
int kposition,tposition,id;
TextView ttitle,tdes;
ImageView timg;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ptype_detail);
tposition=(Integer)getIntent().getExtras().get("tpos");
kposition=(Integer)getIntent().getExtras().get("kpos");
if (kposition==0)
id=tposition+5;
else if(kposition==1)
id=tposition+18;
else if (kposition==2)
id=tposition+20;
else
id=tposition;
ttitle=(TextView)findViewById(R.id.title) ;
tdes=(TextView)findViewById(R.id.typedes);
timg=(ImageView)findViewById(R.id.titleimage);
shop db=new shop(this);
db.gettypedet(id,ttitle,timg,tdes);
}
}
Related
Here my code to parse json from my link http://192.168.1.9/androidwebservice/getdata.php in MainActivity.java
public class MainActivity extends Activity {
String urlGetData = "http://192.168.1.9/androidwebservice/getdata.php";
String url = "http://my-json-feed";
String convertedResponse = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GetData(urlGetData);
}
private void GetData(String url) {
RequestQueue requestQueue = Volley.newRequestQueue(this);
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, url, null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Toast.makeText(MainActivity.this,response.toString(),Toast.LENGTH_SHORT).show();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "LOOIVVVVV", Toast.LENGTH_SHORT).show();
}
});
requestQueue.add(jsonArrayRequest);
}
}
when i run the app with this link , it works. but when i do it with my link http://192.168.1.9/androidwebservice/getdata.php it dont work.(This link i get data from database MySQl and parse to json) And when i check, it's the same.
Here my php file:
<?php
$connect = mysqli_connect("localhost","root","","sinhvien");
mysqli_query($connect,"SET NAMES ");
$query ="SELECT * from student";
$data = mysqli_query($connect,$query);
class SinhVien{
function SinhVien($id,$hoten,$namsinh,$diachi){
$this->ID=$id;
$this->HoTen=$hoten;
$this->NamSinh=$namsinh;
$this->DiaChi=$diachi;
}
}
$mangSV=array();
while($row=mysqli_fetch_assoc($data)){
array_push($mangSV, new SinhVien($row['id'],$row['hoten'],$row['namsinh'],$row['diachi']));
}
echo json_encode($mangSV);
?>
I have 3 API GET calls. The problem I'm facing with my approach is, the app is able to fetch the data successfully from two APIs and I'm able to display it on UI as well. But, for the third API call, due to the below error, the data that is being shown previously disappears which is bad.
D/Volley: [380] BasicNetwork.logSlowRequests: HTTP response for request=<[ ] http://example.com/api/search/getTwitterData?limit=10&tag=JavaScript 0x865f5dc2 NORMAL 3> [lifetime=6683], [size=10543], [rc=200], [retryCount=0]
How do I make concurrent API GET calls using Volley without losing the data on UI. Could anyone please guide me?
Here are excerpts from my code.
public class StaggeredSearchActivity extends AppCompatActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_staggered_search);
requestQueue = Volley.newRequestQueue(this);
Intent intent = getIntent();
String searchText = intent.getStringExtra("searchText");
// Three concurrent API GET Calls
getMediumData(searchText);
getExampleData(searchText);
getGoogleData(searchText);
recyclerView = findViewById(R.id.staggered_recycler_view);
staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(staggeredGridLayoutManager);
}
ArrayList<StaggeredCustomCard> dataset = new ArrayList<>();
private void getMediumData(String searchText) {
progressBar = findViewById(R.id.progressBar);
progressBar.setVisibility(View.VISIBLE);
String url = UrlConstants.getUrl() + searchText;
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
progressBar.setVisibility(View.INVISIBLE);
JSONArray array = response.getJSONArray("mediumposts");
...
dataset.add(new StaggeredCustomCard(user, userpost, postdate));
}
staggeredGridAdapter = new StaggeredGridAdapter(StaggeredSearchActivity.this, dataset);
recyclerView.setAdapter(staggeredGridAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO: Handle error
progressBar.setVisibility(View.INVISIBLE);
}
});
jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(
DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 15,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
requestQueue.add(jsonObjectRequest);
}
private void getExampleData(String searchText) {
...
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest
(Request.Method.GET, url, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
try {
...
dataset.add(new StaggeredCustomCard(user, userpost, postdate));
staggeredGridAdapter = new StaggeredGridAdapter(StaggeredSearchActivity.this, dataset);
recyclerView.setAdapter(staggeredGridAdapter);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
...
}
});
jsonArrayRequest.setRetryPolicy(new DefaultRetryPolicy(
DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 15,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
requestQueue.add(jsonArrayRequest);
}
private void getGoogleData(String searchText) {
...
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
...
dataset.add(new StaggeredCustomCard(user, userpost, postdate));
}
staggeredGridAdapter = new StaggeredGridAdapter(StaggeredSearchActivity.this, dataset);
recyclerView.setAdapter(staggeredGridAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
...
}
});
jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(
DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 15,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
requestQueue.add(jsonObjectRequest);
}
}
The problem is that you are initializing Adapter every time that's why your data will be lost once a new API call. I prefer below approach so that can help you,
Add Data in ArrayList and notify adapter,
Add this line in onCreate,
staggeredGridAdapter = new StaggeredGridAdapter(StaggeredSearchActivity.this, dataset);
recyclerView.setAdapter(staggeredGridAdapter);
Changes in API Callback Response :
...
dataset.add(new StaggeredCustomCard(user, userpost, postdate));
After loop add below line
staggeredGridAdapter.notifyDataSetChanged();
Changes in Adapter
private ArrayList<StaggeredCustomCard> dataSet;
private Context context;
public MyAdapter(ArrayList<StaggeredCustomCard> dataSet, Context context) {
this.data = data;
this.context = context;
}
Note : Don't create new object on adapter.
The approach just doesn't make a lot of sense.
Once you get a response from one of the three endpoints, you seem to create a new Adapter and attach it to the recycler with a random "notifyDataSetChanged" every time...
Maybe look at using a ViewModel with a service layer and network layer that deal with the business login.
The ViewModel updates/posts a MutableLiveData> when a callback from one of the Network methods responds from the endpoints...merging the three pieces of data.
The activity just observes the ViewModel's MutableLiveData and uses a DiffUtil to update the look/cards in the recycler.
The best way is to register your LiveData in the StaggeredSearchActivity in onCreate method and listen for db changes like you did. In the each success responce save its result to db without LiveData. LiveData in onCreate method will be triggered.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
ViewModel viewModel = ViewModelProviders.of(this, factory).get(ViewModel.class);
viewModel.getEntity().observe(this, entity -> {
if (entity != null) {
adapter.notifyDataSetChanged(entity );
}
});
requestQueue = Volley.newRequestQueue(this);
Intent intent = getIntent();
String searchText = intent.getStringExtra("searchText");
// Three concurrent API GET Calls
getMediumData(searchText);
getExampleData(searchText);
getGoogleData(searchText);
recyclerView = findViewById(R.id.staggered_recycler_view);
staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(staggeredGridLayoutManager);
}
ArrayList<StaggeredCustomCard> dataset = new ArrayList<>();
private void getMediumData(String searchText) {
progressBar = findViewById(R.id.progressBar);
progressBar.setVisibility(View.VISIBLE);
String url = UrlConstants.getUrl() + searchText;
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
StaggeredCustomCardDAO.insert();
// TODO just insert to dataBase
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO: Handle error
progressBar.setVisibility(View.INVISIBLE);
}
});
jsonObjectRequest.setRetryPolicy(new
DefaultRetryPolicy(
DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 15,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
requestQueue.add(jsonObjectRequest);
}
private void getExampleData(String searchText) {
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest
(Request.Method.GET, url, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
try {
// TODO just insert to dataBase
StaggeredCustomCardDAO.insert();
} catch (
JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
jsonArrayRequest.setRetryPolicy(new DefaultRetryPolicy(
DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 15,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
requestQueue.add(jsonArrayRequest);
}
private void getGoogleData(String searchText) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// TODO just insert to dataBase
StaggeredCustomCardDAO.insert();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(
DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 15,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
requestQueue.add(jsonObjectRequest);
}
class ViewModel extends androidx.lifecycle.ViewModel {
private LiveData<StaggeredCustomCard> entity;
public ViewModel(Repository repository) {
entity = repository.getNetworkData();
}
public LiveData<StaggeredCustomCard> getEntity() {
return entity;
}
}
class Repository {
LiveData<StaggeredCustomCard> getNetworkData() {
LiveData<StaggeredCustomCard> localeData = StaggeredCustomCardDAO .getLocaleData();//... todo Read from data base
return localeData;
}
#Dao
public interface StaggeredCustomCardDAO {
#Query("Select * from tbl_staggeredCustomCard ")
LiveData<StaggeredCustomCard> getLocaleData();
#Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(List<StaggeredCustomCard> items);
}
}
The data should not disappear due to that error. First thing first I would suggest you to check maybe you clear your dataset somewhere or your screen is getting recreated.
Secondly I would recommend you to move from Volley since it is quite outdated from modern techniques library that requires a lot of attention to details. Use Retrofit - it is modern, powerful and community approved library. Using it you will be sure that all the requests you want to be async are async and all the responses are handled well.
Also I would suggest you not to create adapter each time you load data but use one adapter and add data to it and them use notifyDataSetChanged() to reload list with relevant data.
First way : firstly i would suggest you to make a central request 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);
}
}
}
then add your desired requests to the queue
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonObjReq);
Second way :
Create a Generic Volley class and a Interface, Use the interface to get success and failure responds.
Step 1 Create a separate Volley class
Step 2 Create a interface for accessing the response from volley class
Step 3 create new object for the class and send required parameters
new PostVolleyJsonRequest(TestVolley.this, TestVolley.this(interfcae), "Submit", url, params);
Context of the class
Interface for sending Success and failure responds
Type of request to identify on success
url (mandatory)
Param (optional) for GET no need
Generic volley class
public class PostVolleyJsonRequest {
private String type;
private Activity act;
private VolleyJsonRespondsListener volleyJsonRespondsListener;
private String networkurl;
private JSONObject jsonObject = null;
private JSONObject params;
public PostVolleyJsonRequest(Activity act, VolleyJsonRespondsListener volleyJsonRespondsListener, String type, String netnetworkUrl,JSONObject params) {
this.act = act;
this.volleyJsonRespondsListener = volleyJsonRespondsListener;
this.type = type;
this.networkurl = netnetworkUrl;
this.params = params;
sendRequest();
}
private void sendRequest() {
Log.d("url", "url" + networkurl);
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST,networkurl,params,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.e("response", "response " + response);
volleyJsonRespondsListener.onSuccessJson(response, type);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
try {
NetworkResponse response = error.networkResponse;
Log.e("response", "response " + response);
if (response != null) {
int code = response.statusCode;
String errorMsg = new String(response.data);
Log.e("response", "response" + errorMsg);
try {
jsonObject = new JSONObject(errorMsg);
} catch (JSONException e) {
e.printStackTrace();
}
String msg = jsonObject.optString("message");
volleyJsonRespondsListener.onFailureJson(code, msg);
} else {
String errorMsg = error.getMessage();
volleyJsonRespondsListener.onFailureJson(0, errorMsg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
jsObjRequest.setRetryPolicy(new DefaultRetryPolicy(
600000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
RequestQueue requestqueue = Volley.newRequestQueue(act);
requestqueue.add(jsObjRequest);
}
}
Use the interface to get responds message
public interface VolleyJsonRespondsListener {
public void onSuccessJson(JSONObject result, String type);
public void onFailureJson(int responseCode, String responseMessage);
}
In your class where you want to include multiple request
public class TestVolley extends AppCompatActivity implements VolleyJsonRespondsListener{
//Your class code goes here
//network request
try {
//parameters
//Context,Interface,Type(to indentify your responds),URL,parameter for your request
//request 1
new PostVolleyJsonRequest(TestVolley.this, TestVolley.this, "Submit", url, params);
//request 2
new PostVolleyJsonRequest(TestVolley.this, TestVolley.this, "AccessData", url_2, params_2);
} catch (Exception e) {
e.printStackTrace()
}
//Methods from Interface
#Override
public void onSuccessJson(JSONObject result, String type) {
//Based on the Type you send get the responds and parse it
switch (type) {
case "Submit":
try {
parseSubmit(result);
} catch (Exception e) {
Recently I am working on Android project with Volley for registration and for further operation, I can make function for insertion and other one is for retrieval data. When insert button click 'Insert' function called and data has been inserted to database through volley, and at the same time retrieval function also called. But when USER clicked the button and function called then data showed(database inserted data) with blinking effect, look like loading.
I want to get rid of that effect. I want to show data smoothly without any blinking effect. I do searching but can not find any solution. Please suggest me solution I'am newbie so kindly short and efficient required.
package com.darkcoderz.parsejson;
public class MainActivity extends AppCompatActivity {
private Context mContext;
private Activity mActivity;
//private CoordinatorLayout mCLayout;
private TextView mTextView;
private String mJSONURLString = "http://192.168.10.4/volley/api.php";
String url = "http://192.168.10.4/volley/register.php";
private EditText sms;
private Button sendsms;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get the application context
//mContext = getApplicationContext();
//mActivity = MainActivity.this;
// Get the widget reference from XML layout
//mCLayout = (CoordinatorLayout) findViewById(R.id.coordinator_layout);
mTextView = (TextView) findViewById(R.id.tv);
sms = (EditText) findViewById(R.id.sms);
sendsms = (Button) findViewById(R.id.sendsms);
final Handler firesms = new Handler();
firesms.post(new Runnable() {
#Override
public void run() {
getdata();
firesms.postDelayed(this, 100);
}
});
sendsms.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
reg();
}
});
getdata();
}
// insert
public void reg()
{
final String msg = sms.getText().toString();
StringRequest stringreq = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (response.equals("success"))
{
Toast.makeText(MainActivity.this, "Registration Successfull!", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(MainActivity.this, "Username Already Exist!", Toast.LENGTH_SHORT).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "Great Error "+error.toString(), Toast.LENGTH_LONG).show();
}
})
{
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("sms",msg);
return params;
}
};
RequestQueue reqest = Volley.newRequestQueue(MainActivity.this);
reqest.add(stringreq);
}
private void getdata() {
// Empty the TextView
mTextView.setText("");
// Initialize a new RequestQueue instance
RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);
// Initialize a new JsonArrayRequest instance
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, mJSONURLString, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
// Do something with response
//mTextView.setText(response.toString());
// Process the JSON
try{
// Loop through the array elements
for(int i=0;i<response.length();i++){
// Get current json object
JSONObject student = response.getJSONObject(i);
// Get the current student (json object) data
// String firstName = student.getString("fname");
// String lastName = student.getString("lname");
String age = student.getString("email");
// Display the formatted json data in text view
mTextView.append("SMS : " + age);
mTextView.append("\n\n");
}
}catch (JSONException e){
e.printStackTrace();
}
}
},
new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error){
// Do something when error occurred
Toast.makeText(mContext, "Something Went Wrong", Toast.LENGTH_SHORT).show();
}
}
);
// Add JsonArrayRequest to the RequestQueue
requestQueue.add(jsonArrayRequest);
}
}
private void getdata() {
// Empty the TextView
mTextView.setText("");
// Initialize a new RequestQueue instance
RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);
// Initialize a new JsonArrayRequest instance
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, mJSONURLString, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
//before parsing check your response is in JSONArray Format or JSONObject format
// Process the JSON
try{
}catch (JSONException e){
e.printStackTrace();
//print here to know JSONException if exists
Toast.makeText(mContext, "Exception"+e.toString(), Toast.LENGTH_SHORT).show();
}
}
}
},
new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error){
// Do something when error occurred
Toast.makeText(mContext, "Something Went Wrong", Toast.LENGTH_SHORT).show();
}
}
);
// Add JsonArrayRequest to the RequestQueue
requestQueue.add(jsonArrayRequest);
}
Well, I get Validation:com.android.volley.ParseError: org.json.JSONException:value false of type java.jang.Boolean cannot be converted to JSONObject error whenever I try to receive a boolean value, that is sent by a REST web service, in my android app using volley's JSONObjectRequest format.
I know that using StringRequest will be the easy way to solve this but I really wonder if there's another way to solve this.
My guess is that the primitive boolean value is the problem because it is not equevalent to a json object. so the exeption is thrown in the onResponse(JSONObject response) volley method.
here's the java REST web service:
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Boolean validate(CreditCard card) {
//instructions
if(/* some conditions */) {
cardList.put(card.getId(), card);
return true;
}
return false;
}
and the android app code:
public class MainActivity extends Activity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_id = findViewById(R.id.id);
et_num = findViewById(R.id.number);
et_type = findViewById(R.id.type);
et_ctrlnb = findViewById(R.id.ctrlnum);
et_expd = findViewById(R.id.expdate);
b_validate = findViewById(R.id.validate);
b_validate.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v == b_validate) {
String request_url = "http://192.168.191.1:8080/RESTCardValidator/rest/cardvalidator";
JSONObject cardDetails = new JSONObject();
try {
cardDetails.put("controlNumber", Integer.parseInt(et_ctrlnb.getText().toString()));
cardDetails.put("expiryDate", et_expd.getText().toString());
cardDetails.put("id", Long.parseLong(et_id.getText().toString()));
cardDetails.put("number", et_num.getText().toString());
cardDetails.put("type", et_type.getText().toString());
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, request_url, cardDetails,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Toast.makeText(MainActivity.this, "Validation:" + response.toString(), Toast.LENGTH_LONG).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "Validation:" + error.toString(), Toast.LENGTH_LONG).show();
}
});
Volley.newRequestQueue(this).add(request);
}
}
as you see in the image the value true/false is received
First Screenshot-
Second Screenshot -
When I click on an image in our project, another image gets loaded. It works fine, but when I go back to the previous activity, and click on the same image, it doesn't get loaded.
This is the first activity which opens when app is active. This page will show grid of pictures
public class GentsActivity extends Fragment implements AdapterView.OnItemClickListener {
//Web api url
public static final String DATA_URL = "PHP LINK HERE";
//Tag values to read from json
public static final String TAG_IMAGE_URL = "small_image_url";
//GridView Object
private GridView gridView;
//ArrayList for Storing image urls and titles
private ArrayList<String> images;
private SwipeRefreshLayout swipeContainer;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Returning the layout file after inflating
//Change R.layout.tab1 in you classes
View view= inflater.inflate(R.layout.activity_gents, container, false);
gridView = (GridView) view.findViewById(R.id.gridView);
getData();
//swipeContainer = (SwipeRefreshLayout) view.findViewById(R.id.swipeContainer);
images = new ArrayList<>();
//Calling the getData method
/*swipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
// Your code to refresh the list here.
// Make sure you call swipeContainer.setRefreshing(false)
// once the network request has completed successfully.
//Toast.makeText(this,"refresh ",Toast.LENGTH_SHORT).show();
Intent mIntent= new Intent(SareeActivity.this,SareeActivity.class);
startActivity(mIntent);
swipeContainer.setRefreshing(false);
}
});*/
return view;
}
private void getData(){
//Showing a progress dialog while our app fetches the data from url
//final ProgressDialog loading = ProgressDialog.show(this, "Please wait,","Fetching data.",false,false);
//Creating a json array request to get the json from our api
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(DATA_URL,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
//Dismissing the progressdialog on response
// loading.dismiss();
//Displaying our grid
showGrid(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}
);
//Creating a request queue
RequestQueue requestQueue = Volley.newRequestQueue(getActivity().getApplicationContext());
//Adding our request to the queue
requestQueue.add(jsonArrayRequest);
}
private void showGrid(JSONArray jsonArray){
//Looping through all the elements of json array
for(int i = 0; i<jsonArray.length(); i++){
//Creating a json object of the current index
JSONObject obj = null;
try {
//getting json object from current index
obj = jsonArray.getJSONObject(i);
// Log.d(TAG_IMAGE_URL,"JSON SHOW GRID"+obj);
//getting image url and title from json object
images.add(obj.getString(TAG_IMAGE_URL));
Log.d(TAG_IMAGE_URL,"JSON SHOW GRID"+images);
} catch (JSONException e) {
e.printStackTrace();
}
}
//Creating GridViewAdapter Object
//Adding adapter to gridview
GridViewAdapter gridViewAdapter = new GridViewAdapter(getContext(),images);
gridView.setAdapter(gridViewAdapter);
gridView.setOnItemClickListener(this);
}
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String prompt = (String)adapterView.getItemAtPosition(i);
Intent mIntent= new Intent(getActivity(),LoadPhotoGents.class);
mIntent.putExtra("s",prompt);
startActivity(mIntent);
}
}
When I click on a particular photo, that single photo will open. The code is given below
public class LoadPhotoGents extends AppCompatActivity {
private String data, path;
private ImageView ivi;
public static final String DATA_URL = "PHP LINK HERE";
private static int id=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_load_photo_gents);
data = getIntent().getExtras().getString("s");
path = data.replace(".JPG", "big.JPG");
//Toast.makeText(this, "Path:" + path, Toast.LENGTH_LONG).show();
ivi = (ImageView) findViewById(R.id.fullImage);
Picasso.with(LoadPhotoGents.this).load(path).into(ivi);
getData();
ImageViewTouch img = (ImageViewTouch) findViewById(R.id.fullImage);
img.setBackgroundColor(Color.parseColor("#000000"));
ivi.buildDrawingCache();
Bitmap bmap=ivi.getDrawingCache();
//img.setFitToScreen(true);
img.setImageBitmap(bmap);
}
private void getData(){
String url=DATA_URL+data.trim();
StringRequest stringRequest=new StringRequest(url,new Response.Listener<String>(){
#Override
public void onResponse(String response){
showJSON(response);
}
},
new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error){
}
});
RequestQueue requestQueue= Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
private void showJSON(String response){
String name= "";
try{
JSONArray jsonArray=new JSONArray(response);
//JSONArray result= jsonObject.getJSONArray("result");
JSONObject datas=jsonArray.getJSONObject(0);
name=datas.getString("description");
}catch(JSONException e){
Toast.makeText(this,"inside getData: "+name,Toast.LENGTH_SHORT).show();
}
}
}
This will definitely help you to debug the issue. In your code I can see that you are loading the image directly using Picasso.with().load().into() problem with this method is you do not know what is happening at the background.
You can do two things. First use Callback when you load the image into the ImageView as below
Picasso.with(LoadPhotoGents.this).load(path).into(ivi, new Callback()
{
#Override
public void onSuccess()
{
Timber.d("Image Loaded Successfully");
}
#Override
public void onError()
{
Timber.d("Error Loading Image");
}
});
Above can be used to handle image loaded/not loaded scenario.
Now coming to the actual error while loading the image, you need to use a Picasso.Builder which has a listener which will help you know the actual error.
Build Picasso Builder as below
Picasso.Builder builder = new Picasso.Builder(mContext);
builder.listener(new Picasso.Listener()
{
#Override
public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception)
{
Timber.d(exception.getMessage());
}
});
Picasso pic = builder.build();
To Load the image do the following
pic.load(path).into(ivi, new Callback()
{
#Override
public void onSuccess()
{
Timber.d("Image Loaded Successfully");
}
#Override
public void onError()
{
Timber.d("Image Load Error");
}
});
Ensure that path variable is not null or empty