Hello Im working in a test with Retrofit 2.0 and one of the test is making a resquest to a url that finish with .json:
Example: https://domain.com/contacts.json
baseURl: https://domain.com/
endPoint: /contacts.json
Which is a file, but I want to make a normal GET request and get the json inside directly
If you have control over your web server, you can customize it supports .json file as text/plain or application/json. Please see my following screenshot (I have done with IIS 7.5)
The following screenshot is a request using PostMan:
build.gradle file:
dependencies {
...
compile 'com.squareup.retrofit2:retrofit:2.0.1'
compile 'com.squareup.retrofit2:converter-gson:2.0.1'
}
WebAPIService.java:
public interface WebAPIService {
#GET("/files/jsonsample.json")
Call<JsonObject> readJson();
}
MainAcitivty.java:
Retrofit retrofit1 = new Retrofit.Builder()
.baseUrl("http://...")
.addConverterFactory(GsonConverterFactory.create())
.build();
WebAPIService service1 = retrofit1.create(WebAPIService.class);
Call<JsonObject> jsonCall = service1.readJson();
jsonCall.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
Log.i(LOG_TAG, response.body().toString());
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Log.e(LOG_TAG, t.toString());
}
});
Logcat:
04-15 15:31:31.943 5810-5810/com.example.asyncretrofit I/AsyncRetrofit: {"glossary":{"title":"example glossary","GlossDiv":{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}}}
Hello I found a solution to get the file using your code and it really works now but I haven't touch the MIME on the web server, I think I didn't have added the Converter in the code I guess. Thank you.
WebAPIService.java:
public interface WebAPIService {
#GET("/contacts.json")
Call<JsonObject> getContacts();
}
MainAcitivty.java:
Retrofit retrofit1 = new Retrofit.Builder()
.baseUrl(BuildConfig.API_ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.build();
WebAPIService service1 = retrofit1.create(WebAPIService.class);
Call<List<Contact>> jsonCall = service1.getContacts();
jsonCall.enqueue(new Callback<List<Contact>() {
#Override
public void onResponse(Call<List<Contact>> call, Response<List<Contact>> response) {
Log.i(LOG_TAG, response.body().toString());
}
#Override
public void onFailure(Call<List<Contact>> call, Throwable t) {
Log.e(LOG_TAG, t.toString());
}
});
Related
Actually i'm trying to post a text file to my server and i would be able to handle the error when i've sent the file but i didn't get the response (In case the file has been sent the network is gone down so the server received the file but the device don't know it)
Because for now i'm getting an issue because if i don't get the response when the device return online it send again the same file and i would prevent it.
Seems it's hidely retry to send the file on connection fail or something like that.
Here is my method which i use onClick to send the file:
public void sendPost() {
#SuppressLint({"SdCardPath", "DefaultLocale"}) final File file = new File("/data/data/com.example.igardini.visualposmobile/files/"+String.format("%03d", Integer.valueOf(nTerminalino))+"_"+nTavoli.getText().toString()+".txt");
final MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
final RequestBody fbody = RequestBody.create(MediaType.parse("text/*"), file);
builder.addFormDataPart(String.format("%03d", Integer.valueOf(nTerminalino))+"_"+nTavoli.getText().toString(), file.getName(),fbody);
final MultipartBody requestBody = builder.build();
final APIService apiService = ApiUtils.getAPIService(ipCASSA);
final Call<Void> calls = apiService.savePost(requestBody);
calls.enqueue(new Callback<Void>() {
#Override
public void onResponse(#NonNull Call<Void> call, #NonNull Response<Void> response) {
if (response.isSuccessful()) {
Log.i("RESPONSE: ", response.toString());
Print();
dialogLoading.dismiss();
Runtime.getRuntime().gc();
// checkFile task = new checkFile();
// task.execute();
}else {
Toast.makeText(pterm.this,"ERRORE",Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(#NonNull Call<Void> call, #NonNull Throwable t) {
if(t instanceof IOException) {
Log.e("TAG", t.toString());
MediaPlayer mpFound = MediaPlayer.create(pterm.this, R.raw.errorsound);
mpFound.start();
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
if (v.hasVibrator()) {
v.vibrate(6000);
}
new GlideToast.makeToast(pterm.this, "CONNESSIONE FALLITA!", GlideToast.LENGTHLONG, GlideToast.FAILTOAST).show();
dialogLoading.dismiss();
}
}
});
}
While here are my other useful classes:
class ApiUtils {
private ApiUtils() {}
static APIService getAPIService(String ipCASSA) {
String BASE_URL = "http://"+ipCASSA+"/web/";
final OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(10000, TimeUnit.MILLISECONDS)
.writeTimeout(10000, TimeUnit.MILLISECONDS)
.readTimeout(10000, TimeUnit.MILLISECONDS)
.retryOnConnectionFailure(false)
.build();
return RetrofitClient.getClient(BASE_URL,okHttpClient).create(APIService.class);
}
}
public interface APIService {
#POST("CART=PTERM")
Call<Void> savePost(#Body RequestBody text);
}
class RetrofitClient {
private static Retrofit retrofit = null;
static Retrofit getClient(String baseUrl, OkHttpClient okHttpClient) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
In that case I would add to file some sort of device generated random ID, and send it along with request.
On server side I would change logic to first try to locate file in DB using this ID, if there is none, store it and return status OK along with maybe server side id (might come handy later).
If there is file with ID provided on request, just return server side ID with status 200 - that way you will not store it twice.
You can even go further - if you have not stable connection (it seems like it from description) you could even make seperate REST call to check if file is on server side by generated id or checksum, and if not then start to send it - it will safe bandwitch.
It does not have to be generated ID - it can be checksum of a file for example. Whatever is easier for you.
For generating ID you could use Android's UUID
https://developer.android.com/reference/java/util/UUID
For checksum check this answer:
How to generate an MD5 checksum for a file in Android?
BTW - I would not do 10 seconds timeout limit - it is way too much, and user experience will be terrible
my python code in django is:
#csrf_exempt
def login(request):
data = {'a': '1'}
if request.method == 'POST':
form=login_form(request.POST)
if form.is_valid():
f = form.cleaned_data
if sign_in.objects.filter(username=f['user'], password=hashlib.md5(f['pas'].encode()).hexdigest()):
return JsonResponse(data)
and in android:
ApiInterface apiInterface = ApiClinet.GetClinet().create(ApiInterface.class);
Call<String> call = apiInterface.GetHome_call("x","y");
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
}
#Override
public void onFailure(Call<String> call, Throwable t) {
}
});
this code work in postman and recive:
{
"a": "1"
}
but when run in android. recive internal sever error!
and I work on localhost.
The Error must either be in your ApiClient Code or else check your #POST("") correctly , you need to put forward slash at it's end like this: #POST("login/").
Hope this helps,If not please update your question with the Client Code .
I am trying to understand how retrofit works but every time my response is failed I even used GitHub API but still my response failed, am I doing something wrong
I am so confused
Link
http://api.openweathermap.org/data/2.5/weather?q=Spakane,Us&appid=api_key
Interface Class
#GET("data/2.5/weather")
Call<List<Weather>> getWeatherData(#Query("q") String cityName,#Query("appid") String apikey);
MainActivity
private final String BASE_URL = "http://api.openweathermap.org/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
RestApi api = retrofit.create(RestApi.class);
final Call<List<Weather>> weather = api.getWeatherData("rawalpindi",API_KEY);
final ProgressDialog pg = new ProgressDialog(this);
pg.setTitle("Downloading");
pg.setMessage("Please Wait .....");
pg.show();
weather.enqueue(new Callback<List<Weather>>() {
#Override
public void onResponse(Call<List<Weather>> call, Response<List<Weather>> response) {
pg.dismiss();
Log.d(TAG, "onResponse: "+response.isSuccessful());
Log.d(TAG, "onResponse: "+response.body().get(0).getClouds());
}
#Override
public void onFailure(Call<List<Weather>> call, Throwable t) {
Log.d(TAG, "onFailure: Failed :(");
Log.d(TAG, "onResponseFailed: "+call.request().url());
pg.dismiss();
}
});
Log
D/MainActivity: onFailure: Failed :(
D/MainActivity: onResponseFailed: http://api.openweathermap.org/data/2.5/weather?q=rawalpindi&appid=api_key
throwable message
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
Your answer is not a list, is just an object. Use an interceptor to see responses.
As an example, from Call<List<Weather>> you should use just Call<Weather>.
print throwable error,such as "Log.e(TAG, "NET_ERROR:" + t.toString());". It may be the network problem .
I got such a very strange problem. I already created weather application which using this API. Problem is that, when i am calling "CONDITION" object,than i am getting a null pointer exception.But when i am calling another object,than everything is fine! Its weird. During 2 weeks this API worked fine,but starting from yesterday, not. Can anyone explain me,why it is like that, and what i have to do. Because application is already finished, and i am making the another one, and i don't want to rewriting this application just because of that problem.
I put my response in another application, to check maybe the problem was in my application,not in the API. Here is the code..
API CLASS:
public interface WeatherAPI {
#GET("/v1/current.json?key=fe1c9cd3fd2d4b189c010010172505")
Call<Weather> getForecastWeather(
#Query("q") String cityName
// #Query("days")Integer days
);
}
CONTROLLER CLASS:
public class Controller {
static final String BASE_WEATHER_URL = "https://api.apixu.com/";
public static WeatherAPI getApi(){
Gson gson = new GsonBuilder()
.setLenient()
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_WEATHER_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
WeatherAPI weatherAPI = retrofit.create(WeatherAPI.class);
return weatherAPI;
}
}
MAIN ACTIVITY CLASS:
mWeatherAPI = Controller.getApi();
mWeatherAPI.getForecastWeather("Paris").enqueue(new Callback<Weather>() {
#Override
public void onResponse(Call<Weather> call, Response<Weather> response) {
String description = response.body().getCurrent().getCondition().getIcon();
Log.e("TAG", "description: " + description);
}
#Override
public void onFailure(Call<Weather> call, Throwable t) {
Log.e("TAG", "onFailure: " + t.getMessage());
}
});
Yes, you need to add OkHttpClient to your Retrofit:
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
Retrofit retrofit = Retrofit.Builder().baseUrl(yourBaseUrlString)
.addConverterFactory(GsonConverterFactory.create())
.retrofitBuilder.client(okHttpClientBuilder.build()).build();
Check the json Object whether u created or not.
I am trying to convert this simple response that looks like this
{
"field_one": "bearer",
"field_two": "fgh",
"field_three": 0
}
I am using latest version of Retrofit 2.0.0-beta1. I never used Retrofit before. There are many tutorials and example of old version of Retrofit. I tried different techniques that works with older versions but thats not working with latest one. Due to lack of documentation of latest version of Retrofit I could not find solution.
I want to use latest version.
Here is POJO
public class Auth {
#SerializedName("field_one")
#Expose
private String fieldOne;
#SerializedName("field_two")
#Expose
private String fieldTwo;
#SerializedName("field_three")
#Expose
private Integer fieldThree;
// setter and getter etc. etc.
}
Here is Interface that I am using
interface Authorization {
#Headers("Authorization: This is some header")
#GET("api/v1/mytoken")
Call<Auth> getToken();
}
This is the way I am calling service
OkHttpClient client = new OkHttpClient();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://myendpoint.com/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
Authorization serviceAuthorization = retrofit.create(Authorization.class);
serviceAuthorization.getToken().enqueue(new Callback<Auth>() {
#Override
public void onResponse(Response<Auth> response) {
Log.d("Response", ">>> "+ response.toString());
}
#Override
public void onFailure(Throwable t) {
Log.d("fail", ">>> "+ t.getMessage());
}
});
I am unable to get output. It just print this
Response: >>> retrofit.Response#2567e2c3
I want to get data in Auth Object that I will use later.
Please suggest me best solution
Thanks!
I guess that you are not seeing you are expecting to see your object printed out on this line --
Log.d("Response", ">>> "+ response.toString());
That is going to call the toString method on the response. If you want to call it on your deserialized object, call the body() method first --
if(response.isSuccess()) {
Log.d("Response", ">>> "+ response.body().toString());
} else {
Log.d("Response", "Error - " + response.code())
}