Expected BEGIN_OBJECT but was BEGIN_ARRAY
I get this error because gson expects an object but since response from API starts with array it throws error. I 've looked at many answers on these questions but none seem to work/are understandable. the API returns an array of arrays of objects. (an array of objects for every sensor: temperature, humidity, ...). how should I change my code so it expects an array of arrays of objects?
[[
{"_id":"6022366801ad473cd0160e5d","time":"2020-03-11T18:07:44.000Z","value":"15","unit":"°C"},
{"_id":"602238f413fadf4bf04df86f","time":"2020-03-11T18:07:44.000Z","value":"15","unit":"°C"},
{"_id":"602238f613fadf4bf04df870","time":"2020-03-11T18:07:44.000Z","value":"15","unit":"°C"},
{"_id":"602934f9f8686e39800e4d2b","time":"2020-03-11T19:07:44.000Z","value":"15","unit":"°C"},
{"_id":"602934fdf8686e39800e4d2c","time":"2020-03-11T19:07:44.000Z","value":"15","unit":"°C"},
{"_id":"602934fef8686e39800e4d2d","time":"2020-03-11T19:07:44.000Z","value":"15","unit":"°C"},
{"_id":"60293589f8686e39800e4d36","time":"2020-03-11T18:07:44.000Z","value":"-2","unit":"°C"},
{"_id":"60293589f8686e39800e4d37","time":"2020-03-11T18:07:44.000Z","value":"-2","unit":"°C"},
{"_id":"602935adf8686e39800e4d43","time":"2020-03-11T18:07:44.000Z","value":"-2","unit":"°C"}
],[...]]
.
public void GetDayFromAPI(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.1.106:3000/api/")
.addConverterFactory(GsonConverterFactory.create())
.build();
JsonPlaceholderApi jsonPlaceholderApi = retrofit.create(JsonPlaceholderApi.class);
Call<List<SensorPost>> call = jsonPlaceholderApi.getposts();
call.enqueue(new Callback<List<SensorPost>>() {
#Override
public void onResponse(Call<List<SensorPost>> call, Response<List<SensorPost>> response)
{
if(!response.isSuccessful()){
textViewResult.setText("code: " + response.code());
return;
}
List<SensorPost> posts = response.body();
for (SensorPost post : posts){
String content = "";
content += "Unit: " + post.getUnit() + "\n";
content += "Value: " + post.getValue() + "\n";
content += "Time: " + post.getTime() + "\n\n";
textViewResult.append(content);
}
}
#Override
public void onFailure(Call<List<SensorPost>> call, Throwable t) {
textViewResult.setText(t.getMessage());
}
});
}
Related
I want to get a stores position when I create Mapview and Insert those stores into a map using markers and to do this I need to insert database elements into An ArrayList and retrieve those informations ( for use it to remove Makers and...) but when I use debugging I found that retrieving Infos complete before inserting. I don't know why but maybe retrieving database infos takes time so I need a solution for that.
public void onMapReady(GoogleMap googleMap) {
map = googleMap;
//----------------Get all col / vent collection
getd("all");
//---------------Setup Markers of col/vent-------------------//
ArrayList<MarkerData> mker = new ArrayList<MarkerData>();
for(int i = 0 ; i < mker.size() ; i++) {
Log.d("Date of arrays",mker.get(i).getDate());
}
and getd()
private void getd(String selector){
/*ProgressDialog progress = new ProgressDialog(getActivity());
progress.setTitle("Charger les infos");
progress.setMessage("attendre...");
progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progress.show();*/
//Creating a retrofit object
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Api.BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) //Here we are using the GsonConverterFactory to directly convert json data to object
.build();
Api api = retrofit.create(Api.class);
Call<List<col>> call = api.getHeroes(selector);
call.enqueue(new Callback<List<col>>() {
#Override
public void onResponse(Call<List<col>> call, Response<List<col>> response) {
mker = new ArrayList<>();
List<col> colList = response.body();for ( col c: colList){
Log.d("name : ",c.getNom_col());
Log.d("Lat : ",c.getLat_col());
Log.d("Long : ",c.getLong_col());
Log.d("Email : ",c.getEmailcol());
Log.d("type : ",c.getType());
Log.d("date : ",c.getDate_creation_col());
Log.d("Creator : ",c.getCreator());
mker.add(new MarkerData(c.getNom_col(),c.getLat_col(),c.getLong_col(),c.getEmailcol(),c.getType(),c.getDate_creation_col(),c.getCreator()));
//ArrayList<MarkerData> markersArray = new ArrayList<MarkerData>();
}
}
Write marker insertion code in on response method. This method gets invokes once a response comes from server.
Refer below code :
private void getd(String selector) {
/*ProgressDialog progress = new ProgressDialog(getActivity());
progress.setTitle("Charger les infos");
progress.setMessage("attendre...");
progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progress.show();*/
//Creating a retrofit object
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Api.BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) //Here we are using the GsonConverterFactory to directly convert json data to object
.build();
Api api = retrofit.create(Api.class);
Call<List<col>> call = api.getHeroes(selector);
call.enqueue(new Callback<List<col>>() {
#Override
public void onResponse(Call<List<col>> call, Response<List<col>> response) {
mker = new ArrayList<>();
List<col> colList = response.body();
for (col c : colList) {
Log.d("name : ", c.getNom_col());
Log.d("Lat : ", c.getLat_col());
Log.d("Long : ", c.getLong_col());
Log.d("Email : ", c.getEmailcol());
Log.d("type : ", c.getType());
Log.d("date : ", c.getDate_creation_col());
Log.d("Creator : ", c.getCreator());
mker.add(new MarkerData(c.getNom_col(), c.getLat_col(), c.getLong_col(), c.getEmailcol(), c.getType(), c.getDate_creation_col(), c.getCreator()));
//ArrayList<MarkerData> markersArray = new ArrayList<MarkerData>();
}
// Marker retrieval code should be here
for (int i = 0; i < mker.size(); i++) {
Log.d("Date of arrays", mker.get(i).getDate());
}
}
}
}
I am working on a Messaging Android App. Users should be notified with a push notification.
At the time I have this code:
public void notifyUser(String user_id, String message) {
try {
OneSignal.postNotification(new JSONObject("{'contents': {'en':['" + message + "']}, " +
"'include_player_ids': ['" + user_id + "'], " +
"'headings': {'en': 'Tag sub Title HI {{user_name}}'}, " +
"'data': {'openURL': 'https://imgur.com'}," +
"'buttons':[{'id': 'id1', 'text': 'Go to GreenActivity'}, {'id':'id2', 'text': 'Go to MainActivity'}]}"),
new OneSignal.PostNotificationResponseHandler() {
#Override
public void onSuccess(JSONObject response) {
Log.d("LOL", "postNotification Success: " + response.toString());
}
#Override
public void onFailure(JSONObject response) {
Log.d("LOL", "postNotification Failure: " + response.toString());
}
});
} catch (JSONException e) {
e.printStackTrace();
}
}
But I get an Error in Log:
D/LOL: postNotification Failure: {"errors":["Notification contents for each language must be a string"]}
I searched threw the Internet but didn't find a solution for my Problem.
I hope you can help me...
Thanks in advance.
I believe the error you're seeing is because you're sending up the message inside an array when it should just be a string.
"{'contents': {'en':['" + message + "']} should be "{'contents': {'en':'" + message + "'} (removed the brackets).
I'm making a call using Retrofit's enqueue() method. I'm calling my refreshImages() in my MainActivity's onCreate(), refreshImages() then calls a method refreshImagesIds() which is supposed to make a call out to Flickr's API and return back a PhotosList object, I'll then pull out the Photos from there which will contain a list of Photo objects. My issue is that for some reason the onResponse() inside my enqueue() method is never getting called. When I use the debugger it skips right over it, and when I put Log statements inside they never get written out. I know the endpoint it is hitting is correct because I can see it using OkHttp's logger, and my POJOs all look to be correct for the data being returned.
Any idea why this isn't working? Below are my refreshImages and refreshImagesId. These are both contained in my MainAcitivty and modify class-level variables.
private void refreshImages() {
// make api call
//imageUrls = FlickrServiceManager_withinterface.getKittenImages(8);
refreshImageIds();
List<Photo> photos = photosList.getPhotos().getPhoto();
imageIds = new ArrayList<String>();
for(Photo photo : photos) {
Log.d("TAG", "It is pringint imageIds: " + photo.getId());
imageIds.add(photo.getId());
}
}
private void refreshImageIds() {
Retrofit retrofit = Api.getRestAdapter();
FlickrServiceInterface flickrService = retrofit.create(FlickrServiceInterface.class);
Call<PhotosList> call = flickrService.getPhotos(API_KEY, FORMAT, "1");
imageIds = new ArrayList<String>();
call.enqueue(new Callback<PhotosList>(){
#Override
public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
photosList = response.body();
}
#Override
public void onFailure(Call<PhotosList> call, Throwable t) {
// TODO: Clean up
Log.d("TEMP_TAG", "Call failed");
}
});
}
And my FlickrServiceInterface:
public interface FlickrServiceInterface {
#GET("?method=flickr.photos.getSizes")
Call<PhotoSizes> getPhotoSizes(#Query("api_key") String apiKey, #Query("format") String format, #Query("nojsoncallback") String jsonCallback, #Query("photo_id") String photoId);
#GET("?method=flickr.photos.getRecent")
Call<PhotosList> getPhotos(#Query("api_key") String apiKey, #Query("format") String format, #Query("nojsoncallback") String jsonCallback);
}
Change your call to the synchronous retrofit API :
public static List<String> getImageIds(int size) {
Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
photoIds = new ArrayList<String>();
PhotosList photosList = call.execute().body();
List<Photo> photos = photosList.getPhotos().getPhoto();
for(Photo photo : photos) {
Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
photoIds.add(photo.getId());
}
Log.d("TEMP_TAG", "it's getting here too");
return photoIds;
}
Please note that you need to call this method on an AsyncTask
EDIT
You could also continue to use enqueue, but you need to provide an "onFinish" hook, so you know when your data has been received and then you "notify" the client with the data:
//interface por communication
public interface ImageIdsCallBack {
public void onFinish( List<String> photoIds );
}
Then you receive this interface and send data:
public static List<String> getImageIds(int size, final ImageIdsCallBack callback) {
Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
photoIds = new ArrayList<String>();
call.enqueue(new Callback<PhotosList>(){
#Override
public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
PhotosList photosList = response.body();
List<Photo> photos = photosList.getPhotos().getPhoto();
for(Photo photo : photos) {
Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
photoIds.add(photo.getId());
}
//send the data to the caller
callback.onFinish(photoIds);
}
#Override
public void onFailure(Call<PhotosList> call, Throwable t) {
// TODO: Clean up
Log.d("TEMP_TAG", "Call failed");
}
});
Log.d("TEMP_TAG", "it's getting here too");
return photoIds;
}
calling the method :
getImageIds( 50 , new ImageIdsCallBack() {
public void onFinish( List<String> photoIds ) {
//update UI with photoIds
}
} );
I typically use a library like EventBus to make it easier, I really recommend it to you.
Correct me if I'm wrong, is this on the main thread? That would pose the problem of not waiting for a response.
Consider using async
I'm making a call using Retrofit's enqueue() method. I'm calling my refreshImages() in my MainActivity's onCreate(), refreshImages() then calls a method refreshImagesIds() which is supposed to make a call out to Flickr's API and return back a PhotosList object, I'll then pull out the Photos from there which will contain a list of Photo objects. My issue is that for some reason the onResponse() inside my enqueue() method is never getting called. When I use the debugger it skips right over it, and when I put Log statements inside they never get written out. I know the endpoint it is hitting is correct because I can see it using OkHttp's logger, and my POJOs all look to be correct for the data being returned.
Any idea why this isn't working? Below are my refreshImages and refreshImagesId. These are both contained in my MainAcitivty and modify class-level variables.
private void refreshImages() {
// make api call
//imageUrls = FlickrServiceManager_withinterface.getKittenImages(8);
refreshImageIds();
List<Photo> photos = photosList.getPhotos().getPhoto();
imageIds = new ArrayList<String>();
for(Photo photo : photos) {
Log.d("TAG", "It is pringint imageIds: " + photo.getId());
imageIds.add(photo.getId());
}
}
private void refreshImageIds() {
Retrofit retrofit = Api.getRestAdapter();
FlickrServiceInterface flickrService = retrofit.create(FlickrServiceInterface.class);
Call<PhotosList> call = flickrService.getPhotos(API_KEY, FORMAT, "1");
imageIds = new ArrayList<String>();
call.enqueue(new Callback<PhotosList>(){
#Override
public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
photosList = response.body();
}
#Override
public void onFailure(Call<PhotosList> call, Throwable t) {
// TODO: Clean up
Log.d("TEMP_TAG", "Call failed");
}
});
}
And my FlickrServiceInterface:
public interface FlickrServiceInterface {
#GET("?method=flickr.photos.getSizes")
Call<PhotoSizes> getPhotoSizes(#Query("api_key") String apiKey, #Query("format") String format, #Query("nojsoncallback") String jsonCallback, #Query("photo_id") String photoId);
#GET("?method=flickr.photos.getRecent")
Call<PhotosList> getPhotos(#Query("api_key") String apiKey, #Query("format") String format, #Query("nojsoncallback") String jsonCallback);
}
Change your call to the synchronous retrofit API :
public static List<String> getImageIds(int size) {
Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
photoIds = new ArrayList<String>();
PhotosList photosList = call.execute().body();
List<Photo> photos = photosList.getPhotos().getPhoto();
for(Photo photo : photos) {
Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
photoIds.add(photo.getId());
}
Log.d("TEMP_TAG", "it's getting here too");
return photoIds;
}
Please note that you need to call this method on an AsyncTask
EDIT
You could also continue to use enqueue, but you need to provide an "onFinish" hook, so you know when your data has been received and then you "notify" the client with the data:
//interface por communication
public interface ImageIdsCallBack {
public void onFinish( List<String> photoIds );
}
Then you receive this interface and send data:
public static List<String> getImageIds(int size, final ImageIdsCallBack callback) {
Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
photoIds = new ArrayList<String>();
call.enqueue(new Callback<PhotosList>(){
#Override
public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
PhotosList photosList = response.body();
List<Photo> photos = photosList.getPhotos().getPhoto();
for(Photo photo : photos) {
Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
photoIds.add(photo.getId());
}
//send the data to the caller
callback.onFinish(photoIds);
}
#Override
public void onFailure(Call<PhotosList> call, Throwable t) {
// TODO: Clean up
Log.d("TEMP_TAG", "Call failed");
}
});
Log.d("TEMP_TAG", "it's getting here too");
return photoIds;
}
calling the method :
getImageIds( 50 , new ImageIdsCallBack() {
public void onFinish( List<String> photoIds ) {
//update UI with photoIds
}
} );
I typically use a library like EventBus to make it easier, I really recommend it to you.
Correct me if I'm wrong, is this on the main thread? That would pose the problem of not waiting for a response.
Consider using async
I'm having serious issues trying to find the correct syntax to push a document into an elasticsearch index by type.
My code im using to do this is :
String url = "https://my_url/my_index_name";
StringRequest postRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonResponse = new JSONObject(response).getJSONObject("form");
String site = jsonResponse.getString("site"),
network = jsonResponse.getString("network");
Log.d("Site: ", site + "\nNetwork: "+network);
} catch (JSONException e) {
e.printStackTrace();
Log.e("JSON EXCEPTION", e.toString());
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}
)
{
#Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<>();
// the POST parameters:
params.put("type", "type_name");;
params.put("field1", field1_value);
params.put("field2", field2_value);
params.put("field3", field3_value);
params.put("field4", field4_value);
params.put("field5", field5_value);
return params;
}
};
Volley.newRequestQueue(this).add(postRequest);
It's hitting the server, as I'm getting 400 requests, but I just cant get it to go in using this.
12-14 16:19:04.533 12642-13089/? E/Volley﹕ [41831]
BasicNetwork.performRequest: Unexpected response code 400 for URL
Can some enlighten me as to what the correct syntax is, using java code, or tell me what I'm doing wrong?
I assumed the correct syntax was:
http:// url | index_name | type | body ?
EDIT: I've searched SO, elastic java api's, google groups and all over the internet for 3 days now, with no luck! Anything at all is greatly appreciated !
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
Log.e("VOLLEY ERROR", "" + error.toString());
}
}
Results in : VOLLEY ERROR﹕ com.android.volley.ServerError
Any ideas?
Ok, so I managed to fix it.
There was two issues:
The first issue was with the URL which was:
String url = "https://my_url/my_index_name";
It should have been:
String url = "https://my_url/my_index_name/type%20-d";
The second issue was with the actual arguments:
params.put("type", "type_name");;
params.put("field1", field1_value);
params.put("field2", field2_value);
params.put("field3", field3_value);
params.put("field4", field4_value);
params.put("field5", field5_value);
return params;
I swapped this out for :
String urlParameters =
"{" +
" \"field\": \" + field_value \"," +
" \"field\": \" + field_value \"," +
" \"field\": \" + field_value \"," +
" \"field\": \" + field_value \"," +
" \"field\": \" + field_value \"" +
"}";
And post by:
DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
Everything is working as I want now, thanks for the help.