zoukankan      html  css  js  c++  java
  • okhttputils【 Android 一个改善的okHttp封装库】使用(一)

    版权声明:本文为HaiyuKing原创文章,转载请注明出处!

    前言

    本文使用的OKHttp封装库是张鸿洋(鸿神)写的,因为在项目中一直使用这个库,所以对于一些常用的请求方式都验证过,所以特此整理下。

    本文主要讲的是在项目中导入OkHttpUtils库的一些操作。至于get、post、上传单个、多个文件、下载文件、提交文件、提交json字符串请求等,在下一篇中会有单独的介绍。

    效果图

    代码分析

    1、导入jar包

    2、在MyApplication中配置OKHttpUtils

    3、在AndroidManifest.xml中添加权限并声明自定义的MyApplication

    4、创建urls.xml文件,用来设置URL地址【这种方式不太好,因为urls.xml在res中,所以容易被反编译获取到;应该换成在接口ServerApi中声明常量进行调用

    5、创建logic包,用来封装网络请求

    6、在strings.xml文件中声明一些常用的提示语

    使用步骤

    一、项目组织结构图

    注意事项:

    1、导入类文件后需要change包名以及重新import R文件路径

    2、Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

    二、导入步骤

    1、将相关jar包复制到项目的libs目录下并同步Gradle File【这个是eclipse上的用法】【Android studio中直接使用compile 'com.zhy:okhttputils:2.6.2'

    jar包下载地址:链接:https://pan.baidu.com/s/1AL4zYlgydc2dJ3A9dy4vaA 密码:4gmh

    其中,gson-2.2.4.jar用于Post Json提交。【这个是必须单独引用的,不管Android studio还是eclipse】

    同步Gradle File后:

    2、创建一个包含以下代码的MyApplication.java(自定义的Application子类)

    package com.why.project.okhttputilsbasedemo;
    
    import android.app.Application;
    import android.content.Context;
    
    import com.zhy.http.okhttp.OkHttpUtils;
    import com.zhy.http.okhttp.cookie.CookieJarImpl;
    import com.zhy.http.okhttp.cookie.store.PersistentCookieStore;
    import com.zhy.http.okhttp.https.HttpsUtils;
    import com.zhy.http.okhttp.log.LoggerInterceptor;
    
    import java.util.concurrent.TimeUnit;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.SSLSession;
    
    import okhttp3.OkHttpClient;
    
    /**
     * Created by HaiyuKing
     * Used 自定义Application
     */
    
    public class MyApplication extends Application{
    
        /**系统上下文*/
        private static Context mAppContext;
    
        @Override
        public void onCreate() {
            super.onCreate();
            mAppContext = getApplicationContext();
    
            initOkHttp();//配置OkhttpClient
        }
    
        /**获取系统上下文:用于ToastUtil类*/
        public static Context getAppContext()
        {
            return mAppContext;
        }
    
        /**
         * 配置OkhttpClient
         */
        private void initOkHttp() {
    
            CookieJarImpl cookieJar = new CookieJarImpl(new PersistentCookieStore(getApplicationContext()));//修改成自带的cookie持久化,可以解决程序崩溃时返回到
            //ClearableCookieJar cookieJar1 = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(getApplicationContext()));
    
            HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(null, null, null);//设置可访问所有的https网站
    
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .connectTimeout(60000L, TimeUnit.MILLISECONDS)
                    .readTimeout(60000L, TimeUnit.MILLISECONDS)
                    //配置Log,通过设置拦截器实现,框架中提供了一个LoggerInterceptor,当然你可以自行实现一个Interceptor
                    .addInterceptor(new LoggerInterceptor("TAG"))
                    //配置持久化Cookie(包含Session)
                    .cookieJar(cookieJar)
                    .hostnameVerifier(new HostnameVerifier()
                    {
                        @Override
                        public boolean verify(String hostname, SSLSession session) {
                            // TODO Auto-generated method stub
                            return false;
                        }
                    })
                    //配置Https
                    .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                    .build();
            OkHttpUtils.initClient(okHttpClient);
        }
    
    }

    3、在AndroidManifest.xml中添加权限并声明这个MyApplication

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="com.why.project.okhttputilsbasedemo">
    
        <!-- ======================授权访问网络(OkHttpUtil)========================== -->
        <!-- 允许程序打开网络套接字 -->
        <uses-permission android:name="android.permission.INTERNET"/>
        <!-- 允许程序访问有关GSM网络信息 -->
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <!-- 允许程序访问Wi-Fi网络状态信息 -->
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <!-- 允许一个程序访问精良位置(如GPS)  -->
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
        <!-- 访问电话状态 -->
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <!-- 允许程序写入外部存储,如SD卡上写文件 -->
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        <!-- 允许程序读外部存储,如SD卡上读文件 -->
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    
        <!-- ======================授权访问网络(HttpUtil)========================== -->
        <!-- 允许程序打开网络套接字 -->
        <!--<uses-permission android:name="android.permission.INTERNET"/>-->
        <!-- 允许程序访问有关GSM网络信息 -->
        <!--<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />-->
        <!-- 允许程序访问Wi-Fi网络状态信息 -->
        <!--<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />-->
        <!-- 允许一个程序访问精良位置(如GPS)  -->
        <!--<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />-->
        <!-- 访问电话状态 -->
        <!--<uses-permission android:name="android.permission.READ_PHONE_STATE" />-->
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/AppTheme"
            android:name=".MyApplication">
            <activity android:name=".activity.MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
    
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
        </application>
    
    </manifest>

    4、添加运行时权限的处理(本demo中采用的是修改targetSDKVersion=22)

    5、将urls.xml文件复制到项目的res/valus目录中【存在反编译的风险,舍弃不用了;这里留作记录,后续不再保留这个文件】

    <?xml version="1.0" encoding="utf-8"?>
    <!-- 所有接口的url地址 -->
    <resources>
        
        <!-- 域名(开发环境) -->
        <string name="server_url">http://www.weather.com.cn/data/sk/</string>
        <!-- 域名(测试环境) -->
        <!-- <string name="server_url"></string> -->
        <!-- 域名(正式环境) -->
        <!-- <string name="server_url"></string> -->
    
        <!-- get请求地址 -->
        <string name="get_url">101010100.html</string>
    
    </resources>

    5、将ServerApi文件复制到项目中

    package com.why.project.okhttputilsbasedemo.logic;
    
    /**
     * Created by HaiyuKing
     * Used 接口地址
     */
    
    public interface ServerApi {
    
        String SERVER_URL = "http://www.weather.com.cn/data/sk/";// 域名(开发环境)
        String GET_URL = "101010100.html";// get请求地址
    
    }

    6、将BaseLogic.java、LoginLogic.java复制到项目中

    package com.why.project.okhttputilsbasedemo.logic;
    
    import android.content.Context;
    
    import com.zhy.http.okhttp.OkHttpUtils;
    import com.zhy.http.okhttp.cookie.CookieJarImpl;
    import com.zhy.http.okhttp.cookie.store.CookieStore;
    
    import java.util.List;
    
    import okhttp3.Cookie;
    import okhttp3.CookieJar;
    
    public class BaseLogic {
    
        protected Context context;
        public final String charset = "GBK";//例如:URLEncoder.encode("中途结束", charset)
        
        /**拼接完整的URL地址*/
        protected String getSpcyUrl(String serverUrl){
            String url = ServerApi.SERVER_URL + serverUrl;
            return url;
        }
    
        /**获取cookies*/
        public static String getCookiesStr(){
            String cookiesInfo = "";
            CookieJar cookieJar = OkHttpUtils.getInstance().getOkHttpClient().cookieJar();
            if (cookieJar instanceof CookieJarImpl)
            {
                CookieStore cookieStore = ((CookieJarImpl) cookieJar).getCookieStore();
                List<Cookie> cookies = cookieStore.getCookies();
                for(Cookie cookie : cookies){
                    cookiesInfo = cookiesInfo + cookie.name() + ":" + cookie.value() + ";";
                }
            }
    
            return cookiesInfo;
        }
    
        /**清空cookie缓存*/
        public static void clearCookies()
        {
            CookieJar cookieJar = OkHttpUtils.getInstance().getOkHttpClient().cookieJar();
            if (cookieJar instanceof CookieJarImpl)
            {
                ((CookieJarImpl) cookieJar).getCookieStore().removeAll();
            }
        }
    
    }
    BaseLogic.java
    package com.why.project.okhttputilsbasedemo.logic;
    
    import com.why.project.okhttputilsbasedemo.MyApplication;
    import com.zhy.http.okhttp.OkHttpUtils;
    import com.zhy.http.okhttp.callback.StringCallback;
    
    
    /**
     * @Created HaiyuKing
     * @Used   登录界面相关接口
     */
    public class LoginLogic extends BaseLogic {
        
        private static LoginLogic _Instance = null;
    
        public static LoginLogic Instance() {
            if (_Instance == null)
                _Instance = new LoginLogic();
            return _Instance;
        }
        private LoginLogic() {
            this.context = MyApplication.getAppContext();//防止了内存泄漏
        }
    
        /**
         * get请求测试
         */
        public String getJsonApi(StringCallback callback)
                throws Exception {
            String result = "";
            OkHttpUtils
                    .get()
                    .url(getSpcyUrl(ServerApi.GET_URL))
                    .id(100)
                    .tag(context)
                    .build()
                    .execute(callback);
            return result;
        }
    
    }
    LoginLogic.java

    7、在strings.xml文件中添加以下代码

    <resources>
        <string name="app_name">OkHttpUtilsBaseDemo</string>
    
        <!-- ******************公共字段:用于OkHttpUtil****************** -->
        <string name="login_succeed">登录成功</string>
        <string name="login_fail_username_pwd">用户名或密码错误,请检查!</string>
        <string name="login_fail_username">用户不存在,请联系管理员!</string>
        <string name="login_over_exception">用户已到期,请联系管理员!</string>
        <string name="login_null_exception">服务器响应超时,请稍后重试!</string>
        <string name="login_json_exception">服务器数据解析异常,请联系管理员!</string>
        <string name="login_again">用户超时,请重新登录!</string>
    
        <string name="response_null">数据内容为空</string>
        <string name="response_fail">请求失败,请重新请求!</string>
    
        <!-- ******************公共字段:用于HttpUtil****************** -->
        <string name="network_enable">当前网络未连接</string>
        <string name="network_terrible">当前网络不佳,请检查您的网络设置。</string>
        <string name="network_error">网络连接异常</string>
        <string name="network_timeout">网络请求超时,请重试</string>
        <string name="network_unavailable">网络连接不可用</string>
        <!-- 公共字段 end-->
    
    </resources>

    三、使用方法

    一般搭配HttpUtil、ToastUtil工具类使用。

    注意:Toast提示,这里使用的是ToastUtil【简单的Toast封装类】【未自定义Toast的显示风格】

    package com.why.project.okhttputilsbasedemo.activity;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    import com.why.project.okhttputilsbasedemo.MyApplication;
    import com.why.project.okhttputilsbasedemo.R;
    import com.why.project.okhttputilsbasedemo.logic.LoginLogic;
    import com.why.project.okhttputilsbasedemo.utils.ToastUtil;
    import com.why.project.okhttputilsbasedemo.utils.httputil.HttpUtil;
    import com.zhy.http.okhttp.OkHttpUtils;
    import com.zhy.http.okhttp.callback.StringCallback;
    
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import okhttp3.Call;
    import okhttp3.Request;
    
    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG = "MainActivity";
    
        private Button btn_get;
        private TextView tv_show;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initViews();
            initEvents();
        }
    
        @Override
        public void onPause() {
            // TODO Auto-generated method stub
            super.onPause();
            //取消网络请求,根据tag取消请求
            OkHttpUtils.getInstance().cancelTag(this);
        }
    
        private void initViews() {
            btn_get = (Button) findViewById(R.id.btn_get);
            tv_show = (TextView) findViewById(R.id.tv_show);
        }
    
        private void initEvents() {
            btn_get.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    getJson();
                }
            });
        }
    
        private void getJson() {
            if (HttpUtil.isNetworkAvailable(this)) {
                //执行网络请求接口
                try {
                    LoginLogic.Instance().getJsonApi(new GetJsonStringCallback());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }else{
                ToastUtil.showShortToast(MyApplication.getAppContext().getResources().getString(R.string.network_enable));
            }
        }
    
        /**
         * get接口的自定义回调函数*/
        public class GetJsonStringCallback extends StringCallback
        {
            @Override
            public void onBefore(Request request, int id)
            {//showProgressDialog("");//显示进度加载框
            }
    
            @Override
            public void onAfter(int id)
            {//dismissProgressDialog();//隐藏进度加载框
            }
    
            @Override
            public void onError(Call call, Exception e, int id)
            {
                ToastUtil.showShortToast(MyApplication.getAppContext().getResources().getString(R.string.login_again));
                Log.w(TAG,"{onError}e="+e.toString());
            }
    
            @Override
            public void onResponse(String response, int id)
            {
                Log.e(TAG, "onResponse:response="+response);
                switch (id)
                {
                    case 100://http
                        try {
                            if (response != null && !"".equals(response)){
                                //解析
                                JSONObject responseObj = new JSONObject(response);
                                tv_show.setText(responseObj.toString());
                            }
                            else {
                                ToastUtil.showShortToast(MyApplication.getAppContext().getResources().getString(R.string.login_null_exception));
                            }
                        } catch (JSONException e) {
                            ToastUtil.showShortToast(MyApplication.getAppContext().getResources().getString(R.string.login_json_exception));
                        }catch (Exception e) {
                            ToastUtil.showShortToast(MyApplication.getAppContext().getResources().getString(R.string.login_json_exception));
                        } finally {
                        }
                        break;
                    case 101://https
                        break;
                }
            }
            @Override
            public void inProgress(float progress, long total, int id)
            {
                Log.e(TAG, "inProgress:" + progress);
            }
        }
    }

    混淆配置

    #=====================okhttputils框架=====================
    #====okhttputils====
    #android Studio环境中不需要,eclipse环境中需要
    #-libraryjars libs/okhttputils.jar
    -dontwarn com.zhy.http.**
    -keep class com.zhy.http.**{*;}
    -keep interface com.zhy.http.**{*;}
    
    #====okhttp====
    #android Studio环境中不需要,eclipse环境中需要
    #-libraryjars libs/okhttp-2.7.0.jar
    -dontwarn okhttp3.**
    -keep class okhttp3.**{*;}
    -keep interface okhttp3.**{*;}
    
    -keepattributes Signature
    -keepattributes *Annotation*
    -dontwarn com.squareup.okhttp.**
    -keep class com.squareup.okhttp.**{*;}
    -keep interface com.squareup.okhttp.**{*;}
    
    #====okio====
    #android Studio环境中不需要,eclipse环境中需要
    #-libraryjars libs/okio-1.6.0.jar
    -dontwarn java.nio.file.*
    -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
    -dontwarn okio.**
    -keep class okio.**{*;}
    -keep interface okio.**{*;}
    
    #====gson====
    #android Studio环境中不需要,eclipse环境中需要
    #-libraryjars libs/gson-2.2.4.jar
    -keep class sun.misc.Unsafe{*;}
    -dontwarn com.google.gson.**
    -keep class com.google.gson.**{*;}
    -keep class com.google.gson.stream.**{*;}
    #这一段包名应该是你所有的java bean 定义的目录
    -keep class com.google.gson.examples.android.model.**{*;}

    需要注意,在Android studio开发环境和eclipse开发环境中,混淆配置不同之处在于下面的注释标注的:

    #android Studio环境中不需要,eclipse环境中需要
    #-libraryjars libs/okhttputils.jar

    参考资料

    Android 一个改善的okHttp封装库

    github地址

    项目demo下载地址

    https://github.com/haiyuKing/OkHttpUtilsBaseDemo

  • 相关阅读:
    点击事件在label标签执行2次解决办法
    关于有偿提供拼图响应式后台的通知.
    jquery鼠标悬停导航下划线滑出效果
    javascript深层解释。
    创业者靠什么成功?
    怎么样才是理想的程序员?
    web总结。
    深入认识盒子模型 display:inline-block BFC 和haslayout !
    25种用户十秒离开你网站的原因!
    JavaScript 引用类型数组!
  • 原文地址:https://www.cnblogs.com/whycxb/p/7146572.html
Copyright © 2011-2022 走看看