I'm just new to Android development and I'm trying to make a weather app where it shows list of countries with the city after making a search (ex. London). In openweathermap api, it shows 5 results with different countries with a name of "London" on it but in my codes it doesn't even show 1 result.
Here's my code:
public void getCityData(){
final Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
WeatherService weatherService = retrofit.create(WeatherService.class);
ListService listService = retrofit.create(ListService.class);
String cityName = search.getEditableText().toString();
stringArrayList.clear();
stringArrayList.add(cityName);
for (String city : stringArrayList) {
Call<WeatherData> weatherDataCall = weatherService.getWeatherData("/data/2.5/find?q=" + city + "&APPID=" + API_KEY + "");
weatherDataCall.enqueue(new Callback<WeatherData>() {
#Override
public void onResponse(Call<WeatherData> call, Response<WeatherData> response) {
ProgressBar progressBar = new ProgressBar(AddCityActivity.this, null, android.R.attr.progressBarStyleHorizontal);
progressBar.setIndeterminate(true);
WeatherData weatherData = response.body();
List<cp2.openweatherv3.model.List> lists = weatherData.getList();
for (int i = 0; i < lists.size(); i++){
Log.d("name", lists.get(i).getName());
Log.e("country", lists.get(i).getSys().getCountry());
Log.w("count", String.valueOf(lists.size()));
generateList(lists);
}
}
#Override
public void onFailure(Call<WeatherData> call, Throwable t) {
Log.d("sometag", t.getLocalizedMessage());
Toast.makeText(AddCityActivity.this, "not throwing anything", Toast.LENGTH_SHORT).show();
}
});
}
}
How can I make it possible?
Thank you so much
Related
the code below I have successfully displayed the data but using the recyclerView. I want to ask how to display data if using Textview?
private void loadDataMahasiswa() {
progress = new ProgressDialog(this);
progress.setCancelable(false);
progress.setMessage("Loading ...");
progress.show();
String nip = editTxtnip.getText().toString();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
LoginAPI api = retrofit.create(LoginAPI.class);
Call<Value> call = api.view3(nip);
call.enqueue(new Callback<Value>() {
#Override
public void onResponse(Call<Value> call, Response<Value> response) {
String value = response.body().getValue();
progress.dismiss();
if (value.equals("1")) {
results = response.body().getResult();
viewAdapter = new RecyclerViewAdapter3(Lihat_izin.this, results);
recyclerView.setAdapter(viewAdapter);
}
}
#Override
public void onFailure(Call<Value> call, Throwable t) {
}
});
}
the results of the variables above are not readable sir
<?php
require_once('dbConnect.php');
date_default_timezone_set("Asia/Jakarta");
$timestamp = date('Y-m-d');
if($_SERVER['REQUEST_METHOD']=='GET')
$opd = $_GET['opd'];{
$sql = "SELECT COUNT(*)FROM(SELECT DISTINCT waktu,status from absen_pagi where opd='$opd' AND waktu='$timestamp')as dt";
$res = mysqli_query($con,$sql);
$result = array();
while($row = mysqli_fetch_array($res)){
array_push($result, array('waktu'=>$row['COUNT(*)']));
}
echo json_encode(array("value"=>1,"result"=>$result));
mysqli_close($con);
}
this my php json
If you are not using ArrayList of data then just add this line inside the response body
See below code
public void onResponse(Call<Value> call, Response<Value> response) {
String value = response.body().getValue();
progress.dismiss();
if (value.equals("1")) {
results = response.body().getResult();
viewAdapter = new RecyclerViewAdapter3(Lihat_izin.this, results);
recyclerView.setAdapter(viewAdapter);
String myData = response.body().toString(); // convert data to string
textView.setText(myData); // just add data to textView
}
}
Let me know if not solved yet
This is the error we are facing
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 1119 path $.data[4].last_received_message
public void DeviceList(String api, final ApiType apiTypes, String page_no, String authtoken) {
ProgressDialog progressDialog = new ProgressDialog();
try {
this.pdLoading = progressDialog.getInstance(this.context);
this.pdLoading.setProgressStyle(android.R.style.Widget_ProgressBar_Small);
if (this.pdLoading.isShowing()) {
this.pdLoading.cancel();
}
this.pdLoading.show();
} catch (Exception e) {
e.printStackTrace();
}
this.apiTypeVariable = apiTypes;
/*RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(api) //Setting the Root URL
.build();*/
Retrofit retrofit = new Retrofit.Builder().baseUrl(api).addConverterFactory(GsonConverterFactory.create()).client(okHttpClient).build();
GitApi gi = retrofit.create(GitApi.class);
call = (Call<T>) gi.getDevices(authtoken, page_no);
call.enqueue(new Callback<T>() {
#Override
public void onResponse(Call<T> call, Response<T> response) {
t = (T) response.body();
if (pdLoading.isShowing())
pdLoading.cancel();
onResponseListner.onResponse(t, apiTypeVariable, true);
}
#Override
public void onFailure(Call<T> call, Throwable t) {
Log.e(apiTypes.toString(), t.getMessage() + ".");
if (pdLoading.isShowing())
pdLoading.cancel();
onResponseListner.onResponse(null, apiTypeVariable, false);
}
});
}```
It tells that there is a problem occurred when convert json string to your model. Specifically, one of your model's properties is declared as String type but there is a field (key) of the json string maps to an object type. Please check the compatible of your model and the result you received from api
I'm using retrofit for the first time and I'm looking to parse some json data but I may have made a mistake initiating the network request on MainActivity. The App doesn't crush but it's not returning any values. it's a Gridlayout with an OnclickListener on each item and I'm only looking to return 2 values (name and Id ). The object currently has 3 items (name, id, and a List<>) this is the Full API end point "https://d17h27t6h515a5.cloudfront.net/topher/2017/May/59121517_baking/baking.json"
public class MainActivity extends AppCompatActivity implements
CakeAdapter.CakeClickedListener {
RecyclerView mRecyclerView;
TextView mCakeName;
ImageView mCakeImage;
TextView mCakeId;
private List<CakesItem> mCakeList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = findViewById(R.id.cake_list_recycler_view);
mRecyclerView.setHasFixedSize(true);
GridLayoutManager mGridLayoutManager = new GridLayoutManager(MainActivity.this, 2);
final CakeAdapter mCakeAdapter = new CakeAdapter(this);
mRecyclerView.setLayoutManager(mGridLayoutManager);
mRecyclerView.setAdapter(mCakeAdapter);
mCakeAdapter.getCakeData(mCakeList);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
BakingJsonApi bakingJsonApi = retrofit.create(BakingJsonApi.class);
Call<List<CakesItem>> call = bakingJsonApi.getCakes(Constants.JSON_PATH);
call.enqueue(new Callback<List<CakesItem>>() {
#Override
public void onResponse(Call<List<CakesItem>> call, Response<List<CakesItem>> response) {
if (!response.isSuccessful()) {
Toast.makeText(MainActivity.this, "Code: " + response.code(), Toast.LENGTH_SHORT).show();
return;
}
List<CakesItem> cakeItem = response.body();
mCakeAdapter.getCakeData(cakeItem);
}
#Override
public void onFailure(Call<List<CakesItem>> call, Throwable t) {
Toast.makeText(MainActivity.this, "Unable to load data" + t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
public interface BakingJsonApi {
#GET("/topher/2017/May/59121517_baking/{json}")
Call<List<CakesItem>> getCakes(#Path("json") String path);
}
class Constants {
static final String BAKING_API = "https://d17h27t6h515a5.cloudfront.net/topher/2017/May/59121517_baking/baking.json";
static final String BASE_URL = "https://d17h27t6h515a5.cloudfront.net/";
static final String JSON_PATH = "baking.json";
}
Maybe update Recycler-Adapter can work. I also modified your condition.
call.enqueue(new Callback<List<CakesItem>>() {
#Override
public void onResponse(Call<List<CakesItem>> call, Response<List<CakesItem>> response) {
if (response.isSuccessful()) {
mCakeList = new ArrayList();
mCakeList.addAll(response.body());
mCakeAdapter.notifyDataSetChanged();
}
}
#Override
public void onFailure(Call<List<CakesItem>> call, Throwable t) {
Toast.makeText(MainActivity.this, "Unable to load data" + t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
Try change this condition :
if (!response.isSuccessful()) {
To something like t:
if(response.isSuccessful()){
Modelcake respuesta = response.body();
listcake.addAll(respuesta.getcake()); //in getcake() you get what are you want in your model
adapter.notifyDataSetChanged();
}else{
Log.e("API","onResponse"+response.errorBody());
}
With that should be work.
PostData.java
public class PostData {
List<String> gobalAr=new ArrayList<String>();
public List<String> getList(){
return gobalAr;
}
public void setList( List<String> gl){
this.gobalAr = gl;
}
String url = "http://btownmedia.com/";
ArrayList<Post> postArry = new ArrayList();
public List<String> bankin = new ArrayList<String>();
public void getRetrofitPostHospitalObject() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitObjectAPI service = retrofit.create(RetrofitObjectAPI.class);
Call<PostArtical> call = service.getPostHospitalDetails();
call.enqueue(new Callback<PostArtical>() {
#Override
public void onResponse(Response<PostArtical> response, Retrofit retrofit) {
try {
List<Post> PostData = response.body().getPosts();
for (int i = 0; i < PostData.size(); i++) {
Post p = new Post();
p.setId(PostData.get(i).getId());
p.setTitle(PostData.get(i).getTitle());
p.setExcerpt(PostData.get(i).getExcerpt());
p.setThumbnail(PostData.get(i).getThumbnail());
postArry.add(p);
}
gobalAr=new ArrayList<String>();
for (int i = 0; i < postArry.size(); i++) {
Post c = new Post();
c=postArry.get(i);
gobalAr.add(c.getTitle());
}
setList(gobalAr);
Log.d("valuein",gobalAr.toString()); //[Birtamode Eye Hospital (P) Ltd., Birta City Hospital, Life Line Hospital]
} catch (Exception e) {
Log.d("onResponse", "There is an error");
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable t) {
Log.d("onFailure", t.toString());
}
});
Log.d("valueout",gobalAr.toString()); // null
}}
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PostData postData = new PostData();
postData.getRetrofitPostHospitalObject();
List<String> list = postData.getList();
Log.d("On", list.toString()); //null
}}
When I am Trying to access Data which From PostData class of method getRetrofitPostHospitalObject() variable "List gobalAr " in MainActivity when i call it is showing null value in gobalAr, Where as I have insert Data from of gobalArr in which add getRetrofitPostHospitalObject(), Please can Help..
Actually i want to access data "gobalAr" variable of PostData class to an MainActivity.
create get() method for List,like this
public List<String> getList(){
return *****;
}
Easy solution call this method in MainActivity
public void getRetrofitPostHospitalObject() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitObjectAPI service = retrofit.create(RetrofitObjectAPI.class);
Call<PostArtical> call = service.getPostHospitalDetails();
call.enqueue(new Callback<PostArtical>() {
#Override
public void onResponse(Response<PostArtical> response, Retrofit retrofit) {
try {
List<Post> PostData = response.body().getPosts();
for (int i = 0; i < PostData.size(); i++) {
Post p = new Post();
p.setId(PostData.get(i).getId());
p.setTitle(PostData.get(i).getTitle());
p.setExcerpt(PostData.get(i).getExcerpt());
p.setThumbnail(PostData.get(i).getThumbnail());
postArry.add(p);
}
gobalAr=new ArrayList<String>();
for (int i = 0; i < postArry.size(); i++) {
Post c = new Post();
c=postArry.get(i);
gobalAr.add(c.getTitle());
}
setList(gobalAr);
Log.d("valuein",gobalAr.toString()); //[Birtamode Eye Hospital (P) Ltd., Birta City Hospital, Life Line Hospital]
} catch (Exception e) {
Log.d("onResponse", "There is an error");
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable t) {
Log.d("onFailure", t.toString());
}
});
Log.d("valueout",gobalAr.toString()); // null
}
Then do the rest inside. problem solved
I am using Retrofit in my application and receiving data from my server.
I receive data from my server in responseBody in Retrofit, but when I want to use these received data, my array is null?!!
Here is my class:
public class ActivityApplicationsList extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_applications_list);
Log.i(TAG , "size of response array: " + populateDataFromServer().size())
//this size is 0 but have to be 4 !
}
private ArrayList<StructApplication> populateDataFromServer() {
final ArrayList<StructApplication> mine = new ArrayList<>();
final APIService service = ServiceGenerator.createService(APIService.class, "2015-03-01 14:26:00", "123456", "123456");
Call<ArrayList<AppModel>> call = service.getApp();
call.enqueue(new Callback<ArrayList<AppModel>>() {
#Override
public void onResponse(Call<ArrayList<AppModel>> call, Response<ArrayList<AppModel>> response) {
ArrayList<AppModel> newAppModel = response.body();
for(int i=0 ; i < newAppModel.size();i++){
StructApplication structApplication = new StructApplication();
structApplication.setName(String.valueOf(newAppModel.get(i).getAppId()));
structApplication.setId(newAppModel.get(i).getAppId());
structApplication.setAppVersionReleaseDate(newAppModel.get(i).getAppVersionReDate());
structApplication.setAppDeleted(newAppModel.get(i).getAppDeleted());
mine.add(structApplication);
}
}
#Override
public void onFailure(Call<ArrayList<AppModel>> call, Throwable t) {
}
});
return mine;
}
}
And I debugged to make sure that all data received in onResponse:
As you can see, I received all data correctly, but when I use this response in onCreate of this class it's null!
I really appreciate your answer about this weird problem.
This is because you are printing your list size before the response comes. As request is being sent asynchronously, and your are trying to get size before onResponse() callback method.
try to add this line
Log.i(TAG , "size of response array: " + populateDataFromServer().size())
in onResponse() method after mine.add(structApplication); you will see the right size.
Its return first and execute later, try this way...
private ArrayList<StructApplication> populateDataFromServer() {
final ArrayList<StructApplication> mine = new ArrayList<>();
final APIService service = ServiceGenerator.createService(APIService.class, "2015-03-01 14:26:00", "123456", "123456");
Call<ArrayList<AppModel>> call = service.getApp();
Response<ArrayList<AppModel>> response = responseCall.execute();
ArrayList<AppModel> newAppModel = response.body();
for(int i=0 ; i < newAppModel.size();i++){
StructApplication structApplication = new StructApplication();
structApplication.setName(String.valueOf(newAppModel.get(i).getAppId()));
structApplication.setId(newAppModel.get(i).getAppId());
structApplication.setAppVersionReleaseDate(newAppModel.get(i).getAppVersionReDate());
structApplication.setAppDeleted(newAppModel.get(i).getAppDeleted());
mine.add(structApplication);
}
return mine;
}
It is happening due to api calling because api taking few seconds to get response and meanwhile you returned your mine array. So please return response once you got value from server.
Do like this
Make a global instance for this class like
public class ActivityApplicationsList extends Activity {
ArrayList<StructApplication> mine = new ArrayList();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_applications_list);
populateDataFromServer();
Log.i(TAG , "size of response array: " + mine.size());
}
private void populateDataFromServer() {
final APIService service = ServiceGenerator.createService(APIService.class, "2015-03-01 14:26:00", "123456", "123456");
Call<ArrayList<AppModel>> call = service.getApp();
call.enqueue(new Callback<ArrayList<AppModel>>() {
#Override
public void onResponse(Call<ArrayList<AppModel>> call, Response<ArrayList<AppModel>> response) {
ArrayList<AppModel> newAppModel = response.body();
for(int i=0 ; i < newAppModel.size();i++){
StructApplication structApplication = new StructApplication();
structApplication.setName(String.valueOf(newAppModel.get(i).getAppId()));
structApplication.setId(newAppModel.get(i).getAppId());
structApplication.setAppVersionReleaseDate(newAppModel.get(i).getAppVersionReDate());
structApplication.setAppDeleted(newAppModel.get(i).getAppDeleted());
mine.add(structApplication);
}
}
#Override
public void onFailure(Call<ArrayList<AppModel>> call, Throwable t) {
}
});
}
}
You need to get the response after the request. See code comments
public class ActivityApplicationsList extends Activity
implements Callback<ArrayList<AppModel>> { // Implement callback here
// These are final, so make them fields
final ArrayList<StructApplication> mine = new ArrayList<>();
final APIService service = ServiceGenerator.createService(APIService.class, "2015-03-01 14:26:00", "123456", "123456");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_applications_list);
populateDataFromServer();
}
// Callback implementation
#Override
public void onResponse(Call<ArrayList<AppModel>> call, Response<ArrayList<AppModel>> response) {
final ArrayList<AppModel> responseBody = response.body();
for(AppModel model : responseBody){
StructApplication structApplication = new StructApplication();
structApplication.setName(String.valueOf(model.getAppId()));
structApplication.setId(model.getAppId());
structApplication.setAppVersionReleaseDate(model.getAppVersionReDate());
structApplication.setAppDeleted(model.getAppDeleted());
mine.add(structApplication);
}
// adapter.notifyDataSetChanged(); // Need this if using ListView
Log.d("SIZE", ""+mine.size()); // Correct size
}
#Override
public void onFailure(Call<ArrayList<AppModel>> call, Throwable t) {
// error
}
private void populateDataFromServer() { // this is void; it can't return
service.getApp().enqueue(ActivityApplicationsList.this);
}
Suggestion, make this constructor
public class StructApplication {
public StructApplication(AppModel model) {
setName(String.valueOf(model.getAppId());
setId(model.getAppId());
setAppDeleted(model.getAppDeleted());
setAppVersionReleaseDate(model.getAppVersionReDate());
}
}
Then, that loop can simply be
mine.add(new StructApplication(model));