@capacitor-plus/android 8.0.0-beta.0
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/LICENSE +21 -0
- package/capacitor/build.gradle +94 -0
- package/capacitor/lint-baseline.xml +136 -0
- package/capacitor/lint.xml +9 -0
- package/capacitor/proguard-rules.pro +28 -0
- package/capacitor/src/main/AndroidManifest.xml +3 -0
- package/capacitor/src/main/assets/native-bridge.js +1029 -0
- package/capacitor/src/main/java/com/getcapacitor/AndroidProtocolHandler.java +94 -0
- package/capacitor/src/main/java/com/getcapacitor/App.java +61 -0
- package/capacitor/src/main/java/com/getcapacitor/AppUUID.java +65 -0
- package/capacitor/src/main/java/com/getcapacitor/Bridge.java +1627 -0
- package/capacitor/src/main/java/com/getcapacitor/BridgeActivity.java +212 -0
- package/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java +467 -0
- package/capacitor/src/main/java/com/getcapacitor/BridgeWebViewClient.java +105 -0
- package/capacitor/src/main/java/com/getcapacitor/CapConfig.java +709 -0
- package/capacitor/src/main/java/com/getcapacitor/CapacitorWebView.java +57 -0
- package/capacitor/src/main/java/com/getcapacitor/FileUtils.java +303 -0
- package/capacitor/src/main/java/com/getcapacitor/InvalidPluginException.java +8 -0
- package/capacitor/src/main/java/com/getcapacitor/InvalidPluginMethodException.java +16 -0
- package/capacitor/src/main/java/com/getcapacitor/JSArray.java +51 -0
- package/capacitor/src/main/java/com/getcapacitor/JSExport.java +208 -0
- package/capacitor/src/main/java/com/getcapacitor/JSExportException.java +16 -0
- package/capacitor/src/main/java/com/getcapacitor/JSInjector.java +127 -0
- package/capacitor/src/main/java/com/getcapacitor/JSObject.java +164 -0
- package/capacitor/src/main/java/com/getcapacitor/JSValue.java +65 -0
- package/capacitor/src/main/java/com/getcapacitor/Logger.java +103 -0
- package/capacitor/src/main/java/com/getcapacitor/MessageHandler.java +157 -0
- package/capacitor/src/main/java/com/getcapacitor/NativePlugin.java +37 -0
- package/capacitor/src/main/java/com/getcapacitor/PermissionState.java +31 -0
- package/capacitor/src/main/java/com/getcapacitor/Plugin.java +1050 -0
- package/capacitor/src/main/java/com/getcapacitor/PluginCall.java +394 -0
- package/capacitor/src/main/java/com/getcapacitor/PluginConfig.java +116 -0
- package/capacitor/src/main/java/com/getcapacitor/PluginHandle.java +160 -0
- package/capacitor/src/main/java/com/getcapacitor/PluginInvocationException.java +16 -0
- package/capacitor/src/main/java/com/getcapacitor/PluginLoadException.java +19 -0
- package/capacitor/src/main/java/com/getcapacitor/PluginManager.java +56 -0
- package/capacitor/src/main/java/com/getcapacitor/PluginMethod.java +15 -0
- package/capacitor/src/main/java/com/getcapacitor/PluginMethodHandle.java +33 -0
- package/capacitor/src/main/java/com/getcapacitor/PluginResult.java +84 -0
- package/capacitor/src/main/java/com/getcapacitor/ProcessedRoute.java +37 -0
- package/capacitor/src/main/java/com/getcapacitor/RouteProcessor.java +8 -0
- package/capacitor/src/main/java/com/getcapacitor/ServerPath.java +25 -0
- package/capacitor/src/main/java/com/getcapacitor/UriMatcher.java +184 -0
- package/capacitor/src/main/java/com/getcapacitor/WebViewListener.java +57 -0
- package/capacitor/src/main/java/com/getcapacitor/WebViewLocalServer.java +758 -0
- package/capacitor/src/main/java/com/getcapacitor/annotation/ActivityCallback.java +10 -0
- package/capacitor/src/main/java/com/getcapacitor/annotation/CapacitorPlugin.java +35 -0
- package/capacitor/src/main/java/com/getcapacitor/annotation/Permission.java +22 -0
- package/capacitor/src/main/java/com/getcapacitor/annotation/PermissionCallback.java +10 -0
- package/capacitor/src/main/java/com/getcapacitor/cordova/CapacitorCordovaCookieManager.java +42 -0
- package/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaInterfaceImpl.java +39 -0
- package/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.java +282 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorCookieManager.java +239 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorCookies.java +119 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorHttp.java +119 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java +220 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/WebView.java +48 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/util/AssetUtil.java +358 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/util/CapacitorHttpUrlConnection.java +473 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/util/HttpRequestHandler.java +465 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/util/ICapacitorHttpUrlConnection.java +15 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/util/MimeType.java +17 -0
- package/capacitor/src/main/java/com/getcapacitor/util/HostMask.java +123 -0
- package/capacitor/src/main/java/com/getcapacitor/util/InternalUtils.java +27 -0
- package/capacitor/src/main/java/com/getcapacitor/util/JSONUtils.java +166 -0
- package/capacitor/src/main/java/com/getcapacitor/util/PermissionHelper.java +114 -0
- package/capacitor/src/main/java/com/getcapacitor/util/WebColor.java +28 -0
- package/capacitor/src/main/res/layout/capacitor_bridge_layout_main.xml +15 -0
- package/capacitor/src/main/res/layout/no_webview.xml +14 -0
- package/capacitor/src/main/res/values/colors.xml +6 -0
- package/capacitor/src/main/res/values/strings.xml +3 -0
- package/capacitor/src/main/res/values/styles.xml +6 -0
- package/package.json +31 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
package com.getcapacitor;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.os.Build;
|
|
5
|
+
import android.util.AttributeSet;
|
|
6
|
+
import android.util.TypedValue;
|
|
7
|
+
import android.view.KeyEvent;
|
|
8
|
+
import android.view.inputmethod.BaseInputConnection;
|
|
9
|
+
import android.view.inputmethod.EditorInfo;
|
|
10
|
+
import android.view.inputmethod.InputConnection;
|
|
11
|
+
import android.webkit.WebView;
|
|
12
|
+
import androidx.core.graphics.Insets;
|
|
13
|
+
import androidx.core.view.ViewCompat;
|
|
14
|
+
import androidx.core.view.WindowInsetsCompat;
|
|
15
|
+
|
|
16
|
+
public class CapacitorWebView extends WebView {
|
|
17
|
+
|
|
18
|
+
private BaseInputConnection capInputConnection;
|
|
19
|
+
private Bridge bridge;
|
|
20
|
+
|
|
21
|
+
public CapacitorWebView(Context context, AttributeSet attrs) {
|
|
22
|
+
super(context, attrs);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public void setBridge(Bridge bridge) {
|
|
26
|
+
this.bridge = bridge;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Override
|
|
30
|
+
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
|
31
|
+
CapConfig config;
|
|
32
|
+
if (bridge != null) {
|
|
33
|
+
config = bridge.getConfig();
|
|
34
|
+
} else {
|
|
35
|
+
config = CapConfig.loadDefault(getContext());
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
boolean captureInput = config.isInputCaptured();
|
|
39
|
+
if (captureInput) {
|
|
40
|
+
if (capInputConnection == null) {
|
|
41
|
+
capInputConnection = new BaseInputConnection(this, false);
|
|
42
|
+
}
|
|
43
|
+
return capInputConnection;
|
|
44
|
+
}
|
|
45
|
+
return super.onCreateInputConnection(outAttrs);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@Override
|
|
49
|
+
@SuppressWarnings("deprecation")
|
|
50
|
+
public boolean dispatchKeyEvent(KeyEvent event) {
|
|
51
|
+
if (event.getAction() == KeyEvent.ACTION_MULTIPLE) {
|
|
52
|
+
evaluateJavascript("document.activeElement.value = document.activeElement.value + '" + event.getCharacters() + "';", null);
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return super.dispatchKeyEvent(event);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portions adopted from react-native-image-crop-picker
|
|
3
|
+
*
|
|
4
|
+
* MIT License
|
|
5
|
+
|
|
6
|
+
* Copyright (c) 2017 Ivan Pusic
|
|
7
|
+
|
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
10
|
+
* in the Software without restriction, including without limitation the rights
|
|
11
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
13
|
+
* furnished to do so, subject to the following conditions:
|
|
14
|
+
*
|
|
15
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
* copies or substantial portions of the Software.
|
|
17
|
+
*
|
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
* SOFTWARE.
|
|
25
|
+
*/
|
|
26
|
+
package com.getcapacitor;
|
|
27
|
+
|
|
28
|
+
import android.content.ContentUris;
|
|
29
|
+
import android.content.Context;
|
|
30
|
+
import android.content.res.AssetManager;
|
|
31
|
+
import android.database.Cursor;
|
|
32
|
+
import android.net.Uri;
|
|
33
|
+
import android.os.Environment;
|
|
34
|
+
import android.provider.DocumentsContract;
|
|
35
|
+
import android.provider.MediaStore;
|
|
36
|
+
import android.provider.OpenableColumns;
|
|
37
|
+
import java.io.BufferedReader;
|
|
38
|
+
import java.io.File;
|
|
39
|
+
import java.io.FileOutputStream;
|
|
40
|
+
import java.io.FileReader;
|
|
41
|
+
import java.io.IOException;
|
|
42
|
+
import java.io.InputStream;
|
|
43
|
+
import java.io.InputStreamReader;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Common File utilities, such as resolve content URIs and
|
|
47
|
+
* creating portable web paths from low-level files
|
|
48
|
+
*/
|
|
49
|
+
public class FileUtils {
|
|
50
|
+
|
|
51
|
+
private static String CapacitorFileScheme = Bridge.CAPACITOR_FILE_START;
|
|
52
|
+
|
|
53
|
+
public enum Type {
|
|
54
|
+
IMAGE("image");
|
|
55
|
+
|
|
56
|
+
private String type;
|
|
57
|
+
|
|
58
|
+
Type(String type) {
|
|
59
|
+
this.type = type;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public static String getPortablePath(Context c, String host, Uri u) {
|
|
64
|
+
String path = getFileUrlForUri(c, u);
|
|
65
|
+
if (path.startsWith("file://")) {
|
|
66
|
+
path = path.replace("file://", "");
|
|
67
|
+
}
|
|
68
|
+
return host + Bridge.CAPACITOR_FILE_START + path;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public static String getFileUrlForUri(final Context context, final Uri uri) {
|
|
72
|
+
// DocumentProvider
|
|
73
|
+
if (DocumentsContract.isDocumentUri(context, uri)) {
|
|
74
|
+
// ExternalStorageProvider
|
|
75
|
+
if (isExternalStorageDocument(uri)) {
|
|
76
|
+
final String docId = DocumentsContract.getDocumentId(uri);
|
|
77
|
+
final String[] split = docId.split(":");
|
|
78
|
+
final String type = split[0];
|
|
79
|
+
|
|
80
|
+
if ("primary".equalsIgnoreCase(type)) {
|
|
81
|
+
return legacyPrimaryPath(split[1]);
|
|
82
|
+
} else {
|
|
83
|
+
final int splitIndex = docId.indexOf(':', 1);
|
|
84
|
+
final String tag = docId.substring(0, splitIndex);
|
|
85
|
+
final String path = docId.substring(splitIndex + 1);
|
|
86
|
+
|
|
87
|
+
String nonPrimaryVolume = getPathToNonPrimaryVolume(context, tag);
|
|
88
|
+
if (nonPrimaryVolume != null) {
|
|
89
|
+
String result = nonPrimaryVolume + "/" + path;
|
|
90
|
+
File file = new File(result);
|
|
91
|
+
if (file.exists() && file.canRead()) {
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// DownloadsProvider
|
|
99
|
+
else if (isDownloadsDocument(uri)) {
|
|
100
|
+
final String id = DocumentsContract.getDocumentId(uri);
|
|
101
|
+
final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
|
|
102
|
+
|
|
103
|
+
return getDataColumn(context, contentUri, null, null);
|
|
104
|
+
}
|
|
105
|
+
// MediaProvider
|
|
106
|
+
else if (isMediaDocument(uri)) {
|
|
107
|
+
final String docId = DocumentsContract.getDocumentId(uri);
|
|
108
|
+
final String[] split = docId.split(":");
|
|
109
|
+
final String type = split[0];
|
|
110
|
+
|
|
111
|
+
Uri contentUri = null;
|
|
112
|
+
if ("image".equals(type)) {
|
|
113
|
+
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
|
114
|
+
} else if ("video".equals(type)) {
|
|
115
|
+
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
|
116
|
+
} else if ("audio".equals(type)) {
|
|
117
|
+
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
final String selection = "_id=?";
|
|
121
|
+
final String[] selectionArgs = new String[] { split[1] };
|
|
122
|
+
|
|
123
|
+
return getDataColumn(context, contentUri, selection, selectionArgs);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// MediaStore (and general)
|
|
127
|
+
else if ("content".equalsIgnoreCase(uri.getScheme())) {
|
|
128
|
+
// Return the remote address
|
|
129
|
+
if (isGooglePhotosUri(uri)) return uri.getLastPathSegment();
|
|
130
|
+
return getDataColumn(context, uri, null, null);
|
|
131
|
+
}
|
|
132
|
+
// File
|
|
133
|
+
else if ("file".equalsIgnoreCase(uri.getScheme())) {
|
|
134
|
+
return uri.getPath();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@SuppressWarnings("deprecation")
|
|
141
|
+
private static String legacyPrimaryPath(String pathPart) {
|
|
142
|
+
return Environment.getExternalStorageDirectory() + "/" + pathPart;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Read a plaintext file from the assets directory.
|
|
147
|
+
*
|
|
148
|
+
* @param assetManager Used to open the file.
|
|
149
|
+
* @param fileName The path of the file to read.
|
|
150
|
+
* @return The contents of the file path.
|
|
151
|
+
* @throws IOException Thrown if any issues reading the provided file path.
|
|
152
|
+
*/
|
|
153
|
+
static String readFileFromAssets(AssetManager assetManager, String fileName) throws IOException {
|
|
154
|
+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(assetManager.open(fileName)))) {
|
|
155
|
+
StringBuilder buffer = new StringBuilder();
|
|
156
|
+
String line;
|
|
157
|
+
while ((line = reader.readLine()) != null) {
|
|
158
|
+
buffer.append(line).append("\n");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return buffer.toString();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Read a plaintext file from within the app disk space.
|
|
167
|
+
*
|
|
168
|
+
* @param file The file to read.
|
|
169
|
+
* @return The contents of the file path.
|
|
170
|
+
* @throws IOException Thrown if any issues reading the provided file path.
|
|
171
|
+
*/
|
|
172
|
+
static String readFileFromDisk(File file) throws IOException {
|
|
173
|
+
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
|
174
|
+
StringBuilder buffer = new StringBuilder();
|
|
175
|
+
String line;
|
|
176
|
+
while ((line = reader.readLine()) != null) {
|
|
177
|
+
buffer.append(line).append("\n");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return buffer.toString();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Get the value of the data column for this Uri. This is useful for
|
|
186
|
+
* MediaStore Uris, and other file-based ContentProviders.
|
|
187
|
+
*
|
|
188
|
+
* @param context The context.
|
|
189
|
+
* @param uri The Uri to query.
|
|
190
|
+
* @param selection (Optional) Filter used in the query.
|
|
191
|
+
* @param selectionArgs (Optional) Selection arguments used in the query.
|
|
192
|
+
* @return The value of the _data column, which is typically a file path.
|
|
193
|
+
*/
|
|
194
|
+
private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
|
|
195
|
+
String path = null;
|
|
196
|
+
Cursor cursor = null;
|
|
197
|
+
final String column = "_data";
|
|
198
|
+
final String[] projection = { column };
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
|
|
202
|
+
if (cursor != null && cursor.moveToFirst()) {
|
|
203
|
+
final int index = cursor.getColumnIndexOrThrow(column);
|
|
204
|
+
path = cursor.getString(index);
|
|
205
|
+
}
|
|
206
|
+
} catch (IllegalArgumentException ex) {
|
|
207
|
+
return getCopyFilePath(uri, context);
|
|
208
|
+
} finally {
|
|
209
|
+
if (cursor != null) cursor.close();
|
|
210
|
+
}
|
|
211
|
+
if (path == null) {
|
|
212
|
+
return getCopyFilePath(uri, context);
|
|
213
|
+
}
|
|
214
|
+
return path;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private static String getCopyFilePath(Uri uri, Context context) {
|
|
218
|
+
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
|
|
219
|
+
int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
|
220
|
+
cursor.moveToFirst();
|
|
221
|
+
String name = (cursor.getString(nameIndex));
|
|
222
|
+
String fileName = sanitizeFilename(name);
|
|
223
|
+
File file = new File(context.getFilesDir(), fileName);
|
|
224
|
+
try {
|
|
225
|
+
InputStream inputStream = context.getContentResolver().openInputStream(uri);
|
|
226
|
+
FileOutputStream outputStream = new FileOutputStream(file);
|
|
227
|
+
int read = 0;
|
|
228
|
+
int maxBufferSize = 1024 * 1024;
|
|
229
|
+
int bufferSize = Math.min(inputStream.available(), maxBufferSize);
|
|
230
|
+
final byte[] buffers = new byte[bufferSize];
|
|
231
|
+
while ((read = inputStream.read(buffers)) != -1) {
|
|
232
|
+
outputStream.write(buffers, 0, read);
|
|
233
|
+
}
|
|
234
|
+
inputStream.close();
|
|
235
|
+
outputStream.close();
|
|
236
|
+
} catch (Exception e) {
|
|
237
|
+
return null;
|
|
238
|
+
} finally {
|
|
239
|
+
if (cursor != null) cursor.close();
|
|
240
|
+
}
|
|
241
|
+
return file.getPath();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* @param uri The Uri to check.
|
|
246
|
+
* @return Whether the Uri authority is ExternalStorageProvider.
|
|
247
|
+
*/
|
|
248
|
+
private static boolean isExternalStorageDocument(Uri uri) {
|
|
249
|
+
return "com.android.externalstorage.documents".equals(uri.getAuthority());
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* @param uri The Uri to check.
|
|
254
|
+
* @return Whether the Uri authority is DownloadsProvider.
|
|
255
|
+
*/
|
|
256
|
+
private static boolean isDownloadsDocument(Uri uri) {
|
|
257
|
+
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* @param uri The Uri to check.
|
|
262
|
+
* @return Whether the Uri authority is MediaProvider.
|
|
263
|
+
*/
|
|
264
|
+
private static boolean isMediaDocument(Uri uri) {
|
|
265
|
+
return "com.android.providers.media.documents".equals(uri.getAuthority());
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* @param uri The Uri to check.
|
|
270
|
+
* @return Whether the Uri authority is Google Photos.
|
|
271
|
+
*/
|
|
272
|
+
private static boolean isGooglePhotosUri(Uri uri) {
|
|
273
|
+
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
private static String getPathToNonPrimaryVolume(Context context, String tag) {
|
|
277
|
+
File[] volumes = context.getExternalCacheDirs();
|
|
278
|
+
if (volumes != null) {
|
|
279
|
+
for (File volume : volumes) {
|
|
280
|
+
if (volume != null) {
|
|
281
|
+
String path = volume.getAbsolutePath();
|
|
282
|
+
if (path != null) {
|
|
283
|
+
int index = path.indexOf(tag);
|
|
284
|
+
if (index != -1) {
|
|
285
|
+
return path.substring(0, index) + tag;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
private static String sanitizeFilename(String displayName) {
|
|
295
|
+
String[] badCharacters = new String[] { "..", "/" };
|
|
296
|
+
String[] segments = displayName.split("/");
|
|
297
|
+
String fileName = segments[segments.length - 1];
|
|
298
|
+
for (String suspString : badCharacters) {
|
|
299
|
+
fileName = fileName.replace(suspString, "_");
|
|
300
|
+
}
|
|
301
|
+
return fileName;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.getcapacitor;
|
|
2
|
+
|
|
3
|
+
class InvalidPluginMethodException extends Exception {
|
|
4
|
+
|
|
5
|
+
public InvalidPluginMethodException(String s) {
|
|
6
|
+
super(s);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
public InvalidPluginMethodException(Throwable t) {
|
|
10
|
+
super(t);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public InvalidPluginMethodException(String s, Throwable t) {
|
|
14
|
+
super(s, t);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
package com.getcapacitor;
|
|
2
|
+
|
|
3
|
+
import java.util.ArrayList;
|
|
4
|
+
import java.util.Collection;
|
|
5
|
+
import java.util.List;
|
|
6
|
+
import org.json.JSONArray;
|
|
7
|
+
import org.json.JSONException;
|
|
8
|
+
|
|
9
|
+
public class JSArray extends JSONArray {
|
|
10
|
+
|
|
11
|
+
public JSArray() {
|
|
12
|
+
super();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public JSArray(String json) throws JSONException {
|
|
16
|
+
super(json);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public JSArray(Collection copyFrom) {
|
|
20
|
+
super(copyFrom);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public JSArray(Object array) throws JSONException {
|
|
24
|
+
super(array);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@SuppressWarnings("unchecked")
|
|
28
|
+
public <E> List<E> toList() throws JSONException {
|
|
29
|
+
List<E> items = new ArrayList<>();
|
|
30
|
+
Object o = null;
|
|
31
|
+
for (int i = 0; i < this.length(); i++) {
|
|
32
|
+
o = this.get(i);
|
|
33
|
+
try {
|
|
34
|
+
items.add((E) this.get(i));
|
|
35
|
+
} catch (Exception ex) {
|
|
36
|
+
throw new JSONException("Not all items are instances of the given type");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return items;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create a new JSArray without throwing a error
|
|
44
|
+
*/
|
|
45
|
+
public static JSArray from(Object array) {
|
|
46
|
+
try {
|
|
47
|
+
return new JSArray(array);
|
|
48
|
+
} catch (JSONException ex) {}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
package com.getcapacitor;
|
|
2
|
+
|
|
3
|
+
import static com.getcapacitor.FileUtils.readFileFromAssets;
|
|
4
|
+
|
|
5
|
+
import android.content.Context;
|
|
6
|
+
import android.text.TextUtils;
|
|
7
|
+
import java.io.IOException;
|
|
8
|
+
import java.util.ArrayList;
|
|
9
|
+
import java.util.Collection;
|
|
10
|
+
import java.util.List;
|
|
11
|
+
import org.json.JSONArray;
|
|
12
|
+
import org.json.JSONException;
|
|
13
|
+
import org.json.JSONObject;
|
|
14
|
+
|
|
15
|
+
public class JSExport {
|
|
16
|
+
|
|
17
|
+
private static String CATCHALL_OPTIONS_PARAM = "_options";
|
|
18
|
+
private static String CALLBACK_PARAM = "_callback";
|
|
19
|
+
|
|
20
|
+
public static String getGlobalJS(Context context, boolean loggingEnabled, boolean isDebug) {
|
|
21
|
+
return "window.Capacitor = { DEBUG: " + isDebug + ", isLoggingEnabled: " + loggingEnabled + ", Plugins: {} };";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public static String getMiscFileJS(ArrayList<String> paths, Context context) {
|
|
25
|
+
List<String> lines = new ArrayList<>();
|
|
26
|
+
|
|
27
|
+
for (String path : paths) {
|
|
28
|
+
try {
|
|
29
|
+
String fileContent = readFileFromAssets(context.getAssets(), "public/" + path);
|
|
30
|
+
lines.add(fileContent);
|
|
31
|
+
} catch (IOException ex) {
|
|
32
|
+
Logger.error("Unable to read public/" + path);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return TextUtils.join("\n", lines);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public static String getCordovaJS(Context context) {
|
|
40
|
+
String fileContent = "";
|
|
41
|
+
try {
|
|
42
|
+
fileContent = readFileFromAssets(context.getAssets(), "public/cordova.js");
|
|
43
|
+
} catch (IOException ex) {
|
|
44
|
+
Logger.error("Unable to read public/cordova.js file, Cordova plugins will not work");
|
|
45
|
+
}
|
|
46
|
+
return fileContent;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public static String getCordovaPluginsFileJS(Context context) {
|
|
50
|
+
String fileContent = "";
|
|
51
|
+
try {
|
|
52
|
+
fileContent = readFileFromAssets(context.getAssets(), "public/cordova_plugins.js");
|
|
53
|
+
} catch (IOException ex) {
|
|
54
|
+
Logger.error("Unable to read public/cordova_plugins.js file, Cordova plugins will not work");
|
|
55
|
+
}
|
|
56
|
+
return fileContent;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public static String getPluginJS(Collection<PluginHandle> plugins) {
|
|
60
|
+
List<String> lines = new ArrayList<>();
|
|
61
|
+
JSONArray pluginArray = new JSONArray();
|
|
62
|
+
|
|
63
|
+
lines.add("// Begin: Capacitor Plugin JS");
|
|
64
|
+
for (PluginHandle plugin : plugins) {
|
|
65
|
+
lines.add(
|
|
66
|
+
"(function(w) {\n" +
|
|
67
|
+
"var a = (w.Capacitor = w.Capacitor || {});\n" +
|
|
68
|
+
"var p = (a.Plugins = a.Plugins || {});\n" +
|
|
69
|
+
"var t = (p['" +
|
|
70
|
+
plugin.getId() +
|
|
71
|
+
"'] = {});\n" +
|
|
72
|
+
"t.addListener = function(eventName, callback) {\n" +
|
|
73
|
+
" return w.Capacitor.addListener('" +
|
|
74
|
+
plugin.getId() +
|
|
75
|
+
"', eventName, callback);\n" +
|
|
76
|
+
"}"
|
|
77
|
+
);
|
|
78
|
+
Collection<PluginMethodHandle> methods = plugin.getMethods();
|
|
79
|
+
for (PluginMethodHandle method : methods) {
|
|
80
|
+
if (method.getName().equals("addListener") || method.getName().equals("removeListener")) {
|
|
81
|
+
// Don't export add/remove listener, we do that automatically above as they are "special snowflakes"
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
lines.add(generateMethodJS(plugin, method));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
lines.add("})(window);\n");
|
|
88
|
+
pluginArray.put(createPluginHeader(plugin));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return TextUtils.join("\n", lines) + "\nwindow.Capacitor.PluginHeaders = " + pluginArray.toString() + ";";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public static String getCordovaPluginJS(Context context) {
|
|
95
|
+
return getFilesContent(context, "public/plugins");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public static String getFilesContent(Context context, String path) {
|
|
99
|
+
StringBuilder builder = new StringBuilder();
|
|
100
|
+
try {
|
|
101
|
+
String[] content = context.getAssets().list(path);
|
|
102
|
+
if (content.length > 0) {
|
|
103
|
+
for (String file : content) {
|
|
104
|
+
if (!file.endsWith(".map")) {
|
|
105
|
+
builder.append(getFilesContent(context, path + "/" + file));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
return readFileFromAssets(context.getAssets(), path);
|
|
110
|
+
}
|
|
111
|
+
} catch (IOException ex) {
|
|
112
|
+
Logger.warn("Unable to read file at path " + path);
|
|
113
|
+
}
|
|
114
|
+
return builder.toString();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private static JSONObject createPluginHeader(PluginHandle plugin) {
|
|
118
|
+
JSONObject pluginObj = new JSONObject();
|
|
119
|
+
Collection<PluginMethodHandle> methods = plugin.getMethods();
|
|
120
|
+
try {
|
|
121
|
+
String id = plugin.getId();
|
|
122
|
+
JSONArray methodArray = new JSONArray();
|
|
123
|
+
pluginObj.put("name", id);
|
|
124
|
+
|
|
125
|
+
for (PluginMethodHandle method : methods) {
|
|
126
|
+
methodArray.put(createPluginMethodHeader(method));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
pluginObj.put("methods", methodArray);
|
|
130
|
+
} catch (JSONException e) {
|
|
131
|
+
// ignore
|
|
132
|
+
}
|
|
133
|
+
return pluginObj;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private static JSONObject createPluginMethodHeader(PluginMethodHandle method) {
|
|
137
|
+
JSONObject methodObj = new JSONObject();
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
methodObj.put("name", method.getName());
|
|
141
|
+
if (!method.getReturnType().equals(PluginMethod.RETURN_NONE)) {
|
|
142
|
+
methodObj.put("rtype", method.getReturnType());
|
|
143
|
+
}
|
|
144
|
+
} catch (JSONException e) {
|
|
145
|
+
// ignore
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return methodObj;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
public static String getBridgeJS(Context context) throws JSExportException {
|
|
152
|
+
return getFilesContent(context, "native-bridge.js");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private static String generateMethodJS(PluginHandle plugin, PluginMethodHandle method) {
|
|
156
|
+
List<String> lines = new ArrayList<>();
|
|
157
|
+
|
|
158
|
+
List<String> args = new ArrayList<>();
|
|
159
|
+
// Add the catch all param that will take a full javascript object to pass to the plugin
|
|
160
|
+
args.add(CATCHALL_OPTIONS_PARAM);
|
|
161
|
+
|
|
162
|
+
String returnType = method.getReturnType();
|
|
163
|
+
if (returnType.equals(PluginMethod.RETURN_CALLBACK)) {
|
|
164
|
+
args.add(CALLBACK_PARAM);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Create the method function declaration
|
|
168
|
+
lines.add("t['" + method.getName() + "'] = function(" + TextUtils.join(", ", args) + ") {");
|
|
169
|
+
|
|
170
|
+
switch (returnType) {
|
|
171
|
+
case PluginMethod.RETURN_NONE:
|
|
172
|
+
lines.add(
|
|
173
|
+
"return w.Capacitor.nativeCallback('" +
|
|
174
|
+
plugin.getId() +
|
|
175
|
+
"', '" +
|
|
176
|
+
method.getName() +
|
|
177
|
+
"', " +
|
|
178
|
+
CATCHALL_OPTIONS_PARAM +
|
|
179
|
+
")"
|
|
180
|
+
);
|
|
181
|
+
break;
|
|
182
|
+
case PluginMethod.RETURN_PROMISE:
|
|
183
|
+
lines.add(
|
|
184
|
+
"return w.Capacitor.nativePromise('" + plugin.getId() + "', '" + method.getName() + "', " + CATCHALL_OPTIONS_PARAM + ")"
|
|
185
|
+
);
|
|
186
|
+
break;
|
|
187
|
+
case PluginMethod.RETURN_CALLBACK:
|
|
188
|
+
lines.add(
|
|
189
|
+
"return w.Capacitor.nativeCallback('" +
|
|
190
|
+
plugin.getId() +
|
|
191
|
+
"', '" +
|
|
192
|
+
method.getName() +
|
|
193
|
+
"', " +
|
|
194
|
+
CATCHALL_OPTIONS_PARAM +
|
|
195
|
+
", " +
|
|
196
|
+
CALLBACK_PARAM +
|
|
197
|
+
")"
|
|
198
|
+
);
|
|
199
|
+
break;
|
|
200
|
+
default:
|
|
201
|
+
// TODO: Do something here?
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
lines.add("}");
|
|
205
|
+
|
|
206
|
+
return TextUtils.join("\n", lines);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.getcapacitor;
|
|
2
|
+
|
|
3
|
+
public class JSExportException extends Exception {
|
|
4
|
+
|
|
5
|
+
public JSExportException(String s) {
|
|
6
|
+
super(s);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
public JSExportException(Throwable t) {
|
|
10
|
+
super(t);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public JSExportException(String s, Throwable t) {
|
|
14
|
+
super(s, t);
|
|
15
|
+
}
|
|
16
|
+
}
|