Android开源:Http/Https 组件
Warran
8年前
<h2>android-major-https</h2> <p>android-major-https是一款 Android 上的 Http/Https 组件。内部使用 <strong> Volley </strong> 作为底层 Http 组件。主要特性有:</p> <ul> <li>支持 GET、 POST、 DELETE、 PUT、 HEAD 等;</li> <li>支持 Http、 <strong>Https</strong> ;</li> <li>对 Https 支持 <strong>自定义证书验证</strong> 、 <strong>域名验证</strong> 等;</li> <li>支持 Text、 Binary、 Json、 文件下载、 文件上传等;</li> <li>支持 Json 自动解析为 POJO;</li> <li>接口简洁易用,支持 Java8 <strong>Lambda</strong> 。</li> </ul> <h3>1、Gradle 配置</h3> <pre> <code class="language-java">compile 'com.jungle.majorhttp:major-http:1.0.0'</code></pre> <h3>2、使用方法</h3> <p>使用预定义的各种 Model 来加载 URL,通过各种方法来设置加载参数。最后使用 <strong> load </strong> 或 <strong> loadWithProgress </strong> 来加载请求。</p> <p>load只是在后台加载,界面上没有任何表现。 <strong>loadWithProgress</strong> 在加载的时候会弹出一个加载展示 Dialog(该对话框样式可自定义),并在后台加载。请求返回后,将自动关闭 Dialog。</p> <p>预定义的 Model 列表如下:</p> <table> <thead> <tr> <th>请求类型</th> <th>Model</th> <th>数据结果</th> </tr> </thead> <tbody> <tr> <td>文本请求</td> <td>TextRequestModel</td> <td>String</td> </tr> <tr> <td>Json POJO 请求</td> <td>JsonRequestModel</td> <td>POJO Java 对象</td> </tr> <tr> <td>二进制数据请求</td> <td>BinaryRequestModel</td> <td>byte[]</td> </tr> <tr> <td>数据下载(获取)请求</td> <td>DownloadRequestModel</td> <td>byte[]</td> </tr> <tr> <td>文件下载请求</td> <td>DownloadFileRequestModel</td> <td>String 下载好的文件路径</td> </tr> <tr> <td>上传请求</td> <td>UploadRequestModel</td> <td>String 服务器返回的上传结果</td> </tr> <tr> <td>JsonObject 请求</td> <td>JsonObjectRequestModel</td> <td>JSONObject</td> </tr> <tr> <td>JsonArray 请求</td> <td>JsonArrayRequestModel</td> <td>JSONArray</td> </tr> </tbody> </table> <p>具体代码示例如下:</p> <pre> <code class="language-java">private static final String DEMO_WEB_URL = "https://www.zhihu.com"; private static final String DEMO_JSON_URL = "https://raw.githubusercontent.com/arnozhang/major-http/master/docs/demo.json"; private static final String DEMO_UPLOAD_URL = "https://raw.githubusercontent.com/upload_test"; private void showError(int errorCode, String message) { // ... }</code></pre> <ul> <li>文本请求,使用 <strong> TextRequestModel </strong> :</li> </ul> <pre> <code class="language-java">TextRequestModel .newModel() .url(DEMO_WEB_URL) .success(new ModelSuccessListener<String>() { @Override public void onSuccess(NetworkResp networkResp, String response) { TextViewerActivity.start(getContext(), response); } }) .error(new ModelErrorListener() { @Override public void onError(int errorCode, String message) { showError(errorCode, message); } }) .load();</code></pre> <p>或者只用一个统一的 Listener:</p> <pre> <code class="language-java">TextRequestModel .newModel() .url(DEMO_WEB_URL) .load(new ModelListener<String>() { @Override public void onSuccess(NetworkResp networkResp, String response) { TextViewerActivity.start(getContext(), response); } @Override public void onError(int errorCode, String message) { showError(errorCode, message); } });</code></pre> <p>如果你支持 <strong>Java8</strong> ,你还可以使用 <strong>lambda</strong> 表达式。可以看出使用 lambda 后,整个语法简洁了很多:</p> <pre> <code class="language-java">TextRequestModel .newModel() .url(DEMO_WEB_URL) .success((networkResp, response) -> TextViewerActivity.start(getContext(), response)) .error(this::showError) .load();</code></pre> <ul> <li>Json POJO 请求,使用 <strong> JsonRequestModel </strong> :</li> </ul> <pre> <code class="language-java">public class GithubUserInfo { public static class Project { public String name; public String url; } public String uid; public String userName; public String site; public String[] languages; public List<Project> projects; } JsonRequestModel .newModel(GithubUserInfo.class) .url(DEMO_JSON_URL) .method(ModelMethod.GET) .load(new BizModelListener<GithubUserInfo>() { @Override public void onSuccess(NetworkResp networkResp, GithubUserInfo response) { String info = JSON.toJSONString(response, SerializerFeature.PrettyFormat); info = "Load Json object success!\n\n" + info; TextViewerActivity.start(getContext(), info); } @Override public void onError(int errorCode, String message) { showError(errorCode, message); } });</code></pre> <p>Json 解析为 POJO 的过程,使用第三方 Json 库 <strong> fastjson </strong> 。</p> <ul> <li>文件下载请求,使用 <strong> DownloadFileRequestModel </strong> :</li> </ul> <pre> <code class="language-java">final String file = getDemoFilePath(); String loadingText = String.format("Downloading File: \n%s", file); DownloadFileRequestModel .newModel() .url(DEMO_JSON_URL) .filePath(file) .lifeListener(new ModelLoadLifeListener<DownloadFileRequestModel>() { @Override public void onBeforeLoad(DownloadFileRequestModel model) { ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100); } }) .loadWithProgress(getContext(), loadingText, new BizModelListener<String>() { @Override public void onSuccess(NetworkResp networkResp, String response) { Toast.makeText(getContext(), String.format( "Download file SUCCESS! file = %s.", file), Toast.LENGTH_SHORT).show(); } @Override public void onError(int errorCode, String message) { showError(errorCode, message); } });</code></pre> <ul> <li>文件上传请求,使用 <strong> UploadRequestModel </strong> :</li> </ul> <pre> <code class="language-java">final String file = getDemoFilePath(); UploadRequestModel .newModel() .url(DEMO_UPLOAD_URL) .addFormItem(file) .loadWithProgress(this, "Uploading...", new BizModelListener<String>() { @Override public void onSuccess(NetworkResp networkResp, String response) { Toast.makeText(getContext(), String.format( "Upload file SUCCESS! file = %s.", file), Toast.LENGTH_SHORT).show(); } @Override public void onError(int errorCode, String message) { showError(errorCode, message); } });</code></pre> <h3>3、Http / Https 支持</h3> <p>通过 <strong> MajorHttpClient </strong> 这个组件可以配置 Http / Https:</p> <table> <thead> <tr> <th>方法</th> <th>解释</th> </tr> </thead> <tbody> <tr> <td>setRequestQueueFactory</td> <td>设置请求队列 Factory</td> </tr> <tr> <td>setDefaultTimeoutMilliseconds</td> <td>设置基础请求的超时时间</td> </tr> <tr> <td>setUploadTimeoutMilliseconds</td> <td>设置上传类请求的超时时间</td> </tr> <tr> <td>setExtraHeadersFiller</td> <td>为每个请求设置额外的 Header 填充回调(具体项目中比如动态填入 uid、ticket 等等)</td> </tr> </tbody> </table> <p>3.1、Http 支持</p> <pre> <code class="language-java">MajorHttpClient.getDefault().setRequestQueueFactory(new HttpRequestQueueFactory(context));</code></pre> <p>3.2、Https 支持</p> <pre> <code class="language-java">String[] certs = { "zhihu.cer", "github.cer", "githubusercontent.cer" }; String[] domains = { "zhihu.com", "github.com", "githubusercontent.com" }; HttpsRequestQueueFactory factory = new HttpsRequestQueueFactory(this, certs); factory.setHostnameVerifier(new HttpsUtils.DomainHostnameVerifier(domains)); MajorHttpClient.getDefault().setRequestQueueFactory(factory);</code></pre> <p>Https 可以将证书文件放在 <strong>assets</strong> 文件夹下,或者放在 <strong>res/raw</strong> 文件夹下,然后在代码中创建相应的 <strong> HttpsRequestQueueFactory </strong> 。通过 <strong> HttpsRequestQueueFactory.setHostnameVerifier </strong> 可以设置域名验证。</p> <p>3.3、Https 验证失败异常</p> <p>如果请求的 URL <strong>证书验证</strong> 不通过,则错误如下:</p> <pre> <code class="language-java">com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found..</code></pre> <p>如果请求的 URL <strong>域名验证</strong> 不通过,则错误如下:</p> <pre> <code class="language-java">com.android.volley.NoConnectionError: javax.net.ssl.SSLPeerUnverifiedException: Hostname github.com not verified: certificate: sha1/1O6dKmcSs2FMJy0ViwT8yMoIoLY= DN: CN=github.com,O=GitHub\, Inc.,L=San Francisco,ST=California,C=US,2.5.4.17=#13053934313037,STREET=88 Colin P Kelly\, Jr Street,2.5.4.5=#130735313537353530,1.3.6.1.4.1.311.60.2.1.2=#130844656c6177617265,1.3.6.1.4.1.311.60.2.1.3=#13025553,2.5.4.15=#0c1450726976617465204f7267616e697a6174696f6e subjectAltNames: [github.com, www.github.com].</code></pre> <h2>License</h2> <pre> <code class="language-java">/** * Android Jungle-Major-Http framework project. * * Copyright 2016 Arno Zhang <zyfgood12@163.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */</code></pre> <p> </p> <p> </p> <p> </p>