tharak-android 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/build.gradle +45 -0
- package/consumer-rules.pro +0 -0
- package/libs/vital-sdk.aar +0 -0
- package/package.json +22 -0
- package/proguard-rules.pro +21 -0
- package/src/androidTest/androidTest.iml +11 -0
- package/src/androidTest/java/org/tharak/core/ExampleInstrumentedTest.java +27 -0
- package/src/androidTest/java/org/thiragatisoft/core/ExampleInstrumentedTest.java +26 -0
- package/src/main/AndroidManifest.xml +5 -0
- package/src/main/java/org/thiragatisoft/core/AppUtils.java +31 -0
- package/src/main/java/org/thiragatisoft/core/FileSelector.java +162 -0
- package/src/main/java/org/thiragatisoft/core/MainActivity.java +27 -0
- package/src/main/java/org/thiragatisoft/core/RestClient.java +298 -0
- package/src/main/java/org/thiragatisoft/core/VitalActivity.java +612 -0
- package/src/main/java/org/thiragatisoft/core/VitalsPlugin.java +15 -0
- package/src/main/java/org/thiragatisoft/core/VolleyMultipartRequest.java +218 -0
- package/src/main/java/org/thiragatisoft/core/http/CapacitorCookieManager.java +175 -0
- package/src/main/java/org/thiragatisoft/core/http/CapacitorHttpUrlConnection.java +408 -0
- package/src/main/java/org/thiragatisoft/core/http/FilesystemUtils.java +65 -0
- package/src/main/java/org/thiragatisoft/core/http/FormUploader.java +219 -0
- package/src/main/java/org/thiragatisoft/core/http/Http.java +275 -0
- package/src/main/java/org/thiragatisoft/core/http/HttpRequestHandler.java +515 -0
- package/src/main/java/org/thiragatisoft/core/http/ICapacitorHttpUrlConnection.java +15 -0
- package/src/main/java/org/thiragatisoft/core/http/JSValue.java +68 -0
- package/src/main/java/org/thiragatisoft/core/http/MimeType.java +17 -0
- package/src/main/main.iml +12 -0
- package/src/test/java/org/tharak/ExampleUnitTest.java +17 -0
- package/src/test/java/org/tharak/JSObjectTest.java +209 -0
- package/src/test/java/org/tharak/PluginMethodHandleTest.java +44 -0
- package/src/test/java/org/tharak/util/HostMaskTest.java +70 -0
- package/src/test/java/org/thiragatisoft/core/ExampleUnitTest.java +17 -0
- package/src/test/test.iml +11 -0
@@ -0,0 +1,218 @@
|
|
1
|
+
package org.thiragatisoft.core;
|
2
|
+
|
3
|
+
import com.android.volley.AuthFailureError;
|
4
|
+
import com.android.volley.NetworkResponse;
|
5
|
+
import com.android.volley.ParseError;
|
6
|
+
import com.android.volley.Request;
|
7
|
+
import com.android.volley.Response;
|
8
|
+
import com.android.volley.VolleyError;
|
9
|
+
import com.android.volley.toolbox.HttpHeaderParser;
|
10
|
+
|
11
|
+
import java.io.ByteArrayInputStream;
|
12
|
+
import java.io.ByteArrayOutputStream;
|
13
|
+
import java.io.DataOutputStream;
|
14
|
+
import java.io.IOException;
|
15
|
+
import java.io.UnsupportedEncodingException;
|
16
|
+
import java.util.Map;
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Tharak
|
20
|
+
*/
|
21
|
+
|
22
|
+
public class VolleyMultipartRequest extends Request<NetworkResponse> {
|
23
|
+
|
24
|
+
private final String twoHyphens = "--";
|
25
|
+
private final String lineEnd = "\r\n";
|
26
|
+
private final String boundary = "apiclient-" + System.currentTimeMillis();
|
27
|
+
|
28
|
+
private Response.Listener<NetworkResponse> mListener;
|
29
|
+
private Response.ErrorListener mErrorListener;
|
30
|
+
private Map<String, String> mHeaders;
|
31
|
+
|
32
|
+
|
33
|
+
public VolleyMultipartRequest(int method, String url,
|
34
|
+
Response.Listener<NetworkResponse> listener,
|
35
|
+
Response.ErrorListener errorListener) {
|
36
|
+
super(method, url, errorListener);
|
37
|
+
this.mListener = listener;
|
38
|
+
this.mErrorListener = errorListener;
|
39
|
+
}
|
40
|
+
|
41
|
+
@Override
|
42
|
+
public Map<String, String> getHeaders() throws AuthFailureError {
|
43
|
+
return (mHeaders != null) ? mHeaders : super.getHeaders();
|
44
|
+
}
|
45
|
+
|
46
|
+
@Override
|
47
|
+
public String getBodyContentType() {
|
48
|
+
return "multipart/form-data;boundary=" + boundary;
|
49
|
+
}
|
50
|
+
|
51
|
+
@Override
|
52
|
+
public byte[] getBody() throws AuthFailureError {
|
53
|
+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
54
|
+
DataOutputStream dos = new DataOutputStream(bos);
|
55
|
+
|
56
|
+
try {
|
57
|
+
// populate text payload
|
58
|
+
Map<String, String> params = getParams();
|
59
|
+
if (params != null && params.size() > 0) {
|
60
|
+
textParse(dos, params, getParamsEncoding());
|
61
|
+
}
|
62
|
+
|
63
|
+
// populate data byte payload
|
64
|
+
Map<String, DataPart> data = getByteData();
|
65
|
+
if (data != null && data.size() > 0) {
|
66
|
+
dataParse(dos, data);
|
67
|
+
}
|
68
|
+
|
69
|
+
// close multipart form data after text and file data
|
70
|
+
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
|
71
|
+
|
72
|
+
return bos.toByteArray();
|
73
|
+
} catch (IOException e) {
|
74
|
+
e.printStackTrace();
|
75
|
+
}
|
76
|
+
return null;
|
77
|
+
}
|
78
|
+
|
79
|
+
/**
|
80
|
+
* Custom method handle data payload.
|
81
|
+
*
|
82
|
+
* @return Map data part label with data byte
|
83
|
+
* @throws AuthFailureError
|
84
|
+
*/
|
85
|
+
protected Map<String, DataPart> getByteData() throws AuthFailureError {
|
86
|
+
return null;
|
87
|
+
}
|
88
|
+
|
89
|
+
@Override
|
90
|
+
protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) {
|
91
|
+
try {
|
92
|
+
return Response.success(
|
93
|
+
response,
|
94
|
+
HttpHeaderParser.parseCacheHeaders(response));
|
95
|
+
} catch (Exception e) {
|
96
|
+
return Response.error(new ParseError(e));
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
@Override
|
101
|
+
protected void deliverResponse(NetworkResponse response) {
|
102
|
+
mListener.onResponse(response);
|
103
|
+
}
|
104
|
+
|
105
|
+
@Override
|
106
|
+
public void deliverError(VolleyError error) {
|
107
|
+
mErrorListener.onErrorResponse(error);
|
108
|
+
}
|
109
|
+
|
110
|
+
/**
|
111
|
+
* Parse string map into data output stream by key and value.
|
112
|
+
*
|
113
|
+
* @param dataOutputStream data output stream handle string parsing
|
114
|
+
* @param params string inputs collection
|
115
|
+
* @param encoding encode the inputs, default UTF-8
|
116
|
+
* @throws IOException
|
117
|
+
*/
|
118
|
+
private void textParse(DataOutputStream dataOutputStream, Map<String, String> params, String encoding) throws IOException {
|
119
|
+
try {
|
120
|
+
for (Map.Entry<String, String> entry : params.entrySet()) {
|
121
|
+
buildTextPart(dataOutputStream, entry.getKey(), entry.getValue());
|
122
|
+
}
|
123
|
+
} catch (UnsupportedEncodingException uee) {
|
124
|
+
throw new RuntimeException("Encoding not supported: " + encoding, uee);
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
/**
|
129
|
+
* Parse data into data output stream.
|
130
|
+
*
|
131
|
+
* @param dataOutputStream data output stream handle file attachment
|
132
|
+
* @param data loop through data
|
133
|
+
* @throws IOException
|
134
|
+
*/
|
135
|
+
private void dataParse(DataOutputStream dataOutputStream, Map<String, DataPart> data) throws IOException {
|
136
|
+
for (Map.Entry<String, DataPart> entry : data.entrySet()) {
|
137
|
+
buildDataPart(dataOutputStream, entry.getValue(), entry.getKey());
|
138
|
+
}
|
139
|
+
}
|
140
|
+
|
141
|
+
/**
|
142
|
+
* Write string data into header and data output stream.
|
143
|
+
*
|
144
|
+
* @param dataOutputStream data output stream handle string parsing
|
145
|
+
* @param parameterName name of input
|
146
|
+
* @param parameterValue value of input
|
147
|
+
* @throws IOException
|
148
|
+
*/
|
149
|
+
private void buildTextPart(DataOutputStream dataOutputStream, String parameterName, String parameterValue) throws IOException {
|
150
|
+
dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
|
151
|
+
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + parameterName + "\"" + lineEnd);
|
152
|
+
dataOutputStream.writeBytes(lineEnd);
|
153
|
+
dataOutputStream.writeBytes(parameterValue + lineEnd);
|
154
|
+
}
|
155
|
+
|
156
|
+
/**
|
157
|
+
* Write data file into header and data output stream.
|
158
|
+
*
|
159
|
+
* @param dataOutputStream data output stream handle data parsing
|
160
|
+
* @param dataFile data byte as DataPart from collection
|
161
|
+
* @param inputName name of data input
|
162
|
+
* @throws IOException
|
163
|
+
*/
|
164
|
+
private void buildDataPart(DataOutputStream dataOutputStream, DataPart dataFile, String inputName) throws IOException {
|
165
|
+
dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
|
166
|
+
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" +
|
167
|
+
inputName + "\"; filename=\"" + dataFile.getFileName() + "\"" + lineEnd);
|
168
|
+
if (dataFile.getType() != null && !dataFile.getType().trim().isEmpty()) {
|
169
|
+
dataOutputStream.writeBytes("Content-Type: " + dataFile.getType() + lineEnd);
|
170
|
+
}
|
171
|
+
dataOutputStream.writeBytes(lineEnd);
|
172
|
+
|
173
|
+
ByteArrayInputStream fileInputStream = new ByteArrayInputStream(dataFile.getContent());
|
174
|
+
int bytesAvailable = fileInputStream.available();
|
175
|
+
|
176
|
+
int maxBufferSize = 1024 * 1024;
|
177
|
+
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
|
178
|
+
byte[] buffer = new byte[bufferSize];
|
179
|
+
|
180
|
+
int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
|
181
|
+
|
182
|
+
while (bytesRead > 0) {
|
183
|
+
dataOutputStream.write(buffer, 0, bufferSize);
|
184
|
+
bytesAvailable = fileInputStream.available();
|
185
|
+
bufferSize = Math.min(bytesAvailable, maxBufferSize);
|
186
|
+
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
|
187
|
+
}
|
188
|
+
|
189
|
+
dataOutputStream.writeBytes(lineEnd);
|
190
|
+
}
|
191
|
+
|
192
|
+
class DataPart {
|
193
|
+
private String fileName;
|
194
|
+
private byte[] content;
|
195
|
+
private String type;
|
196
|
+
|
197
|
+
public DataPart() {
|
198
|
+
}
|
199
|
+
|
200
|
+
DataPart(String name, byte[] data) {
|
201
|
+
fileName = name;
|
202
|
+
content = data;
|
203
|
+
}
|
204
|
+
|
205
|
+
String getFileName() {
|
206
|
+
return fileName;
|
207
|
+
}
|
208
|
+
|
209
|
+
byte[] getContent() {
|
210
|
+
return content;
|
211
|
+
}
|
212
|
+
|
213
|
+
String getType() {
|
214
|
+
return type;
|
215
|
+
}
|
216
|
+
|
217
|
+
}
|
218
|
+
}
|
@@ -0,0 +1,175 @@
|
|
1
|
+
package org.thiragatisoft.core.http;
|
2
|
+
|
3
|
+
|
4
|
+
import java.net.CookieManager;
|
5
|
+
import java.net.CookiePolicy;
|
6
|
+
import java.net.CookieStore;
|
7
|
+
import java.net.HttpCookie;
|
8
|
+
import java.net.URI;
|
9
|
+
import java.util.ArrayList;
|
10
|
+
import java.util.Collections;
|
11
|
+
import java.util.HashMap;
|
12
|
+
import java.util.List;
|
13
|
+
import java.util.Map;
|
14
|
+
import java.util.Objects;
|
15
|
+
|
16
|
+
public class CapacitorCookieManager extends CookieManager {
|
17
|
+
|
18
|
+
private final android.webkit.CookieManager webkitCookieManager;
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Create a new cookie manager for use with @capacitor-community/http with the default cookie
|
22
|
+
* store and policy
|
23
|
+
*/
|
24
|
+
public CapacitorCookieManager() {
|
25
|
+
this(null, null);
|
26
|
+
}
|
27
|
+
|
28
|
+
/**
|
29
|
+
* Create a new cookie manager for use with @capacitor-community/http with specified cookie
|
30
|
+
* store and cookie policy.
|
31
|
+
* @param store a {@code CookieStore} to be used by cookiemanager. if {@code null}, cookie
|
32
|
+
* manager will use a default one, which is an in-memory CookieStore implementation.
|
33
|
+
* @param policy a {@code CookiePolicy} instance to be used by cookie manager as policy
|
34
|
+
* callback. if {@code null}, ACCEPT_ORIGINAL_SERVER will be used.
|
35
|
+
*/
|
36
|
+
public CapacitorCookieManager(CookieStore store, CookiePolicy policy) {
|
37
|
+
super(store, policy);
|
38
|
+
webkitCookieManager = android.webkit.CookieManager.getInstance();
|
39
|
+
}
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Gets the cookies for the given URL.
|
43
|
+
* @param url the URL for which the cookies are requested
|
44
|
+
* @return value the cookies as a string, using the format of the 'Cookie' HTTP request header
|
45
|
+
*/
|
46
|
+
public String getCookieString(String url) {
|
47
|
+
return webkitCookieManager.getCookie(url);
|
48
|
+
}
|
49
|
+
|
50
|
+
/**
|
51
|
+
* Gets a cookie value for the given URL and key.
|
52
|
+
* @param url the URL for which the cookies are requested
|
53
|
+
* @param key the key of the cookie to search for
|
54
|
+
* @return the {@code HttpCookie} value of the cookie at the key,
|
55
|
+
* otherwise it will return a new empty {@code HttpCookie}
|
56
|
+
*/
|
57
|
+
public HttpCookie getCookie(String url, String key) {
|
58
|
+
HttpCookie[] cookies = getCookies(url);
|
59
|
+
for (HttpCookie cookie : cookies) {
|
60
|
+
if (cookie.getName().equals(key)) {
|
61
|
+
return cookie;
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
return null;
|
66
|
+
}
|
67
|
+
|
68
|
+
/**
|
69
|
+
* Gets an array of {@code HttpCookie} given a URL.
|
70
|
+
* @param url the URL for which the cookies are requested
|
71
|
+
* @return an {@code HttpCookie} array of non-expired cookies
|
72
|
+
*/
|
73
|
+
public HttpCookie[] getCookies(String url) {
|
74
|
+
try {
|
75
|
+
ArrayList<HttpCookie> cookieList = new ArrayList<>();
|
76
|
+
String cookieString = getCookieString(url);
|
77
|
+
if (cookieString != null) {
|
78
|
+
String[] singleCookie = cookieString.split(";");
|
79
|
+
for (String c : singleCookie) {
|
80
|
+
HttpCookie parsed = HttpCookie.parse(c).get(0);
|
81
|
+
parsed.setValue(parsed.getValue());
|
82
|
+
cookieList.add(parsed);
|
83
|
+
}
|
84
|
+
}
|
85
|
+
HttpCookie[] cookies = new HttpCookie[cookieList.size()];
|
86
|
+
return cookieList.toArray(cookies);
|
87
|
+
} catch (Exception ex) {
|
88
|
+
return new HttpCookie[0];
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
/**
|
93
|
+
* Sets a cookie for the given URL. Any existing cookie with the same host, path and name will
|
94
|
+
* be replaced with the new cookie. The cookie being set will be ignored if it is expired.
|
95
|
+
* @param url the URL for which the cookie is to be set
|
96
|
+
* @param value the cookie as a string, using the format of the 'Set-Cookie' HTTP response header
|
97
|
+
*/
|
98
|
+
public void setCookie(String url, String value) {
|
99
|
+
webkitCookieManager.setCookie(url, value);
|
100
|
+
flush();
|
101
|
+
}
|
102
|
+
|
103
|
+
/**
|
104
|
+
* Sets a cookie for the given URL. Any existing cookie with the same host, path and name will
|
105
|
+
* be replaced with the new cookie. The cookie being set will be ignored if it is expired.
|
106
|
+
* @param url the URL for which the cookie is to be set
|
107
|
+
* @param key the {@code HttpCookie} name to use for lookup
|
108
|
+
* @param value the value of the {@code HttpCookie} given a key
|
109
|
+
*/
|
110
|
+
public void setCookie(String url, String key, String value) {
|
111
|
+
String cookieValue = key + "=" + value;
|
112
|
+
setCookie(url, cookieValue);
|
113
|
+
}
|
114
|
+
|
115
|
+
/**
|
116
|
+
* Removes all cookies. This method is asynchronous.
|
117
|
+
*/
|
118
|
+
public void removeAllCookies() {
|
119
|
+
webkitCookieManager.removeAllCookies(null);
|
120
|
+
flush();
|
121
|
+
}
|
122
|
+
|
123
|
+
/**
|
124
|
+
* Ensures all cookies currently accessible through the getCookie API are written to persistent
|
125
|
+
* storage. This call will block the caller until it is done and may perform I/O.
|
126
|
+
*/
|
127
|
+
public void flush() {
|
128
|
+
webkitCookieManager.flush();
|
129
|
+
}
|
130
|
+
|
131
|
+
@Override
|
132
|
+
public void put(URI uri, Map<String, List<String>> responseHeaders) {
|
133
|
+
// make sure our args are valid
|
134
|
+
if ((uri == null) || (responseHeaders == null)) return;
|
135
|
+
|
136
|
+
// save our url once
|
137
|
+
String url = uri.toString();
|
138
|
+
|
139
|
+
// go over the headers
|
140
|
+
for (String headerKey : responseHeaders.keySet()) {
|
141
|
+
// ignore headers which aren't cookie related
|
142
|
+
if ((headerKey == null) || !(headerKey.equalsIgnoreCase("Set-Cookie2") || headerKey.equalsIgnoreCase("Set-Cookie"))) continue;
|
143
|
+
|
144
|
+
// process each of the headers
|
145
|
+
for (String headerValue : Objects.requireNonNull(responseHeaders.get(headerKey))) {
|
146
|
+
setCookie(url, headerValue);
|
147
|
+
}
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
151
|
+
@Override
|
152
|
+
public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) {
|
153
|
+
// make sure our args are valid
|
154
|
+
if ((uri == null) || (requestHeaders == null)) throw new IllegalArgumentException("Argument is null");
|
155
|
+
|
156
|
+
// save our url once
|
157
|
+
String url = uri.toString();
|
158
|
+
|
159
|
+
// prepare our response
|
160
|
+
Map<String, List<String>> res = new HashMap<>();
|
161
|
+
|
162
|
+
// get the cookie
|
163
|
+
String cookie = getCookieString(url);
|
164
|
+
|
165
|
+
// return it
|
166
|
+
if (cookie != null) res.put("Cookie", Collections.singletonList(cookie));
|
167
|
+
return res;
|
168
|
+
}
|
169
|
+
|
170
|
+
@Override
|
171
|
+
public CookieStore getCookieStore() {
|
172
|
+
// we don't want anyone to work with this cookie store directly
|
173
|
+
throw new UnsupportedOperationException();
|
174
|
+
}
|
175
|
+
}
|