https://pro-api.coinmarketcap.com/v1/tools/price-conversion?symbol=NGN&amount=1000897.01&convert=BTC&CMC_PRO_API_KEY=*********************************
That's the url and here is the json returned from querying that url:
{"status":{"timestamp":"2021-04-20T08:48:16.990Z","error_code":0,"error_message":null,"elapsed":17,"credit_count":1,"notice":null},"data":{"id":2819,"symbol":"NGN","name":"Nigerian Naira","amount":1000897.01,"last_updated":"2021-04-20T08:48:07.000Z","quote":{"BTC":{"price":0.0444454708294559,"last_updated":"2021-04-20T08:48:02.000Z"}}}}
the following is my code in android studio to get data from the above api en point
My pojo classes:
import com.google.gson.annotations.SerializedName;
public class CurrencyModel {
#SerializedName("name")
private String currencyName;
#SerializedName("Amount")
private int currencyAmount;
#SerializedName("quote")
Quota quota;
public CurrencyModel(Quota quota) {
this.quota = quota;
// quota.bitcoinModel.getCoinPrice();
}
public CurrencyModel(String currencyName, int currencyAmount, Quota quota) {
this.currencyName = currencyName;
this.currencyAmount = currencyAmount;
this.quota = quota;
}
public String getCurrencyName() {
return currencyName;
}
public void setCurrencyName(String currencyName) {
this.currencyName = currencyName;
}
public int getCurrencyAmount() {
return currencyAmount;
}
public void setCurrencyAmount(int currencyAmount) {
this.currencyAmount = currencyAmount;
}
public Quota getQuota() {
return quota;
}
public void setQuota(Quota quota) {
this .quota = quota;
}
public class Quota {
int price;
#SerializedName("BTC")
BitcoinModel bitcoinModel;
public Quota(BitcoinModel bitcoinModel) {
this.bitcoinModel = bitcoinModel;
}
public BitcoinModel getBitcoinModel() {
return bitcoinModel = new BitcoinModel(price);
}
public void setBitcoinModel(BitcoinModel bitcoinModel) {
this.bitcoinModel = bitcoinModel;
}
}
public class BitcoinModel {
#SerializedName("price")
private int coinPrice;
public BitcoinModel(int coinPrice) {
this.coinPrice = coinPrice;
}
public int getCoinPrice() {
return coinPrice;
}
public void setCoinPrice(int coinPrice) {
this.coinPrice = coinPrice;
}
}
My activity
public class BitcoinConversionActivity extends AppCompatActivity {
TextInputEditText amountConverted;
Button conversionButton, buyCoinButton;
TextView amountInCurrency;
int amount;
String amountEntered;
Quota quota;
CurrencyModel currencyModel;
JsonPojo pojo;
String symbol = "NGN";
String convert = "BTC";
int amountneeded = 1024587;
String apiKey = "b34416c7-2bb9-44b1-aa76-1293edd14dda";
String currencyName;
int amountnm;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_coinconversion);
amountConverted = findViewById(R.id.amount_edit_text);
amountInCurrency = findViewById(R.id.conversion_rate_tv);
conversionButton = findViewById(R.id.conversion_button);
buyCoinButton = findViewById(R.id.buy_exchange_coin_button);
conversionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
amount = Integer.parseInt(amountConverted.getText().toString());
if (TextUtils.isEmpty(Double.toString(amount))){
Toast.makeText(BitcoinConversionActivity.this, "Please Enter a valid Amount", Toast.LENGTH_LONG).show();
}else{
CoinExchange();
}
}
});
}
private void CoinExchange() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://pro-api.coinmarketcap.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
BitcoinInterface service = retrofit.create(BitcoinInterface.class);
Call<CurrencyModel> call = service.loadNairaToBitcionExchange(symbol,amountneeded,convert,apiKey);
call.enqueue(new Callback<CurrencyModel>() {
#Override
public void onResponse(Call<CurrencyModel> call, Response<CurrencyModel> response) {
if (response.isSuccessful()){
String price = response.body().toString();
//amountInCurrency.setText(price);
amountInCurrency.setText("https://pro-api.coinmarketcap.com/"+symbol+amount+convert+apiKey);
Toast.makeText(BitcoinConversionActivity.this, "Data: " + response.body().getQuota().getBitcoinModel().getCoinPrice(), Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(Call<CurrencyModel> call, Throwable t) {
Toast.makeText(BitcoinConversionActivity.this, "Error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
API interface:
public interface BitcoinInterface {
#GET("v1/tools/price-conversion?")
Call<CurrencyModel> loadNairaToBitcionExchange(#Query("symbol") String coinsSymbol,
#Query("amount") int currencyaAmount,
#Query("convert") String convertedToCurrency,
#Query("CMC_PRO_API_KEY") String ApiKey);
}
The call is returning null and at times zero.
From the API you are not getting exactly the CurrencyModel as response. You are getting another object which is CurrencyModel is a child object.
You have to create resposne object like below:
public class ResponseObject{
//#SerializedName("status")
//private int status;
#SerializedName("data")
private CurrencyModel currencyModel;
//getters and setters goes here
}
And then your interface should be like below as you are expecting ResponseObject here
public interface BitcoinInterface {
#GET("v1/tools/price-conversion?")
Call<ResponseObject> loadNairaToBitcionExchange(#Query("symbol") String coinsSymbol,
#Query("amount") int currencyaAmount,
#Query("convert") String convertedToCurrency,
#Query("CMC_PRO_API_KEY") String ApiKey);
}
Related
Hi I am just started with mvvm with repository pattern I am stuck with the API error
I am using the generic API Response class as per google official repo in java
/**
* Generic class for handling responses from Retrofit
*
* #param <T>
*/
public class ApiResponse<T> {
public ApiResponse<T> create(Throwable error) {
return new ApiErrorResponse<>(error.getMessage().equals("") ? error.getMessage() : "Unknown error\nCheck network connection");
}
public ApiResponse<T> create(Response<T> response) {
if (response.isSuccessful()) {
T body = response.body();
if (body instanceof GithubApiResponse) {
if (AppUtils.isValid((GithubApiResponse) body)) {
String errorMsg = "Empty Response.";
return new ApiErrorResponse<>(errorMsg);
}
}
if (body == null || response.code() == 204) { // 204 is empty response
return new ApiEmptyResponse<>();
} else {
return new ApiSuccessResponse<>(body);
}
} else {
String errorMsg = "";
try {
errorMsg = response.errorBody().string();
} catch (IOException e) {
e.printStackTrace();
errorMsg = response.message();
}
return new ApiErrorResponse<>(errorMsg);
}
}
/**
* Generic success response from api
*
* #param <T>
*/
public class ApiSuccessResponse<T> extends ApiResponse<T> {
private T body;
ApiSuccessResponse(T body) {
this.body = body;
}
public T getBody() {
return body;
}
}
/**
* Generic Error response from API
*
* #param <T>
*/
public class ApiErrorResponse<T> extends ApiResponse<T> {
private String errorMessage;
ApiErrorResponse(String errorMessage) {
this.errorMessage = errorMessage;
}
public String getErrorMessage() {
return errorMessage;
}
}
/**
* separate class for HTTP 204 resposes so that we can make ApiSuccessResponse's body non-null.
*/
public class ApiEmptyResponse<T> extends ApiResponse<T> {
}
}
and My networkBoundResource as like this
public abstract class NetworkBoundResource<ResultType, RequestType> {
private AppExecutors appExecutors;
private MediatorLiveData<Resource<ResultType>> results = new MediatorLiveData<>();
public NetworkBoundResource(AppExecutors appExecutors) {
this.appExecutors = appExecutors;
init();
}
private void init() {
// update LiveData for loading status
results.setValue((Resource<ResultType>) Resource.loading(null));
// observe LiveData source from local db
final LiveData<ResultType> dbSource = loadFromDb();
results.addSource(dbSource, new Observer<ResultType>() {
#Override
public void onChanged(#Nullable ResultType ResultType) {
results.removeSource(dbSource);
if (shouldFetch(ResultType)) {
// get data from the network
fetchFromNetwork(dbSource);
} else {
results.addSource(dbSource, new Observer<ResultType>() {
#Override
public void onChanged(#Nullable ResultType ResultType) {
setValue(Resource.success(ResultType));
}
});
}
}
});
}
/**
* 1) observe local db
* 2) if <condition/> query the network
* 3) stop observing the local db
* 4) insert new data into local db
* 5) begin observing local db again to see the refreshed data from network
*
* #param dbSource
*/
private void fetchFromNetwork(final LiveData<ResultType> dbSource) {
Timber.d("fetchFromNetwork: called.");
// update LiveData for loading status
results.addSource(dbSource, new Observer<ResultType>() {
#Override
public void onChanged(#Nullable ResultType ResultType) {
setValue(Resource.loading(ResultType));
}
});
final LiveData<ApiResponse<RequestType>> apiResponse = createCall();
results.addSource(apiResponse, new Observer<ApiResponse<RequestType>>() {
#Override
public void onChanged(#Nullable final ApiResponse<RequestType> requestObjectApiResponse) {
results.removeSource(dbSource);
results.removeSource(apiResponse);
/*
3 cases:
1) ApiSuccessResponse
2) ApiErrorResponse
3) ApiEmptyResponse
*/
if (requestObjectApiResponse instanceof ApiResponse.ApiSuccessResponse) {
Timber.d("onChanged: ApiSuccessResponse.");
appExecutors.diskIO().execute(new Runnable() {
#Override
public void run() {
// save the response to the local db
saveCallResult((RequestType) processResponse((ApiResponse.ApiSuccessResponse) requestObjectApiResponse));
appExecutors.mainThread().execute(new Runnable() {
#Override
public void run() {
results.addSource(loadFromDb(), new Observer<ResultType>() {
#Override
public void onChanged(#Nullable ResultType ResultType) {
setValue(Resource.success(ResultType));
}
});
}
});
}
});
} else if (requestObjectApiResponse instanceof ApiResponse.ApiEmptyResponse) {
Timber.d("onChanged: ApiEmptyResponse");
appExecutors.mainThread().execute(new Runnable() {
#Override
public void run() {
results.addSource(loadFromDb(), new Observer<ResultType>() {
#Override
public void onChanged(#Nullable ResultType ResultType) {
setValue(Resource.success(ResultType));
}
});
}
});
} else if (requestObjectApiResponse instanceof ApiResponse.ApiErrorResponse) {
Timber.d("onChanged: ApiErrorResponse.");
results.addSource(dbSource, new Observer<ResultType>() {
#Override
public void onChanged(#Nullable ResultType ResultType) {
setValue(
Resource.error(
((ApiResponse.ApiErrorResponse) requestObjectApiResponse).getErrorMessage(),
ResultType
)
);
}
});
}
}
});
}
private ResultType processResponse(ApiResponse.ApiSuccessResponse response) {
return (ResultType) response.getBody();
}
private void setValue(Resource<ResultType> newValue) {
if (results.getValue() != newValue) {
results.setValue(newValue);
}
}
// Called to save the result of the API response into the database.
#WorkerThread
protected abstract void saveCallResult(#NonNull RequestType item);
// Called with the data in the database to decide whether to fetch
// potentially updated data from the network.
#MainThread
protected abstract boolean shouldFetch(#Nullable ResultType data);
// Called to get the cached data from the database.
#NonNull
#MainThread
protected abstract LiveData<ResultType> loadFromDb();
// Called to create the API call.
#NonNull
#MainThread
protected abstract LiveData<ApiResponse<RequestType>> createCall();
// Returns a LiveData object that represents the resource that's implemented
// in the base class.
public final LiveData<Resource<ResultType>> getAsLiveData() {
return results;
}
}
my Repository looks like this
#Singleton
public class GithubRepository {
private GithubDao githubDao;
private GithubTrendingApiService githubApiService;
public GithubRepository(GithubDao githubDao, GithubTrendingApiService githubApiService) {
this.githubDao = githubDao;
this.githubApiService = githubApiService;
}
public LiveData<Resource<List<GithubEntity>>> getRepositories() {
return new NetworkBoundResource<List<GithubEntity>, GithubApiResponse>(AppExecutors.getInstance()) {
#Override
protected void saveCallResult(#NonNull GithubApiResponse item) {
List<GithubEntity> repositories = item.getItems();
githubDao.insertRepositories(repositories);
}
#Override
protected boolean shouldFetch(#Nullable List<GithubEntity> data) {
// Timber.d("shouldFetch: repo: " + data.toString());
// int currentTime = (int) (System.currentTimeMillis() / 1000);
// Timber.d("shouldFetch: current time: " + currentTime);
// int lastRefresh = data.getTimestamp();
// Timber.d("shouldFetch: last refresh: " + lastRefresh);
// Timber.d("shouldFetch: it's been " + ((currentTime - lastRefresh) / 60 / 60 / 24) +
// " days since this recipe was refreshed. 30 days must elapse before refreshing. ");
// if ((currentTime - data.getTimestamp()) >= Constants.RECIPE_REFRESH_TIME) {
// Timber.d("shouldFetch: SHOULD REFRESH RECIPE?! " + true);
// return true;
// }
// Timber.d("shouldFetch: SHOULD REFRESH RECIPE?! " + false);
return true;
}
#NonNull
#Override
protected LiveData<List<GithubEntity>> loadFromDb() {
return githubDao.getTrendingRepository();
}
#NonNull
#Override
protected LiveData<ApiResponse<GithubApiResponse>> createCall() {
return githubApiService.fetchTrendingRepositories();
}
}.getAsLiveData();
}
}
Can anyone tell me whats I am doing wrong because I am getting an API error? somehow I am not able to get the correct data that's why the database is also not filling up
my GithubAPi response class is this
public class GithubApiResponse {
public GithubApiResponse() {
this.items = new ArrayList<>();
}
public GithubApiResponse(List<GithubEntity> items) {
this.items = items;
}
private List<GithubEntity> items;
public List<GithubEntity> getItems() {
return items;
}
public void setItems(List<GithubEntity> items) {
this.items = items;
}
}
and the Entity class is this
#Entity
public class GithubEntity implements Parcelable {
public GithubEntity(#NonNull Long id, String author, String name, String avatar,
String url, String description, Integer stars, Integer forks, Integer currentPeriodStars, String language, String languageColor) {
this.id = id;
this.author = author;
this.name = name;
this.avatar = avatar;
this.url = url;
this.description = description;
this.stars = stars;
this.forks = forks;
this.currentPeriodStars = currentPeriodStars;
this.language = language;
this.languageColor = languageColor;
}
#NonNull
#PrimaryKey
private Long id;
#SerializedName("author")
#Expose
private String author;
#SerializedName("name")
#Expose
private String name;
#SerializedName("avatar")
#Expose
private String avatar;
#SerializedName("url")
#Expose
private String url;
#SerializedName("description")
#Expose
private String description;
#SerializedName("stars")
#Expose
private Integer stars;
#SerializedName("forks")
#Expose
private Integer forks;
#SerializedName("currentPeriodStars")
#Expose
private Integer currentPeriodStars;
#SerializedName("language")
#Expose
private String language;
#SerializedName("languageColor")
#Expose
private String languageColor;
#NonNull
public Long getId() {
return id;
}
public void setId(#NonNull Long id) {
this.id = id;
}
protected GithubEntity(Parcel in) {
author = in.readString();
name = in.readString();
avatar = in.readString();
url = in.readString();
description = in.readString();
if (in.readByte() == 0) {
stars = null;
} else {
stars = in.readInt();
}
if (in.readByte() == 0) {
forks = null;
} else {
forks = in.readInt();
}
if (in.readByte() == 0) {
currentPeriodStars = null;
} else {
currentPeriodStars = in.readInt();
}
language = in.readString();
languageColor = in.readString();
}
public static final Creator<GithubEntity> CREATOR = new Creator<GithubEntity>() {
#Override
public GithubEntity createFromParcel(Parcel in) {
return new GithubEntity(in);
}
#Override
public GithubEntity[] newArray(int size) {
return new GithubEntity[size];
}
};
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getStars() {
return stars;
}
public void setStars(Integer stars) {
this.stars = stars;
}
public Integer getForks() {
return forks;
}
public void setForks(Integer forks) {
this.forks = forks;
}
public Integer getCurrentPeriodStars() {
return currentPeriodStars;
}
public void setCurrentPeriodStars(Integer currentPeriodStars) {
this.currentPeriodStars = currentPeriodStars;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getLanguageColor() {
return languageColor;
}
public void setLanguageColor(String languageColor) {
this.languageColor = languageColor;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(author);
dest.writeString(name);
dest.writeString(avatar);
dest.writeString(url);
dest.writeString(description);
if (stars == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeInt(stars);
}
if (forks == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeInt(forks);
}
if (currentPeriodStars == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeInt(currentPeriodStars);
}
dest.writeString(language);
dest.writeString(languageColor);
}
}
can anyone guide me so that I can fix this issue? stuck here for 2 days
I have an issue with Json
when i use Gson everything is working properly, but when i use retrofit2 something is going wrong.
Class structure is exact same between retrofit and gson. difference is one additional interface and retrofit codes which is working in different cases
i uploaded every piece of code here.
String json2 = "{\"busList\":{\"bus\":[{\"forward\":\"true\",\"lat\": \"41.718979\",\"lon\": \"44.770645\",\"nextStopId\": \"1858\",\"routeNumber\": \"42\"},{\"forward\": \"true\",\"lat\": \"41.71735\",\"lon\": \"44.777855\",\"nextStopId\": \"924\",\"routeNumber\": \"42\" }]}}";
//project structure
//Class1
public class FatherBusList {
#SerializedName("busList")
private BusList busList;
public FatherBusList(BusList busList){
this.busList = busList;
}
public BusList getBusList() {
return busList;
}
}
//Class2
public class BusList {
#SerializedName("bus")
private List<Bus> buses;
public BusList (List<Bus> busses){
this.buses = busses;
}
public List<Bus> getBuses() {
return buses;
}
}
//Class3
public class Bus {
private String forward;
private String lat;
private String lon;
private String nextStopId;
private String routeNumber;
public Bus(String forward, String lat, String lon, String nextStopId, String routeNumber) {
this.forward = forward;
this.lat = lat;
this.lon = lon;
this.nextStopId = nextStopId;
this.routeNumber = routeNumber;
}
public String getForward() {
return forward;
}
public String getLat() {
return lat;
}
public String getLon() {
return lon;
}
public String getNextStopId() {
return nextStopId;
}
public String getRouteNumber() {
return routeNumber;
}
}
//retrofit2 code
//Interface for request
public interface TtcApi {
#GET("buses?routeNumber=37&forward=1&_dc=1556996108032")
Call<FatherBusList> getBus();
}
//MainActivivty
public class MainActivity extends AppCompatActivity {
private TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://transit.ttc.com.ge/pts-portal-services/")
.addConverterFactory(GsonConverterFactory.create())
.build();
TtcApi ttcApi = retrofit.create(TtcApi.class);
Call<FatherBusList> call = ttcApi.getBus();
call.enqueue(new Callback<FatherBusList>() {
#Override
public void onResponse(Call<FatherBusList> call, Response<FatherBusList> response) {
if (!response.isSuccessful()) {
textView.setText("Code: " + response.code());
return;
}
Toast.makeText(MainActivity.this, "Successful", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<FatherBusList> call, Throwable t) {
textView.setText(t.getMessage());
}
});
}
}
I expect to busList have 1 object and this object have arrayList
But its output is null.
{
"bus": [
{
"forward": "true",
"lat": "41.690926",
"lon": "44.816879",
"nextStopId": "1012",
"routeNumber": "37"
}
]
}
I request for your interface, return it.
Your need direct use 'BusList' class entity,don't use 'FatherBusList'
I finished turial from https://www.simplifiedcoding.net/retrofit-android-example/
And I wanted to create my own call, I wanted to get from API newest currency exchange, but I've got a problem (i think so this is it) with my model class. I've changed a bit code, and I've received data as "base" and "date", but whenewer I trying to get some currency value (let's take an BGN for example) program shows me always 0.0. How I may fix it? I right about that model class? Is there a problem?
Model
public class Model {
private String base,date;
private double BGN;
public Model(String base, String date, double BGN) {
this.base = base;
this.date = date;
this.BGN = BGN;
}
public String getBase() {
return base;
}
public String getDate() {
return date;
}
public double getBGN() {
return BGN;
}
}
Api (interface)
public interface Api {
String BASE_URL = "https://api.exchangeratesapi.io/";
#GET("latest")
Call<Model> getCurrency();
}
MainActivity
public class MainActivity extends AppCompatActivity {
private TextView textViewResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewResult = (TextView) findViewById(R.id.label);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Api.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
Api api = retrofit.create(Api.class);
Call<Model> call = api.getCurrency();
call.enqueue(new Callback<Model>() {
#Override
public void onResponse(Call<Model> call, Response<Model> response) {
List<Model> currencyList = Collections.singletonList(response.body());
for (Model currency : currencyList) {
String content = "";
content += "Base: " + currency.getBase() + "\n";
content += "Date: " + currency.getDate() + "\n";
content += "BGN: " + currency.getBGN() + "\n";
textViewResult.append(content);
}
}
#Override
public void onFailure(Call<Model> call, Throwable t) {
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
}
Api, that I trying to use https://exchangeratesapi.io/
To get all the data from retrofit, you need two POJO classes. They need to be like this where you add methods and variables for all the rates you need:
public class Model {
private String base;
private String date;
Rates RatesObject;
// Getter Methods
public String getBase() {
return base;
}
public String getDate() {
return date;
}
public Rates getRates() {
return RatesObject;
}
// Setter Methods
public void setBase(String base) {
this.base = base;
}
public void setDate(String date) {
this.date = date;
}
public void setRates(Rates ratesObject) {
this.RatesObject = ratesObject;
}
}
public class Rates {
private float CAD;
private float CHF;
private float GBP;
private float SEK;
private float EUR;
private float USD;
// Getter Methods
public float getCAD() {
return CAD;
}
public float getCHF() {
return CHF;
}
public float getGBP() {
return GBP;
}
public float getSEK() {
return SEK;
}
public float getEUR() {
return EUR;
}
public float getUSD() {
return USD;
}
// Setter Methods
public void setCAD(float CAD) {
this.CAD = CAD;
}
public void setCHF(float CHF) {
this.CHF = CHF;
}
public void setGBP(float GBP) {
this.GBP = GBP;
}
public void setSEK(float SEK) {
this.SEK = SEK;
}
public void setEUR(float EUR) {
this.EUR = EUR;
}
public void setUSD(float USD) {
this.USD = USD;
}
}
I'm trying to use New York Times API with Retrofit using Observable. But I'm getting this error when trying to use datas.
Can someone help me see where I'm wrong, please ?
Here is my ApiServices interface:
#GET("svc/topstories/v2/home.json?api-key=HiddenApiKeyJustForThisMessage")
Observable<TopStoryResult> getTopStories();
#GET("svc/topstories/v2/home.json?api-key=HiddenApiKeyJustForThisMessage")
Observable<List<NewsItem>> getResults();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.nytimes.com/")
.addConverterFactory(GsonConverterFactory.create(new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
Here is my ApiStreams class
public static Observable<TopStoryResult> streamFetchTopStories(){
ApiServices mApiServices = ApiServices.retrofit.create(ApiServices.class);
return mApiServices.getTopStories()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.timeout(10, TimeUnit.SECONDS);
}
public static Observable<List<NewsItem>> streamFetchNews(){
ApiServices mApiServices = ApiServices.retrofit.create(ApiServices.class);
return mApiServices.getResults()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.timeout(10, TimeUnit.SECONDS);
}
And this is what I'm trying to do in my MainActivity. For now I just want to display in a TextView the list of each Title...
//------------------------
// Update UI
//------------------------
private void updateUIWhenStartingHttpRequest() {
this.textView.setText("Downloading...");
}
private void updateUIWhenStopingHttpRequest(String response) {
this.textView.setText(response);
}
//------------------------
// Rx Java
//------------------------
private void executeRequestWithRetrofit(){
this.updateUIWhenStartingHttpRequest();
this.disposable = ApiStreams.streamFetchNews()
.subscribeWith(new DisposableObserver<List<NewsItem>>(){
#Override
public void onNext(List<NewsItem> topStories) {
Log.e("TAG", "On Next");
updateUIWithResult(topStories);
}
#Override
public void onError(Throwable e) {
Log.e("ERROR", Log.getStackTraceString(e));
}
#Override
public void onComplete() {
Log.e("TAG", "On Complete !");
}
});
}
private void updateUIWithResult(List<NewsItem> newsItemList){
StringBuilder mStringBuilder = new StringBuilder();
for (NewsItem news : newsItemList){
Log.e("TAG", "UPDATE UI" + news.getTitle());
mStringBuilder.append("- " + news.getTitle() + "\n");
}
updateUIWhenStopingHttpRequest(mStringBuilder.toString());
}
[EDIT]
There are my two models for TopStories and NewsItem
TopStories:
private String status;
private String copyright;
private String section;
private String lastUpdated;
private Integer numResults;
private List<NewsItem> results = null;
public String getStatus() {return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getCopyright() {
return copyright;
}
public void setCopyright(String copyright) {
this.copyright = copyright;
}
public String getSection() {
return section;
}
public void setSection(String section) {
this.section = section;
}
public String getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(String lastUpdated) {
this.lastUpdated = lastUpdated;
}
public Integer getNumResults() {
return numResults;
}
public void setNumResults(Integer numResults) {
this.numResults = numResults;
}
public List<NewsItem> getResults() {
return results;
}
public void setResults(List<NewsItem> results) {
this.results = results;
}
NewsItem:
private String section;
private String subsection;
private String title;
private String url;
private String byline;
private String updated_date;
private String created_date;
private String published_date;
private String material_type_facet;
private String kicker;
#SerializedName("abstract")
private String abstract_string;
private List<Multimedia> multimedia;
private transient String des_facet;
private transient String org_facet;
private transient String per_facet;
private transient String geo_facet;
public NewsItem() {
}
public NewsItem(String url) {
this.url = url;
}
public NewsItem(String section, String subsection, String title, String url, String byline, String updated_date, String created_date, String published_date, String material_type_facet, String kicker) {
this.section = section;
this.subsection = subsection;
this.title = title;
this.url = url;
this.byline = byline;
this.updated_date = updated_date;
this.created_date = created_date;
this.published_date = published_date;
this.material_type_facet = material_type_facet;
this.kicker = kicker;
}
public String getSection() {
return section;
}
public void setSection(String section) {
this.section = section;
}
public String getSubsection() {
return subsection;
}
public void setSubsection(String subsection) {
this.subsection = subsection;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getByline() {
return byline;
}
public void setByline(String byline) {
this.byline = byline;
}
public String getUpdated_date() {
return updated_date;
}
public void setUpdated_date(String updated_date) {
this.updated_date = updated_date;
}
public String getCreated_date() {
return created_date;
}
public void setCreated_date(String created_date) {
this.created_date = created_date;
}
public String getPublished_date() {
return published_date;
}
public void setPublished_date(String published_date) {
this.published_date = published_date;
}
public String getMaterial_type_facet() {
return material_type_facet;
}
public void setMaterial_type_facet(String material_type_facet) {
this.material_type_facet = material_type_facet;
}
public String getKicker() {
return kicker;
}
public void setKicker(String kicker) {
this.kicker = kicker;
}
public String getAbstract() {
return abstract_string;
}
public void setAbstract(String abstract_string) {
this.abstract_string = abstract_string;
}
public List<Multimedia> getMultimedia() {
return multimedia;
}
public void setMultimedia(List<Multimedia> multimedia) {
this.multimedia = multimedia;
}
public String getDes_facet() {
return des_facet;
}
public void setDes_facet(String des_facet) {
this.des_facet = des_facet;
}
public String getOrg_facet() {
return org_facet;
}
public void setOrg_facet(String org_facet) {
this.org_facet = org_facet;
}
public String getPer_facet() {
return per_facet;
}
public void setPer_facet(String per_facet) {
this.per_facet = per_facet;
}
public String getGeo_facet() {
return geo_facet;
}
public void setGeo_facet(String geo_facet) {
this.geo_facet = geo_facet;
}
Here is what the JSON looks like:
JSON
First when I tried this one with Github user API, it works fine. But I can't figure out where I'm wrong there...
Is anybody can help me please ?
Thanks a lot !
Expected BEGIN_ARRAY but was BEGIN_OBJECT
this means you are trying to a get a JSON Array as a List in JAVA but the api sent you a JSON OBJECT. So I cannot gather enough information but if I have to guess you should change this
#GET("svc/topstories/v2/home.json?api-key=HiddenApiKeyJustForThisMessage")
Observable<List<NewsItem>> getResults();
to
#GET("svc/topstories/v2/home.json?api-key=HiddenApiKeyJustForThisMessage")
Observable<NewsItemObject> getResults();
NewsItemObject is the Class that wraps NewsItem
In your ApiServices interface you expect that getResults() returns Observable<List<NewsItem>>. Based on JSON you getting back this is not gonna work, because your root JSON element is Object, not an Array.
You have to create new wrapper Class (ResultsWrapper) with "results" field type of List<NewsItem>. Your method in ApiServices interface will then be:
#GET("svc/topstories/v2/home.json?api-key=HiddenApiKeyJustForThisMessage")
Observable<ResultsWrapper> getResults();
That is what "Expected BEGIN_ARRAY but was BEGIN_OBJECT" says to you.
I want to get data from the server (https://data.egov.kz/api/v2/zheke_zhane_zandy_tulgalardy_k1/v6?pretty) as an array of json objects. But I get this Log:
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
I am using Retrofit2 and here my code:
MainActivity.java
public class MainActivity extends AppCompatActivity
implements GetAdmissionSchedule.GetAdmissionScheduleInterface {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GetAdmissionSchedule getAdmissionSchedule = new GetAdmissionSchedule(this);
getAdmissionSchedule.getAdmissionScheduleList();
}
#Override
public void getAdmissionSchedule(List<AdmissionSchedule> admissionScheduleList) {
// here i get my data
}
}
GetAdmissionSchedule.java
public class GetAdmissionSchedule {
private GetAdmissionScheduleInterface getAdmissionScheduleInterface;
public GetAdmissionSchedule(GetAdmissionScheduleInterface getAdmissionScheduleInterface) {
this.getAdmissionScheduleInterface = getAdmissionScheduleInterface;
}
public interface GetAdmissionScheduleInterface {
void getAdmissionSchedule(List<AdmissionSchedule> admissionScheduleList);
}
public void getAdmissionScheduleList() {
DataEgovApi service = DataEgovBaseURL.getRetrofit();
Call<List<AdmissionSchedule>> call = service.getAdmissionScheduleList();
call.enqueue(new Callback<List<AdmissionSchedule>>() {
#Override
public void onResponse(Call<List<AdmissionSchedule>> call, Response<List<AdmissionSchedule>> response) {
Log.d("MyLogs", "MVD: getAdmissionScheduleList " + response.code());
getAdmissionScheduleInterface.getAdmissionSchedule(response.body());
}
#Override
public void onFailure(Call<List<AdmissionSchedule>> call, Throwable t) {
Log.d("MyLogs", "MVD: getAdmissionScheduleList " + t.getLocalizedMessage());
getAdmissionScheduleInterface.getAdmissionSchedule(null);
}
});
}
}
DataEgovBaseURL.java
public class DataEgovBaseURL {
private static final String BASE_URL = "https://data.egov.kz/";
private static Retrofit retrofit = null;
public static DataEgovApi getRetrofit() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit.create(DataEgovApi.class);
}
}
DataEgovApi.java
public interface DataEgovApi {
#GET("api/v2/zheke_zhane_zandy_tulgalardy_k1/v6?pretty")
Call<List<AdmissionSchedule>> getAdmissionScheduleList();
}
AdmissionSchedule.java (My POJO class)
public class AdmissionSchedule {
#SerializedName("id")
#Expose
private String id;
#SerializedName("vremia")
#Expose
private String vremia;
#SerializedName("adres_ru")
#Expose
private String adresRu;
#SerializedName("doljnost_ru")
#Expose
private String doljnostRu;
#SerializedName("name_ru")
#Expose
private String nameRu;
#SerializedName("data")
#Expose
private String data;
#SerializedName("adres_kz")
#Expose
private String adresKz;
#SerializedName("doljnost_kz")
#Expose
private String doljnostKz;
#SerializedName("name_kz")
#Expose
private String nameKz;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getVremia() {
return vremia;
}
public void setVremia(String vremia) {
this.vremia = vremia;
}
public String getAdresRu() {
return adresRu;
}
public void setAdresRu(String adresRu) {
this.adresRu = adresRu;
}
public String getDoljnostRu() {
return doljnostRu;
}
public void setDoljnostRu(String doljnostRu) {
this.doljnostRu = doljnostRu;
}
public String getNameRu() {
return nameRu;
}
public void setNameRu(String nameRu) {
this.nameRu = nameRu;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String getAdresKz() {
return adresKz;
}
public void setAdresKz(String adresKz) {
this.adresKz = adresKz;
}
public String getDoljnostKz() {
return doljnostKz;
}
public void setDoljnostKz(String doljnostKz) {
this.doljnostKz = doljnostKz;
}
public String getNameKz() {
return nameKz;
}
public void setNameKz(String nameKz) {
this.nameKz = nameKz;
}
}
You server url is https and certificate is already not valid.
Change https to http and it will work.
Else you can install valid SSL certificate on the server.