@cloudcare/cocos-sdk 0.1.0-alpha.5 → 0.1.0-alpha.6
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 +13 -1
- package/bin/cli.cjs +40 -21
- package/bin/legacy-asset-hashes.json +27 -0
- package/bin/managed-assets.cjs +67 -0
- package/dist/creator2/core/client.d.ts +23 -7
- package/dist/creator2/core/client.d.ts.map +1 -1
- package/dist/creator2/core/client.js +74 -28
- package/dist/creator2/core/client.js.map +1 -1
- package/dist/creator2/core/index.d.ts +1 -1
- package/dist/creator2/core/index.d.ts.map +1 -1
- package/dist/creator2/core/index.js.map +1 -1
- package/dist/creator2/core/plugin-api.d.ts +15 -0
- package/dist/creator2/core/plugin-api.d.ts.map +1 -0
- package/dist/creator2/core/plugin-api.js +3 -0
- package/dist/creator2/core/plugin-api.js.map +1 -0
- package/dist/creator2/core/types.d.ts +0 -78
- package/dist/creator2/core/types.d.ts.map +1 -1
- package/dist/creator2/core/validation.d.ts +0 -11
- package/dist/creator2/core/validation.d.ts.map +1 -1
- package/dist/creator2/core/validation.js +0 -63
- package/dist/creator2/core/validation.js.map +1 -1
- package/dist/creator2/core/version.d.ts +1 -1
- package/dist/creator2/core/version.js +1 -1
- package/dist/creator2/creator2/auto.d.ts +1 -3
- package/dist/creator2/creator2/auto.d.ts.map +1 -1
- package/dist/creator2/creator2/auto.js +0 -25
- package/dist/creator2/creator2/auto.js.map +1 -1
- package/dist/creator2/creator2/index.d.ts +0 -7
- package/dist/creator2/creator2/index.d.ts.map +1 -1
- package/dist/creator2/creator2/index.js +1 -13
- package/dist/creator2/creator2/index.js.map +1 -1
- package/dist/creator2/creator2/transport.d.ts +0 -1
- package/dist/creator2/creator2/transport.d.ts.map +1 -1
- package/dist/creator2/creator2/transport.js +0 -4
- package/dist/creator2/creator2/transport.js.map +1 -1
- package/dist/creator3/core/client.d.ts +23 -7
- package/dist/creator3/core/client.d.ts.map +1 -1
- package/dist/creator3/core/client.js +72 -28
- package/dist/creator3/core/client.js.map +1 -1
- package/dist/creator3/core/index.d.ts +1 -1
- package/dist/creator3/core/index.d.ts.map +1 -1
- package/dist/creator3/core/index.js.map +1 -1
- package/dist/creator3/core/plugin-api.d.ts +15 -0
- package/dist/creator3/core/plugin-api.d.ts.map +1 -0
- package/dist/creator3/core/plugin-api.js +2 -0
- package/dist/creator3/core/plugin-api.js.map +1 -0
- package/dist/creator3/core/types.d.ts +0 -78
- package/dist/creator3/core/types.d.ts.map +1 -1
- package/dist/creator3/core/validation.d.ts +0 -11
- package/dist/creator3/core/validation.d.ts.map +1 -1
- package/dist/creator3/core/validation.js +0 -61
- package/dist/creator3/core/validation.js.map +1 -1
- package/dist/creator3/core/version.d.ts +1 -1
- package/dist/creator3/core/version.js +1 -1
- package/dist/creator3/creator3/auto.d.ts +1 -3
- package/dist/creator3/creator3/auto.d.ts.map +1 -1
- package/dist/creator3/creator3/auto.js +1 -26
- package/dist/creator3/creator3/auto.js.map +1 -1
- package/dist/creator3/creator3/index.d.ts +0 -7
- package/dist/creator3/creator3/index.d.ts.map +1 -1
- package/dist/creator3/creator3/index.js +1 -12
- package/dist/creator3/creator3/index.js.map +1 -1
- package/dist/creator3/creator3/transport.d.ts +0 -1
- package/dist/creator3/creator3/transport.d.ts.map +1 -1
- package/dist/creator3/creator3/transport.js +0 -4
- package/dist/creator3/creator3/transport.js.map +1 -1
- package/extensions/creator2/install-native.cjs +52 -30
- package/extensions/creator2/install-spm.cjs +16 -8
- package/extensions/creator2/legacy-asset-hashes.json +27 -0
- package/extensions/creator2/managed-assets.cjs +67 -0
- package/extensions/creator3/install-native.cjs +52 -30
- package/extensions/creator3/install-spm.cjs +16 -8
- package/extensions/creator3/legacy-asset-hashes.json +27 -0
- package/extensions/creator3/managed-assets.cjs +67 -0
- package/native/android/src/main/java/com/ft/sdk/cocos/FTBridgeTransport.java +85 -0
- package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosBridge.java +2 -192
- package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosBridgeModules.java +9 -0
- package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosBridgeProvider.java +1 -1
- package/native/ios/FTCocosBridge.m +0 -202
- package/native/ios/FTCocosBridge.podspec +2 -3
- package/native/ios/Package.swift +1 -2
- package/package.json +10 -5
- package/plugin-api/package.json +4 -0
- package/components/creator2/ReplayPrivacy.ts +0 -23
- package/components/creator3/ReplayPrivacy.ts +0 -25
- package/dist/creator2/core/replay-async-transport.d.ts +0 -4
- package/dist/creator2/core/replay-async-transport.d.ts.map +0 -1
- package/dist/creator2/core/replay-async-transport.js +0 -67
- package/dist/creator2/core/replay-async-transport.js.map +0 -1
- package/dist/creator2/core/replay-budget.d.ts +0 -28
- package/dist/creator2/core/replay-budget.d.ts.map +0 -1
- package/dist/creator2/core/replay-budget.js +0 -113
- package/dist/creator2/core/replay-budget.js.map +0 -1
- package/dist/creator2/core/replay-diagnostics.d.ts +0 -36
- package/dist/creator2/core/replay-diagnostics.d.ts.map +0 -1
- package/dist/creator2/core/replay-diagnostics.js +0 -40
- package/dist/creator2/core/replay-diagnostics.js.map +0 -1
- package/dist/creator2/core/replay-encoding.d.ts +0 -31
- package/dist/creator2/core/replay-encoding.d.ts.map +0 -1
- package/dist/creator2/core/replay-encoding.js +0 -63
- package/dist/creator2/core/replay-encoding.js.map +0 -1
- package/dist/creator2/core/replay-file.d.ts +0 -5
- package/dist/creator2/core/replay-file.d.ts.map +0 -1
- package/dist/creator2/core/replay-file.js +0 -101
- package/dist/creator2/core/replay-file.js.map +0 -1
- package/dist/creator2/core/replay-pixels.d.ts +0 -3
- package/dist/creator2/core/replay-pixels.d.ts.map +0 -1
- package/dist/creator2/core/replay-pixels.js +0 -16
- package/dist/creator2/core/replay-pixels.js.map +0 -1
- package/dist/creator2/core/replay-privacy-nodes.d.ts +0 -14
- package/dist/creator2/core/replay-privacy-nodes.d.ts.map +0 -1
- package/dist/creator2/core/replay-privacy-nodes.js +0 -18
- package/dist/creator2/core/replay-privacy-nodes.js.map +0 -1
- package/dist/creator2/core/replay-privacy.d.ts +0 -15
- package/dist/creator2/core/replay-privacy.d.ts.map +0 -1
- package/dist/creator2/core/replay-privacy.js +0 -36
- package/dist/creator2/core/replay-privacy.js.map +0 -1
- package/dist/creator2/core/replay.d.ts +0 -99
- package/dist/creator2/core/replay.d.ts.map +0 -1
- package/dist/creator2/core/replay.js +0 -611
- package/dist/creator2/core/replay.js.map +0 -1
- package/dist/creator2/creator2/capture.d.ts +0 -17
- package/dist/creator2/creator2/capture.d.ts.map +0 -1
- package/dist/creator2/creator2/capture.js +0 -168
- package/dist/creator2/creator2/capture.js.map +0 -1
- package/dist/creator3/core/replay-async-transport.d.ts +0 -4
- package/dist/creator3/core/replay-async-transport.d.ts.map +0 -1
- package/dist/creator3/core/replay-async-transport.js +0 -16
- package/dist/creator3/core/replay-async-transport.js.map +0 -1
- package/dist/creator3/core/replay-budget.d.ts +0 -28
- package/dist/creator3/core/replay-budget.d.ts.map +0 -1
- package/dist/creator3/core/replay-budget.js +0 -105
- package/dist/creator3/core/replay-budget.js.map +0 -1
- package/dist/creator3/core/replay-diagnostics.d.ts +0 -36
- package/dist/creator3/core/replay-diagnostics.d.ts.map +0 -1
- package/dist/creator3/core/replay-diagnostics.js +0 -36
- package/dist/creator3/core/replay-diagnostics.js.map +0 -1
- package/dist/creator3/core/replay-encoding.d.ts +0 -31
- package/dist/creator3/core/replay-encoding.d.ts.map +0 -1
- package/dist/creator3/core/replay-encoding.js +0 -62
- package/dist/creator3/core/replay-encoding.js.map +0 -1
- package/dist/creator3/core/replay-file.d.ts +0 -5
- package/dist/creator3/core/replay-file.d.ts.map +0 -1
- package/dist/creator3/core/replay-file.js +0 -31
- package/dist/creator3/core/replay-file.js.map +0 -1
- package/dist/creator3/core/replay-pixels.d.ts +0 -3
- package/dist/creator3/core/replay-pixels.d.ts.map +0 -1
- package/dist/creator3/core/replay-pixels.js +0 -13
- package/dist/creator3/core/replay-pixels.js.map +0 -1
- package/dist/creator3/core/replay-privacy-nodes.d.ts +0 -14
- package/dist/creator3/core/replay-privacy-nodes.d.ts.map +0 -1
- package/dist/creator3/core/replay-privacy-nodes.js +0 -15
- package/dist/creator3/core/replay-privacy-nodes.js.map +0 -1
- package/dist/creator3/core/replay-privacy.d.ts +0 -15
- package/dist/creator3/core/replay-privacy.d.ts.map +0 -1
- package/dist/creator3/core/replay-privacy.js +0 -33
- package/dist/creator3/core/replay-privacy.js.map +0 -1
- package/dist/creator3/core/replay.d.ts +0 -99
- package/dist/creator3/core/replay.d.ts.map +0 -1
- package/dist/creator3/core/replay.js +0 -534
- package/dist/creator3/core/replay.js.map +0 -1
- package/dist/creator3/creator3/capture.d.ts +0 -17
- package/dist/creator3/creator3/capture.d.ts.map +0 -1
- package/dist/creator3/creator3/capture.js +0 -112
- package/dist/creator3/creator3/capture.js.map +0 -1
- package/dist/creator3/creator3/replay-render-cycle.d.ts +0 -9
- package/dist/creator3/creator3/replay-render-cycle.d.ts.map +0 -1
- package/dist/creator3/creator3/replay-render-cycle.js +0 -12
- package/dist/creator3/creator3/replay-render-cycle.js.map +0 -1
- package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosReplayImageJobs.java +0 -55
- package/native/ios/FTCocosReplayImageJobs.h +0 -11
- package/native/ios/FTCocosReplayImageJobs.m +0 -54
- package/native/shared/FTReplayFileBridge.h +0 -62
- package/native/shared/FTReplayFileWorker.h +0 -88
|
@@ -145,11 +145,11 @@ function preserveCmakeIntegration(projectFile, project, entry) {
|
|
|
145
145
|
if (!fs.existsSync(stateFile) || fs.readFileSync(stateFile, 'utf8') !== serialized) fs.writeFileSync(stateFile, serialized);
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
function removeSwiftPackages(projectFile) {
|
|
148
|
+
function removeSwiftPackages(projectFile, productNames = ['FTCocosBridge', 'FTCocosReplayBridge', 'HybridSampleHost']) {
|
|
149
149
|
const project = readProject(projectFile);
|
|
150
150
|
const objects = project.objects;
|
|
151
151
|
const removed = new Set();
|
|
152
|
-
for (const productName of
|
|
152
|
+
for (const productName of productNames) {
|
|
153
153
|
const packageID = identifier(`package:${productName}`);
|
|
154
154
|
if (!objects[packageID]) continue;
|
|
155
155
|
removed.add(packageID);
|
|
@@ -159,23 +159,31 @@ function removeSwiftPackages(projectFile) {
|
|
|
159
159
|
removed.add(identifier(`framework:${id}:${productName}`));
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
|
-
if (!removed.size) return;
|
|
163
162
|
for (const id of removed) delete objects[id];
|
|
164
163
|
for (const object of Object.values(objects)) {
|
|
165
164
|
for (const key of ['packageReferences', 'packageProductDependencies', 'files']) {
|
|
166
165
|
if (Array.isArray(object[key])) object[key] = object[key].filter((id) => !removed.has(id));
|
|
167
166
|
}
|
|
168
|
-
|
|
167
|
+
|
|
169
168
|
}
|
|
170
169
|
const stateFile = path.join(path.dirname(projectFile), 'cocos-sdk-spm.json');
|
|
171
170
|
if (fs.existsSync(stateFile)) {
|
|
172
171
|
const state = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
state.packages = state.packages.filter(item => !productNames.includes(item.productName));
|
|
173
|
+
if (state.packages.length) {
|
|
174
|
+
fs.writeFileSync(stateFile, `${JSON.stringify(state, null, 2)}\n`);
|
|
175
|
+
} else {
|
|
176
|
+
for (const [id, settings] of Object.entries(state.buildLocations)) {
|
|
177
|
+
if (objects[id]) Object.assign(objects[id].buildSettings ||= {}, settings);
|
|
178
|
+
}
|
|
179
|
+
for (const object of Object.values(objects)) {
|
|
180
|
+
if (object.isa === 'PBXShellScriptBuildPhase') object.shellScript = (object.shellScript || '').replace(restorePattern, '');
|
|
181
|
+
}
|
|
182
|
+
fs.unlinkSync(stateFile);
|
|
183
|
+
fs.rmSync(path.join(path.dirname(projectFile), 'cocos-sdk-spm.cjs'), { force: true });
|
|
175
184
|
}
|
|
176
|
-
fs.unlinkSync(stateFile);
|
|
177
|
-
fs.rmSync(path.join(path.dirname(projectFile), 'cocos-sdk-spm.cjs'), { force: true });
|
|
178
185
|
}
|
|
186
|
+
|
|
179
187
|
writeProject(projectFile, project);
|
|
180
188
|
}
|
|
181
189
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[
|
|
2
|
+
"058341971ed42ddfde76c28ce19fcc0bba5020fec1f7e1c613c7bda7d2df7677",
|
|
3
|
+
"11ee16e609096ccfe90b17f61d87ab65275a39df4bef6f8c29577e7395aa00f8",
|
|
4
|
+
"15338071a78f1505265cc8efbdc9628e9362f7a2c9fc00989d57461126f8f3f5",
|
|
5
|
+
"1a51af27d68cdf0bf3ce709c9cd60f9b8a2d7defd46d06896ce9a916e1dfc767",
|
|
6
|
+
"2caa0d3d542f5cca0b6b7f3aa2851c7e296b08fce286202a844b52920b1f6dc0",
|
|
7
|
+
"3189144de638b936e14d64ddbf9d4c95e95146ceecc357021473ca8adcc757d1",
|
|
8
|
+
"48ff77a12a7b9b59172f5470a642f23e4c61e9f7e10ee6d9d3f4f41377d696ac",
|
|
9
|
+
"4d2dcd924f1073b8a6fb94d342bee33a281f93c19302104be172e5de9981b3f0",
|
|
10
|
+
"51c71e12df61cfe7e75c3d97080e31a398fbea8719a3e964cec5dd332df1202c",
|
|
11
|
+
"5f33108f27f38836214f2c11badd7bb76ba9ec090f9d5b1490834a9257976939",
|
|
12
|
+
"85ad9622480d954c33a4f9442a391f6d3d9d617a2f1261e5ad769170c6e9cf12",
|
|
13
|
+
"86cf732195aad676898520192ac8aa878267877dc09f85fcf425279d8badc9b8",
|
|
14
|
+
"910792f383c25cd46ddc7d851080a687fa532a93d605fb709b7baff9bb2789cf",
|
|
15
|
+
"95bdc516c4e1b72833af3bec13b18e3c2ac6ae83de284c3f711e97765ed1b461",
|
|
16
|
+
"a748564f0bba03effbf4aa381308f60eedcb618cbd2a37e1c67cdbee596e9ceb",
|
|
17
|
+
"a8a57b5892e7a5063078d561fce790b44d900d2bb3869e43ed4c4de82f1f62ed",
|
|
18
|
+
"cd03df57f7861d19b0a8e0a97e8aff1fa08e5c26d4f43152743968245632535b",
|
|
19
|
+
"d26fb42c6bee416eaf29bc2ed8579edc7a28ca3d0e18433dcb8abea11fac9920",
|
|
20
|
+
"d2d171e4ef1777facdb6fe665105372ea2e6452028d4c32f5e2ccc74dacc8850",
|
|
21
|
+
"d538d9eebaf181687ebf8537fc6ce7c8fae59fa424daeb45c3f900a8e210ecfc",
|
|
22
|
+
"df8e3014e583d60922cd1b7f7f16964c433b260a7e1a7e6c285cb08ce2d9e7e4",
|
|
23
|
+
"e70ca2a537cec56f8424ff4d551c1e97af133938fc7ba863a3944859dcfd194d",
|
|
24
|
+
"f0211acbaaa312bd5a4478bba81fa98293c855692ceca69f141600ff991c5904",
|
|
25
|
+
"f09f9b35ddfb17a7c4e4439384afae93ded6ee0285e778ad013d320cfc880cab",
|
|
26
|
+
"fa88198c5434613ff5ab2d44dce6e7eb8b825085b5b498402810eb144cf81f96"
|
|
27
|
+
]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { createHash } = require('crypto');
|
|
5
|
+
const legacyHashes = new Set(require('./legacy-asset-hashes.json'));
|
|
6
|
+
// Older combined installations predate the ownership manifest. Never leave a
|
|
7
|
+
// locally modified obsolete Replay bridge compiling beside the new bridge.
|
|
8
|
+
const legacyReplayNames = new Set(['FTCocosReplayImageJobs.java', 'FTCocosReplayImageJobs.h', 'FTCocosReplayImageJobs.m', 'FTReplayFileBridge.h', 'FTReplayFileWorker.h']);
|
|
9
|
+
const manifestName = '.cocos-sdk-managed.json';
|
|
10
|
+
const hash = bytes => createHash('sha256').update(bytes).digest('hex');
|
|
11
|
+
|
|
12
|
+
function files(root) {
|
|
13
|
+
const result = [];
|
|
14
|
+
if (!fs.existsSync(root)) return result;
|
|
15
|
+
function visit(directory) {
|
|
16
|
+
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
17
|
+
if (entry.name === manifestName || entry.name === '.DS_Store') continue;
|
|
18
|
+
const file = path.join(directory, entry.name);
|
|
19
|
+
if (entry.isSymbolicLink()) throw new Error(`[cocos-sdk] Refusing to copy symbolic link: ${file}`);
|
|
20
|
+
if (entry.isDirectory()) visit(file);
|
|
21
|
+
else result.push(path.relative(root, file).split(path.sep).join('/'));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
visit(root);
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Reconciles only files written by the SDK, preserving unrelated project assets. */
|
|
29
|
+
function syncManagedDirectory(destination, sources, overrides = {}) {
|
|
30
|
+
const desired = new Map();
|
|
31
|
+
for (const { root, prefix = '' } of sources) {
|
|
32
|
+
if (!fs.existsSync(root)) throw new Error(`[cocos-sdk] Missing package assets: ${root}`);
|
|
33
|
+
for (const file of files(root)) desired.set(prefix + file, fs.readFileSync(path.join(root, file)));
|
|
34
|
+
}
|
|
35
|
+
for (const [file, content] of Object.entries(overrides)) desired.set(file, Buffer.from(content));
|
|
36
|
+
const manifest = path.join(destination, manifestName);
|
|
37
|
+
const previous = fs.existsSync(manifest) ? JSON.parse(fs.readFileSync(manifest, 'utf8')) : {};
|
|
38
|
+
const existing = files(destination);
|
|
39
|
+
const remove = [];
|
|
40
|
+
// Check every conflict before writing or deleting any managed file.
|
|
41
|
+
for (const file of existing) {
|
|
42
|
+
const digest = hash(fs.readFileSync(path.join(destination, file)));
|
|
43
|
+
const old = previous[file];
|
|
44
|
+
const next = desired.get(file);
|
|
45
|
+
const legacy = legacyHashes.has(digest);
|
|
46
|
+
if (!next && !old && !legacy && legacyReplayNames.has(path.basename(file))) {
|
|
47
|
+
throw new Error(`[cocos-sdk] Preserve or reconcile modified legacy Replay asset before reinstalling: ${path.join(destination, file)}`);
|
|
48
|
+
}
|
|
49
|
+
if ((old || next) && digest !== old && !legacy && (!next || digest !== hash(next))) {
|
|
50
|
+
throw new Error(`[cocos-sdk] Preserve or reconcile modified SDK asset before reinstalling: ${path.join(destination, file)}`);
|
|
51
|
+
}
|
|
52
|
+
if (!next && (old || legacy) && !file.endsWith('.meta')) remove.push(file);
|
|
53
|
+
}
|
|
54
|
+
fs.mkdirSync(destination, { recursive: true });
|
|
55
|
+
for (const file of remove) fs.unlinkSync(path.join(destination, file));
|
|
56
|
+
const nextManifest = {};
|
|
57
|
+
for (const [file, content] of desired) {
|
|
58
|
+
const target = path.resolve(destination, file);
|
|
59
|
+
if (!target.startsWith(path.resolve(destination) + path.sep)) throw new Error('Invalid SDK asset path');
|
|
60
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
61
|
+
if (!fs.existsSync(target) || hash(fs.readFileSync(target)) !== hash(content)) fs.writeFileSync(target, content);
|
|
62
|
+
nextManifest[file] = hash(content);
|
|
63
|
+
}
|
|
64
|
+
fs.writeFileSync(manifest, `${JSON.stringify(nextManifest, null, 2)}\n`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = { syncManagedDirectory };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
package com.ft.sdk.cocos;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import android.app.ActivityManager;
|
|
5
|
+
import android.app.Application;
|
|
6
|
+
import android.content.Context;
|
|
7
|
+
import android.net.Uri;
|
|
8
|
+
import android.os.Build;
|
|
9
|
+
import android.os.Bundle;
|
|
10
|
+
import android.os.Process;
|
|
11
|
+
import java.util.List;
|
|
12
|
+
|
|
13
|
+
/** Shared process routing. Optional modules are selected by the generated allowlist. */
|
|
14
|
+
public final class FTBridgeTransport {
|
|
15
|
+
private FTBridgeTransport() {}
|
|
16
|
+
public static String invoke(String endpoint, String method, String payload) {
|
|
17
|
+
String forwarded = forwardToMainProcess(endpoint, method, payload);
|
|
18
|
+
return forwarded != null ? forwarded : FTCocosBridgeModules.invokeLocal(endpoint, method, payload);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private static String forwardToMainProcess(String endpoint, String method, String payload) {
|
|
22
|
+
Activity activity = resolveActivity();
|
|
23
|
+
if (activity == null || !isSecondaryProcess(activity)) return null;
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
Bundle arguments = new Bundle();
|
|
27
|
+
arguments.putString("endpoint", endpoint);
|
|
28
|
+
arguments.putString(FTCocosBridgeProvider.ARGUMENT_PAYLOAD, payload);
|
|
29
|
+
Uri uri = Uri.parse("content://" + activity.getPackageName()
|
|
30
|
+
+ FTCocosBridgeProvider.AUTHORITY_SUFFIX);
|
|
31
|
+
Bundle result = activity.getContentResolver().call(
|
|
32
|
+
uri,
|
|
33
|
+
FTCocosBridgeProvider.METHOD_INVOKE,
|
|
34
|
+
method,
|
|
35
|
+
arguments);
|
|
36
|
+
return result == null
|
|
37
|
+
? null
|
|
38
|
+
: result.getString(FTCocosBridgeProvider.RESULT_RESPONSE);
|
|
39
|
+
} catch (IllegalArgumentException providerUnavailable) {
|
|
40
|
+
// Existing integrations may not have registered the optional bridge
|
|
41
|
+
// provider yet. Preserve their same-process behavior.
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private static boolean isSecondaryProcess(Context context) {
|
|
47
|
+
String currentProcess = currentProcessName(context);
|
|
48
|
+
String mainProcess = context.getApplicationInfo().processName;
|
|
49
|
+
return currentProcess != null && mainProcess != null && !mainProcess.equals(currentProcess);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private static String currentProcessName(Context context) {
|
|
53
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
54
|
+
return Application.getProcessName();
|
|
55
|
+
}
|
|
56
|
+
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
|
57
|
+
if (manager == null) return null;
|
|
58
|
+
List<ActivityManager.RunningAppProcessInfo> processes = manager.getRunningAppProcesses();
|
|
59
|
+
if (processes == null) return null;
|
|
60
|
+
int currentPid = Process.myPid();
|
|
61
|
+
for (ActivityManager.RunningAppProcessInfo process : processes) {
|
|
62
|
+
if (process.pid == currentPid) return process.processName;
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public static Activity resolveActivity() {
|
|
68
|
+
String[] classNames = {"com.cocos.lib.CocosActivity", "org.cocos2dx.lib.Cocos2dxActivity"};
|
|
69
|
+
String[] methodNames = {"getContext", "getActivity"};
|
|
70
|
+
for (String className : classNames) {
|
|
71
|
+
for (String methodName : methodNames) {
|
|
72
|
+
try {
|
|
73
|
+
Object value = Class.forName(className).getMethod(methodName).invoke(null);
|
|
74
|
+
if (value instanceof Activity) return (Activity) value;
|
|
75
|
+
if (value instanceof Context && ((Context) value).getApplicationContext() instanceof Activity) {
|
|
76
|
+
return (Activity) ((Context) value).getApplicationContext();
|
|
77
|
+
}
|
|
78
|
+
} catch (Throwable ignored) {
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
}
|
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
package com.ft.sdk.cocos;
|
|
2
2
|
|
|
3
|
-
import android.app.Activity;
|
|
4
|
-
import android.app.ActivityManager;
|
|
5
|
-
import android.app.Application;
|
|
6
|
-
import android.content.Context;
|
|
7
|
-
import android.net.Uri;
|
|
8
|
-
import android.os.Build;
|
|
9
|
-
import android.os.Bundle;
|
|
10
|
-
import android.os.Process;
|
|
11
3
|
|
|
12
4
|
import com.ft.sdk.DetectFrequency;
|
|
13
5
|
import com.ft.sdk.FTLogger;
|
|
@@ -19,24 +11,15 @@ import com.ft.sdk.FTSdk;
|
|
|
19
11
|
import com.ft.sdk.FTTraceConfig;
|
|
20
12
|
import com.ft.sdk.FTTraceManager;
|
|
21
13
|
import com.ft.sdk.LogCacheDiscard;
|
|
22
|
-
import com.ft.sdk.SessionReplayManager;
|
|
23
14
|
import com.ft.sdk.TraceType;
|
|
24
15
|
import com.ft.sdk.garble.bean.AppState;
|
|
25
16
|
import com.ft.sdk.garble.bean.NetStatusBean;
|
|
26
17
|
import com.ft.sdk.garble.bean.ResourceParams;
|
|
27
18
|
import com.ft.sdk.garble.bean.UserData;
|
|
28
|
-
import com.ft.sdk.sessionreplay.FTSessionReplayConfig;
|
|
29
|
-
import com.ft.sdk.sessionreplay.SessionReplayInternalCallback;
|
|
30
|
-
import com.ft.sdk.sessionreplay.TouchPrivacy;
|
|
31
19
|
|
|
32
20
|
import org.json.JSONArray;
|
|
33
21
|
import org.json.JSONObject;
|
|
34
22
|
|
|
35
|
-
import java.io.ByteArrayOutputStream;
|
|
36
|
-
import java.io.File;
|
|
37
|
-
import java.io.FileInputStream;
|
|
38
|
-
import java.lang.reflect.InvocationTargetException;
|
|
39
|
-
import java.lang.reflect.Method;
|
|
40
23
|
import java.util.ArrayList;
|
|
41
24
|
import java.util.HashMap;
|
|
42
25
|
import java.util.Iterator;
|
|
@@ -52,9 +35,7 @@ public final class FTCocosBridge {
|
|
|
52
35
|
}
|
|
53
36
|
|
|
54
37
|
public static String invoke(String method, String payload) {
|
|
55
|
-
|
|
56
|
-
if (forwarded != null) return forwarded;
|
|
57
|
-
return invokeLocal(method, payload);
|
|
38
|
+
return FTBridgeTransport.invoke("sdk", method, payload);
|
|
58
39
|
}
|
|
59
40
|
|
|
60
41
|
static String invokeLocal(String method, String payload) {
|
|
@@ -77,63 +58,11 @@ public final class FTCocosBridge {
|
|
|
77
58
|
}
|
|
78
59
|
}
|
|
79
60
|
|
|
80
|
-
private static String forwardToMainProcess(String method, String payload) {
|
|
81
|
-
Activity activity = resolveActivity();
|
|
82
|
-
if (activity == null || !isSecondaryProcess(activity)) return null;
|
|
83
|
-
|
|
84
|
-
try {
|
|
85
|
-
Bundle arguments = new Bundle();
|
|
86
|
-
arguments.putString(FTCocosBridgeProvider.ARGUMENT_PAYLOAD, payload);
|
|
87
|
-
Uri uri = Uri.parse("content://" + activity.getPackageName()
|
|
88
|
-
+ FTCocosBridgeProvider.AUTHORITY_SUFFIX);
|
|
89
|
-
Bundle result = activity.getContentResolver().call(
|
|
90
|
-
uri,
|
|
91
|
-
FTCocosBridgeProvider.METHOD_INVOKE,
|
|
92
|
-
method,
|
|
93
|
-
arguments);
|
|
94
|
-
return result == null
|
|
95
|
-
? null
|
|
96
|
-
: result.getString(FTCocosBridgeProvider.RESULT_RESPONSE);
|
|
97
|
-
} catch (IllegalArgumentException providerUnavailable) {
|
|
98
|
-
// Existing integrations may not have registered the optional bridge
|
|
99
|
-
// provider yet. Preserve their same-process behavior.
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
private static boolean isSecondaryProcess(Context context) {
|
|
105
|
-
String currentProcess = currentProcessName(context);
|
|
106
|
-
String mainProcess = context.getApplicationInfo().processName;
|
|
107
|
-
return currentProcess != null && mainProcess != null && !mainProcess.equals(currentProcess);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
private static String currentProcessName(Context context) {
|
|
111
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
112
|
-
return Application.getProcessName();
|
|
113
|
-
}
|
|
114
|
-
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
|
115
|
-
if (manager == null) return null;
|
|
116
|
-
List<ActivityManager.RunningAppProcessInfo> processes = manager.getRunningAppProcesses();
|
|
117
|
-
if (processes == null) return null;
|
|
118
|
-
int currentPid = Process.myPid();
|
|
119
|
-
for (ActivityManager.RunningAppProcessInfo process : processes) {
|
|
120
|
-
if (process.pid == currentPid) return process.processName;
|
|
121
|
-
}
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
61
|
private static Object dispatch(String method, JSONObject payload) throws Exception {
|
|
126
62
|
switch (method) {
|
|
127
|
-
case "replay.beginSaveImage":
|
|
128
|
-
return FTCocosReplayImageJobs.begin(payload);
|
|
129
|
-
case "replay.pollSaveImage":
|
|
130
|
-
return FTCocosReplayImageJobs.poll(payload.getString("job"));
|
|
131
63
|
case "hybrid.attach":
|
|
132
64
|
attachHybrid(payload);
|
|
133
65
|
return null;
|
|
134
|
-
case "hybrid.setExternalRecorderActive":
|
|
135
|
-
setExternalRecorderActive(payload.getBoolean("active"));
|
|
136
|
-
return null;
|
|
137
66
|
case "sdk.configure":
|
|
138
67
|
configureSdk(payload);
|
|
139
68
|
return null;
|
|
@@ -196,25 +125,6 @@ public final class FTCocosBridge {
|
|
|
196
125
|
case "trace.getHeaders":
|
|
197
126
|
return FTTraceManager.get().getTraceHeader(
|
|
198
127
|
payload.optString("resourceKey", ""), payload.getString("url"));
|
|
199
|
-
case "replay.configure":
|
|
200
|
-
configureReplay(payload);
|
|
201
|
-
return null;
|
|
202
|
-
case "replay.getContext":
|
|
203
|
-
return SessionReplayManager.get().getCurrentFlutterRumContext();
|
|
204
|
-
case "replay.saveImage":
|
|
205
|
-
return saveReplayImage(payload);
|
|
206
|
-
case "replay.saveImageV2":
|
|
207
|
-
return saveReplayImageV2(payload);
|
|
208
|
-
case "replay.writeSegment":
|
|
209
|
-
SessionReplayManager.get().writeExternalSegment(
|
|
210
|
-
payload.getString("segment"), payload.getString("viewId"));
|
|
211
|
-
return null;
|
|
212
|
-
case "replay.setRecordCount":
|
|
213
|
-
SessionReplayManager.get().setExternalRecordCount(
|
|
214
|
-
payload.getString("viewId"), payload.getLong("count"));
|
|
215
|
-
return null;
|
|
216
|
-
case "replay.stop":
|
|
217
|
-
return null;
|
|
218
128
|
default:
|
|
219
129
|
throw new IllegalArgumentException("Unknown bridge method: " + method);
|
|
220
130
|
}
|
|
@@ -225,7 +135,6 @@ public final class FTCocosBridge {
|
|
|
225
135
|
if (hasText(json, "sdkVersion")) {
|
|
226
136
|
FTSdk.appendGlobalContext(COCOS_SDK_VERSION_KEY, json.getString("sdkVersion"));
|
|
227
137
|
}
|
|
228
|
-
if (json.optBoolean("requiresReplay", false)) hybridRecorderSwitchMethod();
|
|
229
138
|
}
|
|
230
139
|
|
|
231
140
|
private static void ensureNativeHostInitialized() {
|
|
@@ -235,28 +144,6 @@ public final class FTCocosBridge {
|
|
|
235
144
|
}
|
|
236
145
|
}
|
|
237
146
|
|
|
238
|
-
private static Method hybridRecorderSwitchMethod() {
|
|
239
|
-
try {
|
|
240
|
-
return SessionReplayManager.class.getMethod(
|
|
241
|
-
"setExternalRecorderActive", boolean.class);
|
|
242
|
-
} catch (NoSuchMethodException error) {
|
|
243
|
-
throw new IllegalStateException(
|
|
244
|
-
"Android Session Replay does not support Hybrid recorder switching; "
|
|
245
|
-
+ "upgrade the Native SDK");
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
private static void setExternalRecorderActive(boolean active) throws Exception {
|
|
250
|
-
ensureNativeHostInitialized();
|
|
251
|
-
try {
|
|
252
|
-
hybridRecorderSwitchMethod().invoke(SessionReplayManager.get(), active);
|
|
253
|
-
} catch (InvocationTargetException error) {
|
|
254
|
-
Throwable cause = error.getCause();
|
|
255
|
-
if (cause instanceof Exception) throw (Exception) cause;
|
|
256
|
-
throw error;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
147
|
private static void configureSdk(JSONObject json) throws Exception {
|
|
261
148
|
FTSDKConfig config;
|
|
262
149
|
if (hasText(json, "datakitUrl")) {
|
|
@@ -340,20 +227,6 @@ public final class FTCocosBridge {
|
|
|
340
227
|
FTSdk.initTraceWithConfig(config);
|
|
341
228
|
}
|
|
342
229
|
|
|
343
|
-
private static void configureReplay(JSONObject json) throws Exception {
|
|
344
|
-
FTSessionReplayConfig config = new FTSessionReplayConfig();
|
|
345
|
-
if (json.has("sampleRate")) config.setSampleRate((float) json.getDouble("sampleRate"));
|
|
346
|
-
if (json.has("sessionOnErrorSampleRate")) config.setSessionReplayOnErrorSampleRate((float) json.getDouble("sessionOnErrorSampleRate"));
|
|
347
|
-
if ("show".equals(json.optString("touchPrivacy"))) config.setTouchPrivacy(TouchPrivacy.SHOW);
|
|
348
|
-
config.setInternalCallback(new SessionReplayInternalCallback() {
|
|
349
|
-
@Override public Activity getCurrentActivity() { return resolveActivity(); }
|
|
350
|
-
});
|
|
351
|
-
Method externalMode = FTSessionReplayConfig.class.getDeclaredMethod("setExternalRecorderMode", boolean.class);
|
|
352
|
-
externalMode.setAccessible(true);
|
|
353
|
-
externalMode.invoke(config, true);
|
|
354
|
-
FTSdk.initSessionReplayConfig(config);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
230
|
private static void addResource(JSONObject payload) throws Exception {
|
|
358
231
|
JSONObject content = payload.getJSONObject("content");
|
|
359
232
|
ResourceParams params = new ResourceParams();
|
|
@@ -383,58 +256,6 @@ public final class FTCocosBridge {
|
|
|
383
256
|
FTRUMGlobalManager.get().addResource(payload.getString("key"), params, status);
|
|
384
257
|
}
|
|
385
258
|
|
|
386
|
-
private static String saveReplayImage(JSONObject json) throws Exception {
|
|
387
|
-
byte[] bytes = readFile(new File(json.getString("path")));
|
|
388
|
-
return SessionReplayManager.get().saveFlutterImageResource(bytes, json.getInt("width"), json.getInt("height"));
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
private static Object saveReplayImageV2(JSONObject json) throws Exception {
|
|
392
|
-
byte[] bytes = readFile(new File(json.getString("path")));
|
|
393
|
-
Method method;
|
|
394
|
-
try {
|
|
395
|
-
method = SessionReplayManager.class.getMethod(
|
|
396
|
-
"saveExternalImageResourceV2",
|
|
397
|
-
byte[].class,
|
|
398
|
-
int.class,
|
|
399
|
-
int.class,
|
|
400
|
-
float.class,
|
|
401
|
-
int.class);
|
|
402
|
-
} catch (NoSuchMethodException unavailable) {
|
|
403
|
-
throw new IllegalArgumentException("Unknown bridge method: replay.saveImageV2");
|
|
404
|
-
}
|
|
405
|
-
try {
|
|
406
|
-
return method.invoke(
|
|
407
|
-
SessionReplayManager.get(),
|
|
408
|
-
bytes,
|
|
409
|
-
json.getInt("width"),
|
|
410
|
-
json.getInt("height"),
|
|
411
|
-
(float) json.optDouble("quality", 0.45),
|
|
412
|
-
json.optInt("maxFrameBytes", 40 * 1024));
|
|
413
|
-
} catch (InvocationTargetException error) {
|
|
414
|
-
Throwable cause = error.getCause();
|
|
415
|
-
if (cause instanceof Exception) throw (Exception) cause;
|
|
416
|
-
throw error;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
private static Activity resolveActivity() {
|
|
421
|
-
String[] classNames = {"com.cocos.lib.CocosActivity", "org.cocos2dx.lib.Cocos2dxActivity"};
|
|
422
|
-
String[] methodNames = {"getContext", "getActivity"};
|
|
423
|
-
for (String className : classNames) {
|
|
424
|
-
for (String methodName : methodNames) {
|
|
425
|
-
try {
|
|
426
|
-
Object value = Class.forName(className).getMethod(methodName).invoke(null);
|
|
427
|
-
if (value instanceof Activity) return (Activity) value;
|
|
428
|
-
if (value instanceof Context && ((Context) value).getApplicationContext() instanceof Activity) {
|
|
429
|
-
return (Activity) ((Context) value).getApplicationContext();
|
|
430
|
-
}
|
|
431
|
-
} catch (Throwable ignored) {
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
return null;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
259
|
private static TraceType traceType(String value) {
|
|
439
260
|
if ("zipkinMultiHeader".equals(value)) return TraceType.ZIPKIN_MULTI_HEADER;
|
|
440
261
|
if ("zipkinSingleHeader".equals(value)) return TraceType.ZIPKIN_SINGLE_HEADER;
|
|
@@ -521,16 +342,5 @@ public final class FTCocosBridge {
|
|
|
521
342
|
return json.has(name) ? json.optLong(name, -1) : -1;
|
|
522
343
|
}
|
|
523
344
|
|
|
524
|
-
|
|
525
|
-
FileInputStream input = new FileInputStream(file);
|
|
526
|
-
try {
|
|
527
|
-
ByteArrayOutputStream output = new ByteArrayOutputStream((int) Math.min(file.length(), Integer.MAX_VALUE));
|
|
528
|
-
byte[] buffer = new byte[16 * 1024];
|
|
529
|
-
int read;
|
|
530
|
-
while ((read = input.read(buffer)) >= 0) output.write(buffer, 0, read);
|
|
531
|
-
return output.toByteArray();
|
|
532
|
-
} finally {
|
|
533
|
-
input.close();
|
|
534
|
-
}
|
|
535
|
-
}
|
|
345
|
+
|
|
536
346
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
package com.ft.sdk.cocos;
|
|
2
|
+
|
|
3
|
+
/** SDK-managed endpoint allowlist, regenerated when optional modules change. */
|
|
4
|
+
final class FTCocosBridgeModules {
|
|
5
|
+
static String invokeLocal(String endpoint, String method, String payload) {
|
|
6
|
+
if ("sdk".equals(endpoint)) return FTCocosBridge.invokeLocal(method, payload);
|
|
7
|
+
return "{\"ok\":false,\"error\":\"Native SDK extension is not installed; rerun the integration installer\"}";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -32,7 +32,7 @@ public final class FTCocosBridgeProvider extends ContentProvider {
|
|
|
32
32
|
}
|
|
33
33
|
String payload = extras == null ? null : extras.getString(ARGUMENT_PAYLOAD);
|
|
34
34
|
Bundle result = new Bundle();
|
|
35
|
-
result.putString(RESULT_RESPONSE,
|
|
35
|
+
result.putString(RESULT_RESPONSE, FTCocosBridgeModules.invokeLocal(extras == null ? "sdk" : extras.getString("endpoint", "sdk"), argument, payload));
|
|
36
36
|
return result;
|
|
37
37
|
}
|
|
38
38
|
|