1. A Cookie is introduced

Personally, I understand that cookies are actually to record some information and status behaviors of users. In such a scenario, after the user logs in successfully, the server will return a Cookie, which contains the user’s login status information, etc., so that when the user accesses his favorite list, add this Cookie, then he can directly obtain the article list. If there is no Cookie, How does the server know which user’s article list you’re trying to get?

On the browser, the returned Cookie will be saved in the browser, and the Cookie will be automatically added in the next visit. On the Android side, we need to save the Cookie returned by the server and add it in the next visit. As for how to save (Cookie persistence), there are many methods, you can use database, file, SharedPreferences, you can also use the CookieManager of Webview.

You can read this article about cookies and the summary of their use in Android in great detail. Just read this article

We have already described how to add headers in the previous article, but obviously we can’t do this. We can’t write headers on every API that needs cookies or add them dynamically. That would be too tedious, so we will add them dynamically through interceptors.

2. Interface description

For this article, I will use the login interface and the favorite article list interface of the Wandroid website

landing

https://www.wanandroid.com/user/loginMethod: POST Parameters: username, passwordCopy the code

After login, the system returns the account password in the cookie. After persistent cookie storage is configured on the client, the login is automatically authenticated.

List of favorite articles

https://www.wanandroid.com/lg/collect/list/0/jsonMethod: GET Parameter: page number: concatenated in the link from0Start.Copy the code

After login on the website, can direct access to the www.wanandroid.com/lg/collect/… Check out your favorite articles.

You can check it out atWeb siteRegister an account and bookmark a few articles for use below.

3. Relationship between Retrofit and OkHttp

Why OkHttp? Because Retrofit is basically implemented using OkHttp, it’s just wrapped around it. We can set the request header by Interceptor from OkHttp, The request headers are then modified via retrofit.client(okHttpClient), which saves us from adding them manually.

4. Interceptor creation

Here we create two interceptors, one for receiving cookies on login and saving them locally, and one for adding cookies to requests on access.

4.1 Interception Cookies are saved to the local interceptor

4.1.1 Creating an Interceptor inherits from Interceptor

public class ReceivedCookiesInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {    
        // Intercepted cookies are stored in originalResponse
        Response originalResponse = chain.proceed(chain.request());
        // Prints cookie information
        Log.i(TAG, "intercept: "+ originalResponse.headers("Set-Cookie").toString()); .returnoriginalResponse; }}Copy the code

The response obtained by chain.proceed(chain.request()) saves the intercepted cookie information.

Log. I (TAG, “Intercept: “+ OriginalResponse.headers (” set-cookie “).tostring ()); Prints header logs

We can see the cookie information returned by the network request. All we need to do is save this cookie locally.

4.1.2 Saving Cookie Information locally

I’m going to store cookies in a sharepreference

  • Check that the header of set-cookie is not empty

    if(! originalResponse.headers("Set-Cookie").isEmpty()) {
        ...
    }
    Copy the code
  • The Cookie information is looped into the HashSet collection

    HashSet<String> cookies = new HashSet<>();
    for(String header: originalResponse.headers("Set-Cookie"))
    {
    	cookies.add(header);
    }
    Copy the code
  • Cookie information is saved locally through SharePreference

    // Save the sharePreference file named cookieData
    SharedPreferences sharedPreferences = context.getSharedPreferences("cookieData", Context.MODE_PRIVATE);								
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putStringSet("cookie", cookies);
    editor.commit();
    Copy the code

4.1.3 Complete code

public class ReceivedCookiesInterceptor implements Interceptor {
    
    public ReceivedCookiesInterceptor(a) {
        super(a); }@Override
    public Response intercept(Chain chain) throws IOException {        
        Response originalResponse = chain.proceed(chain.request());
        // Get the cookie returned by the request
        if(! originalResponse.headers("Set-Cookie").isEmpty()) {
          
            HashSet<String> cookies = new HashSet<>();
            for(String header: originalResponse.headers("Set-Cookie"))
            {
                LogUtil.i(TAG, "The intercepted cookie is:"+header);
                cookies.add(header);
            }
           // Save the sharePreference file named cookieData
            SharedPreferences sharedPreferences = App.getInstance().getSharedPreferences("cookieData", Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = sharedPreferences.edit();
            editor.putStringSet("cookie", cookies);

            editor.commit();
        }

        returnoriginalResponse; }}Copy the code

4.2 Adding an Interceptor for Local Cookies for Network Access

4.2.1 Creating an Interceptor inherits from Interceptor

public class AddCookiesInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {... }}Copy the code

4.2.2 Read cookies from Sharepreference and add them to the header

Request.Builder builder = chain.request().newBuilder();

HashSet<String> perferences = (HashSet) App.getInstance().getSharedPreferences("cookieData", Context.MODE_PRIVATE).getStringSet("cookie".null);
if(perferences ! =null) {
    for (String cookie : perferences) {
        builder.addHeader("Cookie", cookie); }}return chain.proceed(builder.build());
Copy the code

4.2.3 Complete code

public class AddCookiesInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {

        Request.Builder builder = chain.request().newBuilder();
        HashSet<String> perferences = (HashSet) App.getInstance().getSharedPreferences("cookieData", Context.MODE_PRIVATE).getStringSet("cookie".null);
        if(perferences ! =null) {
            for (String cookie : perferences) {
                builder.addHeader("Cookie", cookie); }}returnchain.proceed(builder.build()); }}Copy the code

5. Application

5.1 Login Cookie Interception

5.1.1 Creating an OkhttpClient object

OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new ReceivedCookiesInterceptor())
                .build();
Copy the code

5.1.2 Create a Retrofit object and add this OkhttpClient object

private Retrofit retrofitLogin;
retrofitLogin = new Retrofit.Builder()
                .baseUrl("https://a/")
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build();
Copy the code

5.1.3 Creating Interface Objects for Access

public interface Api {    
    // Login interface
    @FormUrlEncoded
    @POST
    Call<UserBean> login(@Url String url, @FieldMap Map<String, String> param);
}
Copy the code
private Api loginApi;
loginApi = retrofitLogin.create(Api.class);
Copy the code
Map<String, String> param = new HashMap<>();
param.put("username", etUsername.getText().toString());
param.put("password", etPwd.getText().toString());

loginApi.login(loginUrl, param).enqueue(new Callback<UserBean>() {
    @Override
    public void onResponse(Call<UserBean> call, Response<UserBean> response) {
        if(response ! =null&& response.body() ! =null) {
            if (response.body().getErrorCode() == 0) {
                Toast.makeText(getApplicationContext(), "Login successful", Toast.LENGTH_SHORT).show(); }else {
                Toast.makeText(getApplicationContext(), "Login failed"+ response.body().getErrorCode() + response.body().getErrorMsg(), Toast.LENGTH_SHORT).show(); }}}@Override
    public void onFailure(Call<UserBean> call, Throwable t) {
        Toast.makeText(getApplicationContext(), "Login failed"+t, Toast.LENGTH_SHORT).show(); }}); }else {
    Toast.makeText(this."Please enter complete user information", Toast.LENGTH_SHORT).show();
}
Copy the code

5.2 Get favorites list attached local Cookie

5.2.1 Creating an OkhttpClient object

OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(new AddCookiesInterceptor())
                .build();
Copy the code

5.2.2 Create a Retrofit object and add this OkhttpClient object

retrofitCollect = new Retrofit.Builder()
                .baseUrl("https://www.wanandroid.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build();        
Copy the code

5.2.3 Creating Interface Objects for Access

public interface Api {
    // Get the list of favorites
    @GET("lg/collect/list/{page}/json")
    Call<MyCollectionBean> getCollecEssay(@Path("page") int page);
}
Copy the code
private Retrofit retrofitCollect;
private Api getCollectApi;
getCollectApi = retrofitCollect.create(Api.class);
Copy the code
getCollectApi.getCollecEssay(0).enqueue(new Callback<MyCollectionBean>() {
    @Override
    public void onResponse(Call<MyCollectionBean> call, Response<MyCollectionBean> response) {
        if(response ! =null&& response.body() ! =null) {
            if (response.body().getErrorCode() == 0) {
                Log.i(TAG, "OnResponse: Succeeded in getting the list of articles");
                for (int i = 0; i < response.body().getData().getDatas().size(); i++) {
                    Log.i(TAG, "\n Collection title:"+ response.body().getData().getDatas().get(i).getTitle()); }}else {
                 Log.i(TAG, "OnResponse: Failed to get list of articles"+response.body().getErrorMsg()); }}}@Override
    public void onFailure(Call<MyCollectionBean> call, Throwable t) {
         Log.i(TAG, "OnResponse: Failed to get list of articles"+t); }});Copy the code

6. Summary

That’s all. See Github for the code.

In fact, the purpose of using the interceptor is to save the Cookie information locally and add cookies to the header information through the interceptor. It is to simplify the step of adding the header information manually.

The above is all the content, if there is a mistake in the place also hope to point out, to help you if you trouble to see the officer to like a start. The article about Retrofit image uploading is still being edited. As for how to use cloud server to write an image uploading interface for everyone, I’m still trying to figure out how to do it.

7. Refer to the article

Retrofit uses OkHttp to save and add cookies

Android cookies are received and sent

Cookie introduction and the use of Android summary in detail, just read this article