For some time now I ask a question related to the retofit android library that I use to create an authorization screen in my application. I have already been told and advised a lot of things, I read a lot of things on the Internet. As a result, at the moment I created a naked application for working with the retofit library which converts the entered text into the form fields in json and then after clicking on the submit button, the converted information is displayed in the textview. To work with this issue, I used my previous questions: Please help me with the Retrofit android library during authorization in the application

Explain the principles of authorization development in android

There are a lot of practical advice, after which I divided my task into several subtasks, namely, I have created (it seems to me that everything works correctly there) just the project structure for converting data to json, but the server to which I’m not sending my requests http://jsonplaceholder.typicode.com/ and most likely just used in the example to emulate queries. Here are my classes for work: 1.

import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class RetrofitClient { private static Retrofit retrofit = null; public static Retrofit getClient() { if (retrofit==null) { retrofit = new Retrofit.Builder() .baseUrl("http://jsonplaceholder.typicode.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); } return retrofit; } } 

2

 import com.example.developer_4.test_log.APIService; public class ApiUtils { private ApiUtils() {} public static APIService getAPIService() { return RetrofitClient.getClient().create(APIService.class); } } 

3

 import com.example.developer_4.test_log.data.model.model.LoginRequest; import retrofit2.Call; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; import retrofit2.http.POST; public interface APIService { @POST("/posts") @FormUrlEncoded //Call<ServerResponce> authUser(@Body LoginRequest body); Call<LoginRequest> savePost(@Field("login") String login, @Field("password") String password); } 

four.

  public class LoginRequest { @SerializedName("login") @Expose private String login; @SerializedName("password") @Expose private String password; public String getLogin() { return login; } public void setLogin(String login) { this.login = login; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "LoginRequest{" + "login ='" + login + '\'' + ", password =" + password + '}'; } } 

and now I want to send a request to the server I need, but I don’t get it, I don’t seem to have an error and the program doesn’t crash, but I still can’t understand what the problem is. server request and if anyone knows how to explain this question to me, I will be very grateful to him.

  • You need to correct the question. Sending a request to the server is not associated with a retrofit. Give the code that you use to send to the server, and we will help you debug it =) - Georgy Chebotaryov
  • I understand that my question is not very well defined)) for sending to the server I thought that we use the post method but now I’m not very sure about this, in fact I couldn’t create a piece of code that is responsible for sending data to the server, I have my serialized request is still being output from a textview, and I don’t know how to send to the server yet, I can edit the question as I need, but you don’t have anything to ask me to go. - Andrew Goroshko

2 answers 2

This is not exactly the answer to your question, but a good hint how to understand what is going wrong.

Retrofit has a logging-interceptor module. Connects like this:

 implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0' 

Used only for debug builds (Kotlin):

 val builder = OkHttpClient.Builder() if (BuildConfig.DEBUG) { val logging = HttpLoggingInterceptor() logging.level = HttpLoggingInterceptor.Level.BODY builder.addInterceptor(logging) } val okHttpClient = builder.build() val retrofit = Retrofit.Builder() .baseUrl("http://jsonplaceholder.typicode.com/") .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient) .build() return retrofit.create(APIService::class.java) 

As a result, in LogCat you will see all your raw requests and server responses, too.

I hope this helps to figure out what and why it does not work as it should.

  • but for java this can also be done ??? and where to embed this piece of code? in onCreate? - Andrew Goroshko
  • Yes, I can find how))))) - Andrew Goroshko

I will give you a simple code that I use myself for the application without authorization (I pull the schedule from the site in open access).

RequestWrapper - class wrapper requests.

 import okhttp3.Call import okhttp3.Callback import okhttp3.Request import okhttp3.Response import java.io.IOException class RequestWrapper(private val apiClient: okhttp3.OkHttpClient, private var apiCall: Call?) { fun enqueue( request: Request, requestCallback: RequestCallback) { val modifiedApiClient = apiClient .newBuilder() .build() apiCall = modifiedApiClient.newCall(request.newBuilder().build()) apiCall!!.enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { requestCallback.onFailure(call, e) } @Throws(IOException::class) override fun onResponse(call: Call?, response: Response) { var responseBody: String? = null try { responseBody = response.body()!!.string() } catch (e: IOException) { e.printStackTrace() } requestCallback.onResponse(call, response, responseBody) } }) } interface RequestCallback { fun onFailure(call: Call, e: IOException) fun onResponse(call: Call?, response: Response, bodyString: String?) } } 

RequestConfig - config to work with the server.

 class RequestConfig { companion object { const val BASE_URL = "http://ruz2.spbstu.ru/api/v1/ruz/" const val FACULTIES = "faculties/" } } 

NetworkFragment - the parent fragment for all fragments that work with the server (api):

 import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.os.Bundle import android.os.Handler import android.os.Message import android.support.v4.app.Fragment import android.widget.Toast import argument.twins.com.polykekschedule.Application.Companion.apiCall import argument.twins.com.polykekschedule.Application.Companion.apiClient import argument.twins.com.polykekschedule.models.Faculties import argument.twins.com.polykekschedule.requests.RequestConfig.Companion.BASE_URL import argument.twins.com.polykekschedule.requests.RequestConfig.Companion.FACULTIES import argument.twins.com.polykekschedule.requests.RequestWrapper import com.google.gson.Gson import com.google.gson.GsonBuilder import okhttp3.Call import okhttp3.HttpUrl import okhttp3.Request import okhttp3.Response import org.json.JSONException import org.json.JSONObject import java.io.IOException open class NetworkFragment : Fragment() { private val SCHOOLS: String = "schools" private var viewModel: ScheduleViewModel ?= null private lateinit var mHandler: Handler override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) viewModel = ViewModelProviders.of(this).get(ScheduleViewModel::class.java) mHandler = Handler() } protected fun getSchoolsList(){ val endPointFaculties = BASE_URL + FACULTIES getRequest(endPointFaculties, SCHOOLS) } private fun getRequest(url: String, type: String, vararg urlParts: String) { val builder = HttpUrl.parse(url)!!.newBuilder() for(part in urlParts) builder.addPathSegment(part) val requestBuilder = Request.Builder() .url(builder.build()) .header("content-type", "application/json") .get() val request = requestBuilder.build() RequestWrapper(apiClient, apiCall) .enqueue(request, object : RequestWrapper.RequestCallback { override fun onResponse(call: Call?, response: Response, bodyString: String?) { if (response.code() == 204 || bodyString == null || !response.isSuccessful) { Toast.makeText(context, "Ошибка сервера", Toast.LENGTH_SHORT).show() return } try { val jsonObject = JSONObject(bodyString) val gson = getBuiltGsonInstance() when(type){ SCHOOLS -> { val facultiesObj = gson.fromJson(jsonObject.toString(), Faculties::class.java) viewModel?.schools = facultiesObj.faculties } } mHandler.post { updateView() } } catch (e: JSONException) { Toast.makeText(context, "Ошибка сервера # 2", Toast.LENGTH_SHORT).show() } } override fun onFailure(call: Call, e: IOException) { Toast.makeText(context, "Ошибка сети", Toast.LENGTH_SHORT).show() } }) } fun getBuiltGsonInstance(): Gson { return GsonBuilder() .serializeNulls() .create() } open fun updateView(){ Toast.makeText(context, "Обновление по-умолчанию", Toast.LENGTH_SHORT).show() } } 

For sending requests I use the okhttp3 library and the library for parsing json objects:

 implementation 'com.squareup.okhttp3:okhttp:3.10.0' implementation 'com.google.code.gson:gson:2.8.5' 

You can see how my simple example works, and start sending simple requests based on it. But to solve your future problems of this class is not enough. Since you are implementing authorization, you will have to implement work with tokens. The user can not log in 1 time, and then do not remind myself. Usually, after authorization, the user is given 2 tokens. 1 is eternal (it seems to be called access token, almost eternal), say another for an hour (refresh token). If an hour later, the user makes a request, and by this time the refresh token is quit), then you must first request the server to update this token, and only after that make a request for receiving data (that is, it is at least a queue of two requests). You should read about it well. In general, there is nothing difficult in authorization, but to implement it competently is not a simple matter. Good luck.

  • one
    Author requested Retrofit :) - Eugene Krivenja
  • and what, it is able to send requests for the north?) - Georgy Chebotarev
  • one
    Can :) Retrofit: A type-safe HTTP client for Android and Java , square.imtqy.com/retrofit - Eugene Krivenja
  • ohh .. well then of course my option is absolutely crutch in case of using retrofit. Look for how to make a request by means of a retrofit =) - Georgy Chebotarev
  • Your option is quite working, although not without flaws, only on Retrofit would be much less code. - Eugene Krivenja