admin
2021-12-22 0a1336cd2b95126d66d6f3126cb48a446cdbfad1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
package com.hanju.video.app.ui.video.parser;
 
 
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
 
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
 
import androidx.annotation.Nullable;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
 
public class WriteHandlingWebViewClient extends WebViewClient {
 
    private static final String TAG = "WriteHandlingWebViewClient";
    private final String MARKER = "AJAXINTERCEPT";
 
    /**
     * 请求参数Map集
     */
    private Map<String, String> ajaxRequestContents = new HashMap<>();
    private List<VideoPlayUrlParseFragment.ParseParams> parseParamsList = null;
    private OnResponseListener responseListener;
 
    public void init(List<VideoPlayUrlParseFragment.ParseParams> parseParamsList, OnResponseListener responseListener) {
        ajaxRequestContents.clear();
        this.parseParamsList = parseParamsList;
        this.responseListener = responseListener;
    }
 
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        return super.shouldOverrideUrlLoading(view, request);
    }
 
    @Nullable
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        return super.shouldInterceptRequest(view, url);
    }
 
    public WriteHandlingWebViewClient(WebView webView) {
        AjaxInterceptJavascriptInterface ajaxInterface = new AjaxInterceptJavascriptInterface(this);
        webView.addJavascriptInterface(ajaxInterface, "interception");
    }
 
    /*
     ** This here is the "fixed" shouldInterceptRequest method that you should override.
     ** It receives a WriteHandlingWebResourceRequest instead of a WebResourceRequest.
     */
    public WebResourceResponse shouldInterceptRequest(final WebView view, WriteHandlingWebResourceRequest request) {
        OkHttpClient client = new OkHttpClient();
        try {
            String url = request.getUrl().toString();
            Log.i(TAG,"url:"+url);
//            if (!Pattern.matches(regex, url)) {
//                return super.shouldInterceptRequest(view, request);
//            }
 
            Request.Builder builder = new Request.Builder().url(new URL(request.getUrl().toString()));
            Map<String, String> headers = request.getRequestHeaders();
            if (headers != null)
                for (Iterator<String> its = headers.keySet().iterator(); its.hasNext(); ) {
                    String key = its.next();
                    builder.addHeader(key, headers.get(key));
                }
 
 
            if ("POST".equals(request.getMethod())) {
                builder.post(RequestBody.create(MediaType.parse("text"), request.getAjaxData()));
            }
 
            Response response = client.newCall(builder.build()).execute();
            // Read input
            String charset = "UTF-8"; //conn.getContentEncoding() != null ? conn.getContentEncoding() : Charset.defaultCharset().displayName();
            String mime = response.header("content-type");
            byte[] bytes = response.body().bytes();
            for (VideoPlayUrlParseFragment.ParseParams parseParams : parseParamsList) {
                if (Pattern.matches(parseParams.getInterceptRegex(), url))
                    responseListener.onResult(request, parseParams, new String(bytes));
            }
            // Convert the contents and return
            InputStream isContents = new ByteArrayInputStream(bytes);
            response.close();
            return new WebResourceResponse(mime, charset, isContents);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
 
        return null;
    }
 
    /**
     * 拦截了webview中的所有请求
     *
     * @param view
     * @param request
     * @return
     */
    @Override
    public final WebResourceResponse shouldInterceptRequest(final WebView view, WebResourceRequest request) {
        String requestBody = null;
        Uri uri = request.getUrl();
 
        // 判断是否为Ajax请求(只要链接中包含AJAXINTERCEPT即是)
        if (isAjaxRequest(request)) {
            // 获取post请求参数
            requestBody = getRequestBody(request);
            // 获取原链接
            uri = getOriginalRequestUri(request, MARKER);
        }
 
        // 重新构造请求,并获取response
        WebResourceResponse webResourceResponse = shouldInterceptRequest(view, new WriteHandlingWebResourceRequest(request, requestBody, uri));
        if (webResourceResponse == null) {
            return webResourceResponse;
        } else {
            return injectIntercept(webResourceResponse, view.getContext());
        }
    }
 
    void addAjaxRequest(String id, String body) {
        ajaxRequestContents.put(id, body);
    }
 
    /**
     * 获取post请求参数
     *
     * @param request
     * @return
     */
    private String getRequestBody(WebResourceRequest request) {
        String requestID = getAjaxRequestID(request);
        return getAjaxRequestBodyByID(requestID);
    }
 
    /**
     * 判断是否为Ajax请求
     *
     * @param request
     * @return
     */
    private boolean isAjaxRequest(WebResourceRequest request) {
        return request.getUrl().toString().contains(MARKER);
    }
 
    private String[] getUrlSegments(WebResourceRequest request, String divider) {
        String urlString = request.getUrl().toString();
        return urlString.split(divider);
    }
 
    /**
     * 获取请求的id
     *
     * @param request
     * @return
     */
    private String getAjaxRequestID(WebResourceRequest request) {
        return getUrlSegments(request, MARKER)[1];
    }
 
    /**
     * 获取原链接
     *
     * @param request
     * @param marker
     * @return
     */
    private Uri getOriginalRequestUri(WebResourceRequest request, String marker) {
        String urlString = getUrlSegments(request, marker)[0];
        return Uri.parse(urlString);
    }
 
    /**
     * 通过请求id获取请求参数
     *
     * @param requestID
     * @return
     */
    private String getAjaxRequestBodyByID(String requestID) {
        String body = ajaxRequestContents.get(requestID);
        ajaxRequestContents.remove(requestID);
        return body;
    }
 
    /**
     * 如果请求是网页,则html注入
     *
     * @param response
     * @param context
     * @return
     */
    private WebResourceResponse injectIntercept(WebResourceResponse response, Context context) {
        String encoding = response.getEncoding();
        String mime = response.getMimeType();
 
        // WebResourceResponse的mime必须为"text/html",不能是"text/html; charset=utf-8"
        if (mime != null && mime.contains("text/html")) {
            mime = "text/html";
        }
 
        InputStream responseData = response.getData();
        InputStream injectedResponseData = injectInterceptToStream(
                context,
                responseData,
                mime,
                encoding
        );
        return new WebResourceResponse(mime, encoding, injectedResponseData);
    }
 
    /**
     * 如果请求是网页,则html注入
     *
     * @param context
     * @param is
     * @param mime
     * @param charset
     * @return
     */
    private InputStream injectInterceptToStream(Context context, InputStream is, String mime, String charset) {
        try {
            byte[] pageContents = Utils.consumeInputStream(is);
            if (mime != null && mime.contains("text/html")) {
                pageContents = AjaxInterceptJavascriptInterface
                        .enableIntercept(context, pageContents)
                        .getBytes(charset);
            }
 
            return new ByteArrayInputStream(pageContents);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }
 
    public interface OnResponseListener {
        public void onResult(WriteHandlingWebResourceRequest request, VideoPlayUrlParseFragment.ParseParams parseParams, String result);
    }
}