,
6 | val message: String
7 | )
8 |
9 | data class Data(
10 | val absoluteUrl: String,
11 | val filePath: String,
12 | val relativeUrl: String
13 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/yujing/test/bean/User.kt:
--------------------------------------------------------------------------------
1 | package com.yujing.test.bean
2 |
3 | import java.util.*
4 |
5 | data class User(
6 | val code: Int,
7 | val data: DD?,
8 | val message: String
9 | )
10 |
11 | data class DD(
12 | val 可用内存: String,
13 | val 已使用内存: String,
14 | val 服务器时间: Date,
15 | val 用户: 用户?
16 | )
17 |
18 | data class 用户(
19 | val createTime: Date,
20 | val endLoginTime: Date,
21 | val id: Int,
22 | val name: String,
23 | val nickName: String,
24 | val phone: String
25 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/yujing/test/bean/YResponse.java:
--------------------------------------------------------------------------------
1 | package com.yujing.test.bean;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | *
7 | * 返回结果封装类
8 | * @author yujing 2019年11月21日15:09:51
9 | *
10 | */
11 | public class YResponse implements Serializable {
12 |
13 | private int ResultType;
14 | private String Msg;
15 | private int ErrorCode;
16 | private String ErrorMsg;
17 | private T Data;
18 |
19 | public int getResultType() {
20 | return ResultType;
21 | }
22 |
23 | public void setResultType(int resultType) {
24 | ResultType = resultType;
25 | }
26 |
27 | public String getMsg() {
28 | return Msg;
29 | }
30 |
31 | public void setMsg(String msg) {
32 | Msg = msg;
33 | }
34 |
35 | public int getErrorCode() {
36 | return ErrorCode;
37 | }
38 |
39 | public void setErrorCode(int errorCode) {
40 | ErrorCode = errorCode;
41 | }
42 |
43 | public String getErrorMsg() {
44 | return ErrorMsg;
45 | }
46 |
47 | public void setErrorMsg(String errorMsg) {
48 | ErrorMsg = errorMsg;
49 | }
50 |
51 | public T getData() {
52 | return Data;
53 | }
54 |
55 | public void setData(T data) {
56 | Data = data;
57 | }
58 |
59 | @Override
60 | public String toString() {
61 | return "YResponse{" +
62 | "ResultType=" + ResultType +
63 | ", Msg='" + Msg + '\'' +
64 | ", ErrorCode=" + ErrorCode +
65 | ", ErrorMsg='" + ErrorMsg + '\'' +
66 | ", Data=" + Data +
67 | '}';
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yutils/view/WarpLinearLayout.java:
--------------------------------------------------------------------------------
1 | package com.yutils.view;
2 |
3 |
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.util.AttributeSet;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import com.yujing.test.R;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | /**
16 | * 瀑布流布局
17 | */
18 | public class WarpLinearLayout extends ViewGroup {
19 | private Type mType;
20 | private List mWarpLineGroup;
21 |
22 | public WarpLinearLayout(Context context) {
23 | this(context, null);
24 | }
25 |
26 | public WarpLinearLayout(Context context, AttributeSet attrs) {
27 | this(context, attrs, R.style.WarpLinearLayoutDefault);
28 | }
29 |
30 | public WarpLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
31 | super(context, attrs, defStyleAttr);
32 | mType = new Type(context, attrs);
33 | }
34 |
35 | @Override
36 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
37 | int withMode = MeasureSpec.getMode(widthMeasureSpec);
38 | int withSize = MeasureSpec.getSize(widthMeasureSpec);
39 | int heightMode = MeasureSpec.getMode(heightMeasureSpec);
40 | int heightSize = MeasureSpec.getSize(heightMeasureSpec);
41 | int with = 0;
42 | int height = 0;
43 | int childCount = getChildCount();
44 | /**
45 | * 在调用childView。getMeasre之前必须先调用该行代码,用于对子View大小的测量
46 | */
47 | measureChildren(widthMeasureSpec, heightMeasureSpec);
48 | /**
49 | * 计算宽度
50 | */
51 | switch (withMode) {
52 | case MeasureSpec.EXACTLY:
53 | //noinspection DuplicateBranchesInSwitch
54 | with = withSize;
55 | break;
56 | case MeasureSpec.AT_MOST:
57 | for (int i = 0; i < childCount; i++) {
58 | if (i != 0) {
59 | with += mType.horizontal_Space;
60 | }
61 | with += getChildAt(i).getMeasuredWidth();
62 | }
63 | with += getPaddingLeft() + getPaddingRight();
64 | with = Math.min(with, withSize);
65 | break;
66 | case MeasureSpec.UNSPECIFIED:
67 | for (int i = 0; i < childCount; i++) {
68 | if (i != 0) {
69 | with += mType.horizontal_Space;
70 | }
71 | with += getChildAt(i).getMeasuredWidth();
72 | }
73 | with += getPaddingLeft() + getPaddingRight();
74 | break;
75 | default:
76 | with = withSize;
77 | break;
78 |
79 | }
80 | /**
81 | * 根据计算出的宽度,计算出所需要的行数
82 | */
83 | WarpLine warpLine = new WarpLine();
84 | /**
85 | * 不能够在定义属性时初始化,因为onMeasure方法会多次调用
86 | */
87 | mWarpLineGroup = new ArrayList<>();
88 | for (int i = 0; i < childCount; i++) {
89 | if (warpLine.lineWidth + getChildAt(i).getMeasuredWidth() + mType.horizontal_Space > with) {
90 | if (warpLine.lineView.size() == 0) {
91 | warpLine.addView(getChildAt(i));
92 | mWarpLineGroup.add(warpLine);
93 | warpLine = new WarpLine();
94 | } else {
95 | mWarpLineGroup.add(warpLine);
96 | warpLine = new WarpLine();
97 | warpLine.addView(getChildAt(i));
98 | }
99 | } else {
100 | warpLine.addView(getChildAt(i));
101 | }
102 | }
103 | /**
104 | * 添加最后一行
105 | */
106 | if (warpLine.lineView.size() > 0 && !mWarpLineGroup.contains(warpLine)) {
107 | mWarpLineGroup.add(warpLine);
108 | }
109 | /**
110 | * 计算宽度
111 | */
112 | height = getPaddingTop() + getPaddingBottom();
113 | for (int i = 0; i < mWarpLineGroup.size(); i++) {
114 | if (i != 0) {
115 | height += mType.vertical_Space;
116 | }
117 | height += mWarpLineGroup.get(i).height;
118 | }
119 | switch (heightMode) {
120 | case MeasureSpec.EXACTLY:
121 | height = heightSize;
122 | break;
123 | case MeasureSpec.AT_MOST:
124 | height = Math.min(height, heightSize);
125 | break;
126 | case MeasureSpec.UNSPECIFIED:
127 | break;
128 | default:
129 | break;
130 | }
131 | setMeasuredDimension(with, height);
132 | }
133 |
134 | @Override
135 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
136 | t = getPaddingTop();
137 | for (int i = 0; i < mWarpLineGroup.size(); i++) {
138 | int left = getPaddingLeft();
139 | WarpLine warpLine = mWarpLineGroup.get(i);
140 | int lastWidth = getMeasuredWidth() - warpLine.lineWidth;
141 | for (int j = 0; j < warpLine.lineView.size(); j++) {
142 | View view = warpLine.lineView.get(j);
143 | if (isFull()) {//需要充满当前行时
144 | view.layout(left, t, left + view.getMeasuredWidth() + lastWidth / warpLine.lineView.size(), t + view.getMeasuredHeight());
145 | left += view.getMeasuredWidth() + mType.horizontal_Space + lastWidth / warpLine.lineView.size();
146 | } else {
147 | switch (getGrivate()) {
148 | case 0://右对齐
149 | view.layout(left + lastWidth, t, left + lastWidth + view.getMeasuredWidth(), t + view.getMeasuredHeight());
150 | break;
151 | case 2://居中对齐
152 | view.layout(left + lastWidth / 2, t, left + lastWidth / 2 + view.getMeasuredWidth(), t + view.getMeasuredHeight());
153 | break;
154 | default://左对齐
155 | view.layout(left, t, left + view.getMeasuredWidth(), t + view.getMeasuredHeight());
156 | break;
157 | }
158 | left += view.getMeasuredWidth() + mType.horizontal_Space;
159 | }
160 | }
161 | t += warpLine.height + mType.vertical_Space;
162 | }
163 | }
164 |
165 | /**
166 | * 用于存放一行子View
167 | */
168 | private final class WarpLine {
169 | private List lineView = new ArrayList();
170 | /**
171 | * 当前行中所需要占用的宽度
172 | */
173 | private int lineWidth = getPaddingLeft() + getPaddingRight();
174 | /**
175 | * 该行View中所需要占用的最大高度
176 | */
177 | private int height = 0;
178 |
179 | private void addView(View view) {
180 | if (lineView.size() != 0) {
181 | lineWidth += mType.horizontal_Space;
182 | }
183 | height = Math.max(height, view.getMeasuredHeight());
184 | lineWidth += view.getMeasuredWidth();
185 | lineView.add(view);
186 | }
187 | }
188 |
189 | /**
190 | * 对样式的初始化
191 | */
192 | private final static class Type {
193 | /*
194 | *对齐方式 right 0,left 1,center 2
195 | */
196 | private int grivate;
197 | /**
198 | * 水平间距,单位px
199 | */
200 | private float horizontal_Space;
201 | /**
202 | * 垂直间距,单位px
203 | */
204 | private float vertical_Space;
205 | /**
206 | * 是否自动填满
207 | */
208 | private boolean isFull;
209 |
210 | Type(Context context, AttributeSet attrs) {
211 | if (attrs == null) {
212 | return;
213 | }
214 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.WarpLinearLayout);
215 | grivate = typedArray.getInt(R.styleable.WarpLinearLayout_grivate, grivate);
216 | horizontal_Space = typedArray.getDimension(R.styleable.WarpLinearLayout_horizontal_Space, horizontal_Space);
217 | vertical_Space = typedArray.getDimension(R.styleable.WarpLinearLayout_vertical_Space, vertical_Space);
218 | isFull = typedArray.getBoolean(R.styleable.WarpLinearLayout_isFull, isFull);
219 | }
220 | }
221 |
222 | public int getGrivate() {
223 | return mType.grivate;
224 | }
225 |
226 | public float getHorizontal_Space() {
227 | return mType.horizontal_Space;
228 | }
229 |
230 | public float getVertical_Space() {
231 | return mType.vertical_Space;
232 | }
233 |
234 | public boolean isFull() {
235 | return mType.isFull;
236 | }
237 |
238 | public void setGrivate(int grivate) {
239 | mType.grivate = grivate;
240 | }
241 |
242 | public void setHorizontal_Space(float horizontal_Space) {
243 | mType.horizontal_Space = horizontal_Space;
244 | }
245 |
246 | public void setVertical_Space(float vertical_Space) {
247 | mType.vertical_Space = vertical_Space;
248 | }
249 |
250 | public void setIsFull(boolean isFull) {
251 | mType.isFull = isFull;
252 | }
253 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/yutils/view/utils/Create.kt:
--------------------------------------------------------------------------------
1 | package com.yutils.view.utils
2 |
3 | import android.graphics.Bitmap
4 | import android.view.Gravity
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import android.widget.*
8 | import com.yujing.test.App
9 | import com.yujing.utils.YScreenUtil.dp2px
10 |
11 | /**
12 | * 动态创建view
13 | */
14 | @Suppress("MemberVisibilityCanBePrivate")
15 | class Create {
16 | companion object {
17 | //动态创建Button
18 | fun button(name: String = "按钮", listener: View.OnClickListener): Button {
19 | val layoutParams = LinearLayout.LayoutParams(
20 | LinearLayout.LayoutParams.WRAP_CONTENT,
21 | LinearLayout.LayoutParams.WRAP_CONTENT
22 | )
23 | val view = Button(App.get())
24 | view.isAllCaps = false//不自动变大写
25 | name.let { view.text = it }
26 | view.layoutParams = layoutParams
27 | view.setOnClickListener(listener)
28 | return view
29 | }
30 |
31 | //动态创建Button
32 | fun button(
33 | linearLayout: ViewGroup?, name: String = "按钮",
34 | listener: View.OnClickListener
35 | ): Button {
36 | val view = button(name, listener)
37 | linearLayout?.addView(view)
38 | return view
39 | }
40 |
41 | //动态创建TextView
42 | fun textView(value: String? = null): TextView {
43 | val layoutParams = LinearLayout.LayoutParams(
44 | LinearLayout.LayoutParams.WRAP_CONTENT,
45 | LinearLayout.LayoutParams.WRAP_CONTENT
46 | )
47 | val view = TextView(App.get())
48 | value.let { view.text = it }
49 | view.layoutParams = layoutParams
50 | return view
51 | }
52 |
53 | //动态创建TextView
54 | fun textView(linearLayout: ViewGroup?, value: String? = null): TextView {
55 | val view = textView(value)
56 | linearLayout?.addView(view)
57 | return view
58 | }
59 |
60 | //动态创建EditText
61 | fun editText(value: String = ""): EditText {
62 | val layoutParams = LinearLayout.LayoutParams(
63 | LinearLayout.LayoutParams.WRAP_CONTENT,
64 | LinearLayout.LayoutParams.WRAP_CONTENT
65 | )
66 | val view = EditText(App.get())
67 | view.setText(value)
68 | view.hint = "在这儿输入内容"
69 | view.layoutParams = layoutParams
70 | return view
71 | }
72 |
73 |
74 | //动态创建EditText
75 | fun editText(linearLayout: ViewGroup?, value: String = ""): EditText {
76 | val view = editText(value)
77 | linearLayout?.addView(view)
78 | return view
79 | }
80 |
81 | //动态创建EditText
82 | fun imageView(bitmap: Bitmap? = null): ImageView {
83 | val layoutParams = LinearLayout.LayoutParams(dp2px(300f), dp2px(300f))
84 | layoutParams.gravity = Gravity.CENTER_HORIZONTAL
85 | val view = ImageView(App.get())
86 | view.layoutParams = layoutParams
87 | bitmap.let { view.setImageBitmap(it) }
88 | return view
89 | }
90 |
91 | //动态创建EditText
92 | fun imageView(linearLayout: ViewGroup?, bitmap: Bitmap? = null): ImageView {
93 | val view = imageView(bitmap)
94 | linearLayout?.addView(view)
95 | return view
96 | }
97 |
98 | //添加空行
99 | fun space(linearLayout: ViewGroup?): Space {
100 | val view = Space(linearLayout?.context)
101 | val layoutParams = LinearLayout.LayoutParams(
102 | LinearLayout.LayoutParams.MATCH_PARENT,
103 | LinearLayout.LayoutParams.WRAP_CONTENT
104 | )
105 | view.layoutParams = layoutParams
106 | linearLayout?.addView(view)
107 | return view
108 | }
109 | }
110 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_all_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
16 |
17 |
20 |
21 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yutils/yhttp/52e791efa014d282b56414d1d209c442ba0c39fd/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yutils/yhttp/52e791efa014d282b56414d1d209c442ba0c39fd/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yutils/yhttp/52e791efa014d282b56414d1d209c442ba0c39fd/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yutils/yhttp/52e791efa014d282b56414d1d209c442ba0c39fd/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yutils/yhttp/52e791efa014d282b56414d1d209c442ba0c39fd/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yutils/yhttp/52e791efa014d282b56414d1d209c442ba0c39fd/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yutils/yhttp/52e791efa014d282b56414d1d209c442ba0c39fd/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yutils/yhttp/52e791efa014d282b56414d1d209c442ba0c39fd/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yutils/yhttp/52e791efa014d282b56414d1d209c442ba0c39fd/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yutils/yhttp/52e791efa014d282b56414d1d209c442ba0c39fd/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #6200EE
4 | #3700B3
5 | #03DAC5
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | test
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/network_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/provider_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/test/java/com/yujing/test/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.yujing.test
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/test/java/com/yujing/test/User.kt:
--------------------------------------------------------------------------------
1 | package com.yujing.test
2 |
3 | data class User(
4 | val code: Int,
5 | val data: DD?,
6 | val message: String
7 | )
8 |
9 | data class DD(
10 | val 可用内存: String,
11 | val 已使用内存: String,
12 | val 服务器时间: String,
13 | val 用户: 用户?
14 | )
15 |
16 | data class 用户(
17 | val createTime: String,
18 | val endLoginTime: String,
19 | val id: Int,
20 | val name: String,
21 | val nickName: String,
22 | val phone: String
23 | )
24 | class Test{
25 | fun test(){
26 |
27 |
28 | }
29 | }
--------------------------------------------------------------------------------
/app/src/test/java/com/yujing/test/YHttpTest.java:
--------------------------------------------------------------------------------
1 | package com.yujing.test;
2 |
3 | import com.yujing.utils.YNumber;
4 | import com.yutils.http.YHttp;
5 | import com.yutils.http.contract.YHttpDownloadFileListener;
6 | import com.yutils.http.contract.YHttpListener;
7 | import com.yutils.http.contract.YObjectListener;
8 | import com.yutils.http.model.Upload;
9 |
10 | import java.io.File;
11 | import java.util.ArrayList;
12 | import java.util.HashMap;
13 | import java.util.List;
14 | import org.junit.Test;
15 |
16 | public class YHttpTest {
17 |
18 | @Test
19 | public void main() throws InterruptedException {
20 | YHttp.setShowLog(false);
21 | test1();
22 | Thread.sleep(2000);
23 | download();
24 | }
25 |
26 | String session;
27 | private void test1() {
28 | String url = "http://192.168.6.9:8090/crash/user/login";
29 | HashMap hashMap = new HashMap<>();// = hashMapOf("name" to "yujing", "password" to "wtugeqh")
30 | hashMap.put("name", "yujing");
31 | hashMap.put("password", "wtugeqh");
32 |
33 | YHttp.create().setSessionListener(s -> session = s).post(url, hashMap, new YHttpListener() {
34 | @Override
35 | public void success(byte[] bytes, String s) {
36 | System.out.println("请求成功:" + s);
37 | test2();
38 | test3();
39 | }
40 |
41 | @Override
42 | public void fail(String s) {
43 | System.out.println("请求失败:" + s);
44 | }
45 | });
46 | }
47 |
48 | private void test2() {
49 | String url = "http://192.168.6.9:8090/crash/";
50 | YHttp.create().setSessionId(session).get(url, new YObjectListener() {
51 | @Override
52 | public void success(byte[] bytes, User value) {
53 | System.out.println("请求成功:" + value.toString());
54 | }
55 |
56 | @Override
57 | public void fail(String value) {
58 | System.out.println("请求失败:" + value);
59 | }
60 | });
61 | }
62 |
63 | private void test3() {
64 | String url = "http://192.168.6.9:8090/crash/upload/file";
65 | List uploads = new ArrayList<>();
66 | uploads.add(new Upload("file1", new File("D:/1.jpg")));
67 |
68 | YHttp.create().setSessionId(session).upload(url, "", uploads, new YHttpListener() {
69 | @Override
70 | public void success(byte[] bytes, String value) throws Exception {
71 | System.out.println("上传成功:" + value.toString());
72 | }
73 |
74 | @Override
75 | public void fail(String value) {
76 | System.out.println("上传失败:" + value.toString());
77 | }
78 | });
79 | }
80 |
81 | private void download() {
82 | String url = "https://down.qq.com/qqweb/PCQQ/PCQQ_EXE/PCQQ2020.exe";
83 | File f = new File("D:/PCQQ2020.exe ");
84 | YHttp.create().downloadFile(url, f, new YHttpDownloadFileListener() {
85 | @Override
86 | public void progress(int downloadSize, int fileSize) {
87 | System.out.println("当前进度:" + downloadSize + " " + fileSize + " " + YNumber.showNumber(downloadSize * 100d / fileSize));
88 | }
89 |
90 | @Override
91 | public void success(File file) {
92 | System.out.println("下载完成:" + file.getPath());
93 | }
94 |
95 | @Override
96 | public void fail(String value) {
97 | System.out.println("下载失败:" + value);
98 | }
99 | });
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application' version '8.0.1' apply false
3 | id 'com.android.library' version '8.0.1' apply false
4 | id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
5 | }
6 | task clean(type: Delete) {
7 | delete rootProject.buildDir
8 | }
--------------------------------------------------------------------------------
/doc/logcat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yutils/yhttp/52e791efa014d282b56414d1d209c442ba0c39fd/doc/logcat.png
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style=official
22 |
23 |
24 | #
25 | #signing.keyId=AEAADF14
26 | #signing.password=wtugeqh
27 | #signing.secretKeyRingFile=C\:\\Users\\yujing\\yujing_0xAEAADF14_public.gpg
28 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yutils/yhttp/52e791efa014d282b56414d1d209c442ba0c39fd/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 14 15:22:21 CST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenCentral()
6 | maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
7 | }
8 | }
9 |
10 | dependencyResolutionManagement {
11 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
12 | repositories {
13 | maven { url 'https://repo1.maven.org/maven2' }
14 | google()
15 | mavenCentral()
16 | }
17 | }
18 | rootProject.name='utils_yhttp'
19 | include ':app',':yhttp'
--------------------------------------------------------------------------------
/yhttp/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/yhttp/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java-library'
3 | }
4 | java {
5 | sourceCompatibility = JavaVersion.VERSION_1_8
6 | targetCompatibility = JavaVersion.VERSION_1_8
7 | }
8 | dependencies {
9 | //gson,https://mvnrepository.com/artifact/com.google.code.gson/gson
10 | implementation 'com.google.code.gson:gson:2.10.1'
11 | }
12 | //maven配置和签名文件,请注释掉该行
13 | apply from: "${getRootDir().absolutePath}/gradles/publish-maven.gradle"
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/Android.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.OutputStream;
5 | import java.lang.reflect.Constructor;
6 | import java.lang.reflect.Method;
7 |
8 | /**
9 | * 安卓常用方法,反射调用
10 | *
11 | * @author yujing 2021年9月11日15:56:45
12 | */
13 | /*
14 | 用法:
15 | //判断是否是安卓
16 | Android.isAndroid()
17 | //主线程中运行
18 | Android.runOnUiThread { }
19 | //Log
20 | Android.Log("d", "tag", "内容")
21 | //Toast
22 | Android.Toast(context,"内容")
23 | //bitmap转Byte数组
24 | Android.bitmapToByteArray(bitmap)
25 | */
26 | @SuppressWarnings("ALL")
27 | public class Android {
28 | //安卓里面的 Handler(Looper.getMainLooper());
29 | private static Object handler;
30 |
31 | static {
32 | try {
33 | if (handler == null) {
34 | //获取 Looper.getMainLooper()
35 | Class cLooper = Class.forName("android.os.Looper");
36 | Method mGetMainLooper = cLooper.getMethod("getMainLooper");
37 | Object looper = mGetMainLooper.invoke(null);
38 |
39 | //构造 Handler handler = new Handler(Looper.getMainLooper());
40 | Class cHandler = Class.forName("android.os.Handler");
41 | Constructor conHandler = cHandler.getConstructor(cLooper);
42 | handler = conHandler.newInstance(looper);
43 | }
44 | } catch (Exception e) {
45 | Log("e", "错误", e.getMessage());
46 | }
47 | }
48 |
49 | /**
50 | * 判断是否是安卓项目
51 | *
52 | * @return 是否
53 | */
54 | public static boolean isAndroid() {
55 | return handler != null;
56 | }
57 |
58 | /**
59 | * 在主线程中运行
60 | * 实际逻辑:
61 | * if (Looper.myLooper() == Looper.getMainLooper()) {
62 | * runnable.run();
63 | * } else {
64 | * HANDLER.post(runnable);
65 | * }
66 | *
67 | * @param runnable 执行的内容
68 | * @return 是否成功
69 | */
70 | public static boolean runOnUiThread(Runnable runnable) {
71 | if (!isAndroid()) {
72 | runnable.run();
73 | return true;
74 | }
75 | try {
76 | Class cLooper = Class.forName("android.os.Looper");
77 | Method mGetMainLooper = cLooper.getMethod("getMainLooper");
78 | Method mMyLooper = cLooper.getMethod("myLooper");
79 | if (mGetMainLooper.invoke(null) == mMyLooper.invoke(null)) {
80 | runnable.run();
81 | } else {
82 | Class classHandler = Class.forName("android.os.Handler");
83 | Method mPost = classHandler.getMethod("post", Runnable.class);
84 | mPost.invoke(handler, runnable);
85 | }
86 | return true;
87 | } catch (Exception e) {
88 | //Log("e", "错误", e.getMessage());
89 | //如果是非安卓,返回false
90 | return false;
91 | }
92 | }
93 |
94 | /**
95 | * 调用安卓Log,如Log.d("tag" ,"内容")
96 | * 使用方法,如: Log(""内容")
97 | *
98 | * @param msg msg
99 | * @return 是否成功
100 | */
101 | public static boolean Log(String msg) {
102 | return Log("i", "Android", msg, null);
103 | }
104 |
105 | /**
106 | * 调用安卓Log,如Log.d("tag" ,"内容")
107 | * 使用方法,如: Log("d","tag" ,"内容")
108 | *
109 | * @param type log——类型
110 | * @param tag log——tag
111 | * @param msg log——内容
112 | * @return 是否成功
113 | */
114 | public static boolean Log(String type, String tag, String msg) {
115 | return Log(type, tag, msg, null);
116 | }
117 |
118 | /**
119 | * 调用安卓Log,如Log.d("tag" ,"内容" , throwable)
120 | * 使用方法,如: Log("d","tag" ,"内容" , throwable)
121 | *
122 | * @param type log——类型
123 | * @param tag log——tag
124 | * @param msg log——内容
125 | * @param throwable log——throwable
126 | * @return 是否成功
127 | */
128 | public static boolean Log(String type, String tag, String msg, Throwable throwable) {
129 | try {
130 | Class cLog = Class.forName("android.util.Log");
131 | Method method = cLog.getMethod(type, String.class, String.class, Throwable.class);
132 | method.invoke(null, tag, " \n" + msg, throwable);
133 | return true;
134 | } catch (Exception e) {
135 | //System.out.println("打印日志错误:" + e.getMessage() + "\n日志:\ttype:" + type + "\ttag:" + tag + "\tmsg:" + msg);
136 | System.out.println("type:" + type + "\ttag:" + tag + "\tmsg:" + msg + ((throwable == null) ? "" : ("\tthrowable:" + throwable.toString())));
137 | }
138 | return false;
139 | }
140 |
141 | /**
142 | * 显示Toast
143 | * 实际逻辑:
144 | * Toast toast=Toast.makeText(context, "msg", Toast.LENGTH_SHORT)
145 | * toast.show()
146 | *
147 | * @param context context
148 | * @param msg 内容
149 | * @return 是否成功
150 | */
151 | public static boolean Toast(Object context, String msg) {
152 | return runOnUiThread(new Runnable() {
153 | @Override
154 | public void run() {
155 | try {
156 | Class cToast = Class.forName("android.widget.Toast");
157 | Method mMakeText = cToast.getMethod("makeText", Class.forName("android.content.Context"), Class.forName("java.lang.CharSequence"), int.class);
158 | Object obj = mMakeText.invoke(null, context, msg, 0);
159 | Method mShow = cToast.getMethod("show");
160 | mShow.invoke(obj);
161 | } catch (Exception e) {
162 | System.out.println("显示Toast错误:" + e.getMessage() + "\nmsg:" + msg);
163 | }
164 | }
165 | });
166 | }
167 |
168 |
169 | /**
170 | * bitmap转ByteArray
171 | * 相当于:
172 | * ByteArrayOutputStream baos = new ByteArrayOutputStream();
173 | * bitmap.compress(Bitmap.CompressFormat.JPEG, 90, baos);
174 | * baos.toByteArray();
175 | *
176 | * @param bitmap bitmap
177 | * @return ByteArray
178 | */
179 | public static byte[] bitmapToByteArray(Object bitmap) {
180 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
181 | try {
182 | Class cBitmap = Class.forName("android.graphics.Bitmap");
183 | Class cCompressFormat = Class.forName("android.graphics.Bitmap$CompressFormat");
184 | Object oFormat = null;
185 | for (int i = 0; i < cCompressFormat.getEnumConstants().length; i++) {
186 | //JPEG,PNG,WEBP
187 | if ("JPEG".equals(cCompressFormat.getEnumConstants()[i].toString())) {
188 | oFormat = cCompressFormat.getEnumConstants()[i];
189 | break;
190 | }
191 | }
192 | Method mCompress = cBitmap.getMethod("compress", cCompressFormat, int.class, OutputStream.class);
193 | mCompress.invoke(bitmap, oFormat, 90, baos);
194 | return baos.toByteArray();
195 | } catch (Exception e) {
196 | System.out.println("转换bitmap错误:" + e.getMessage());
197 | }
198 | return null;
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/YHttp.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http;
2 |
3 | import com.google.gson.Gson;
4 | import com.yutils.http.contract.ObjectListener;
5 | import com.yutils.http.contract.YFailListener;
6 | import com.yutils.http.contract.YHttpDownloadFileListener;
7 | import com.yutils.http.contract.YHttpListener;
8 | import com.yutils.http.contract.YHttpLoadListener;
9 | import com.yutils.http.contract.YObjectListener;
10 | import com.yutils.http.contract.YSessionListener;
11 | import com.yutils.http.contract.YSuccessListener;
12 | import com.yutils.http.model.Upload;
13 |
14 | import java.io.File;
15 | import java.io.FileNotFoundException;
16 | import java.io.IOException;
17 | import java.io.UnsupportedEncodingException;
18 | import java.net.MalformedURLException;
19 | import java.util.ArrayList;
20 | import java.util.List;
21 | import java.util.Map;
22 |
23 | /**
24 | * 网络请求类
25 | *
26 | * @author yujing 2021年12月24日09:50:29
27 | * 详细说明和最新版请查看 https://github.com/yutils/yhttp
28 | * 优点:
29 | * 1.支持get,post,put,delete请求,一行实现同步请求,一行实现异步请求
30 | * 2.post请求可为字符串,map,byte[]
31 | * 3.直接返回请求结果为 字符串 或 对象 或 byte[]
32 | * 4.支持各种格式文件下载,回调进度条
33 | * 5.单次文件上传请求中可以包含多种不同格式文件
34 | * 6.日志详细记录请求数据和结果,可关闭日志,异常请求回调异常原因
35 | * 7.支持https,支持设置ssl文件
36 | * 8.sessionID的获取和设置,可以切换多个不同sessionID
37 | * 9.简单好用,作者持续更新
38 | * 10.支持安卓,请求结果直接回调到UI线程(主线程)
39 | * 11.自定义gson,如:可以直接序列化指定日期格式的内容
40 | * 12.链式调用,代码更加简洁,可以不监听失败回调
41 | */
42 | /*基本用法举例
43 | //java
44 | YHttp.create().post(url, hashMap, new YObjectListener() {
45 | @Override
46 | public void success(byte[] bytes, User value) {
47 | //请求结果,对象
48 | }
49 |
50 | @Override
51 | public void fail(String value) {
52 | //错误原因
53 | }
54 | });
55 |
56 | //java文件上传
57 | String url = "http://192.168.6.9:8090/crash/upload/file";
58 | List uploads = new ArrayList<>();
59 | uploads.add(new Upload("file1", new File("D:/1.jpg")));
60 | uploads.add(new Upload("file2", "ABCDEF".getBytes()).setFilename("abcd.txt"));
61 |
62 | YHttp.create().setSessionId(session).upload(url, "", uploads, new YHttpListener() {
63 | @Override
64 | public void success(byte[] bytes, String value){
65 | System.out.println("上传成功:" + value);
66 | }
67 | @Override
68 | public void fail(String value) {
69 | System.out.println("上传失败:" + value);
70 | }
71 | });
72 |
73 |
74 | //kotlin
75 | val url = "https://down.qq.com/qqweb/PCQQ/PCQQ_EXE/PCQQ2020.exe"
76 | YHttp.create().setSessionId(session).get(url, object : YObjectListener(){
77 | override fun success(bytes: ByteArray?, value: User?) {
78 | //成功 User对象
79 | }
80 |
81 | override fun fail(value: String?) {
82 | //错误原因
83 | }
84 | })
85 |
86 | //文件上传
87 | val url = "http://192.168.6.9:8090/crash/upload/file"
88 | val list: MutableList = ArrayList()
89 | list.add(Upload("file1",file))
90 | list.add(Upload("file2", "ABCDEF".toByteArray()).setFilename("abcd.txt"))
91 | list.add(Upload("file3",bitmap))
92 | YHttp.create().setSessionId(session).upload(url, "", list, object : YHttpListener {
93 | override fun success(bytes: ByteArray?, value: String?) {
94 | //成功
95 | }
96 | override fun fail(value: String?) {
97 | //失败
98 | }
99 | })
100 |
101 | //文件下载,如是安卓,返回值自动回到主线程
102 | val url = "https://down.qq.com/qqweb/PCQQ/PCQQ_EXE/PCQQ2020.exe"
103 | var f = File( "D:/BB.exe")
104 | YHttp.create().downloadFile(url, f, object :
105 | YHttpDownloadFileListener {
106 | override fun progress(downloadSize: Int, fileSize: Int) {
107 | val progress = (10000.0 * downloadSize / fileSize).toInt() / 100.0 //下载进度,保留2位小数
108 | }
109 | override fun success(file: File) {}//下载完成
110 | override fun fail(value: String) {}//下载出错
111 | })
112 |
113 | //链式请求 java
114 | String url = "http://192.168.6.9:8090/crash/user/login";
115 | Map hashMap = new HashMap();// = hashMapOf("name" to "yujing", "password" to "wtugeqh")
116 | hashMap.put("name", "yujing");
117 | hashMap.put("password", "wtugeqh");
118 | YHttp.create()
119 | .url(url)
120 | .post(hashMap)
121 | .setSuccessListener((bytes, value) -> {
122 | System.out.println("请求成功:" + value);
123 | }).start();
124 |
125 | //链式,get
126 | YHttp
127 | .create()
128 | .url("http://192.168.6.9:8090/crash/")
129 | .get()
130 | .setSuccessListener { bytes, value -> textView1.text = "成功:$value" }
131 | .setFailListener { value -> textView2.text = "失败:$value" }
132 | .start()
133 |
134 | //链式,post
135 | val url = "http://192.168.6.9:8090/crash/user/login"
136 | val gson=YJson.getGsonDate( "yyyy年MM月dd日 HH:mm:ss")
137 | val hashMap: HashMap = hashMapOf("name" to "yujing", "password" to "wtugeqh")
138 | YHttp.create()
139 | .url(url)
140 | .post(hashMap)
141 | .setGson(gson)
142 | .setObjectListener(object : ObjectListener() {
143 | override fun success(bytes: ByteArray?, value: User?) {
144 | textView2.text = "\n对象:${value.toString()}"
145 | }
146 | })
147 | .setFailListener { value -> textView2.text = "失败:$value" }
148 | .start()
149 |
150 | //链式,自定义请求
151 | YHttp.create()
152 | .url(url)
153 | .method("POST")
154 | .setContentType("application/x-www-form-urlencoded;charset=utf-8")
155 | .addRequestProperty("connection", "Keep-Alive")
156 | .body(hashMap)
157 | .setGson(gson)
158 | .setSessionId(session)
159 | .setCrtSSL("SSL证书内容")
160 | .setSuccessListener { bytes, value -> textView1.text = "成功:$value" }
161 | .setObjectListener(object : ObjectListener() {
162 | override fun success(bytes: ByteArray?, value: User?) {
163 | textView2.text = "\n对象:${value.toString()}"
164 | }
165 | })
166 | .setFailListener { value -> textView2.text = "失败:$value" }
167 | .setSessionListener { sessionId -> session = sessionId }
168 | .start()
169 | */
170 | public class YHttp extends YHttpBase {
171 | private static volatile boolean showLog = true;
172 | private Object gson;//防止对方没引用Gson时完全无法使用
173 | private String requestUrl;//请求url
174 | private byte[] requestBytes;//请求内容
175 | private String requestMethod;//请求方式,只能是 "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
176 | private YSuccessListener successListener;//成功监听
177 | private ObjectListener objectListener;//成功监听,返回对象
178 | private YFailListener failListener;//失败监听
179 |
180 | /**
181 | * 设置 是否显示日志
182 | *
183 | * @param showLog 是否显示日志
184 | */
185 | public static void setShowLog(boolean showLog) {
186 | YHttp.showLog = showLog;
187 | }
188 |
189 | public YHttp() {
190 | }
191 |
192 | /**
193 | * 获取YHttp实例
194 | *
195 | * @return YHttp
196 | */
197 | public static YHttp create() {
198 | return new YHttp();
199 | }
200 |
201 | /**
202 | * 获取当前Gson对象
203 | *
204 | * @return Gson
205 | */
206 | public Gson getGson() {
207 | if (gson != null && gson instanceof Gson) {
208 | return (Gson) gson;
209 | } else {
210 | gson = new Gson();
211 | }
212 | return (Gson) gson;
213 | }
214 |
215 | /**
216 | * 设置当前Gson对象
217 | *
218 | * @param gson Gson
219 | * @return YHttp
220 | */
221 | public YHttp setGson(Gson gson) {
222 | this.gson = gson;
223 | return this;
224 | }
225 |
226 | /**
227 | * @param contentType 设置contentType,常见如
228 | * "application/x-www-form-urlencoded;charset=utf-8"
229 | * "application/json;charset=utf-8"
230 | * @return YHttp
231 | */
232 | @Override
233 | public YHttp setContentType(String contentType) {
234 | super.setContentType(contentType);
235 | return this;
236 | }
237 |
238 | /**
239 | * 设置超时时间
240 | *
241 | * @param connectTimeout 毫秒
242 | * @return YHttp
243 | */
244 | @Override
245 | public YHttp setConnectTimeout(int connectTimeout) {
246 | super.setConnectTimeout(connectTimeout);
247 | return this;
248 | }
249 |
250 | /**
251 | * 设置SSL证书内容
252 | *
253 | * @param crtSSL ssl
254 | * @return YHttp
255 | */
256 | @Override
257 | public YHttp setCrtSSL(String crtSSL) {
258 | super.setCrtSSL(crtSSL);
259 | return this;
260 | }
261 |
262 | /**
263 | * 设置请求头
264 | * 如:
265 | * "connection","Keep-Alive"
266 | * "Charset","utf-8"
267 | *
268 | * @param key key
269 | * @param value value
270 | * @return YHttp
271 | */
272 | @Override
273 | public YHttp setRequestProperty(String key, String value) {
274 | super.setRequestProperty(key, value);
275 | return this;
276 | }
277 |
278 | /**
279 | * 添加请求头
280 | * 如:
281 | * "connection","Keep-Alive"
282 | * "Charset","utf-8"
283 | *
284 | * @param key key
285 | * @param value value
286 | * @return YHttp
287 | */
288 | @Override
289 | public YHttp addRequestProperty(String key, String value) {
290 | super.addRequestProperty(key, value);
291 | return this;
292 | }
293 |
294 | /**
295 | * 设置 Session回调
296 | *
297 | * @param ySessionListener 回调服务返回的sessionId
298 | * @return YHttp
299 | */
300 | @Override
301 | public YHttp setSessionListener(YSessionListener ySessionListener) {
302 | super.setSessionListener(ySessionListener);
303 | return this;
304 | }
305 |
306 | /**
307 | * 设置 sessionId
308 | *
309 | * @param sessionId sessionId
310 | * @return YHttp
311 | */
312 | @Override
313 | public YHttp setSessionId(String sessionId) {
314 | super.setSessionId(sessionId);
315 | return this;
316 | }
317 |
318 | /**
319 | * 设置 请求地址
320 | *
321 | * @param url url地址,http:// 或 https:// 开头
322 | * @return YHttp
323 | */
324 | public YHttp url(String url) {
325 | requestUrl = url;
326 | return this;
327 | }
328 |
329 | /**
330 | * 设置 请求内容
331 | *
332 | * @param json json/文本
333 | * @return YHttp
334 | */
335 | public YHttp body(String json) {
336 | requestBytes = json.getBytes();
337 | return this;
338 | }
339 |
340 | /**
341 | * 设置 请求内容
342 | *
343 | * @param paramsMap paramsMap,key,value方式
344 | * @return YHttp
345 | */
346 | public YHttp body(Map paramsMap) {
347 | requestBytes = YHttpUtils.mapToParams(paramsMap).toString().getBytes();
348 | return this;
349 | }
350 |
351 | /**
352 | * 设置 请求内容
353 | *
354 | * @param bytes bytes
355 | * @return YHttp
356 | */
357 | public YHttp body(byte[] bytes) {
358 | requestBytes = bytes;
359 | return this;
360 | }
361 |
362 | /**
363 | * 设置 请求方式
364 | *
365 | * @param method "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
366 | * @return YHttp
367 | */
368 | public YHttp method(String method) {
369 | this.requestMethod = method;
370 | return this;
371 | }
372 |
373 | /**
374 | * 设置 请求成功监听,回调字符串
375 | *
376 | * @param successListener 成功返回请求的字符串,和byte数组
377 | * @return YHttp
378 | */
379 | public YHttp setSuccessListener(YSuccessListener successListener) {
380 | this.successListener = successListener;
381 | return this;
382 | }
383 |
384 | /**
385 | * 设置 请求成功监听,回调对象
386 | *
387 | * @param objectListener 成功返回object
388 | * @return YHttp
389 | */
390 | public YHttp setObjectListener(ObjectListener objectListener) {
391 | this.objectListener = objectListener;
392 | return this;
393 | }
394 |
395 | /**
396 | * 设置 请求失败监听
397 | *
398 | * @param failListener 失败返回原因
399 | * @return YHttp
400 | */
401 | public YHttp setFailListener(YFailListener failListener) {
402 | this.failListener = failListener;
403 | return this;
404 | }
405 |
406 | /**
407 | * 设置请求类型 get
408 | *
409 | * @return YHttp
410 | */
411 | public YHttp get() {
412 | requestMethod = "GET";
413 | return this;
414 | }
415 |
416 | /**
417 | * 设置请求类型 post
418 | *
419 | * @return YHttp
420 | */
421 | public YHttp post() {
422 | requestMethod = "POST";
423 | return this;
424 | }
425 |
426 | /**
427 | * 设置请求类型 post
428 | *
429 | * @param json json/字符串
430 | * @return YHttp
431 | */
432 | public YHttp post(String json) {
433 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
434 | return post().body(json);
435 | }
436 |
437 | /**
438 | * 设置请求类型 post
439 | *
440 | * @param paramsMap paramsMap
441 | * @return YHttp
442 | */
443 | public YHttp post(Map paramsMap) {
444 | return post().body(paramsMap);
445 | }
446 |
447 | /**
448 | * 设置请求类型 post
449 | *
450 | * @param bytes bytes
451 | * @return YHttp
452 | */
453 | public YHttp post(byte[] bytes) {
454 | return post().body(bytes);
455 | }
456 |
457 | /**
458 | * 设置请求类型 put
459 | *
460 | * @return YHttp
461 | */
462 | public YHttp put() {
463 | requestMethod = "PUT";
464 | return this;
465 | }
466 |
467 | /**
468 | * 设置请求类型 put
469 | *
470 | * @param json json/字符串
471 | * @return YHttp
472 | */
473 | public YHttp put(String json) {
474 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
475 | return put().body(json);
476 | }
477 |
478 | /**
479 | * 设置请求类型 put
480 | *
481 | * @param paramsMap paramsMap
482 | * @return YHttp
483 | */
484 | public YHttp put(Map paramsMap) {
485 | return put().body(paramsMap);
486 | }
487 |
488 | /**
489 | * 设置请求类型 put
490 | *
491 | * @param bytes bytes
492 | * @return YHttp
493 | */
494 | public YHttp put(byte[] bytes) {
495 | return put().body(bytes);
496 | }
497 |
498 | /**
499 | * 设置请求类型 delete
500 | *
501 | * @return YHttp
502 | */
503 | public YHttp delete() {
504 | requestMethod = "DELETE";
505 | return this;
506 | }
507 |
508 | /**
509 | * 设置请求类型 delete
510 | *
511 | * @param json json/字符串
512 | * @return YHttp
513 | */
514 | public YHttp delete(String json) {
515 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
516 | return delete().body(json);
517 | }
518 |
519 | /**
520 | * 设置请求类型 delete
521 | *
522 | * @param paramsMap paramsMap
523 | * @return YHttp
524 | */
525 | public YHttp delete(Map paramsMap) {
526 | return delete().body(paramsMap);
527 | }
528 |
529 | /**
530 | * 设置请求类型 delete
531 | *
532 | * @param bytes bytes
533 | * @return YHttp
534 | */
535 | public YHttp delete(byte[] bytes) {
536 | return delete().body(bytes);
537 | }
538 |
539 | /**
540 | * 设置请求成功监听
541 | *
542 | * @param listener 成功返回object,失败返回原因
543 | */
544 | public void YObjectListener(YObjectListener listener) {
545 | YObjectListener listener2 = listener;
546 | }
547 |
548 | /**
549 | * 开始网络请求,链式时可以调用
550 | */
551 | public void start() {
552 | request(requestUrl, requestBytes, requestMethod, new YHttpListener() {
553 | @Override
554 | public void success(byte[] bytes, String value) throws Exception {
555 | if (successListener != null) successListener.success(bytes, value);
556 | if (objectListener != null) {
557 | println("json转对象:" + objectListener.getType());
558 | try {
559 | //如果是安卓就用handler调回到主线程,如果是普通JAVA工程,直接回调到线程
560 | Android.runOnUiThread(() -> {
561 | try {
562 | if (String.class.equals(objectListener.getType())) {
563 | objectListener.success(bytes, (T) value);
564 | } else if ("byte[]".equals(objectListener.getType().toString())) {
565 | objectListener.success(bytes, (T) bytes);
566 | } else {
567 | T object = getGson().fromJson(value, objectListener.getType());
568 | objectListener.success(bytes, object);
569 | }
570 | } catch (Exception e) {
571 | if (failListener != null)
572 | failListener.fail("异常:" + e.getMessage());
573 | e.printStackTrace();
574 | }
575 | });
576 | } catch (java.lang.ClassCastException e) {
577 | if (failListener != null)
578 | failListener.fail("对象转换失败");
579 | e.printStackTrace();
580 | } catch (Exception e) {
581 | if (failListener != null)
582 | failListener.fail("异常:" + e.getMessage());
583 | e.printStackTrace();
584 | }
585 | }
586 | }
587 |
588 | @Override
589 | public void fail(String value) {
590 | failListener.fail(value);
591 | }
592 | });
593 | }
594 | //----------------------------------------------GET----------------------------------------------
595 |
596 | /**
597 | * get请求
598 | *
599 | * @param requestUrl url
600 | * @param listener 监听
601 | */
602 | public void get(final String requestUrl, YHttpListener listener) {
603 | request(requestUrl, new byte[0], "GET", listener);
604 | }
605 |
606 | /**
607 | * get请求
608 | *
609 | * @param requestUrl url
610 | * @param listener 监听
611 | */
612 | public void get(final String requestUrl, YObjectListener listener) {
613 | request(requestUrl, new byte[0], "GET", listener);
614 | }
615 | //----------------------------------------------POST----------------------------------------------
616 |
617 | /**
618 | * post请求
619 | *
620 | * @param requestUrl url
621 | * @param paramsMap key,value
622 | * @param listener 监听
623 | */
624 | public void post(final String requestUrl, Map paramsMap, YHttpListener listener) {
625 | request(requestUrl, YHttpUtils.mapToParams(paramsMap).toString().getBytes(), "POST", listener);
626 | }
627 |
628 | /**
629 | * post请求
630 | *
631 | * @param requestUrl url
632 | * @param json json/文本
633 | * @param listener 监听
634 | */
635 | public void post(final String requestUrl, String json, YHttpListener listener) {
636 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
637 | request(requestUrl, json.getBytes(), "POST", listener);
638 | }
639 |
640 | /**
641 | * post请求
642 | *
643 | * @param requestUrl url
644 | * @param requestBytes bytes
645 | * @param listener 监听
646 | */
647 | public void post(final String requestUrl, byte[] requestBytes, YHttpListener listener) {
648 | request(requestUrl, requestBytes, "POST", listener);
649 | }
650 |
651 | /**
652 | * post请求
653 | *
654 | * @param requestUrl url
655 | * @param paramsMap key,value
656 | * @param listener 监听
657 | */
658 | public void post(String requestUrl, Map paramsMap, YObjectListener listener) {
659 | request(requestUrl, YHttpUtils.mapToParams(paramsMap).toString().getBytes(), "POST", listener);
660 | }
661 |
662 | /**
663 | * post请求
664 | *
665 | * @param requestUrl url
666 | * @param json json/文本
667 | * @param listener 监听
668 | */
669 | public void post(String requestUrl, String json, YObjectListener listener) {
670 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
671 | request(requestUrl, json.getBytes(), "POST", listener);
672 | }
673 |
674 | /**
675 | * post请求
676 | *
677 | * @param requestUrl url
678 | * @param requestBytes bytes
679 | * @param listener 监听
680 | */
681 | public void post(String requestUrl, byte[] requestBytes, YObjectListener listener) {
682 | request(requestUrl, requestBytes, "POST", listener);
683 | }
684 |
685 | //----------------------------------------------PUT----------------------------------------------
686 |
687 | /**
688 | * put请求
689 | *
690 | * @param requestUrl url
691 | * @param paramsMap key,value
692 | * @param listener 监听
693 | */
694 | public void put(String requestUrl, Map paramsMap, YHttpListener listener) {
695 | request(requestUrl, YHttpUtils.mapToParams(paramsMap).toString().getBytes(), "PUT", listener);
696 | }
697 |
698 | /**
699 | * put请求
700 | *
701 | * @param requestUrl url
702 | * @param json json/文本
703 | * @param listener 监听
704 | */
705 | public void put(String requestUrl, String json, YHttpListener listener) {
706 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
707 | request(requestUrl, json.getBytes(), "PUT", listener);
708 | }
709 |
710 | /**
711 | * put请求
712 | *
713 | * @param requestUrl url
714 | * @param requestBytes bytes
715 | * @param listener 监听
716 | */
717 | public void put(String requestUrl, byte[] requestBytes, YHttpListener listener) {
718 | request(requestUrl, requestBytes, "PUT", listener);
719 | }
720 |
721 | /**
722 | * put请求
723 | *
724 | * @param requestUrl url
725 | * @param paramsMap key,value
726 | * @param listener 监听
727 | */
728 | public void put(String requestUrl, Map paramsMap, YObjectListener listener) {
729 | request(requestUrl, YHttpUtils.mapToParams(paramsMap).toString().getBytes(), "PUT", listener);
730 | }
731 |
732 | /**
733 | * put请求
734 | *
735 | * @param requestUrl url
736 | * @param json json/文本
737 | * @param listener 监听
738 | */
739 | public void put(String requestUrl, String json, YObjectListener listener) {
740 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
741 | request(requestUrl, json.getBytes(), "PUT", listener);
742 | }
743 |
744 | /**
745 | * put请求
746 | *
747 | * @param requestUrl url
748 | * @param requestBytes bytes
749 | * @param listener 监听
750 | */
751 | public void put(String requestUrl, byte[] requestBytes, YObjectListener listener) {
752 | request(requestUrl, requestBytes, "PUT", listener);
753 | }
754 |
755 | //----------------------------------------------DELETE----------------------------------------------
756 |
757 | /**
758 | * delete请求
759 | *
760 | * @param requestUrl url
761 | * @param paramsMap key,value
762 | * @param listener 监听
763 | */
764 | public void delete(String requestUrl, Map paramsMap, YHttpListener listener) {
765 | request(requestUrl, YHttpUtils.mapToParams(paramsMap).toString().getBytes(), "DELETE", listener);
766 | }
767 |
768 | /**
769 | * delete请求
770 | *
771 | * @param requestUrl url
772 | * @param json json/文本
773 | * @param listener 监听
774 | */
775 | public void delete(String requestUrl, String json, YHttpListener listener) {
776 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
777 | request(requestUrl, json.getBytes(), "DELETE", listener);
778 | }
779 |
780 | /**
781 | * delete请求
782 | *
783 | * @param requestUrl url
784 | * @param requestBytes bytes
785 | * @param listener 监听
786 | */
787 | public void delete(String requestUrl, byte[] requestBytes, YHttpListener listener) {
788 | request(requestUrl, requestBytes, "DELETE", listener);
789 | }
790 |
791 | /**
792 | * delete请求
793 | *
794 | * @param requestUrl url
795 | * @param paramsMap key,value
796 | * @param listener 监听
797 | */
798 | public void delete(String requestUrl, Map paramsMap, YObjectListener listener) {
799 | request(requestUrl, YHttpUtils.mapToParams(paramsMap).toString().getBytes(), "DELETE", listener);
800 | }
801 |
802 | /**
803 | * delete请求
804 | *
805 | * @param requestUrl url
806 | * @param json json/文本
807 | * @param listener 监听
808 | */
809 | public void delete(String requestUrl, String json, YObjectListener listener) {
810 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
811 | request(requestUrl, json.getBytes(), "DELETE", listener);
812 | }
813 |
814 | /**
815 | * delete请求
816 | *
817 | * @param requestUrl url
818 | * @param requestBytes bytes
819 | * @param listener 监听
820 | */
821 | public void delete(String requestUrl, byte[] requestBytes, YObjectListener listener) {
822 | request(requestUrl, requestBytes, "DELETE", listener);
823 | }
824 |
825 | //----------------------------------------------request----------------------------------------------
826 |
827 | /**
828 | * request请求
829 | *
830 | * @param requestUrl url
831 | * @param paramsMap key,value
832 | * @param requestMethod 请求类型,只能是 "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
833 | * @param listener 监听
834 | */
835 | public void request(String requestUrl, Map paramsMap, String requestMethod, YHttpListener listener) {
836 | request(requestUrl, YHttpUtils.mapToParams(paramsMap).toString().getBytes(), requestMethod, listener);
837 | }
838 |
839 | /**
840 | * request请求
841 | *
842 | * @param requestUrl url
843 | * @param json json/文本
844 | * @param requestMethod 请求类型,只能是 "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
845 | * @param listener 监听
846 | */
847 | public void request(String requestUrl, String json, String requestMethod, YHttpListener listener) {
848 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
849 | request(requestUrl, json.getBytes(), requestMethod, listener);
850 | }
851 |
852 | /**
853 | * request请求
854 | *
855 | * @param requestUrl url
856 | * @param paramsMap key,value
857 | * @param requestMethod 请求类型,只能是 "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
858 | * @param listener 监听
859 | */
860 | public void request(String requestUrl, Map paramsMap, String requestMethod, YObjectListener listener) {
861 | request(requestUrl, YHttpUtils.mapToParams(paramsMap).toString().getBytes(), requestMethod, listener);
862 | }
863 |
864 | /**
865 | * request请求
866 | *
867 | * @param requestUrl url
868 | * @param json json/文本
869 | * @param requestMethod 请求类型,只能是 "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
870 | * @param listener 监听
871 | */
872 | public void request(String requestUrl, String json, String requestMethod, YObjectListener listener) {
873 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
874 | request(requestUrl, json.getBytes(), requestMethod, listener);
875 | }
876 |
877 | /**
878 | * request请求
879 | *
880 | * @param requestUrl url
881 | * @param requestBytes byte数组
882 | * @param requestMethod 请求类型,只能是 "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
883 | * @param listener 监听
884 | */
885 | public void request(final String requestUrl, final byte[] requestBytes, String requestMethod, final YHttpListener listener) {
886 | Thread thread = new Thread(() -> {
887 | long startTime = System.currentTimeMillis();
888 | try {
889 | byte[] bytes = request(requestUrl, requestBytes, requestMethod);
890 | String result = new String(bytes);
891 | if (showLog) {
892 | String info = "请求地址:" + requestMethod + "--->" + requestUrl;
893 | if (requestBytes != null && requestBytes.length != 0)
894 | info += "\n请求参数:" + new String(requestBytes);
895 | info += "\n请求结果:" + result;
896 | info += "\n耗时:" + (System.currentTimeMillis() - startTime) + "毫秒";
897 | println(info);
898 | }
899 | Android.runOnUiThread(() -> {
900 | try {
901 | listener.success(bytes, result);
902 | } catch (Exception e) {
903 | listener.fail("异常:" + e.getMessage());
904 | e.printStackTrace();
905 | }
906 | });
907 | } catch (Exception e) {
908 | if (showLog) {
909 | String info = "请求地址:" + requestMethod + "--->" + requestUrl;
910 | if (requestBytes != null) info += "\n请求参数:" + new String(requestBytes);
911 | info += "\n请求异常:" + exceptionToString(e);
912 | info += "\n耗时:" + (System.currentTimeMillis() - startTime) + "毫秒";
913 | println(info);
914 | }
915 | exception(e, listener);
916 | } finally {
917 | YHttpThreadPool.shutdown();
918 | }
919 | });
920 | thread.setName("request请求:" + requestUrl);
921 | YHttpThreadPool.add(thread);
922 | }
923 |
924 | /**
925 | * request请求
926 | *
927 | * @param requestUrl url
928 | * @param requestBytes byte数组
929 | * @param requestMethod 请求类型,只能是 "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
930 | * @param listener 监听
931 | */
932 | public void request(String requestUrl, byte[] requestBytes, String requestMethod, final YObjectListener listener) {
933 | request(requestUrl, requestBytes, requestMethod, new YHttpListener() {
934 | @Override
935 | public void success(byte[] bytes, String value) {
936 | println("json转对象:" + listener.getType());
937 | try {
938 | Android.runOnUiThread(() -> {
939 | try {
940 | if (String.class.equals(listener.getType())) {
941 | listener.success(bytes, (T) value);
942 | } else if ("byte[]".equals(listener.getType().toString())) {
943 | listener.success(bytes, (T) bytes);
944 | } else {
945 | T object = getGson().fromJson(value, listener.getType());
946 | listener.success(bytes, object);
947 | }
948 | } catch (Exception e) {
949 | listener.fail("异常:" + e.getMessage());
950 | e.printStackTrace();
951 | }
952 | });
953 | } catch (java.lang.ClassCastException e) {
954 | listener.fail("对象转换失败");
955 | e.printStackTrace();
956 | } catch (Exception e) {
957 | listener.fail("异常:" + e.getMessage());
958 | e.printStackTrace();
959 | }
960 | }
961 |
962 | @Override
963 | public void fail(String value) {
964 | listener.fail(value);
965 | }
966 | });
967 | }
968 |
969 | /**
970 | * 文件上传post
971 | *
972 | * @param requestUrl url
973 | * @param paramsMap key,value
974 | * @param fileMap 文件列表
975 | * @param listener 监听
976 | */
977 | public void upload(String requestUrl, Map paramsMap, Map fileMap, YHttpListener listener) {
978 | upload(requestUrl, YHttpUtils.mapToParams(paramsMap).toString().getBytes(), fileMap, listener);
979 | }
980 |
981 | /**
982 | * 文件上传post
983 | *
984 | * @param requestUrl url
985 | * @param json json/文本
986 | * @param fileMap 文件列表
987 | * @param listener 监听
988 | */
989 | public void upload(String requestUrl, String json, Map fileMap, YHttpListener listener) {
990 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
991 | upload(requestUrl, json.getBytes(), fileMap, listener);
992 | }
993 |
994 | /**
995 | * 文件上传post
996 | *
997 | * @param requestUrl url
998 | * @param requestBytes bytes
999 | * @param fileMap 文件列表
1000 | * @param listener 监听
1001 | */
1002 | public void upload(String requestUrl, byte[] requestBytes, Map fileMap, YHttpListener listener) {
1003 | List uploads = new ArrayList<>();
1004 | for (Map.Entry entry : fileMap.entrySet()) {
1005 | if (entry.getValue() == null) continue;
1006 | uploads.add(new Upload(entry.getKey(), entry.getValue()));
1007 | }
1008 | upload(requestUrl, requestBytes, uploads, listener);
1009 | }
1010 |
1011 | /**
1012 | * 文件上传post
1013 | *
1014 | * @param requestUrl url
1015 | * @param paramsMap key,value
1016 | * @param uploads 上传的key,内容,文件名,contentType
1017 | * @param listener 监听
1018 | */
1019 | public void upload(String requestUrl, Map paramsMap, List uploads, YHttpListener listener) {
1020 | upload(requestUrl, YHttpUtils.mapToParams(paramsMap).toString().getBytes(), uploads, listener);
1021 | }
1022 |
1023 | /**
1024 | * 文件上传post
1025 | *
1026 | * @param requestUrl url
1027 | * @param json json/文本
1028 | * @param uploads 上传的key,内容,文件名,contentType
1029 | * @param listener 监听
1030 | */
1031 | public void upload(String requestUrl, String json, List uploads, YHttpListener listener) {
1032 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
1033 | upload(requestUrl, json.getBytes(), uploads, listener);
1034 | }
1035 |
1036 | /**
1037 | * 文件上传post
1038 | *
1039 | * @param requestUrl url
1040 | * @param requestBytes bytes
1041 | * @param uploads 上传的key,内容,文件名,contentType
1042 | * @param listener 监听
1043 | */
1044 | public void upload(final String requestUrl, final byte[] requestBytes, final List uploads, final YHttpListener listener) {
1045 | Thread thread = new Thread(() -> {
1046 | long startTime = System.currentTimeMillis();
1047 | try {
1048 | byte[] bytes = upload(requestUrl, requestBytes, uploads);
1049 | String result = new String(bytes);
1050 | if (showLog) {
1051 | String info = "文件上传\n请求地址:" + requestMethod + "--->" + requestUrl;
1052 | if (requestBytes != null && requestBytes.length != 0)
1053 | info += "\n请求参数:" + new String(requestBytes);
1054 | info += "\n文件数:" + uploads.size();
1055 | info += "\n请求结果:" + result;
1056 | info += "\n耗时:" + (System.currentTimeMillis() - startTime) + "毫秒";
1057 | println(info);
1058 | }
1059 | Android.runOnUiThread(() -> {
1060 | try {
1061 | listener.success(bytes, result);
1062 | } catch (Exception e) {
1063 | listener.fail("异常:" + e.getMessage());
1064 | e.printStackTrace();
1065 | }
1066 | });
1067 | } catch (Exception e) {
1068 | if (showLog) {
1069 | String info = "文件上传\n请求地址:" + requestMethod + "--->" + requestUrl;
1070 | if (requestBytes != null) info += "\n请求参数:" + new String(requestBytes);
1071 | info += "\n文件数:" + uploads.size();
1072 | info += "\n请求异常:" + exceptionToString(e);
1073 | info += "\n耗时:" + (System.currentTimeMillis() - startTime) + "毫秒";
1074 | println(info);
1075 | }
1076 | exception(e, listener);
1077 | } finally {
1078 | YHttpThreadPool.shutdown();
1079 | }
1080 | });
1081 | thread.setName("文件上传post:" + requestUrl);
1082 | YHttpThreadPool.add(thread);
1083 | }
1084 |
1085 | /**
1086 | * 文件上传post,返回对象
1087 | *
1088 | * @param requestUrl url
1089 | * @param paramsMap 参数
1090 | * @param uploads 上传对象列表
1091 | * @param listener 返回对象监听
1092 | */
1093 | public void upload(String requestUrl, Map paramsMap, List uploads, YObjectListener listener) {
1094 | upload(requestUrl, YHttpUtils.mapToParams(paramsMap).toString().getBytes(), uploads, listener);
1095 | }
1096 |
1097 | /**
1098 | * 文件上传post,返回对象
1099 | *
1100 | * @param requestUrl url
1101 | * @param json json/文本
1102 | * @param uploads 上传对象列表
1103 | * @param listener 返回对象监听
1104 | */
1105 | public void upload(String requestUrl, String json, List uploads, YObjectListener listener) {
1106 | if (getContentType() == null) setContentType("application/json;charset=utf-8");
1107 | upload(requestUrl, json.getBytes(), uploads, listener);
1108 | }
1109 |
1110 | /**
1111 | * 文件上传post,返回对象
1112 | *
1113 | * @param requestUrl url
1114 | * @param requestBytes 参数
1115 | * @param uploads 上传对象列表
1116 | * @param listener 返回对象监听
1117 | */
1118 | public void upload(final String requestUrl, final byte[] requestBytes, final List uploads, final YObjectListener listener) {
1119 | upload(requestUrl, requestBytes, uploads, new YHttpListener() {
1120 | @Override
1121 | public void success(byte[] bytes, String value) {
1122 | println("json转对象:" + listener.getType());
1123 | try {
1124 | Android.runOnUiThread(() -> {
1125 | try {
1126 | if (String.class.equals(listener.getType())) {
1127 | listener.success(bytes, (T) value);
1128 | } else if ("byte[]".equals(listener.getType().toString())) {
1129 | listener.success(bytes, (T) bytes);
1130 | } else {
1131 | T object = getGson().fromJson(value, listener.getType());
1132 | listener.success(bytes, object);
1133 | }
1134 | } catch (Exception e) {
1135 | listener.fail("异常:" + e.getMessage());
1136 | e.printStackTrace();
1137 | }
1138 | });
1139 | } catch (java.lang.ClassCastException e) {
1140 | listener.fail("对象转换失败");
1141 | e.printStackTrace();
1142 | } catch (Exception e) {
1143 | listener.fail("异常:" + e.getMessage());
1144 | e.printStackTrace();
1145 | }
1146 | }
1147 |
1148 | @Override
1149 | public void fail(String value) {
1150 | listener.fail(value);
1151 | }
1152 | });
1153 | }
1154 |
1155 | /**
1156 | * 文件下载,get请求,回调进度
1157 | *
1158 | * @param requestUrl url
1159 | * @param file 保存的文件
1160 | * @param listener 监听
1161 | */
1162 | public void downloadFile(final String requestUrl, final File file, final YHttpDownloadFileListener listener) {
1163 | Thread thread = new Thread(() -> {
1164 | long startTime = System.currentTimeMillis();
1165 | try {
1166 | downloadFile(requestUrl, file, (size, sizeCount) -> {
1167 | Android.runOnUiThread(() -> {
1168 | try {
1169 | listener.progress(size, sizeCount);
1170 | } catch (Exception e) {
1171 | listener.fail("异常:" + e.getMessage());
1172 | e.printStackTrace();
1173 | }
1174 | });
1175 | });
1176 | if (showLog) {
1177 | String info = "文件下载\n请求地址:" + "GET" + "--->" + requestUrl;
1178 | info += "\n保存成功:" + file.getPath();
1179 | info += "\n耗时:" + (System.currentTimeMillis() - startTime) + "毫秒";
1180 | println(info);
1181 | }
1182 | Android.runOnUiThread(() -> {
1183 | try {
1184 | listener.success(file);
1185 | } catch (Exception e) {
1186 | listener.fail("异常:" + e.getMessage());
1187 | e.printStackTrace();
1188 | }
1189 | });
1190 | } catch (Exception e) {
1191 | if (showLog) {
1192 | String info = "文件下载\n请求地址:" + "GET" + "--->" + requestUrl;
1193 | info += "\n请求异常:" + exceptionToString(e);
1194 | info += "\n耗时:" + (System.currentTimeMillis() - startTime) + "毫秒";
1195 | println(info);
1196 | }
1197 | exception(e, listener);
1198 | } finally {
1199 | YHttpThreadPool.shutdown();
1200 | }
1201 | });
1202 | thread.setName("文件下载,get:" + requestUrl);
1203 | YHttpThreadPool.add(thread);
1204 | }
1205 |
1206 | /**
1207 | * 加载get请求,回调进度
1208 | *
1209 | * @param requestUrl url
1210 | * @param listener 监听
1211 | */
1212 | public void load(final String requestUrl, final YHttpLoadListener listener) {
1213 | Thread thread = new Thread(() -> {
1214 | long startTime = System.currentTimeMillis();
1215 | try {
1216 | byte[] bytes = load(requestUrl, (size, sizeCount) -> {
1217 | Android.runOnUiThread(() -> {
1218 | try {
1219 | listener.progress(size, sizeCount);
1220 | } catch (Exception e) {
1221 | listener.fail("异常:" + e.getMessage());
1222 | e.printStackTrace();
1223 | }
1224 | });
1225 | });
1226 | if (showLog) {
1227 | String info = "文件加载\n请求地址:" + "GET" + "--->" + requestUrl;
1228 | info += "\n文件加载完成";
1229 | info += "\n耗时:" + (System.currentTimeMillis() - startTime) + "毫秒";
1230 | println(info);
1231 | }
1232 | Android.runOnUiThread(() -> {
1233 | try {
1234 | listener.success(bytes);
1235 | } catch (Exception e) {
1236 | listener.fail("异常:" + e.getMessage());
1237 | e.printStackTrace();
1238 | }
1239 | });
1240 | } catch (Exception e) {
1241 | if (showLog) {
1242 | String info = "文件加载\n请求地址:" + "GET" + "--->" + requestUrl;
1243 | info += "\n请求异常:" + exceptionToString(e);
1244 | info += "\n耗时:" + (System.currentTimeMillis() - startTime) + "毫秒";
1245 | println(info);
1246 | }
1247 | exception(e, listener);
1248 | } finally {
1249 | YHttpThreadPool.shutdown();
1250 | }
1251 | });
1252 | thread.setName("加载get请求,回调进度:" + requestUrl);
1253 | YHttpThreadPool.add(thread);
1254 | }
1255 |
1256 | /**
1257 | * 错误情况处理
1258 | *
1259 | * @param e 错误
1260 | * @param listener 监听
1261 | */
1262 | void exception(Exception e, Object listener) {
1263 | Android.runOnUiThread(() -> {
1264 | error(exceptionToString(e), listener);
1265 | });
1266 | }
1267 |
1268 | String exceptionToString(Exception e) {
1269 | if (e instanceof MalformedURLException) {
1270 | return "URL地址不规范";
1271 | } else if (e instanceof java.net.SocketTimeoutException) {
1272 | return "网络连接超时";
1273 | } else if (e instanceof UnsupportedEncodingException) {
1274 | return "不支持的编码";
1275 | } else if (e instanceof FileNotFoundException) {
1276 | return "找不到该地址";
1277 | } else if (e instanceof IOException) {
1278 | return "连接服务器失败";
1279 | } else {
1280 | if ("终止下载".equals(e.getMessage())) {
1281 | return "终止下载";
1282 | } else {
1283 | return "请求失败 " + e.getMessage();
1284 | }
1285 | }
1286 | }
1287 |
1288 | /**
1289 | * 错误回调
1290 | *
1291 | * @param error 错误
1292 | * @param listener 监听
1293 | */
1294 | void error(String error, Object listener) {
1295 | printlnE(error);
1296 | if (listener instanceof YHttpListener) {
1297 | ((YHttpListener) listener).fail(error);
1298 | } else if (listener instanceof YHttpLoadListener) {
1299 | ((YHttpLoadListener) listener).fail(error);
1300 | } else if (listener instanceof YHttpDownloadFileListener) {
1301 | ((YHttpDownloadFileListener) listener).fail(error);
1302 | } else if (listener instanceof YFailListener) {
1303 | ((YFailListener) listener).fail(error);
1304 | }
1305 | }
1306 |
1307 | /**
1308 | * 打印日志。如果发现包含Log就用Log打印,否则就用println
1309 | *
1310 | * @param str 日志
1311 | */
1312 | void println(String str) {
1313 | if (Android.isAndroid()) {
1314 | println("d", "YHttp", str);
1315 | } else {
1316 | System.out.println(str);
1317 | }
1318 | }
1319 |
1320 | /**
1321 | * 打印错误日志。如果发现包含Log就用Log打印,否则就用println
1322 | *
1323 | * @param str 错误内容
1324 | */
1325 | void printlnE(String str) {
1326 | if (Android.isAndroid()) {
1327 | println("e", "YHttp", str);
1328 | } else {
1329 | System.err.println(str);
1330 | }
1331 | }
1332 |
1333 | /**
1334 | * 打印日志
1335 | *
1336 | * @param tag tag
1337 | * @param msg 内容
1338 | */
1339 | private static void println(String type, String tag, String msg) {
1340 | int LOG_MAX_LENGTH = 2000;
1341 | int strLength = msg.length();
1342 | int start = 0;
1343 | int end = LOG_MAX_LENGTH;
1344 | for (int i = 0; i < (msg.length() / LOG_MAX_LENGTH + 1); i++) {
1345 | //剩下的文本还是大于规定长度则继续重复截取并输出
1346 | if (strLength > end) {
1347 | String s = tag + " " + i;
1348 | Android.Log(type, s, msg.substring(start, end));
1349 | start = end;
1350 | end = end + LOG_MAX_LENGTH;
1351 | } else {
1352 | String s = i == 0 ? tag : tag + " " + i;
1353 | Android.Log(type, s, msg.substring(start, strLength));
1354 | break;
1355 | }
1356 | }
1357 | }
1358 | }
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/YHttpBase.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http;
2 |
3 | import com.yutils.http.contract.YHttpProgressListener;
4 | import com.yutils.http.contract.YSessionListener;
5 | import com.yutils.http.model.Upload;
6 |
7 | import java.io.ByteArrayOutputStream;
8 | import java.io.DataInputStream;
9 | import java.io.DataOutputStream;
10 | import java.io.File;
11 | import java.io.FileInputStream;
12 | import java.io.FileOutputStream;
13 | import java.io.IOException;
14 | import java.io.InputStream;
15 | import java.io.OutputStream;
16 | import java.net.HttpURLConnection;
17 | import java.util.ArrayList;
18 | import java.util.HashMap;
19 | import java.util.IdentityHashMap;
20 | import java.util.List;
21 | import java.util.Map;
22 | import java.util.Objects;
23 |
24 | /**
25 | * 网络请求基础类,柱塞式
26 | *
27 | * @author yujing 2020年7月28日10:22:35
28 | */
29 | public class YHttpBase {
30 | protected String contentType = null;// "application/x-www-form-urlencoded;charset=utf-8";//"application/json;charset=utf-8"
31 | protected int connectTimeout = 1000 * 20;
32 | //userAgent,Android ----> Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Mobile Safari/537.36
33 | //userAgent,iPhoneX ----> Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1
34 | //userAgent,iPad ----> Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1 Edg/85.0.4183.83
35 | //userAgent,windows10 ----> Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
36 | protected String userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36";
37 | /**
38 | * boundary就是request头和上传文件内容的分隔符
39 | */
40 | protected static final String BOUNDARY = "------------YuJing---------------";
41 | /**
42 | * session获取监听
43 | */
44 | protected YSessionListener sessionListener;
45 | /**
46 | * SessionId
47 | */
48 | protected String sessionId;
49 | /**
50 | * 下载是否停止
51 | */
52 | protected boolean downLoadStop = false;
53 |
54 | //立即终止当前文件下载
55 | public void downloadFileStop() {
56 | downLoadStop = true;
57 | }
58 |
59 | //ContentType
60 | public String getContentType() {
61 | return contentType;
62 | }
63 |
64 | public YHttpBase setContentType(String contentType) {
65 | this.contentType = contentType;
66 | return this;
67 | }
68 |
69 | //Timeout
70 | public int getConnectTimeout() {
71 | return connectTimeout;
72 | }
73 |
74 | public YHttpBase setConnectTimeout(int connectTimeout) {
75 | this.connectTimeout = connectTimeout;
76 | return this;
77 | }
78 |
79 | //crt证书
80 | protected String crtSSL;
81 |
82 | public String getCrtSSL() {
83 | return crtSSL;
84 | }
85 |
86 | public YHttpBase setCrtSSL(String crtSSL) {
87 | this.crtSSL = crtSSL;
88 | return this;
89 | }
90 |
91 | //RequestProperty,请求头
92 | protected Map mapSetRequestProperty;
93 | protected Map mapAddRequestProperty;
94 |
95 | public YHttpBase setRequestProperty(String key, String value) {
96 | if (mapSetRequestProperty == null)
97 | mapSetRequestProperty = new HashMap<>();
98 | mapSetRequestProperty.put(key, value);
99 | return this;
100 | }
101 |
102 | @SuppressWarnings("StringOperationCanBeSimplified")
103 | public YHttpBase addRequestProperty(String key, String value) {
104 | //可以重复key的map,但是key的内存地址要不一样
105 | if (mapAddRequestProperty == null)
106 | mapAddRequestProperty = new IdentityHashMap<>();
107 | mapAddRequestProperty.put(new String(key), value);
108 | return this;
109 | }
110 |
111 | //session监听
112 | public YHttpBase setSessionListener(YSessionListener ySessionListener) {
113 | this.sessionListener = ySessionListener;
114 | return this;
115 | }
116 |
117 | //setSessionId
118 | public YHttpBase setSessionId(String sessionId) {
119 | this.sessionId = sessionId;
120 | return this;
121 | }
122 |
123 | /**
124 | * get请求,同步柱塞试
125 | *
126 | * @param requestUrl url
127 | * @return 请求结果
128 | * @throws Exception 异常
129 | */
130 | public byte[] get(String requestUrl) throws Exception {
131 | return request(requestUrl, null, "GET");
132 | }
133 |
134 | /**
135 | * post请求,同步柱塞试
136 | *
137 | * @param requestUrl rul
138 | * @param requestBytes 请求内容
139 | * @return 请求结果
140 | * @throws Exception 异常
141 | */
142 | public byte[] post(String requestUrl, byte[] requestBytes) throws Exception {
143 | return request(requestUrl, requestBytes, "POST");
144 | }
145 |
146 | /**
147 | * put请求,同步柱塞试
148 | *
149 | * @param requestUrl rul
150 | * @param requestBytes 请求内容
151 | * @return 请求结果
152 | * @throws Exception 异常
153 | */
154 | public byte[] put(String requestUrl, byte[] requestBytes) throws Exception {
155 | return request(requestUrl, requestBytes, "PUT");
156 | }
157 |
158 | /**
159 | * delete请求,同步柱塞试
160 | *
161 | * @param requestUrl rul
162 | * @param requestBytes 请求内容
163 | * @return 请求结果
164 | * @throws Exception 异常
165 | */
166 | public byte[] delete(String requestUrl, byte[] requestBytes) throws Exception {
167 | return request(requestUrl, requestBytes, "DELETE");
168 | }
169 |
170 | /**
171 | * delete请求,同步柱塞试
172 | *
173 | * @param requestUrl rul
174 | * @param requestBytes 请求内容
175 | * @param requestMethod 请求方式,只能是 "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
176 | * @return 请求结果
177 | * @throws Exception 异常
178 | */
179 | public byte[] request(String requestUrl, byte[] requestBytes, String requestMethod) throws Exception {
180 | // 打开一个HttpURLConnection连接
181 | HttpURLConnection urlConn = YHttpURLConnectionFactory.create(requestUrl, crtSSL);
182 | //设置从主机读取数据超时
183 | urlConn.setReadTimeout(connectTimeout);
184 | setHttpURLConnection(urlConn, requestMethod);
185 | if ("GET".equals(requestMethod)) {
186 | // 设置session
187 | setSession(urlConn);
188 | // 开始连接
189 | urlConn.connect();
190 | // 获取session
191 | getSession(urlConn);
192 | // 判断请求是否成功
193 | int responseCode = urlConn.getResponseCode();
194 | if (responseCode != HttpURLConnection.HTTP_OK) {
195 | throw new Exception("错误码:" + responseCode);
196 | }
197 | // 关闭连接
198 | } else {
199 | // 发送POST请求必须设置如下两行
200 | urlConn.setDoOutput(true);
201 | urlConn.setDoInput(true);
202 | // 设置session
203 | setSession(urlConn);
204 | // 开始连接
205 | urlConn.connect();
206 | // 发送请求参数
207 | DataOutputStream dos = new DataOutputStream(urlConn.getOutputStream());
208 | dos.write(requestBytes);
209 | dos.flush();
210 | dos.close();
211 | // 获取session
212 | getSession(urlConn);
213 | // 判断请求是否成功
214 | int responseCode = urlConn.getResponseCode();
215 | if (responseCode != HttpURLConnection.HTTP_OK) {
216 | throw new Exception("错误码:" + responseCode);
217 | }
218 | }
219 | // 关闭连接
220 | byte[] bytes = YHttpUtils.inputStreamToBytes(urlConn.getInputStream());
221 | urlConn.disconnect();
222 | return bytes;
223 | }
224 |
225 | /**
226 | * 文件下载,同步柱塞试
227 | *
228 | * @param requestUrl url
229 | * @param file 下载的文件
230 | * @param listener 进度监听
231 | * @throws Exception 异常
232 | */
233 | @SuppressWarnings("ResultOfMethodCallIgnored")
234 | public void downloadFile(String requestUrl, File file, YHttpProgressListener listener) throws Exception {
235 | File parent = file.getParentFile();
236 | if (!Objects.requireNonNull(parent).exists()) parent.mkdirs();
237 | if (file.exists()) file.delete();// 删除存在文件
238 | // 打开一个HttpURLConnection连接
239 | HttpURLConnection urlConn = YHttpURLConnectionFactory.create(requestUrl, crtSSL);
240 | setHttpURLConnection(urlConn, "GET");
241 | // 设置session
242 | setSession(urlConn);
243 | // 开始连接
244 | urlConn.connect();
245 | // 获取session
246 | getSession(urlConn);
247 | // 判断请求是否成功
248 | int responseCode = urlConn.getResponseCode();
249 | if (responseCode != HttpURLConnection.HTTP_OK) {
250 | throw new Exception("错误码:" + responseCode);
251 | }
252 | int downloadSize = 0;
253 | int fileSize = urlConn.getContentLength(); // 获取不到文件大小时候fileSize=-1
254 | int len;
255 | byte[] buffer = new byte[1024 * 8];
256 | FileOutputStream fos = new FileOutputStream(file);
257 | InputStream inputStream = urlConn.getInputStream();
258 | downLoadStop = false;//这设置成false,在下载过程中downLoadIsStop的值可能会被改变
259 | while (!downLoadStop && (len = inputStream.read(buffer)) != -1) {
260 | // 写到本地
261 | fos.write(buffer, 0, len);
262 | downloadSize += len;
263 | listener.progress(downloadSize, fileSize);
264 | }
265 | if (downLoadStop) throw new Exception("终止下载");
266 | // 关闭连接
267 | urlConn.disconnect();
268 | }
269 |
270 | /**
271 | * 加载,同步柱塞试
272 | *
273 | * @param requestUrl url
274 | * @param listener 进度监听
275 | * @return 结果
276 | * @throws Exception 异常
277 | */
278 | public byte[] load(String requestUrl, YHttpProgressListener listener) throws Exception {
279 | // 打开一个HttpURLConnection连接
280 | HttpURLConnection urlConn = YHttpURLConnectionFactory.create(requestUrl, crtSSL);
281 | urlConn.setAllowUserInteraction(true);
282 | setHttpURLConnection(urlConn, "GET");
283 | // 设置session
284 | setSession(urlConn);
285 | // 开始连接
286 | urlConn.connect();
287 | // 获取session
288 | getSession(urlConn);
289 | // 判断请求是否成功
290 | int responseCode = urlConn.getResponseCode();
291 | if (responseCode != HttpURLConnection.HTTP_OK) {
292 | throw new Exception("错误码:" + responseCode);
293 | }
294 | int downloadSize = 0;
295 | int fileSize = urlConn.getContentLength(); // 获取不到文件大小时候fileSize=-1
296 | int len;
297 | byte[] buffer = new byte[1024 * 8];
298 | ByteArrayOutputStream bs = new ByteArrayOutputStream();
299 | InputStream inputStream = urlConn.getInputStream();
300 | while ((len = inputStream.read(buffer)) != -1) {
301 | bs.write(buffer, 0, len);
302 | downloadSize += len;
303 | listener.progress(downloadSize, fileSize);
304 | }
305 | bs.flush();
306 | byte[] bytes = bs.toByteArray();
307 | // 关闭连接
308 | urlConn.disconnect();
309 | return bytes;
310 | }
311 |
312 | /**
313 | * 文件上传,同步柱塞试
314 | *
315 | * @param requestUrl url
316 | * @param requestBytes 请求内容
317 | * @param fileMap key,文件
318 | * @return 请求结果
319 | * @throws Exception 异常
320 | */
321 | public byte[] upload(String requestUrl, byte[] requestBytes, Map fileMap) throws Exception {
322 | List uploads = new ArrayList<>();
323 | for (Map.Entry entry : fileMap.entrySet()) {
324 | if (entry.getValue() == null) continue;
325 | uploads.add(new Upload(entry.getKey(), entry.getValue()));
326 | }
327 | return upload(requestUrl, requestBytes, uploads);
328 | }
329 |
330 | /**
331 | * 文件上传,同步柱塞试
332 | *
333 | * @param requestUrl url
334 | * @param requestBytes 请求内容
335 | * @param uploads 上传的key,内容,文件名,contentType
336 | * @return 请求结果
337 | * @throws Exception 异常
338 | */
339 | public byte[] upload(String requestUrl, byte[] requestBytes, List uploads) throws Exception {
340 | // 打开一个HttpURLConnection连接
341 | HttpURLConnection urlConn = YHttpURLConnectionFactory.create(requestUrl, crtSSL);
342 | //设置从主机读取数据超时
343 | urlConn.setReadTimeout(connectTimeout);
344 | setContentType("multipart/form-data; boundary=" + BOUNDARY);
345 | setHttpURLConnection(urlConn, "POST");
346 | // 设置session
347 | setSession(urlConn);
348 | // 发送POST请求必须设置如下两行
349 | urlConn.setDoOutput(true);
350 | urlConn.setDoInput(true);
351 | // 开始连接
352 | urlConn.connect();
353 | // 发送请求参数
354 | send(urlConn, requestBytes, uploads);
355 | // 获取session
356 | getSession(urlConn);
357 | // 判断请求是否成功
358 | int responseCode = urlConn.getResponseCode();
359 | if (responseCode != HttpURLConnection.HTTP_OK) {
360 | throw new Exception("错误码:" + responseCode);
361 | }
362 | byte[] bytes = YHttpUtils.inputStreamToBytes(urlConn.getInputStream());
363 | // 关闭连接
364 | urlConn.disconnect();
365 | return bytes;
366 | }
367 |
368 | /**
369 | * 发送文件的数据组装
370 | *
371 | * @param httpURLConnection 连接对象
372 | * @param requestBytes 请求的参数
373 | * @param uploads 上传的文件
374 | * @throws IOException 异常
375 | */
376 | protected void send(HttpURLConnection httpURLConnection, byte[] requestBytes, List uploads) throws IOException {
377 | OutputStream out = new DataOutputStream(httpURLConnection.getOutputStream());
378 | // 文本参数
379 | if (requestBytes != null) out.write(requestBytes);
380 | // 文件
381 | if (uploads != null) {
382 | for (Upload item : uploads) {
383 | if (item.getBytes() != null) {
384 | StringBuilder strBuf = new StringBuilder();
385 | strBuf.append("\r\n--").append(BOUNDARY).append("\r\n")
386 | .append("Content-Disposition: form-data; name=\"")
387 | .append(item.getKey())
388 | .append("\"; filename=\"")
389 | .append(item.getFilename())
390 | .append("\"\r\n");
391 | strBuf.append("Content-Type:").append(item.getContentType()).append("\r\n\r\n");
392 | out.write(strBuf.toString().getBytes());
393 | out.write(item.getBytes());
394 | } else if (item.getFile() != null) {
395 | StringBuilder strBuf = new StringBuilder();
396 | strBuf.append("\r\n--").append(BOUNDARY).append("\r\n")
397 | .append("Content-Disposition: form-data; name=\"")
398 | .append(item.getKey())
399 | .append("\"; filename=\"")
400 | .append(item.getFilename())
401 | .append("\"\r\n");
402 | strBuf.append("Content-Type:").append(item.getContentType()).append("\r\n\r\n");
403 | out.write(strBuf.toString().getBytes());
404 | DataInputStream in = new DataInputStream(new FileInputStream(item.getFile()));
405 | int bytes;
406 | byte[] bufferOut = new byte[1024 * 8];
407 | while ((bytes = in.read(bufferOut)) != -1)
408 | out.write(bufferOut, 0, bytes);
409 | in.close();
410 | } else {
411 | try {
412 | Class.forName("android.graphics.Bitmap");
413 | if (item.getBitmap() != null) {
414 | StringBuilder strBuf = new StringBuilder();
415 | strBuf.append("\r\n--").append(BOUNDARY).append("\r\n")
416 | .append("Content-Disposition: form-data; name=\"")
417 | .append(item.getKey())
418 | .append("\"; filename=\"")
419 | .append(item.getFilename())
420 | .append("\"\r\n");
421 | strBuf.append("Content-Type:").append(item.getContentType()).append("\r\n\r\n");
422 | out.write(strBuf.toString().getBytes());
423 | // bitmap转Bytes
424 | byte[] bytes = Android.bitmapToByteArray(item.getBitmap());
425 | out.write(bytes);
426 | }
427 | } catch (Exception e) {
428 | System.err.println("上传Bitmap异常:" + e.getMessage());
429 | }
430 | }
431 | }
432 | }
433 | out.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes());// 结束标记
434 | out.flush();
435 | out.close();
436 | }
437 |
438 | /**
439 | * HttpURLConnection 的一些基础设置
440 | *
441 | * @param urlConn 连接
442 | * @param requestMethod 请求类型
443 | * @throws Exception Exception
444 | */
445 | private void setHttpURLConnection(HttpURLConnection urlConn, String requestMethod) throws Exception {
446 | // 设置连接超时时间
447 | urlConn.setConnectTimeout(connectTimeout);
448 | //设置请求允许输入 默认是true
449 | urlConn.setDoInput(true);
450 | // Post请求不能使用缓存
451 | urlConn.setUseCaches(false);
452 | // 设置为请求类型
453 | if (requestMethod != null)
454 | urlConn.setRequestMethod(requestMethod);
455 | //设置本次连接是否自动处理重定向
456 | urlConn.setInstanceFollowRedirects(true);
457 | // 配置请求Content-Type
458 | urlConn.setRequestProperty("accept", "*/*");
459 | urlConn.setRequestProperty("connection", "Keep-Alive");
460 | urlConn.setRequestProperty("Charset", "utf-8");
461 | urlConn.setRequestProperty("Content-Type", contentType == null ? "application/x-www-form-urlencoded;charset=utf-8" : contentType);
462 | urlConn.setRequestProperty("User-Agent", userAgent);
463 | if (mapSetRequestProperty != null)
464 | for (Map.Entry entry : mapSetRequestProperty.entrySet())
465 | urlConn.setRequestProperty(entry.getKey(), entry.getValue());
466 | if (mapAddRequestProperty != null)
467 | for (Map.Entry entry : mapAddRequestProperty.entrySet())
468 | urlConn.addRequestProperty(entry.getKey(), entry.getValue());
469 | }
470 |
471 | /**
472 | * 设置session,把JSESSIONID变量的值设置成session
473 | *
474 | * @param httpURLConnection httpURLConnection
475 | */
476 | public void setSession(HttpURLConnection httpURLConnection) {
477 | if (sessionId != null && !sessionId.isEmpty()) {
478 | httpURLConnection.setRequestProperty("Cookie", "JSESSIONID=" + sessionId);
479 | }
480 | }
481 |
482 | /**
483 | * 获取session 并保存到JSESSIONID变量
484 | *
485 | * @param httpURLConnection httpURLConnection
486 | */
487 | public void getSession(HttpURLConnection httpURLConnection) {
488 | Map> map = httpURLConnection.getHeaderFields();
489 | if (map != null) {
490 | List list = map.get("Set-Cookie");
491 | if (list != null) {
492 | for (int i = 0; i < list.size(); i++) {
493 | //System.out.println("Set-Cookie:"+list.get(i));
494 | int start = list.get(i).indexOf("JSESSIONID");
495 | if (start != -1) {
496 | int idStart = start + 10 + 1;
497 | int idEnd = start + 10 + 1 + 32;
498 | if (list.get(i).length() >= idEnd) {
499 | String JSESSIONID = list.get(i).substring(idStart, idEnd);// 如:list.get(i)="JSESSIONID=743D39694F006763220CA0CA63FE8978";
500 | if (sessionListener != null)
501 | Android.runOnUiThread(() -> sessionListener.sessionId(JSESSIONID));
502 | sessionId = JSESSIONID;
503 | }
504 | }
505 | }
506 | }
507 | }
508 | }
509 | }
510 |
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/YHttpThreadPool.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http;
2 |
3 | import java.util.concurrent.ScheduledThreadPoolExecutor;
4 |
5 | /**
6 | * 线程池管理类
7 | *
8 | * @author yujing 2020年7月28日10:22:35
9 | */
10 | public class YHttpThreadPool {
11 | private static volatile int threadNum = 20;
12 | private static ScheduledThreadPoolExecutor sTpe = new ScheduledThreadPoolExecutor(threadNum);
13 |
14 | /**
15 | * 停止当前队列中全部请求
16 | */
17 | public static void stopAll() {
18 | if (sTpe != null)
19 | sTpe.getQueue().clear();
20 | }
21 |
22 | /**
23 | * 把一个线程扔进线程池
24 | *
25 | * @param runnable 要执行的线程
26 | */
27 | public synchronized static void add(Runnable runnable) {
28 | synchronized (sTpe) {
29 | if (sTpe.isShutdown()) {
30 | sTpe = new ScheduledThreadPoolExecutor(threadNum);
31 | synchronized (sTpe) {
32 | sTpe.execute(runnable);
33 | }
34 | } else {
35 | sTpe.execute(runnable);
36 | }
37 | }
38 | }
39 |
40 | /**
41 | * 获取当前有多少线程
42 | *
43 | * @return 线程数量
44 | */
45 | public static int getPoolSize() {
46 | return sTpe.isShutdown() ? -1 : sTpe.getPoolSize();
47 | }
48 |
49 | /**
50 | * 关闭释放线程池
51 | */
52 | public synchronized static void shutdown() {
53 | synchronized (sTpe) {
54 | if (!sTpe.isShutdown())
55 | sTpe.shutdown();
56 | }
57 | }
58 |
59 | /**
60 | * 释放当前线程池,并重新创建线程池一个最大值未threadNum的线程池
61 | *
62 | * @param threadNum 线程池最大值
63 | */
64 | public static void setThreadNum(int threadNum) {
65 | YHttpThreadPool.threadNum = threadNum;
66 | shutdown();
67 | sTpe = new ScheduledThreadPoolExecutor(threadNum);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/YHttpURLConnectionFactory.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.net.HttpURLConnection;
5 | import java.net.URL;
6 | import java.security.KeyStore;
7 | import java.security.SecureRandom;
8 | import java.security.cert.Certificate;
9 | import java.security.cert.CertificateFactory;
10 | import java.security.cert.X509Certificate;
11 | import java.util.Locale;
12 |
13 | import javax.net.ssl.HttpsURLConnection;
14 | import javax.net.ssl.SSLContext;
15 | import javax.net.ssl.SSLSocketFactory;
16 | import javax.net.ssl.TrustManager;
17 | import javax.net.ssl.TrustManagerFactory;
18 | import javax.net.ssl.X509TrustManager;
19 |
20 | /**
21 | * HttpURLConnection工厂,如果带有crtString,就创建HTTPS请求,否则就HTTP请求
22 | *
23 | * @author yujing 2020年7月28日10:22:35
24 | */
25 | public class YHttpURLConnectionFactory {
26 | /**
27 | * 创建HttpURLConnection对象,如果请求包含https就创建HttpsURLConnection,并且创建证书
28 | *
29 | * @param url 请求地址
30 | * @param crtSSL crt证书
31 | * @return HttpURLConnection
32 | * @throws Exception Exception
33 | */
34 | public static HttpURLConnection create(String url, String crtSSL) throws Exception {
35 | if (crtSSL != null && (url.toLowerCase(Locale.getDefault()).contains("https://"))) {
36 | HttpsURLConnection httpsURLConnection = (HttpsURLConnection) (new URL(url)).openConnection();
37 | httpsURLConnection.setSSLSocketFactory(createSSLSocketFactory(crtSSL));
38 | //屏蔽https验证
39 | httpsURLConnection.setHostnameVerifier((hostname, session) -> true);
40 | return httpsURLConnection;
41 | } else {
42 | return (HttpURLConnection) (new URL(url)).openConnection();
43 | }
44 | }
45 |
46 | /**
47 | * 创建SSL套接字工厂
48 | *
49 | * @param crtString crt证书
50 | * @return SSLSocketFactory
51 | * @throws Exception Exception
52 | */
53 | private static SSLSocketFactory createSSLSocketFactory(String crtString) throws Exception {
54 | CertificateFactory cf = CertificateFactory.getInstance("X.509");
55 | //如果是src/main/assets/test.crt,直接获取InputStream:getAssets().open("test.crt")
56 | Certificate ca = cf.generateCertificate(new ByteArrayInputStream(crtString.getBytes()));
57 |
58 | String keyStoreType = KeyStore.getDefaultType();
59 | KeyStore keyStore = KeyStore.getInstance(keyStoreType);
60 | keyStore.load(null, null);
61 | keyStore.setCertificateEntry("ca", ca);
62 |
63 | String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
64 | TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
65 | tmf.init(keyStore);
66 |
67 | SSLContext context = SSLContext.getInstance("TLS");
68 | context.init(null, new TrustManager[]{new X509TrustManager() {
69 | @Override
70 | public void checkClientTrusted(X509Certificate[] chain, String authType) {
71 |
72 | }
73 |
74 | @Override
75 | public void checkServerTrusted(X509Certificate[] chain, String authType) {
76 |
77 | }
78 |
79 | @Override
80 | public X509Certificate[] getAcceptedIssuers() {
81 | return new X509Certificate[0];
82 | }
83 | }}, new SecureRandom());
84 | return context.getSocketFactory();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/YHttpUtils.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.util.Map;
7 |
8 | /**
9 | * 网络请求工具类
10 | *
11 | * @author 2020年7月28日10:22:35
12 | */
13 | public class YHttpUtils {
14 | /**
15 | * 请求map转换成String
16 | *
17 | * @param paramsMap paramsMap
18 | * @return StringBuffer
19 | */
20 | public static StringBuffer mapToParams(Map paramsMap) {
21 | if (paramsMap == null) {
22 | return null;
23 | }
24 | StringBuffer params = new StringBuffer();
25 | for (Map.Entry element : paramsMap.entrySet()) {
26 | if (element.getValue() == null)
27 | continue;
28 | params.append(element.getKey()).append("=").append(element.getValue()).append("&");
29 | }
30 | if (params.length() > 0)
31 | params.deleteCharAt(params.length() - 1);
32 | return params;
33 | }
34 |
35 | /**
36 | * inputStream 转换成byte[]
37 | *
38 | * @param inputStream inputStream
39 | * @return byte[]
40 | * @throws IOException IOException
41 | */
42 | public static byte[] inputStreamToBytes(InputStream inputStream) throws IOException {
43 | ByteArrayOutputStream bs = new ByteArrayOutputStream();
44 | byte[] buffer = new byte[1024];
45 | int len;
46 | while ((len = inputStream.read(buffer)) != -1) {
47 | bs.write(buffer, 0, len);
48 | }
49 | bs.flush();
50 | return bs.toByteArray();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/contract/ObjectListener.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http.contract;
2 |
3 | import java.lang.reflect.ParameterizedType;
4 | import java.lang.reflect.Type;
5 |
6 | /**
7 | * 请求结果返回对象监听
8 | * 【注意:】此处不能用interface只能使用 abstract class,因为要取出泛型T的具体实现类型,
9 | * interface不能取出T类型,
10 | * 所以只能采用abstract class。
11 | *
12 | * @param 泛型
13 | * @author 余静 2021年3月25日10:00:11
14 | */
15 |
16 | public abstract class ObjectListener {
17 | private final Type type;
18 |
19 | protected ObjectListener() {
20 | //取出泛型具体类型
21 | type = getSuperclassTypeParameter(getClass());
22 | }
23 |
24 | //取出class的父类泛类类型
25 | static Type getSuperclassTypeParameter(Class> subclass) {
26 | Type superclass = subclass.getGenericSuperclass();
27 | if (superclass instanceof Class) {
28 | throw new RuntimeException("Missing type parameter.");
29 | }
30 | ParameterizedType parameterized = (ParameterizedType) superclass;
31 | return parameterized.getActualTypeArguments()[0];
32 | }
33 |
34 | /**
35 | * 取出泛型的具体类型
36 | *
37 | * @return Type
38 | */
39 | public Type getType() {
40 | return type;
41 | }
42 |
43 | public abstract void success(byte[] bytes, T value);
44 | }
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/contract/YFailListener.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http.contract;
2 |
3 | /**
4 | * 失败监听
5 | * @author yujing 2021年3月24日23:24:09
6 | */
7 | public interface YFailListener {
8 | void fail(String value);
9 | }
10 |
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/contract/YHttpDownloadFileListener.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http.contract;
2 |
3 | import java.io.File;
4 |
5 | /**
6 | * 文件下载监听
7 | *
8 | * @author yujing 2020年7月28日10:23:26
9 | */
10 | public interface YHttpDownloadFileListener extends YHttpProgressListener, YFailListener {
11 | void success(File file);
12 | }
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/contract/YHttpListener.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http.contract;
2 |
3 | /**
4 | * 请求信息监听
5 | *
6 | * @author 余静 2020年7月28日10:23:26
7 | */
8 | public interface YHttpListener extends YSuccessListener, YFailListener {
9 | }
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/contract/YHttpLoadListener.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http.contract;
2 |
3 | /**
4 | * 文件下载监听
5 | *
6 | * @author yujing 2020年7月28日10:23:26
7 | */
8 | public interface YHttpLoadListener extends YHttpProgressListener, YFailListener {
9 | void success(byte[] bytes);
10 | }
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/contract/YHttpProgressListener.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http.contract;
2 |
3 | /**
4 | * 进度监听
5 | *
6 | * @author yujing 2020年7月28日10:23:26
7 | */
8 | public interface YHttpProgressListener {
9 | void progress(int size, int sizeCount);
10 | }
11 |
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/contract/YObjectListener.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http.contract;
2 |
3 | import java.lang.reflect.ParameterizedType;
4 | import java.lang.reflect.Type;
5 |
6 | /**
7 | * 请求结果返回对象监听
8 | * 【注意:】此处不能用interface只能使用 abstract class,因为要取出泛型T的具体实现类型,
9 | * interface不能取出T类型,
10 | * 所以只能采用abstract class。
11 | *
12 | * @param 泛型
13 | * @author 余静 2020年7月28日10:23:26
14 | */
15 |
16 | public abstract class YObjectListener extends ObjectListener implements YFailListener {
17 | private final Type type;
18 |
19 | protected YObjectListener() {
20 | //取出泛型具体类型
21 | type = getSuperclassTypeParameter(getClass());
22 | }
23 |
24 | //取出class的父类泛类类型
25 | static Type getSuperclassTypeParameter(Class> subclass) {
26 | Type superclass = subclass.getGenericSuperclass();
27 | if (superclass instanceof Class) {
28 | throw new RuntimeException("Missing type parameter.");
29 | }
30 | ParameterizedType parameterized = (ParameterizedType) superclass;
31 | return parameterized.getActualTypeArguments()[0];
32 | }
33 |
34 | /**
35 | * 取出泛型的具体类型
36 | *
37 | * @return Type
38 | */
39 | public Type getType() {
40 | return type;
41 | }
42 |
43 | public abstract void success(byte[] bytes, T value);
44 | }
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/contract/YSessionListener.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http.contract;
2 |
3 | /**
4 | * sessionId 监听
5 | * 返回值为新的sessionId
6 | * @author 余静 2020年7月28日10:23:26
7 | */
8 | public interface YSessionListener {
9 | void sessionId(String sessionId);
10 | }
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/contract/YSuccessListener.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http.contract;
2 |
3 | /**
4 | * 成功监听
5 | *
6 | * @author 余静 2021年3月24日23:24:03
7 | */
8 | public interface YSuccessListener {
9 | void success(byte[] bytes, String value) throws Exception;
10 | }
--------------------------------------------------------------------------------
/yhttp/src/main/java/com/yutils/http/model/Upload.java:
--------------------------------------------------------------------------------
1 | package com.yutils.http.model;
2 |
3 | import java.io.File;
4 |
5 | /**
6 | * 上传文件实体
7 | *
8 | * @author yujing 2020年8月28日12:08:34
9 | * 上传文件,检查到bytes不为null就走bytes,其次file,其次bitmap
10 | */
11 | /*
12 | //java文件上传
13 | String url = "http://192.168.6.9:8090/crash/upload/file";
14 | List uploads = new ArrayList<>();
15 | uploads.add(new Upload("file1", new File("D:/1.jpg")));
16 | uploads.add(new Upload("file2", "ABCDEF".getBytes()).setFilename("abcd.txt"));
17 |
18 | YHttp.create().setSessionId(session).upload(url, "", uploads, new YHttpListener() {
19 | @Override
20 | public void success(byte[] bytes, String value){
21 | System.out.println("上传成功:" + value);
22 | }
23 | @Override
24 | public void fail(String value) {
25 | System.out.println("上传失败:" + value);
26 | }
27 | });
28 | */
29 | public class Upload {
30 | /**
31 | * 上传文件的key值
32 | */
33 | private String key;
34 |
35 | /**
36 | * 文件内容为byte[],与File,Bitmap,互斥
37 | */
38 | private byte[] bytes;
39 |
40 | /**
41 | * 文件内容为file,与byte[],Bitmap,互斥
42 | */
43 | private File file;
44 |
45 | /**
46 | * 文件内容为object,与File,byte[],互斥
47 | * 为了兼容java原生项目,所以此处设置为Object
48 | */
49 | private Object object;
50 |
51 | /**
52 | * 文件名
53 | */
54 | private String filename;
55 |
56 | /**
57 | * 此文件的contentType
58 | */
59 | private String contentType;
60 |
61 | public Upload(String key, byte[] bytes) {
62 | this.key = key;
63 | this.bytes = bytes;
64 | filename = key;
65 | contentType = "application/octet-stream";
66 | }
67 |
68 | public Upload(String key, File file) {
69 | this.key = key;
70 | this.file = file;
71 | filename = file.getName();
72 | if (file.getName().lastIndexOf(".png") != -1) {
73 | contentType = "image/png";
74 | } else if (file.getName().lastIndexOf(".jpg") != -1 || file.getName().lastIndexOf(".jpeg") != -1) {
75 | contentType = "image/jpeg";
76 | } else {
77 | contentType = "application/octet-stream";
78 | }
79 | }
80 |
81 | public Upload(String key, Object object) {
82 | this.key = key;
83 | this.object = object;
84 | filename = key;
85 | filename = "image" + System.currentTimeMillis() + ".jpg";
86 | contentType = "image/jpeg";
87 | }
88 |
89 | public String getKey() {
90 | return key;
91 | }
92 |
93 | public byte[] getBytes() {
94 | return bytes;
95 | }
96 |
97 | public File getFile() {
98 | return file;
99 | }
100 |
101 | public Object getBitmap() {
102 | return object;
103 | }
104 |
105 | public String getFilename() {
106 | return filename;
107 | }
108 |
109 | public Upload setFilename(String filename) {
110 | this.filename = filename;
111 | return this;
112 | }
113 |
114 | public String getContentType() {
115 | return contentType;
116 | }
117 |
118 | public Upload setContentType(String contentType) {
119 | this.contentType = contentType;
120 | return this;
121 | }
122 | }
123 |
--------------------------------------------------------------------------------