MainActivity.java
public class MainActivity extends AppCompatActivity {
String server_ip = "192.168.252.100";
String url = "http://"+server_ip+"/lib/androidAPI.php";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] list = {"Action","Adventure", "Family"};
for(int x=0;x<list.length;x++){
int y = x;
movie_class test = new movie_class();
test.getJsonResponse("Get__Movies_By_Genre_Limit", list[x], getApplicationContext(), new VolleyCallback() {
#Override
public void onSuccess(JSONArray result2) {
try {
System.out.println("array list using y as index: ("+y+")="+list[y]);
System.out.println("-Database Query Results");
for (int j = 0; j < result2.length(); j++) {
JSONObject obj = result2.getJSONObject(j);
System.out.println("--(" + j + ")" + obj.getString("name"));
}
}catch (JSONException e){
}
}
#Override
public void onError(String result) {
System.out.println("(error) populate genres " + result);
}
});
}
}
public interface VolleyCallback {
void onSuccess(JSONArray result);
void onError(String result);
}
}
movie_class.java
public class movie_class extends MainActivity{
public void getJsonResponse(String getType, String parameters, Context mainContext, final VolleyCallback callback) {
StringRequest strReq = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
//JSONArray array = new JSONArray();
JSONArray array = jsonObject.getJSONArray("array");
callback.onSuccess(array);
}catch (JSONException e){
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
callback.onError(volleyError + "");
}
}){
#Override
public String getBodyContentType() {
// as we are passing data in the form of url encoded
// so we are passing the content type below
return "application/x-www-form-urlencoded; charset=UTF-8";
}
#Override
protected Map<String, String> getParams() {
// below line we are creating a map for storing our values in key and value pair.
Map<String, String> params = new HashMap<String, String>();
// on below line we are passing our key and value pair to our parameters.
params.put("getType", getType);
params.put("parameters", parameters);
// at last we are returning our params.
return params;
}
};
Volley.newRequestQueue(mainContext).add(strReq);
}
}
Output 1:
array list using y as index: (0)=Action
-Database Query Results
--(0)Air Force One
--(1)Ant-Man
array list using y as index: (2)=Family
-Database Query Results
--(0)Cocomelon
--(1)Finding Dory
array list using y as index: (1)=Adventure
-Database Query Results
--(0)Air Force One
--(1)Ant-Man
Output 2 without changing the codes:
array list using y as index: (1)=Adventure
-Database Query Results
--(0)Air Force One
--(1)Ant-Man
array list using y as index: (0)=Action
-Database Query Results
--(0)Air Force One
--(1)Ant-Man
array list using y as index: (2)=Family
-Database Query Results
--(0)Cocomelon
--(1)Finding Dory
Question is why the for loop index (x) is not in order or randomly change order when using it inside the movie_class.getJsonResponse?
I'm using that technique many times in php but it was different in java.
I've solve the problem by manipulating the data in php file so that I will just call one request in client side android. :)
Related
I'm trying to convert a string array list to a JSONArray then send it to a remote server
I expect it to send my array in a JSONarray format
this is the error "'java.lang.String org.json.JSONObject.getString(java.lang.String)' on a null object reference"
My array got 2 elements,
when i try to fetch them in the log.d : list ja [null,null]
This is the code i'm using
public void sendCommande (){
bt_newCommande.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//----------------------------------
StringRequest stringRequest = new StringRequest(Request.Method.POST,url_ProdCommande, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG,"element envoie !");
//listProRest.clear();
//adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
})
{
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<String,String>();
JSONArray ja = new JSONArray(db.afficherTousProduit());
Log.d(TAG,"list ja "+ja.toString());
for(int i =0;i<ja.length();i++){
JSONObject j = ja.optJSONObject(i);
/*
try {
params.put("idProduit",j.getString(db.afficherTousProduit().get(i).getIdProduct()));
params.put("qte",j.getString(String.valueOf(db.afficherTousProduit().get(i).getQtePro())));
params.put("heure",j.getString(db.afficherTousProduit().get(i).gethCollete()));
params.put("date",j.getString(db.afficherTousProduit().get(i).getDateCollete()));
} catch (JSONException e) {
e.printStackTrace();
}
*/
}
//params.put("id",arrayList.get(position).getIdProduct());
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
requestQueue.add(stringRequest);
}
});
}
It looks like something is going wrong with
db.afficherTousProduit().get(i).getIdProduct()
I would set a breakpoint and check that the db is returning what you expect it to return.
From looking at your code, it seems like you are doing extra work converting to and from JSON several times. I could be wrong, but I think this could be cleaned up like so:
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<String,String>();
JSONArray ja = new JSONArray(db.afficherTousProduit());
Log.d(TAG,"list ja "+ja.toString());
// Begin iterating through the JSON Array
for (int i=0; i < arr.length(); i++) {
// Get current JSON Object at index i
JSONObject j = arr.getJSONObject(i)
try {
// Return the specified value associated with the String for the current object
params.put("key",j.getJsonString("key");
} catch (JSONException e) {
e.printStackTrace();
}
}
//params.put("id",arrayList.get(position).getIdProduct());
return params;
}
It shouldn't require more than one db access to get the json array, and then it's a simple matter of iterating through each object and grabbing what you need from it. Check out the Java docs for more info.
Question1: How to get response value in onResponse function.
Question2: I create cauHoiArrayList. when I check and get cauHoiArrayList values in onResponse function => it worked. But if I check and get cauHoiArrayList values in GETDATA function ==> it did not work. How to I get cauHoiArrayList values.
Thanks you,
This is my code details:
public void GetCauHoi(String url) {
RequestQueue requestQueue = Volley.newRequestQueue(this);
StringRequest stringRequest = new StringRequest(
Request.Method.POST,
url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray array = new JSONArray(response);
cauHoiArrayList = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
_id = object.getInt("_ID");
cauhoi = object.getString("CauHoi");
tenmh = object.getString("TenMH");
tenmonhoc = object.getString("TenMonHoc");
dapan_a = object.getString("DapAn_A");
dapan_b = object.getString("DapAn_B");
dapan_c = object.getString("DapAn_C");
dapan_d = object.getString("DapAn_D");
dapandung = object.getString("DapAnDung");
hinhanh = object.getString("HinhAnh");
dokho = object.getInt("DoKho");
cauHoiArrayList.add(new CauHoi(_id, cauhoi, tenmh, tenmonhoc, dapan_a, dapan_b, dapan_c, dapan_d, dapandung, hinhanh, dokho));
}
Log.d("tag",""+cauHoiArrayList.get(0).getCauHoi());
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(ScreenSlideActivity.this, ""+error, Toast.LENGTH_SHORT).show();
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("laytenmonhocc", "" + laytenmonhoc);
params.put("laydokhoc", "" + laydokho);
return params;
}
};
requestQueue.add(stringRequest);
}
public ArrayList<CauHoi> GETDATA (){
return cauHoiArrayList;
}
Volley requests are asynchronous. You must be calling GETDATA by time when response is not arrived yet. You need to sure call GETGATA when you have response. Only OnResponse method is guarantee that response is present.
I'm pretty new to Java, and currently build client program based on Android.
I have backend server written in Python that will produce result containing some List inside Array.
Here is result from python I should get:
[[id, shopName], [id, shopName], ...]
Example:
[[1, Jakarta], [2, Bali], ...]
Basically, I need to have String[] containing id, and String[] containing name, for spinner adapter.
String[] shopServId, shopServName;
List arrayListShopServId, arrayListShopServName;
// in onCreate()
arrayListShopServId = new ArrayList();
arrayListShopServName = new ArrayList();
and on XMLRPCCallback listener onResponse()
Object[] classObjs = (Object[]) result;
int length = classObjs.length;
shopServId = new String[classObjs.length];
shopServName = new String[classObjs.length];
if ( length > 0) {
arrayListShopServId.clear();
arrayListShopServName.clear();
for (int i=0; i<length; i++) {
#SuppressWarnings("unchecked")
Map<String,Object> classObj = (Map<String,Object>)classObjs[i];
arrayListShopServId.add(classObj.get("id"));
arrayListShopServName.add(classObj.get("name"));
// id and name here are object fields key to get by using XMLRPC
shopServId[i] = arrayListShopServId.get(i).toString();
shopServName[i] = arrayListShopServName.get(i).toString();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
loadSpinnerSaleShop();
}
});
} else {
System.out.println("SaleShop not found!");
}
But it gives me an error
java.lang.ClassCastException: java.lang.Object[] cannot be cast to java.util.Map
How can I achieve that?
EDIT
For those who want to know, I use XMLRPC AsynTask.
Full part of the relevant code:
TaskId:
private void readSaleShop() {
readSaleShopTaskId = util.soe_salesman_shops(listener, database, uid, password, "sale.order",
employeeId);
}
The Listener:
XMLRPCCallback listener = new XMLRPCCallback() {
public void onResponse(long id, Object result) {
Looper.prepare();
if(id==readSaleShopTaskId) {
Object[] classObjs = (Object[]) result;
int length = classObjs.length;
shopServId = new String[classObjs.length];
shopServName = new String[classObjs.length];
if ( length > 0) {
arrayListShopServId.clear();
arrayListShopServName.clear();
for (int i=0; i<length; i++) {
#SuppressWarnings("unchecked")
Map<String,Object> classObj = (Map<String,Object>)classObjs[i];
arrayListShopServId.add(classObj.get("id"));
arrayListShopServName.add(classObj.get("name"));
shopServId[i] = arrayListShopServId.get(i).toString();
shopServName[i] = arrayListShopServName.get(i).toString();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
loadSpinnerSaleShop();
}
});
} else {
System.out.println("SaleShop not found!");
}
} else if(id==updateSaleOrderTaskId) {
final Boolean updateResult =(Boolean)result;
if(updateResult)
{
Log.v("SO UPDATE", "successfully");
util.MessageDialog(SOFormActivity.this,
"Update SO succeed.");
}
else{
util.MessageDialog(SOFormActivity.this,
"Update SO failed. Server return was false");
}
} else if (id == createSOTaskId) {
String createResult = result.toString();
if(createResult != null)
{
Log.v("SO CREATE", "successfully");
util.MessageDialog(SOFormActivity.this,
"Create SO succeed. ID = " + createResult);
}
else
{
util.MessageDialog(SOFormActivity.this,
"Create SO failed. Server return was false");
}
}
Looper.loop();
}
public void onError(long id, XMLRPCException error) {
Looper.prepare();
Log.e("SOForm", error.getMessage());
util.MessageDialog(SOFormActivity.this, error.getMessage());
Looper.loop();
}
public void onServerError(long id, XMLRPCServerException error) {
Looper.prepare();
Log.e("SOForm", error.getMessage());
util.MessageDialog(SOFormActivity.this, error.getMessage());
Looper.loop();
}
};
method I use from UtilAsync class:
public long soe_salesman_shops(XMLRPCCallback listener, String db, String uid, String password,
String object, String employeeId) {
long id = client.callAsync(listener, "execute", db, Integer.parseInt(uid), password, object,
"soe_salesman_shops", Integer.parseInt(employeeId));
return id;
}
classObjs[i] is a an object array. What you can do is cast it to an Array and then get the required data:
Object[] classObj = (Object[])classObjs[i];
arrayListShopServId.add(classObj[0]);
arrayListShopServName.add(classObj[1]);
Your result is a Object[][], so you can do
classObj.put(classObjs[i][0], classObjs[i][1]);
But you can directly do
arrayListShopServId.add(classObjs[i][0]);
arrayListShopServName.add(classObjs[i][1]);
This is a normal behavior.
You have :
Object[] classObjs = (Object[]) result;
Map<String,Object> classObj = (Map<String,Object>)classObjs[i];
You're trying to cast an Object[] element (classObjs[i]) to a different type (Map).
You have to construct the element of the classObj Map in a proper way.
I've ended up changing my python code so it will produce result List of Python Dictionary like this
[{'id':id, 'name':name}, {'id':id, 'name':name}, ...}]
So my code is working now.
But still confuse how to get certain element from List inside List.
So, if someone have working solution, I'll mark that as an answer.
I have a method which returns an arraylist, and it is populated from jsonarray
jsonrequest works fine, but when i call the method the arraylist returns a size of 0 even it is populated.
Below is the code, what am i doing wrong
private ArrayList<String> queryRes(String url, String searchString) {
final ArrayList<String> mylist = new ArrayList<>();
AsyncHttpClient client = new AsyncHttpClient();
client.get(url + searchString,
new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONArray jsonArray) {
for(int i =0; i < jsonArray.length(); i++) {
mylist.add(i, jsonArray.optJSONObject(i).optString("id"));
//Check if it is added to the list
Log.d("Try: ", mylist.get(i));
}
}
#Override
public void onFailure(int statusCode, Throwable throwable, JSONObject error) {
}
});
return mylist;
}
onSuccess() called when you get the response means AsynHttp call is done in another thread so your return statement call before onSucess thats why size is 0.
you can verify it on debugger
my suggestion is call a method from onSuccess() so you will get Arraylist
If you are doing everything in a single class
public void populateList(String url, String searchString)
{
final ArrayList<String> mylist = new ArrayList<>();
AsyncHttpClient client = new AsyncHttpClient();
client.get(url + searchString,
new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONArray jsonArray) {
for(int i =0; i < jsonArray.length(); i++) {
mylist.add(i, jsonArray.optJSONObject(i).optString("id"));
//Check if it is added to the list
Log.d("Try: ", mylist.get(i));
}
onListPopulated(myList);
}
#Override
public void onFailure(int statusCode, Throwable throwable, JSONObject error) {
}
});
}
A method to do something with the list
public void onListPopulated(ArrayList<String> list)
{
//do something with the list
}
I am a rookie in the Android world and I built up a small training SW based on the 2.1 Google API.
At that time I did not know yet about main thread and worker threads, so I put all my code in the main thread.
Since, I fixed it with async classes for my netwkork access to fit the 4.0 Google API.
Ok, but one last thing bothers me and I just can not find any clues.
It is about an AutoCompleteTextView on a field ville ("town" in french).
BEFORE (2.1):
public void onTextChanged(CharSequence s, int start, int before, int count)
{
String result = null;
InputStream is = null;
List<String> r = new ArrayList<String>();
if (ville.enoughToFilter())
{
is = connexionHttp(BASE_URL + "ville.php?ville=" + ville.getText());
result = lectureData(is);
try
{
JSONArray jArray = new JSONArray(result);
JSONObject json_data=null;
for(int i=0;i<jArray.length();i++)
{
json_data = jArray.getJSONObject(i);
r.add(json_data.getString("VILLE"));
a_idVil.add(json_data.getString("CLEF_VILLE"));
}
ville.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_selectable_list_item,r));
ville.setOnItemSelectedListener(new villeListener());
}
catch(JSONException e1)
{
Toast.makeText(getBaseContext(),e1.toString() ,Toast.LENGTH_LONG).show();
Log.d("***** TestActivity/onTextChanged: JSONException *****", "--"+e1.toString()+"--");
}
catch(ParseException e1)
{
Toast.makeText(getBaseContext(),e1.toString() ,Toast.LENGTH_LONG).show();
Log.d("***** TestActivity/onTextChanged: ParseException *****", "--"+e1.toString()+"--");
}
}
}
public class villeListener implements OnItemSelectedListener
{
public void onItemSelected(AdapterView<?> parent, View v, int pos, long row)
{
villePosition = pos;
}
public void onNothingSelected(AdapterView<?> arg0) { }
}
runs 100% perfect:
-> after the 4th caracters, the query runs on MySql to find all the towns beginning with the 4 given letters, and displays the selection list to select the right one: OK
-> the listener give the index of the choosen town: OK
AFTER (4.0)
public void onTextChanged(CharSequence s, int start, int before, int count)
{
if (ville.enoughToFilter())
{
new RemplirVille().execute(BASE_URL + "ville.php?ville=" + ville.getText());
Log.d("***********","AVANT");
ville.setOnItemSelectedListener(new villeListener());
Log.d("***********","APRES");
}
}
public class villeListener implements OnItemSelectedListener
{
public void onItemSelected(AdapterView<?> parent, View v, int pos, long row)
{
villePosition = pos;
Log.d("*************9999999", "1111111111");
}
public void onNothingSelected(AdapterView<?> arg0) { }
}
class RemplirVille extends AsyncTask<String, String, List<String>>
{
Integer errorMsgId;
String errorMsgParam;
protected List<String> doInBackground(String... param)
{
List<String> listeAffichageVille = new ArrayList<String>();
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(param[0]);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
if (response.getStatusLine().getStatusCode() < 400)
{
HttpEntity entity = response.getEntity();
String entityStr = EntityUtils.toString(entity);
JSONArray json_array = new JSONArray(entityStr);
for(int i=0;i<json_array.length();i++)
{
JSONObject json_ligne = json_array.getJSONObject(i);
listeAffichageVille.add(json_ligne.getString("VILLE"));
a_idVil.add(json_ligne.getString("CLEF_VILLE"));
}
}
else
{
Log.d("***** TestActivity/ASYNC RemplirVille: EXCEPTION http error *****", "--"+response.getStatusLine().toString()+"--");
this.errorMsgId = R.string.http_site_error;
listeAffichageVille = null;
}
}
catch (Exception ex)
{
Log.d("***** TestActivity/ASYNC RemplirVille: EXCEPTION decode error *****", "--"+ex.toString()+"--");
this.errorMsgId = R.string.http_decode_error;
this.errorMsgParam = ex.getLocalizedMessage();
listeAffichageVille = null;
}
return listeAffichageVille;
}
protected void onProgressUpdate(String... item) { }
protected void onPreExecute(List<String> list) { }
protected void onPostExecute(List<String> list)
{
if (list == null)
{
if (this.errorMsgId != null)
{
String msg = TestActivity.this.getString(this.errorMsgId);
Toast.makeText(TestActivity.this,msg,Toast.LENGTH_LONG).show();
}
}
else
{
ville.setAdapter(new ArrayAdapter<String>(TestActivity.this,android.R.layout.simple_selectable_list_item,list));
}
}
}
runs with troubles:
-> you have to put in (enoughToFilter + 1) caractères to diplay the list of the towns: BAD
-> the listener is even not run anymore: BAD
In fact enoughToFilter works well, it launches the RemplirVille class which runs ok except that it does not displays the list!
But, if you put in 1 more caracter:
-> enoughToFilter still working well
-> RemplirVille brings the data one more time.... but this time the selection list displays well.
Any idea about that topic?
I guess it is a context problem, but even with a GetApplicationCOntext I just can not get it.
Thanks.
Calling AutoCompleteTextView.setAdapter() does not automatically show the dropdown, but you can force the dropdown to be shown with AutoCompleteTextView.showDropDown().
protected void onPostExecute(List<String> list){
//...
ville.setAdapter(new ArrayAdapter<String>(TestActivity.this,android.R.layout.simple_selectable_list_item,list));
if(ville.isInputMethodTarget()){
ville.showDropDown();
}
//...
}
Without this, the dropdown was not shown until the next character was typed, which gave the (enoughToFilter + 1) problem.