I was testing the API in the Retrofit for first time, I was putting the code that they were showing but I don't know why my code doesn't work
it just shows that I am receiving the null value;
I was learning to implement the Retrofit library in my android app . so i was following some tutorial and i was following the code but don't know why i am getting this error
i tried to solve the error by changing the url but the response is the same it shows the null.
Please help me out
public class Todo {
private int userId;
private int id;
private String todo;
private boolean completed;
public int getUserId() {
return userId;
}
public int getId() {
return id;
}
public String getTitle() {
return todo;
}
public boolean isCompleted() {
return completed;
}
}
public interface ApiInterface {
#GET("/todo/{id}")
Call<Todo> getTodo(#Path("id") int id);
}
public class ApiClient {
private static final String BASE_URL ="https://dummyjson.com";
private static Retrofit retrofit= null;
public static Retrofit getclient(){
if(retrofit == null){
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
public class MainActivity extends AppCompatActivity {
TextView hello;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
hello= findViewById(R.id.textview);
ApiInterface apiInterface = ApiClient.getclient().create(ApiInterface.class);
Call<Todo> call =apiInterface.getTodo(1);
call.enqueue(new Callback<Todo>() {
#Override
public void onResponse(Call<Todo> call, Response<Todo> response) {
Log.e("info","onResponse"+response.body());
#Override
public void onFailure(Call<Todo> call, Throwable t) {
Log.e("info","onFailure" + t.getLocalizedMessage());
}
});
}
}
You are missing the plural 's' in todo. Change your path to #GET("/todos/{id}")
Related
I want to post this object
public class EditTask {
#SerializedName("id")
private int id;
#SerializedName("active")
private int active;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getActive() {
return active;
}
public void setActive(int active) {
this.active = active;
}
public EditTask(int id, int active) {
this.id = id;
this.active = active;
}
}
My api:
public interface TaskApi {
#GET("func.php?load")
Call<List<Task» getTaskList();
#FormUrlEncoded
#POST("func.php?add")
Call<String> addTask(#Field("name") String name);
#POST("func.php?edit")
Call<EditTask> editTask(#Body EditTask editTask);
}
My Repositary:
public class TaskRepository {
private static TaskRepository taskRepository;
public static TaskRepository getInstance() {
if (taskRepository == null) {
taskRepository = new TaskRepository();
}
return taskRepository;
}
private TaskApi taskApi;
public TaskRepository() {
taskApi = RetrofitService.createService(TaskApi.class);
}
public void editTask(int id, int active) {
EditTask editTask = new EditTask(id, active);
taskApi.editTask(editTask).enqueue(new Callback<EditTask>() {
#Override
public void onResponse(Call<EditTask> call, Response<EditTask> response) {
Log.i("Artemy", "cool");
}
#Override
public void onFailure(Call<EditTask> all, Throwable t) {
Log.i("Artemy", "notcool");
}
});
}
}
My RetrofitService:
public class RetrofitService {
private static Gson gson = new GsonBuilder()
.setLenient()
.create();
private static Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://loginov.tech/android/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
public static <S> S createService(Class<S> serviceClass) {
return retrofit.create(serviceClass);
}
}
My ViewModel:
public class TaskViewModel extends ViewModel {
private MutableLiveData<List<Task»mutableLiveData;
private TaskRepository taskRepository;
public void init() {
if (mutableLiveData != null) {
return;
}
taskRepository = TaskRepository.getInstance();
mutableLiveData = taskRepository.getTasks();
}
public LiveData<List<Task»
getTaskRepository() {
return mutableLiveData;
}
public void addTask(String name) {
taskRepository.addTask(name);
}
public void editTask(int id, int active) {
taskRepository.editTask(id, active);
}
}
Main Activity:
public class TaskViewModel extends ViewModel {
private MutableLiveData<List<Task»mutableLiveData;
private TaskRepository taskRepository;
public void init() {
if (mutableLiveData != null) {
return;
}
taskRepository = TaskRepository.getInstance();
mutableLiveData = taskRepository.getTasks();
}
public LiveData<List<Task»
getTaskRepository() {
return mutableLiveData;
}
public void addTask(String name) {
taskRepository.addTask(name);
}
public void editTask(int id, int active) {
taskRepository.editTask(id, active);
}
}
I must create post request to server and post int id and int active parameters.But i always get error :java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 2 column 1 path
I tried to post List of EditTasks also i tried to make post with #FormUrlEncoded it did not help.
I'm making a response to this Google Books API URL
I have an Retrofit request:'
public interface BookApiService {
#GET("/books/v1/volumes")
Call<Books> getBooks(#Query("q") String query);
}
And have an Entity classes
Books.java
public class Books {
#SerializedName("items")
#Expose
private List<Book> items;
public List<Book> getItems() {
return items;
}
}
and Book.java
public class Book {
#SerializedName("title")
#Expose
private String mTitle;
public String getTitle() {
return mTitle;
}
}
Request is working correct, i mean no errors with connection, and retrofit returns onResponse, not onFailure.
But my String "title" is null. How can i get this. Please check JSON response by link above.
UPDATE:
Retrofit call:
public class BookService{
private static final String BASE_URL = "https://www.googleapis.com/";
private BookApiService mApiService;
private BookCallback mListener;
public BookService(BookCallback listener){
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build();
mApiService = retrofit.create(BookApiService.class);
mListener = listener;
}
public void getBooks(String query){
Call<Books> call = mApiService.getBooks(query);
call.enqueue(new Callback<Books>() {
#Override
public void onResponse(Call<Books> call, Response<Books> response) {
mListener.notifyDataReceived(response.body());
}
#Override
public void onFailure(Call<Books> call, Throwable t) {
mListener.notifyErrorReceived(t);
}
});
}
public interface BookCallback{
void notifyDataReceived(Books books);
void notifyErrorReceived(Throwable error);
}
BookCallback listener is my MainActivity:
When i check Logs, there is
"SUCCESS" "TITLE 1 null"
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.addItemDecoration(new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL));
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
new BookService(this).getBooks("android");
}
#Override
public void notifyDataReceived(Books books) {
if(books.getItems() != null) {
List<Book> items = books.getItems();
Log.d(TAG, "Success");
Log.d(TAG, "TITLE 1" + items.get(0).getTitle());
setupAdapter(items);
}
}
You can request the JSON directly in your browser here. Looking closely at this data, you will see that items[0] doesn't have a property title. Instead, there is a property volumeInfo that contains title. Your Retrofit entity class needs to correctly navigate to that property in order to get the data you need.
I'm making requets to Google Books API with Retrofit2 and use GSON converter, but have an error
ErrorExpected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path
$
API URL to JSON
This is my
BookService.java
public class BookService{
private static final String BASE_URL = "https://www.googleapis.com/";
private BookApiService mApiService;
private BookCallback mListener;
public BookService(BookCallback listener){
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build();
mApiService = retrofit.create(BookApiService.class);
mListener = listener;
}
public void getBooks(String query){
final ApiResponse apiResponse = new ApiResponse();
Call<List<Book>> call = mApiService.getBooks(query);
call.enqueue(new Callback<List<Book>>() {
#Override
public void onResponse(Call<List<Book>> call, Response<List<Book>> response) {
apiResponse.setBooks(response.body());
mListener.notifyDataReceived(apiResponse);
}
#Override
public void onFailure(Call<List<Book>> call, Throwable t) {
apiResponse.setError(t);
mListener.notifyDataReceived(apiResponse);
}
});
}
public interface BookCallback{
void notifyDataReceived(ApiResponse apiResponse);
}
}
and my Interface
BookApiService.java
public interface BookApiService {
#GET("/books/v1/volumes")
Call<List<Book>> getBooks(#Query("q") String query);
}
Then making request from MainActivity.java that implements BookCallback
public class MainActivity extends AppCompatActivity implements BookService.BookCallback {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main)
new BookService(this).getBooks("android");
}
}
Your response is not an array. its an object with array in it.
For fix this you must create other response class like BookResponse
BookResponse.java
public class BookResponse{
#SerializedName("kind")
private Sting kind;
#SerializedName("totalItems")
private Int totalItems;
#SerializedName("items")
private List<Book> items;
}
And change your interface like this
public interface BookApiService {
#GET("/books/v1/volumes")
Call<BookResponse> getBooks(#Query("q") String query);
}
The response you are having is not an array of Books, but it is an object, which perhaps is a response that has an array with books. So what the error says: Your JsonResponse is not starting with [] but is starting with {}
I'm trying to get data from web api but something is wrong and I can't figure it out.
My JSON looks like this
{
"partners":
[
"partner1",
"partner2",
"partner3",
... ,
"partner150"
]
}
I have Table partners (ActiveAndroid) in which I would like to save all partners from api.
#Table(name = "Partners")
public class Partners extends Model {
#Column(name = "Name")
String name;
public Partners() {}
public Partners(String name) {
this.name = name;
}
}
Here is my Pojo model class:
public class Partners extends ArrayList<String> {
#SerializedName("partners")
#Expose
public List<String> partners = new ArrayList<String>();
public List<String> getPartners() {
return partners;
}
public void setName(List<String> partners) {
this.partners = partners;
}
}
This is my interface
public interface APIService {
#GET("Partners")
Call<Partners> getPartners();
}
This is my APIHelper class
public class APIHelper {
public static final String PARTNERS_URL = "https://part-of-link.com/partners.json/";
public static APIService apiService;
public static APIService getApiService() {
if (apiService == null) {
Retrofit retrofit = new Retrofit.Builder().baseUrl(PARTNERS_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
apiService = retrofit.create(APIService.class);
}
return apiService;
}
}
And this is Fragment where I have an Button on which I would like to implement onClick method to get data from API and save it into Partners table.
public class DownloadMain extends Fragment implements Callback<Partners> {
private Button dloadPartners;
private Call<Partners> callPartners;
public static APIService apiService;
public DownloadMain() {}
public DownloadMain newInstance() { return new DownloadMain(); }
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.download_main, container, false);
dloadPartners = (Button) view.findViewById(R.id.downloadPartners);
dloadPartners.setOnClickListener(btnListener);
callPartners = APIHelper.getApiService().getPartners();
callPartners.enqueue(this);
return view;
}
Button.OnClickListener btnListener = (new View.OnClickListener() {
#Override
public void onClick(View v) {
APIHelper helper = new APIHelper();
apiService = helper.getApiService();
Call<Partners> call = apiService.getPartners();
call.enqueue(new Callback<Partners>() {
#Override
public void onResponse(Call<Partners> call, Response<Partners> response) {
APIHelper helper = new APIHelper();
helper.getApiService();
Call<Partners> call = apiService.getPartners();
call.enqueue(new Callback<Partners>() {
#Override
public void onResponse(Call<Partners> call, Response<Partners> response) {
List<String> partners = response.body().getPartners();
Log.d(TAG, "Number of partners received: " + partners.size());
/*if (response.body() != null) {
ArrayList<String> partnersList;
partnersList = response.body();
Log.d("DOWNLOAD", String.valueOf(partnersList));
}*/
}
#Override
public void onFailure(Call<Partners> call, Throwable t) {
Toast.makeText(getActivity(), "FAIL!!!", Toast.LENGTH_SHORT).show();
}
});
}
});
#Override
public void onResponse(Call<Partners> call, Response<Partners> response) {
}
#Override
public void onFailure(Call<Partners> call, Throwable t) {
}
}
And here is my problem. Everything works and there is no errors but when I click on button nothing happens.
So I presume I've made some mistake but I can't figure it out (First time doing with retrofit).
What I want on button click is to get all partners from web and save it into my Partners table.
Question: Could somebody guide me and tell me what is wrong and help me to fix this?
EDIT:
Button.OnClickListener btnListener = (new View.OnClickListener() {
#Override
public void onClick(View v) {
APIHelper helper = new APIHelper();
apiService = helper.getApiService();
Call<ArrayList<String>> call = null;
call.enqueue(new Callback<ArrayList<String>>() {
#Override
public void onResponse(Call<ArrayList<String>> call, Response<ArrayList<String>> response) {
ArrayList<String> partners = response.body();
Log.d(TAG, "Number of partners received: " + partners.size());
}
#Override
public void onFailure(Call<ArrayList<String>> call, Throwable t) {
Toast.makeText(getActivity(), "FAIL!!!", Toast.LENGTH_SHORT).show();
}
});
}
});
Error logs:
Error:(68, 60) error: is not abstract and does not
override abstract method
onResponse(Call>,Response>) in
Callback
Error:(72, 53) error: cannot find symbol method body()
Error:(69, 17) error: method does not override or implement a method
from a supertype
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
Compilation failed; see the compiler error output for details.
your problem is here in the onClick()
helper.getApiService();
you did not assign the service into the variable
change it to this:
apiService = helper.getApiService();
EDIT:
based on new updates i think you dont need to use a POJO
just use the following in your Call
Call<ArrayList<String>>
and to get response just use response.body() without .partners() .
try to replace it everywhere in your code and check
Based on your JSON response, your POJO class should be:
public class Partners {
private ArrayList<String> partners = new ArrayList<>(0);
// Get; Set methods //
}
Try putting this in your APIHelper class to get more information about what you are sending
public static APIService apiService;
//this http loggin interceptor allows you debug requests and responses
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
// set your desired log level
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
// add your other interceptors …
// add logging as last interceptor
httpClient.addInterceptor(logging); // <-- this is the important line!
public static APIService getApiService() {
if (apiService == null) {
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
}
return apiService;
}
Maybe you are sending information in a wrong way...
And remember that in server side you must decode the information that receive (with json_decode).
I am trying to implement RxJava and Retrofit2. But I am getting this error java.lang.IllegalArgumentException: Unable to create call adapter for rx.Observable
Here is my code :-
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bFetch = (Button) findViewById(R.id.button_fetch);
assert bFetch != null;
bFetch.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
GithubService service;
final Retrofit retrofit = new Retrofit.Builder()
.baseUrl(GithubService.SERVICE_ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.build();
service = retrofit.create(GithubService.class);
Observable<Github> observable = service.getUser("writingminds");
observable.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Github>() {
#Override
public final void onCompleted() {
// do nothing
}
#Override
public final void onError(Throwable e) {
Log.e("GithubDemo", e.getMessage());
}
#Override
public final void onNext(Github response) {
Log.e("---%s", response.getBlog());
Log.e("--%s", response.getLogin());
}
});
}
});
}
}
And here is my Interface GithubService
public interface GithubService {
String SERVICE_ENDPOINT = "https://api.github.com";
#GET("/users/{login}")
Observable<Github> getUser(#Path("login") String login);
}
Here is my model :
public class Github {
private String login;
private String blog;
private int public_repos;
public String getLogin() {
return login;
}
public String getBlog() {
return blog;
}
public int getPublicRepos() {
return public_repos;
}
}
Thank you in advance
you need to tell Retrofit, you want to use RxJava. You can do it using
addCallAdapterFactory(RxJavaCallAdapterFactory.create())
E.g
final Retrofit retrofit = new Retrofit.Builder()
.baseUrl(GithubService.SERVICE_ENDPOINT)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
you will have to add
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
to your build.gradle dependency list, if you didn't it already