I saw this issue many times, but still can't understand. It looks like I send request on site and it's body isn't correct. But why? May be I don't understand clearly how retrofit works, but do not I just collect a link for the request and wait for the answer from the server?
Here is the link: here
An interface with request
public interface NService {
#GET("/computers?p=2")
Call<Model> getItems();
}
and class with base URL
public class APIUtils {
public static final String BASE_URL = "http://testwork.nsd.naumen.ru/rest/";
public static NService getMService() {
return RetrofitClient.getClient(BASE_URL).create(NService.class);
}
}
retrofit build class
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseURL) {
if (retrofit==null) {
Gson gson = new GsonBuilder()
.setLenient()
.create();
retrofit = new Retrofit.Builder()
.baseUrl(baseURL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
return retrofit;
}
}
JSON were parsed though this
and MainActivity is:
public class MainActivity extends AppCompatActivity {
private List<Item> responseModel;
private NService mService;
private TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("testcrap", "before loading set");
setContentView(R.layout.activity_main);
mService = APIUtils.getMService(); // Строим retrofit объект, собираем ссылку
Log.d("testcrap", "before loading");
loadSomeCrap();
Log.d("testcrap", "after loading");
}
public void loadSomeCrap() {
Log.d("testcrap", "started parsing");
mService.getItems().enqueue(new Callback<Model>() {
#Override
public void onResponse(Call<Model> call, Response<Model> response) {
Log.d("testcrap", "started onResponse");
if(response.isSuccessful()) {
Log.d("testcrap", "posts loaded from API");
}else {
Log.d("testcrap", "posts not loaded from API");
}
}
#Override
public void onFailure(Call<Model> call, Throwable t) {
//showErrorMes sage();
Log.d("testcrap", t.toString());
}
});
}
}
Log:
before loading set
before loading
started parsing
after loading
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 13 column 1 path $
So, if it's wrong request, what should I change for normal work?
Make these changes ..
BASE_URL = "http://testwork.nsd.naumen.ru/"
And then on interface ..
#GET("rest/computers?p=2")
.............
Your API or JSON response is returning JSON_OBJECT but you are getting it in String so this JsonSyntaxException is shown you. Try to fetch response in OBJECT.
Related
i am making login function in android using retrofit. I have created an endpoint for login validation, then I have tested it using Postman using raw (json) and it worked. But when I enter the endpoint into android using retrofit I get an error message like this:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 39 path $.message
can anyone help me?
So here my source:
ApiClient
public class ApiClient {
public static final String BASE_URL = "";
public static Retrofit retrofit;
public static Retrofit getRetrofit() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
AuthInterface
public interface AuthInterface {
#Headers("Content-Type: application/json")
#POST("auth/login")
Call<AuthPost> authPostCall(#Body String body);
}
AuthPost
public class AuthPost {
#SerializedName("status")
private String status;
#SerializedName("error_code")
private int error_code;
#SerializedName("message")
private String message;
#SerializedName("token")
private String token;
...getter and setter
}
LoginActivity
JSONObject payload = new JSONObject();
try {
payload.put("login_username", loginUsernameText);
payload.put("login_password", loginPasswordText);
} catch (JSONException e) {
e.printStackTrace();
}
Call<AuthPost> authPostCall = authInterface.authPostCall(payload.toString());
authPostCall.enqueue(new Callback<AuthPost>() {
#Override
public void onResponse(Call<AuthPost> call, Response<AuthPost> response) {
if (response.code() == 200) {
} else {
}
}
#Override
public void onFailure(Call<AuthPost> call, Throwable t) {
t.printStackTrace();
}
});
Are you sure about:
#SerializedName("message")
private String message;
Usually this error appears if this field is Object.
Does your JSON looks like
"message":"test"
or something like:
"message":{"field":"value"}
If it is the second variant so you should simple change the field to necessary type.
i'm beginner of java, and i need some help, I had see many posts about, but not work they issues
I had json object from url like that
{
'history':[{
'id':2,
'name':'irine'},
{
'id':3,
'name':'karine'
}]
}
but i need
[
{
'id':2,
'name':'irine'},
{
'id':3,
'name':'karine'}
]
my ApiClient.java
public class ApiClient {
public static final String BASE_URL = "http://192.168.150.100";
public static Retrofit retrofit;
public static Retrofit getApiClient(final String authToken){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request.Builder ongoing = chain.request().newBuilder();
ongoing.addHeader("Accept", "application/json;");
ongoing.addHeader("Authorization", authToken);
return chain.proceed(ongoing.build());
}
})//.addInterceptor(interceptor)
.build();
if (retrofit==null){
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
getting response from url
call.enqueue(new Callback<List<Contact>>() {
#Override
public void onResponse(Call<List<Contact>> call, Response<List<Contact>> response) {
progressBar.setVisibility(View.GONE);
contacts=response.body();
if(contacts==null)
Snackbar.make(findViewById(R.id.lt_search), "Nothing found",Snackbar.LENGTH_LONG).show();
adapter = new Adapter(contacts, SearchActivity.this);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<List<Contact>> call, Throwable t) {
progressBar.setVisibility(View.GONE);
Log.d("GHaa ka sk aksjdk j", contacts.toString());
Toast.makeText(SearchActivity.this, "Error\n"+t.toString(), Toast.LENGTH_LONG).show();
}
});
how to convert object to array or clear word 'history' from object?
You have provided the wrong class for API response.You are getting the list object against a string key which might change(not known). So, you will have to use HashMap. The API response is in the form of HashMap<String,<List<Contact>>>. So in the code, you will have to use Callback<HashMap<String,List<Contact>>>() instead of Callback<List<Contact>>().
Then from the HashMap you can easily get the list using hashmap.get('key'). In your case, hashmap.get('history').
The right way to reselve this problem:
call.enqueue(new Callback<HashMap<String,List<Contact>>>() {
#Override
public void onResponse(Call<HashMap<String, List<Contact>>> call, Response<HashMap<String, List<Contact>>> response) {
HashMap<String, List<Contact>> history=response.body();
contacts= new ArrayList<>(history.get("hitory"));
Log.d(TAG, contacts.toString());
progressBar.setVisibility(View.GONE);
//contacts=response.toString();
Log.d(TAG,response.toString());
if(contacts==null)
Snackbar.make(findViewById(R.id.lt_search), "Nothing found",Snackbar.LENGTH_LONG).show();
adapter = new Adapter(contacts, SearchActivity.this);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<HashMap<String, List<Contact>>> call, Throwable t) {
progressBar.setVisibility(View.GONE);
//Log.d("GHaa ka sk aksjdk j", contacts.toString());
Toast.makeText(SearchActivity.this, "Error\n"+t.toString(), Toast.LENGTH_LONG).show();
}
});
I am new to Android and I want to make an application based on REST API.
So I search and found the Retrofit 2.
I used a sample of retrofit that I found in Github to learn how it works.
This files are my Java classes :
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textv = findViewById(R.id.textv);
GitHubClient gitHubClient;
gitHubClient = ServiceGenerator.createService(GitHubClient.class);
final Call<GitHubUser> call = gitHubClient.getFeed("google");
call.enqueue(new Callback<GitHubUser>() {
#Override
public void onResponse(Call<GitHubUser> call, Response<GitHubUser> response) {
GitHubUser gitModel = response.body();
if (gitModel != null) {
textv.setText(getString(R.string.main_response_text,
gitModel.getName(),
gitModel.getBlog()));
} else {
textv.setText("user doesn't exist");
}
}
#Override
public void onFailure(Call<GitHubUser> call, Throwable t) {
textv.setText(t.getMessage());
}
});
}
}
GithubClient.java
public interface GitHubClient {
#GET("users/{user}")
Call<GitHubUser> getFeed(#Path("user") String user);
}
ServiceGenerator.java
public class ServiceGenerator {
public static final String API_BASE_URL = "https://api.github.com/";
private static HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
private static Interceptor logging = interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
private static OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(logging)
.build();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient).build();
return retrofit.create(serviceClass);
}
}
GithubUser.java
public class GitHubUser {
private String name;
private String blog;
public String getName() {
return name;
}
public String getBlog() {
return blog;
}
}
JSON code from Github
{
...
"name": "Google",
"blog": "https://opensource.google.com/",
...
}
I want to get the name and blog URL
And when I run the program the output is:
javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb8952b10: Failure in SSL library, usually a protocol error
error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version(external/openssl/ssl/s23_clnt.c:741 0x83bc3770:0x00000000)
What's the problem and how can I fix?
The first step here would be to understand the error.
Try printing the error from your onFailure method like this:
#Override
public void onFailure(Call<GitHubUser> call, Throwable t) {
textv.setText("unknown error"); // can also do textv.setText(t.getMessage()) to display error reason
t.printStackTrace();
}
You should get in your logcat some more useful information about what went wrong, it will be easier to figure out how to solve it after that
Also have you added internet access permission in your manifest?
SSL Exception comes when SSL Certificate issue . You need to add ssl certificate to server side.
Have you tried
android:networkSecurityConfig="#xml/network_security_config"
in your manifest tag
also put the following file in res >> xml >>
network_security_config.xml
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">static.food2fork.com</domain>
</domain-config>
</network-security-config>
Can anyone please give me some example how we can use protobuf in retrofit - I tried but its failed with some error , let me give you a sample of my implementation on that.
I hope you guys will help me.
ApiInterface.java
public interface ApiInterface {
#GET
Call<CommonProto.Country> makeGetRequest(#Url String url);
}
ApiClient.java
public class ApiClient {
public static final String BASE_URL = "**************************";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(Proto3ConverterFactory.create())
.build();
}
return retrofit;
}
}
MainActivity.java
ApiInterface apiService =
ApiClient.getClient().create(ApiInterface.class);
Call<CommonProto.Country> call = apiService.makeGetRequest("Services/CountryServices/GetAllCountry");
call.enqueue(new Callback<CommonProto.Country>() {
#Override
public void onResponse(Call<CommonProto.Country> call, Response<CommonProto.Country> response) {
String bodyString = null;
try {
Log.e("RETROFIT ::::::: ", String.valueOf(response.body())+"TEST");
} catch (Exception e) {
Log.e("RETROFIT ERROR ::::::: ", e.getMessage()+"TEST");
e.printStackTrace();
}
}
#Override
public void onFailure(Call<CommonProto.Country> call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
}
);
when i run this way i got the error
java.lang.RuntimeException: com.google.protobuf.InvalidProtocolBufferException: Protocol message tag had invalid wire type.
my Proto.java file and also have Proto.proto file both are here in this link,
https://drive.google.com/folderview?id=0B4loQuzINvHCRUlNbk5LUXE1NXM&usp=sharing
Please let me know how to do this GET Req and also I was Struggling with POST Req.
you can create interface like this
public interface LoginInterface {
#FormUrlEncoded
#POST("url goes here")
Call<LoginResponseData> getUserLoginDeatail(#FieldMap Map<String, String> fields);
}
make an instance of retro file and call interface method something like this
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("base url")
.build();
webApis = retrofit.create(WebApis.class);
Call<LoginResponseData> call = webApis.getCurrentRide(keyValue);
call.enqueue(new Callback<LoginResponseData>() {
#Override
public void onResponse(Call<LoginResponseData> call, Response<LoginResponseData> response) {
try {
} catch (Exception e) {
// customizedToast.showToast(context.getResources().getString(
// R.string.exception));
e.printStackTrace();
}
}
#Override
public void onFailure(Call<LoginResponseData> call, Throwable t) {
}
});
for protocol buffer you can find a reference here
I have JSON file like this http://androiddocs.ru/api/friends.json
{
"data":"dbfriends",
"friends": [{"id":"1","name":"Andrew","city":"Moscow","contacts":{"mobile":"+7 0000000","email":"andrew#androiddocs.ru","skype":"andrew"}}, {"id":"2","name":"Ivan","city":"Kiev","contacts":{"mobile":"+38 0000000","email":"ivan#androiddocs.ru","skype":"ivan"}}]
}
my retrofit interface
public interface Friends_API {
String BASE_URL = " http://androiddocs.ru/api/";
#GET("friends.json") Call<Friends> getFriends();
class Factory {
private static Friends_API service;
public static Friends_API getInstance(){
if (service == null) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build();
service = retrofit.create(Friends_API.class);
return service;
} else {
return service;
}
}
}
}
POJO file generated by http://www.jsonschema2pojo.org/
and my code to get data value and:
Friends_API.Factory.getInstance().getFriends().enqueue(new Callback<Friends>() {
#Override
public void onResponse(Call<Friends> call, Response<Friends> response) {
String getData = response.body().getData();
}
#Override
public void onFailure(Call<Friends> call, Throwable t) {
}
}
i can't understood how i can get value: id, name, city...
thanks for help!
You can get the data from retrieved response using:
Friends friends = response.body();
And then you can retrieve the List<Friend> using friends.getFriends() object. Now you can iterate through this list of friends and can get id,name, city or contact details.