codeplay-common 1.7.7 → 1.7.9
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/.gitattributes +2 -2
- package/LICENSE +1 -1
- package/README.md +11 -11
- package/files/buildCodeplay/add-splash-screen-1.3.js +113 -113
- package/files/buildCodeplay/{codeplayBeforeBuild-4.1.js → codeplayBeforeBuild-4.3.js} +831 -831
- package/files/buildCodeplay/ios-emi-admob-modification.js +52 -52
- package/files/buildCodeplay/modify-plugin-xml.js +36 -36
- package/files/buildCodeplay/packageidBaseModification-1.1.js +259 -259
- package/files/buildCodeplay/setSplashAnimation-1.1.js +167 -167
- package/files/buildCodeplay/splashxml/codeplay_splashScreen.xml +11 -11
- package/files/finalrelease20 +685 -685
- package/files/iap-install-2.js +145 -145
- package/files/ionic.config.json +6 -6
- package/package.json +16 -16
- package/scripts/sync-files.js +82 -82
- package/scripts/uninstall.js +77 -77
package/files/finalrelease20
CHANGED
|
@@ -1,685 +1,685 @@
|
|
|
1
|
-
import { existsSync, readFileSync, readdirSync, promises, constants, writeFileSync, unlinkSync, mkdirSync, renameSync } from 'fs';
|
|
2
|
-
import { join, resolve } from 'path';
|
|
3
|
-
import { execSync } from 'child_process';
|
|
4
|
-
import { createInterface } from 'readline';
|
|
5
|
-
|
|
6
|
-
import { fileURLToPath } from 'url';
|
|
7
|
-
import { dirname } from 'path';
|
|
8
|
-
|
|
9
|
-
// Define a mapping between store IDs and store names
|
|
10
|
-
const storeNames = {
|
|
11
|
-
"1": "PlayStore",
|
|
12
|
-
"2": "SamsungStore",
|
|
13
|
-
"7": "AmazonStore"
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
let isAdmobFound = false;
|
|
18
|
-
|
|
19
|
-
const amazonMinSdkVersion=23;
|
|
20
|
-
|
|
21
|
-
const androidManifestPath = join("android", "app", "src", "main", "AndroidManifest.xml");
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
26
|
-
const __dirname = dirname(__filename);
|
|
27
|
-
|
|
28
|
-
function fileExists(filePath) {
|
|
29
|
-
return existsSync(filePath);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const capacitorConfigPath = join(process.cwd(), 'capacitor.config.json');
|
|
34
|
-
|
|
35
|
-
function getAdMobConfig() {
|
|
36
|
-
if (!fileExists(capacitorConfigPath)) {
|
|
37
|
-
throw new Error('❌ capacitor.config.json not found. Ensure this is a Capacitor project.');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const config = JSON.parse(readFileSync(capacitorConfigPath, 'utf8'));
|
|
41
|
-
const admobConfig = config.plugins?.AdMob;
|
|
42
|
-
|
|
43
|
-
if (!admobConfig) {
|
|
44
|
-
throw new Error('❌ AdMob configuration is missing in capacitor.config.json.');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Default to true if ADMOB_ENABLED is not specified
|
|
48
|
-
const isEnabled = admobConfig.ADMOB_ENABLED !== false;
|
|
49
|
-
|
|
50
|
-
if (!isEnabled) {
|
|
51
|
-
return { ADMOB_ENABLED: false }; // Skip further validation
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (!admobConfig.APP_ID_ANDROID || !admobConfig.APP_ID_IOS) {
|
|
55
|
-
throw new Error(' ❌ AdMob configuration is incomplete. Ensure APP_ID_ANDROID and APP_ID_IOS are defined.');
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
ADMOB_ENABLED: true,
|
|
60
|
-
APP_ID_ANDROID: admobConfig.APP_ID_ANDROID,
|
|
61
|
-
APP_ID_IOS: admobConfig.APP_ID_IOS,
|
|
62
|
-
USE_LITE_ADS: admobConfig.USE_LITE_ADS === "lite",
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const _capacitorConfig = getAdMobConfig();
|
|
69
|
-
|
|
70
|
-
const _isADMOB_ENABLED=_capacitorConfig.ADMOB_ENABLED;
|
|
71
|
-
|
|
72
|
-
// Proceed only if ADMOB_ENABLED is true
|
|
73
|
-
//if (_capacitorConfig.ADMOB_ENABLED)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const admobConfigPath = join('src', 'js','Ads', 'admob-ad-configuration.json');
|
|
77
|
-
let admobConfig;
|
|
78
|
-
|
|
79
|
-
if (_isADMOB_ENABLED)
|
|
80
|
-
{
|
|
81
|
-
try
|
|
82
|
-
{
|
|
83
|
-
admobConfig = JSON.parse(readFileSync(admobConfigPath, 'utf8'));
|
|
84
|
-
}
|
|
85
|
-
catch (err)
|
|
86
|
-
{
|
|
87
|
-
console.error("❌ Failed to read admob-ad-configuration.json", err);
|
|
88
|
-
process.exit(1);
|
|
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
|
-
const checkCommonFileStoreId=()=>{
|
|
114
|
-
const possibleConfigFiles = ['vite.config.mjs', 'vite.config.js'];
|
|
115
|
-
let viteConfigPath;
|
|
116
|
-
for (const configFile of possibleConfigFiles) {
|
|
117
|
-
const fullPath = resolve( configFile);
|
|
118
|
-
if (existsSync(fullPath)) {
|
|
119
|
-
viteConfigPath = fullPath;
|
|
120
|
-
break;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (!viteConfigPath) {
|
|
125
|
-
console.error('❌ Error: No vite.config.mjs or vite.config.js file found.');
|
|
126
|
-
process.exit(1);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
try {
|
|
130
|
-
// Read vite config file
|
|
131
|
-
const viteConfigContent = readFileSync(viteConfigPath, 'utf-8');
|
|
132
|
-
|
|
133
|
-
// Extract @common alias path
|
|
134
|
-
const aliasPattern = /'@common':\s*path\.resolve\(__dirname,\s*'(.+?)'\)/;
|
|
135
|
-
const match = viteConfigContent.match(aliasPattern);
|
|
136
|
-
|
|
137
|
-
if (!match) {
|
|
138
|
-
console.error(`❌ Error: @common alias not found in ${viteConfigPath}`);
|
|
139
|
-
process.exit(1);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const commonFilePath = match[1];
|
|
143
|
-
const resolvedCommonPath = resolve(__dirname, commonFilePath);
|
|
144
|
-
|
|
145
|
-
// Read the common file content
|
|
146
|
-
if (!existsSync(resolvedCommonPath)) {
|
|
147
|
-
console.error(`❌ Error: Resolved common file does not exist: ${resolvedCommonPath}`);
|
|
148
|
-
process.exit(1);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const commonFileContent = readFileSync(resolvedCommonPath, 'utf-8');
|
|
152
|
-
|
|
153
|
-
// Check for the _storeid export line
|
|
154
|
-
const storeIdPattern = /export\s+let\s+_storeid\s*=\s*import\.meta\.env\.VITE_STORE_ID\s*\|\|\s*1\s*;/;
|
|
155
|
-
if (!storeIdPattern.test(commonFileContent)) {
|
|
156
|
-
console.error(`❌ Error: _storeid value is wrong in ${commonFilePath}`);
|
|
157
|
-
process.exit(1);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
console.log(commonFilePath,'Success - No problem found');
|
|
161
|
-
} catch (error) {
|
|
162
|
-
console.error('❌ Error:', error);
|
|
163
|
-
process.exit(1);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const checkIsTestingInAdmob=()=>{
|
|
169
|
-
|
|
170
|
-
if (admobConfig.config && admobConfig.config.isTesting === true) {
|
|
171
|
-
console.error(`❌ Problem found while generating the AAB file. Please change "isTesting: true" to "isTesting: false" in the "admob-ad-configuration.json" file.`);
|
|
172
|
-
process.exit(1); // Exit with an error code to halt the process
|
|
173
|
-
} else {
|
|
174
|
-
console.log('✅ No problem found. "isTesting" is either already false or not defined.');
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const checkIsAdsDisableByReturnStatement=()=>{
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const adsFolder = join('src', 'js', 'Ads');
|
|
182
|
-
const filePattern = /^admob-emi-(\d+\.)+\d+\.js$/;
|
|
183
|
-
|
|
184
|
-
// Step 1: Find the admob file
|
|
185
|
-
const files = readdirSync(adsFolder);
|
|
186
|
-
const admobFile = files.find(f => filePattern.test(f));
|
|
187
|
-
|
|
188
|
-
if (!admobFile) {
|
|
189
|
-
console.log('❌ No Admob file found.');
|
|
190
|
-
process.exit(1);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const filePath = join(adsFolder, admobFile);
|
|
194
|
-
const content = readFileSync(filePath, 'utf-8');
|
|
195
|
-
|
|
196
|
-
// Step 2: Extract the adsOnDeviceReady function body
|
|
197
|
-
const functionRegex = /async\s+function\s+adsOnDeviceReady\s*\([^)]*\)\s*{([\s\S]*?)^}/m;
|
|
198
|
-
const match = content.match(functionRegex);
|
|
199
|
-
|
|
200
|
-
if (!match) {
|
|
201
|
-
console.log(`❌ Function 'adsOnDeviceReady' not found in file: ${admobFile}`);
|
|
202
|
-
process.exit(1);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const body = match[1];
|
|
206
|
-
const lines = body.split('\n').map(line => line.trim());
|
|
207
|
-
|
|
208
|
-
// Step 3: Skip blank lines and comments, get the first real code line
|
|
209
|
-
let firstCodeLine = '';
|
|
210
|
-
for (const line of lines) {
|
|
211
|
-
if (line === '' || line.startsWith('//')) continue;
|
|
212
|
-
firstCodeLine = line;
|
|
213
|
-
break;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Step 4: Block if it's any of the unwanted returns
|
|
217
|
-
const badReturnPattern = /^return\s*(true|false)?\s*;?$/;
|
|
218
|
-
|
|
219
|
-
if (badReturnPattern.test(firstCodeLine)) {
|
|
220
|
-
console.log(`❌ BLOCKED in file '${admobFile}': First active line in 'adsOnDeviceReady' is '${firstCodeLine}'`);
|
|
221
|
-
process.exit(2);
|
|
222
|
-
} else {
|
|
223
|
-
console.log(`✅ Safe: No early return (true/false) found in 'adsOnDeviceReady' of file '${admobFile}'.`);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const addPermission_AD_ID=async()=>{
|
|
230
|
-
|
|
231
|
-
const admobPluginXmlPath = join('node_modules', 'emi-indo-cordova-plugin-admob', 'plugin.xml');
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
//let isAdmobFound = false;
|
|
235
|
-
try {
|
|
236
|
-
await promises.access(admobPluginXmlPath, constants.F_OK);
|
|
237
|
-
isAdmobFound = true;
|
|
238
|
-
} catch (err) {
|
|
239
|
-
isAdmobFound = false;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (isAdmobFound) {
|
|
244
|
-
// Check if AndroidManifest.xml exists
|
|
245
|
-
if (existsSync(androidManifestPath)) {
|
|
246
|
-
// Read the content of AndroidManifest.xml
|
|
247
|
-
let manifestContent = readFileSync(androidManifestPath, 'utf8');
|
|
248
|
-
|
|
249
|
-
// Check if the ad_id permission already exists
|
|
250
|
-
const adIdPermission = '<uses-permission android:name="com.google.android.gms.permission.AD_ID" />';
|
|
251
|
-
if (!manifestContent.includes(adIdPermission)) {
|
|
252
|
-
console.log("ad_id permission not found. Adding to AndroidManifest.xml.");
|
|
253
|
-
|
|
254
|
-
// Add the ad_id permission before the closing </manifest> tag
|
|
255
|
-
manifestContent = manifestContent.replace('</manifest>', ` ${adIdPermission}\n</manifest>`);
|
|
256
|
-
|
|
257
|
-
// Write the updated manifest content back to AndroidManifest.xml
|
|
258
|
-
writeFileSync(androidManifestPath, manifestContent, 'utf8');
|
|
259
|
-
console.log("✅ ad_id permission added successfully.");
|
|
260
|
-
} else {
|
|
261
|
-
console.log("ℹ️ ad_id permission already exists in AndroidManifest.xml.");
|
|
262
|
-
}
|
|
263
|
-
} else {
|
|
264
|
-
console.error("❌ AndroidManifest.xml not found at the specified path.");
|
|
265
|
-
}
|
|
266
|
-
} else {
|
|
267
|
-
console.log("\x1b[33m%s\x1b[0m", "⚠️ No admob found, so permission.AD_ID is not added");
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
checkCommonFileStoreId();
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (_isADMOB_ENABLED)
|
|
286
|
-
{
|
|
287
|
-
checkIsTestingInAdmob();
|
|
288
|
-
checkIsAdsDisableByReturnStatement()
|
|
289
|
-
|
|
290
|
-
await addPermission_AD_ID()
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const { playstore, samsung, amazon } = (_isADMOB_ENABLED && admobConfig.IAP) ? admobConfig.IAP : { playstore: false, samsung: false, amazon: false };
|
|
299
|
-
console.log(`ℹ️ IAP Configurations - PlayStore: ${playstore}, Samsung: ${samsung}, Amazon: ${amazon}`);
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
// Get the store ID from the command line arguments
|
|
307
|
-
const storeIdArg = process.argv[2]; // Get the store ID from the command line
|
|
308
|
-
const storeIds = storeIdArg ? [storeIdArg] : ["1", "2", "7"]; // If a specific ID is provided, use it; otherwise, use all store IDs
|
|
309
|
-
|
|
310
|
-
// Store the original minSdkVersion globally
|
|
311
|
-
let originalMinSdkVersion;
|
|
312
|
-
|
|
313
|
-
// Remove any existing AAB files before starting the build process
|
|
314
|
-
const aabDirectory = join("android", "app", "build", "outputs", "bundle", "release");
|
|
315
|
-
if (existsSync(aabDirectory)) {
|
|
316
|
-
const files = readdirSync(aabDirectory).filter(file => file.endsWith('.aab'));
|
|
317
|
-
files.forEach(file => {
|
|
318
|
-
const filePath = join(aabDirectory, file);
|
|
319
|
-
unlinkSync(filePath);
|
|
320
|
-
console.log(`ℹ️ Deleted existing AAB file: ${file}`);
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
const aabOutputDir = join("AAB");
|
|
325
|
-
if (!existsSync(aabOutputDir)) {
|
|
326
|
-
mkdirSync(aabOutputDir);
|
|
327
|
-
console.log(`Created directory: ${aabOutputDir}`);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if (existsSync(aabOutputDir)) {
|
|
331
|
-
const files = readdirSync(aabOutputDir).filter(file => file.endsWith('.aab'));
|
|
332
|
-
files.forEach(file => {
|
|
333
|
-
const filePath = join(aabOutputDir, file);
|
|
334
|
-
unlinkSync(filePath);
|
|
335
|
-
console.log(`Deleted existing AAB file: ${file}`);
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
// Extract version code and version name from build.gradle
|
|
341
|
-
const gradleFilePath = join("android", "app", "build.gradle");
|
|
342
|
-
const gradleContent = readFileSync(gradleFilePath, 'utf8');
|
|
343
|
-
|
|
344
|
-
const versionCodeMatch = gradleContent.match(/versionCode\s+(\d+)/);
|
|
345
|
-
const versionNameMatch = gradleContent.match(/versionName\s+"([^"]+)"/);
|
|
346
|
-
|
|
347
|
-
const versionCode = versionCodeMatch ? versionCodeMatch[1] : '';
|
|
348
|
-
const versionName = versionNameMatch ? versionNameMatch[1] : '';
|
|
349
|
-
|
|
350
|
-
// Display the current versionCode and versionName
|
|
351
|
-
console.log(`Current versionCode: ${versionCode}`);
|
|
352
|
-
console.log(`Current versionName: ${versionName}`);
|
|
353
|
-
|
|
354
|
-
// Create an interface for user input
|
|
355
|
-
const rl = createInterface({
|
|
356
|
-
input: process.stdin,
|
|
357
|
-
output: process.stdout
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
// Ask for new versionCode
|
|
361
|
-
rl.question('Enter new versionCode (press enter to keep current): ', (newVersionCode) => {
|
|
362
|
-
const finalVersionCode = newVersionCode || versionCode; // Use existing if no input
|
|
363
|
-
|
|
364
|
-
// Ask for new versionName
|
|
365
|
-
rl.question('Enter new versionName (press enter to keep current): ', (newVersionName) => {
|
|
366
|
-
const finalVersionName = newVersionName || versionName; // Use existing if no input
|
|
367
|
-
|
|
368
|
-
// Log the final version details
|
|
369
|
-
console.log(`📦 Final versionCode: ${finalVersionCode}`);
|
|
370
|
-
console.log(`📝 Final versionName: ${finalVersionName}`);
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
// Update build.gradle with the new version details
|
|
375
|
-
let updatedGradleContent = gradleContent
|
|
376
|
-
.replace(/versionCode\s+\d+/, `versionCode ${finalVersionCode}`)
|
|
377
|
-
.replace(/versionName\s+"[^"]+"/, `versionName "${finalVersionName}"`);
|
|
378
|
-
|
|
379
|
-
// Check if resConfigs "en" already exists
|
|
380
|
-
const resConfigsLine = ' resConfigs "en"';
|
|
381
|
-
if (!updatedGradleContent.includes(resConfigsLine)) {
|
|
382
|
-
// Add resConfigs "en" below versionName
|
|
383
|
-
updatedGradleContent = updatedGradleContent.replace(/versionName\s+"[^"]+"/, `versionName "${finalVersionName}"\n${resConfigsLine}`);
|
|
384
|
-
} else {
|
|
385
|
-
console.log('ℹ️ resConfigs "en" already exists in build.gradle.');
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
if (/minifyEnabled\s+false/.test(updatedGradleContent)) {
|
|
394
|
-
updatedGradleContent = updatedGradleContent.replace(/minifyEnabled\s+false/, 'minifyEnabled true');
|
|
395
|
-
console.log('Replaced minifyEnabled false with true.');
|
|
396
|
-
} else if (!/minifyEnabled\s+true/.test(updatedGradleContent)) {
|
|
397
|
-
// Only insert if minifyEnabled (true or false) is NOT present
|
|
398
|
-
if (/buildTypes\s*{[\s\S]*?release\s*{/.test(updatedGradleContent)) {
|
|
399
|
-
updatedGradleContent = updatedGradleContent.replace(
|
|
400
|
-
/(buildTypes\s*{[\s\S]*?release\s*{)/,
|
|
401
|
-
'$1\n minifyEnabled true'
|
|
402
|
-
);
|
|
403
|
-
console.log('✅ Inserted minifyEnabled true into release block.');
|
|
404
|
-
} else {
|
|
405
|
-
console.log('⚠️ Warning: buildTypes > release block not found. minifyEnabled was not added.');
|
|
406
|
-
}
|
|
407
|
-
} else {
|
|
408
|
-
console.log('ℹ️ minifyEnabled true already present. No change needed.');
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
// Write the updated gradle content back to build.gradle
|
|
417
|
-
writeFileSync(gradleFilePath, updatedGradleContent, 'utf8');
|
|
418
|
-
console.log(`✅ Updated build.gradle with versionCode: ${finalVersionCode}, versionName: ${finalVersionName}, resConfigs "en" and "minifyEnabled true"`);
|
|
419
|
-
|
|
420
|
-
storeIds.forEach((id) => {
|
|
421
|
-
console.log(`ℹ️ Building for Store ID ${id}`);
|
|
422
|
-
|
|
423
|
-
// Set the environment variable for store ID
|
|
424
|
-
process.env.VITE_STORE_ID = id;
|
|
425
|
-
|
|
426
|
-
// Conditionally set the new file name
|
|
427
|
-
let newFileName;
|
|
428
|
-
let storeName = storeNames[id];
|
|
429
|
-
|
|
430
|
-
managePackages(storeName);
|
|
431
|
-
|
|
432
|
-
if (storeName === "SamsungStore") {
|
|
433
|
-
// For SamsungStore, rename to versionCode value only
|
|
434
|
-
newFileName = `${finalVersionCode}.aab`;
|
|
435
|
-
} else {
|
|
436
|
-
// For other stores, use the standard naming format
|
|
437
|
-
newFileName = `app-release-signed-${storeName}-b${finalVersionCode}-v${finalVersionName}.aab`;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
//storeName="amazon"
|
|
441
|
-
const checkFullPath = join("AAB", newFileName); // Update to point to the new AAB directory
|
|
442
|
-
|
|
443
|
-
// Modify minSdkVersion in variables.gradle for SamsungStore
|
|
444
|
-
const variablesGradleFilePath = join("android", "variables.gradle");
|
|
445
|
-
let variablesGradleContent = readFileSync(variablesGradleFilePath, 'utf8');
|
|
446
|
-
|
|
447
|
-
// Extract the current minSdkVersion
|
|
448
|
-
const minSdkVersionMatch = variablesGradleContent.match(/minSdkVersion\s*=\s*(\d+)/);
|
|
449
|
-
const currentMinSdkVersion = minSdkVersionMatch ? parseInt(minSdkVersionMatch[1], 10) : null;
|
|
450
|
-
|
|
451
|
-
// Store the original minSdkVersion (only on the first iteration)
|
|
452
|
-
if (!originalMinSdkVersion) {
|
|
453
|
-
originalMinSdkVersion = currentMinSdkVersion;
|
|
454
|
-
}
|
|
455
|
-
try {
|
|
456
|
-
// Modify the minSdkVersion based on the store
|
|
457
|
-
if (storeName === "SamsungStore" || storeName === "PlayStore") {
|
|
458
|
-
if (currentMinSdkVersion !== 24) {
|
|
459
|
-
variablesGradleContent = variablesGradleContent.replace(/minSdkVersion\s*=\s*\d+/, 'minSdkVersion = 24');
|
|
460
|
-
console.log('minSdkVersion updated to 24 for SamsungStore & PlayStore');
|
|
461
|
-
writeFileSync(variablesGradleFilePath, variablesGradleContent);
|
|
462
|
-
}
|
|
463
|
-
} else {
|
|
464
|
-
// For PlayStore and AmazonStore, ensure minSdkVersion is originalMinSdkVersion
|
|
465
|
-
//if (currentMinSdkVersion !== originalMinSdkVersion) {
|
|
466
|
-
variablesGradleContent = variablesGradleContent.replace(/minSdkVersion\s*=\s*\d+/, `minSdkVersion = ${amazonMinSdkVersion}`);
|
|
467
|
-
console.log(`minSdkVersion reverted to ${amazonMinSdkVersion} for ${storeName}`);
|
|
468
|
-
writeFileSync(variablesGradleFilePath, variablesGradleContent);
|
|
469
|
-
//}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
// Run the Node.js script to modify plugin.xml
|
|
475
|
-
if (isAdmobFound) {
|
|
476
|
-
execSync('node buildCodeplay/modify-plugin-xml.js', { stdio: 'inherit' });
|
|
477
|
-
} else {
|
|
478
|
-
console.log("\x1b[33m%s\x1b[0m", "Seems to Pro Version [No ads found]");
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
// Run the Vite build
|
|
482
|
-
execSync(`npm run build:storeid${id}`, { stdio: 'inherit' });
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
// Copy the built files to the appropriate folder
|
|
487
|
-
const src = join("www", "*");
|
|
488
|
-
const dest = join("android", "app", "src", "main", "assets", "public");
|
|
489
|
-
|
|
490
|
-
// Use 'xcopy' command for Windows
|
|
491
|
-
execSync(`xcopy ${src} ${dest} /E /I /Y`, { stdio: 'inherit' });
|
|
492
|
-
|
|
493
|
-
// Build Android AAB file
|
|
494
|
-
//child_process.execSync('cd android && ./gradlew bundleRelease', { stdio: 'inherit' });
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
// Build Android AAB file with Capacitor
|
|
498
|
-
execSync('npx cap sync android', { stdio: 'inherit' });
|
|
499
|
-
execSync('npx cap build android --androidreleasetype=AAB', { stdio: 'inherit' });
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
variablesGradleContent = variablesGradleContent.replace(/minSdkVersion\s*=\s*\d+/, 'minSdkVersion = 24');
|
|
504
|
-
console.log('minSdkVersion revert to 24 (default)');
|
|
505
|
-
writeFileSync(variablesGradleFilePath, variablesGradleContent);
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
// Rename the output AAB file
|
|
509
|
-
const oldFilePath = join(aabDirectory, "app-release-signed.aab");
|
|
510
|
-
if (existsSync(oldFilePath)) {
|
|
511
|
-
renameSync(oldFilePath, checkFullPath);
|
|
512
|
-
console.log(`✅ Renamed output AAB file to: ${newFileName}`);
|
|
513
|
-
} else {
|
|
514
|
-
console.error("❌ AAB file not found after build.");
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
} catch (error) {
|
|
518
|
-
console.error(`❌ Error during build for Store ID ${id}:`, error);
|
|
519
|
-
process.exit(1);
|
|
520
|
-
}
|
|
521
|
-
});
|
|
522
|
-
|
|
523
|
-
rl.close(); // Close the readline interface after all operations
|
|
524
|
-
});
|
|
525
|
-
});
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
function managePackages(store) {
|
|
532
|
-
console.log(`IAP Configurations - PlayStore: ${playstore}, Samsung: ${samsung}, Amazon: ${amazon}`);
|
|
533
|
-
|
|
534
|
-
let install = "";
|
|
535
|
-
let uninstall = "";
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
let manifestContent = readFileSync(androidManifestPath, 'utf-8');
|
|
540
|
-
|
|
541
|
-
const permissionsToRemove = [
|
|
542
|
-
'com.android.vending.BILLING',
|
|
543
|
-
'com.samsung.android.iap.permission.BILLING'
|
|
544
|
-
];
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
permissionsToRemove.forEach(permission => {
|
|
548
|
-
const permissionRegex = new RegExp(`^\\s*<uses-permission\\s+android:name="${permission}"\\s*/?>\\s*[\r\n]?`, 'm');
|
|
549
|
-
if (permissionRegex.test(manifestContent)) {
|
|
550
|
-
manifestContent = manifestContent.replace(permissionRegex, '');
|
|
551
|
-
console.log(`✅ Removed <uses-permission android:name="${permission}" /> from AndroidManifest.xml`);
|
|
552
|
-
}
|
|
553
|
-
});
|
|
554
|
-
|
|
555
|
-
// Write the updated content back to the file
|
|
556
|
-
writeFileSync(androidManifestPath, manifestContent, 'utf-8');
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
if ((playstore && store === "PlayStore") || (amazon && store === "AmazonStore")) {
|
|
561
|
-
install = '@revenuecat/purchases-capacitor';
|
|
562
|
-
uninstall = 'cordova-plugin-samsungiap';
|
|
563
|
-
|
|
564
|
-
// Update AndroidManifest.xml for PlayStore
|
|
565
|
-
if(playstore)
|
|
566
|
-
updateAndroidManifest(store,
|
|
567
|
-
'<uses-permission android:name="com.android.vending.BILLING" />');
|
|
568
|
-
|
|
569
|
-
} else if (samsung && store === "SamsungStore") {
|
|
570
|
-
install = 'cordova-plugin-samsungiap';
|
|
571
|
-
uninstall = '@revenuecat/purchases-capacitor';
|
|
572
|
-
|
|
573
|
-
// Update AndroidManifest.xml for SamsungStore
|
|
574
|
-
updateAndroidManifest(store,
|
|
575
|
-
'<uses-permission android:name="com.samsung.android.iap.permission.BILLING" />');
|
|
576
|
-
|
|
577
|
-
} else {
|
|
578
|
-
console.log("No valid store specified or no configurations found. Both plugins will be uninstalled.");
|
|
579
|
-
try {
|
|
580
|
-
execSync(`npm uninstall cordova-plugin-samsungiap`, { stdio: 'inherit' });
|
|
581
|
-
execSync(`npm uninstall @revenuecat/purchases-capacitor`, { stdio: 'inherit' });
|
|
582
|
-
console.log(`✅ Both plugins uninstalled successfully.`);
|
|
583
|
-
} catch (err) {
|
|
584
|
-
console.error("❌ Error uninstalling plugins:", err);
|
|
585
|
-
}
|
|
586
|
-
return;
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
console.log(`⚠️ Installing ${install} and uninstalling ${uninstall} for ${store}...`);
|
|
590
|
-
try {
|
|
591
|
-
if (install) {
|
|
592
|
-
execSync(`npm install ${install}`, { stdio: 'inherit' });
|
|
593
|
-
}
|
|
594
|
-
if (uninstall) {
|
|
595
|
-
execSync(`npm uninstall ${uninstall}`, { stdio: 'inherit' });
|
|
596
|
-
}
|
|
597
|
-
console.log(`✅ ${install} installed and ${uninstall} uninstalled successfully.`);
|
|
598
|
-
} catch (err) {
|
|
599
|
-
console.error(`❌ Error managing packages for ${store}:`, err);
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
function updateAndroidManifest(store, addPermission) {
|
|
606
|
-
try {
|
|
607
|
-
if (!existsSync(androidManifestPath)) {
|
|
608
|
-
console.error("❌ AndroidManifest.xml file not found!");
|
|
609
|
-
return;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
// Read the content of the AndroidManifest.xml
|
|
613
|
-
let manifestContent = readFileSync(androidManifestPath, 'utf-8');
|
|
614
|
-
|
|
615
|
-
// Normalize line endings to `\n` for consistent processing
|
|
616
|
-
manifestContent = manifestContent.replace(/\r\n/g, '\n');
|
|
617
|
-
|
|
618
|
-
// Check if the permission is already present
|
|
619
|
-
if (manifestContent.includes(addPermission.trim())) {
|
|
620
|
-
console.log(`${addPermission} is already in the AndroidManifest.xml. Skipping addition.`);
|
|
621
|
-
return; // Skip if the permission is already present
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
// Insert the permission before the closing </manifest> tag
|
|
625
|
-
const closingTag = '</manifest>';
|
|
626
|
-
const formattedPermission = ` ${addPermission.trim()}\n`;
|
|
627
|
-
if (manifestContent.includes(closingTag)) {
|
|
628
|
-
manifestContent = manifestContent.replace(
|
|
629
|
-
closingTag,
|
|
630
|
-
`${formattedPermission}${closingTag}`
|
|
631
|
-
);
|
|
632
|
-
console.log(`✅ Added ${addPermission} before </manifest> tag.`);
|
|
633
|
-
} else {
|
|
634
|
-
console.warn(`⚠️ </manifest> tag not found. Adding ${addPermission} at the end of the file.`);
|
|
635
|
-
manifestContent += `\n${formattedPermission}`;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
// Normalize line endings back to `\r\n` and write the updated content
|
|
639
|
-
manifestContent = manifestContent.replace(/\n/g, '\r\n');
|
|
640
|
-
writeFileSync(androidManifestPath, manifestContent, 'utf-8');
|
|
641
|
-
console.log(`✅ AndroidManifest.xml updated successfully for ${store}`);
|
|
642
|
-
} catch (err) {
|
|
643
|
-
console.error(`❌ Error updating AndroidManifest.xml for ${store}:`, err);
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
/* function updateAndroidManifest1(store, addPermission) {
|
|
650
|
-
try {
|
|
651
|
-
if (!fs.existsSync(androidManifestPath)) {
|
|
652
|
-
console.error("AndroidManifest.xml file not found!");
|
|
653
|
-
return;
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
let manifestContent = fs.readFileSync(androidManifestPath, 'utf-8');
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
// Add the required permission if not already present
|
|
661
|
-
if (!manifestContent.includes(addPermission)) {
|
|
662
|
-
const manifestLines = manifestContent.split('\n');
|
|
663
|
-
const insertIndex = manifestLines.findIndex(line => line.trim().startsWith('<application'));
|
|
664
|
-
if (insertIndex > -1) {
|
|
665
|
-
manifestLines.splice(insertIndex, 0, ` ${addPermission}`);
|
|
666
|
-
manifestContent = manifestLines.join('\n');
|
|
667
|
-
console.log(`Added ${addPermission} to AndroidManifest.xml`);
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
// Write the updated content back to the file
|
|
672
|
-
fs.writeFileSync(androidManifestPath, manifestContent, 'utf-8');
|
|
673
|
-
console.log(`AndroidManifest.xml updated successfully for ${store}`);
|
|
674
|
-
} catch (err) {
|
|
675
|
-
console.error(`Error updating AndroidManifest.xml for ${store}:`, err);
|
|
676
|
-
}
|
|
677
|
-
} */
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, promises, constants, writeFileSync, unlinkSync, mkdirSync, renameSync } from 'fs';
|
|
2
|
+
import { join, resolve } from 'path';
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import { createInterface } from 'readline';
|
|
5
|
+
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { dirname } from 'path';
|
|
8
|
+
|
|
9
|
+
// Define a mapping between store IDs and store names
|
|
10
|
+
const storeNames = {
|
|
11
|
+
"1": "PlayStore",
|
|
12
|
+
"2": "SamsungStore",
|
|
13
|
+
"7": "AmazonStore"
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
let isAdmobFound = false;
|
|
18
|
+
|
|
19
|
+
const amazonMinSdkVersion=23;
|
|
20
|
+
|
|
21
|
+
const androidManifestPath = join("android", "app", "src", "main", "AndroidManifest.xml");
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
26
|
+
const __dirname = dirname(__filename);
|
|
27
|
+
|
|
28
|
+
function fileExists(filePath) {
|
|
29
|
+
return existsSync(filePath);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
const capacitorConfigPath = join(process.cwd(), 'capacitor.config.json');
|
|
34
|
+
|
|
35
|
+
function getAdMobConfig() {
|
|
36
|
+
if (!fileExists(capacitorConfigPath)) {
|
|
37
|
+
throw new Error('❌ capacitor.config.json not found. Ensure this is a Capacitor project.');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const config = JSON.parse(readFileSync(capacitorConfigPath, 'utf8'));
|
|
41
|
+
const admobConfig = config.plugins?.AdMob;
|
|
42
|
+
|
|
43
|
+
if (!admobConfig) {
|
|
44
|
+
throw new Error('❌ AdMob configuration is missing in capacitor.config.json.');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Default to true if ADMOB_ENABLED is not specified
|
|
48
|
+
const isEnabled = admobConfig.ADMOB_ENABLED !== false;
|
|
49
|
+
|
|
50
|
+
if (!isEnabled) {
|
|
51
|
+
return { ADMOB_ENABLED: false }; // Skip further validation
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!admobConfig.APP_ID_ANDROID || !admobConfig.APP_ID_IOS) {
|
|
55
|
+
throw new Error(' ❌ AdMob configuration is incomplete. Ensure APP_ID_ANDROID and APP_ID_IOS are defined.');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
ADMOB_ENABLED: true,
|
|
60
|
+
APP_ID_ANDROID: admobConfig.APP_ID_ANDROID,
|
|
61
|
+
APP_ID_IOS: admobConfig.APP_ID_IOS,
|
|
62
|
+
USE_LITE_ADS: admobConfig.USE_LITE_ADS === "lite",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
const _capacitorConfig = getAdMobConfig();
|
|
69
|
+
|
|
70
|
+
const _isADMOB_ENABLED=_capacitorConfig.ADMOB_ENABLED;
|
|
71
|
+
|
|
72
|
+
// Proceed only if ADMOB_ENABLED is true
|
|
73
|
+
//if (_capacitorConfig.ADMOB_ENABLED)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
const admobConfigPath = join('src', 'js','Ads', 'admob-ad-configuration.json');
|
|
77
|
+
let admobConfig;
|
|
78
|
+
|
|
79
|
+
if (_isADMOB_ENABLED)
|
|
80
|
+
{
|
|
81
|
+
try
|
|
82
|
+
{
|
|
83
|
+
admobConfig = JSON.parse(readFileSync(admobConfigPath, 'utf8'));
|
|
84
|
+
}
|
|
85
|
+
catch (err)
|
|
86
|
+
{
|
|
87
|
+
console.error("❌ Failed to read admob-ad-configuration.json", err);
|
|
88
|
+
process.exit(1);
|
|
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
|
+
const checkCommonFileStoreId=()=>{
|
|
114
|
+
const possibleConfigFiles = ['vite.config.mjs', 'vite.config.js'];
|
|
115
|
+
let viteConfigPath;
|
|
116
|
+
for (const configFile of possibleConfigFiles) {
|
|
117
|
+
const fullPath = resolve( configFile);
|
|
118
|
+
if (existsSync(fullPath)) {
|
|
119
|
+
viteConfigPath = fullPath;
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (!viteConfigPath) {
|
|
125
|
+
console.error('❌ Error: No vite.config.mjs or vite.config.js file found.');
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
// Read vite config file
|
|
131
|
+
const viteConfigContent = readFileSync(viteConfigPath, 'utf-8');
|
|
132
|
+
|
|
133
|
+
// Extract @common alias path
|
|
134
|
+
const aliasPattern = /'@common':\s*path\.resolve\(__dirname,\s*'(.+?)'\)/;
|
|
135
|
+
const match = viteConfigContent.match(aliasPattern);
|
|
136
|
+
|
|
137
|
+
if (!match) {
|
|
138
|
+
console.error(`❌ Error: @common alias not found in ${viteConfigPath}`);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const commonFilePath = match[1];
|
|
143
|
+
const resolvedCommonPath = resolve(__dirname, commonFilePath);
|
|
144
|
+
|
|
145
|
+
// Read the common file content
|
|
146
|
+
if (!existsSync(resolvedCommonPath)) {
|
|
147
|
+
console.error(`❌ Error: Resolved common file does not exist: ${resolvedCommonPath}`);
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const commonFileContent = readFileSync(resolvedCommonPath, 'utf-8');
|
|
152
|
+
|
|
153
|
+
// Check for the _storeid export line
|
|
154
|
+
const storeIdPattern = /export\s+let\s+_storeid\s*=\s*import\.meta\.env\.VITE_STORE_ID\s*\|\|\s*1\s*;/;
|
|
155
|
+
if (!storeIdPattern.test(commonFileContent)) {
|
|
156
|
+
console.error(`❌ Error: _storeid value is wrong in ${commonFilePath}`);
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
console.log(commonFilePath,'Success - No problem found');
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error('❌ Error:', error);
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const checkIsTestingInAdmob=()=>{
|
|
169
|
+
|
|
170
|
+
if (admobConfig.config && admobConfig.config.isTesting === true) {
|
|
171
|
+
console.error(`❌ Problem found while generating the AAB file. Please change "isTesting: true" to "isTesting: false" in the "admob-ad-configuration.json" file.`);
|
|
172
|
+
process.exit(1); // Exit with an error code to halt the process
|
|
173
|
+
} else {
|
|
174
|
+
console.log('✅ No problem found. "isTesting" is either already false or not defined.');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const checkIsAdsDisableByReturnStatement=()=>{
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
const adsFolder = join('src', 'js', 'Ads');
|
|
182
|
+
const filePattern = /^admob-emi-(\d+\.)+\d+\.js$/;
|
|
183
|
+
|
|
184
|
+
// Step 1: Find the admob file
|
|
185
|
+
const files = readdirSync(adsFolder);
|
|
186
|
+
const admobFile = files.find(f => filePattern.test(f));
|
|
187
|
+
|
|
188
|
+
if (!admobFile) {
|
|
189
|
+
console.log('❌ No Admob file found.');
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const filePath = join(adsFolder, admobFile);
|
|
194
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
195
|
+
|
|
196
|
+
// Step 2: Extract the adsOnDeviceReady function body
|
|
197
|
+
const functionRegex = /async\s+function\s+adsOnDeviceReady\s*\([^)]*\)\s*{([\s\S]*?)^}/m;
|
|
198
|
+
const match = content.match(functionRegex);
|
|
199
|
+
|
|
200
|
+
if (!match) {
|
|
201
|
+
console.log(`❌ Function 'adsOnDeviceReady' not found in file: ${admobFile}`);
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const body = match[1];
|
|
206
|
+
const lines = body.split('\n').map(line => line.trim());
|
|
207
|
+
|
|
208
|
+
// Step 3: Skip blank lines and comments, get the first real code line
|
|
209
|
+
let firstCodeLine = '';
|
|
210
|
+
for (const line of lines) {
|
|
211
|
+
if (line === '' || line.startsWith('//')) continue;
|
|
212
|
+
firstCodeLine = line;
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Step 4: Block if it's any of the unwanted returns
|
|
217
|
+
const badReturnPattern = /^return\s*(true|false)?\s*;?$/;
|
|
218
|
+
|
|
219
|
+
if (badReturnPattern.test(firstCodeLine)) {
|
|
220
|
+
console.log(`❌ BLOCKED in file '${admobFile}': First active line in 'adsOnDeviceReady' is '${firstCodeLine}'`);
|
|
221
|
+
process.exit(2);
|
|
222
|
+
} else {
|
|
223
|
+
console.log(`✅ Safe: No early return (true/false) found in 'adsOnDeviceReady' of file '${admobFile}'.`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
const addPermission_AD_ID=async()=>{
|
|
230
|
+
|
|
231
|
+
const admobPluginXmlPath = join('node_modules', 'emi-indo-cordova-plugin-admob', 'plugin.xml');
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
//let isAdmobFound = false;
|
|
235
|
+
try {
|
|
236
|
+
await promises.access(admobPluginXmlPath, constants.F_OK);
|
|
237
|
+
isAdmobFound = true;
|
|
238
|
+
} catch (err) {
|
|
239
|
+
isAdmobFound = false;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
if (isAdmobFound) {
|
|
244
|
+
// Check if AndroidManifest.xml exists
|
|
245
|
+
if (existsSync(androidManifestPath)) {
|
|
246
|
+
// Read the content of AndroidManifest.xml
|
|
247
|
+
let manifestContent = readFileSync(androidManifestPath, 'utf8');
|
|
248
|
+
|
|
249
|
+
// Check if the ad_id permission already exists
|
|
250
|
+
const adIdPermission = '<uses-permission android:name="com.google.android.gms.permission.AD_ID" />';
|
|
251
|
+
if (!manifestContent.includes(adIdPermission)) {
|
|
252
|
+
console.log("ad_id permission not found. Adding to AndroidManifest.xml.");
|
|
253
|
+
|
|
254
|
+
// Add the ad_id permission before the closing </manifest> tag
|
|
255
|
+
manifestContent = manifestContent.replace('</manifest>', ` ${adIdPermission}\n</manifest>`);
|
|
256
|
+
|
|
257
|
+
// Write the updated manifest content back to AndroidManifest.xml
|
|
258
|
+
writeFileSync(androidManifestPath, manifestContent, 'utf8');
|
|
259
|
+
console.log("✅ ad_id permission added successfully.");
|
|
260
|
+
} else {
|
|
261
|
+
console.log("ℹ️ ad_id permission already exists in AndroidManifest.xml.");
|
|
262
|
+
}
|
|
263
|
+
} else {
|
|
264
|
+
console.error("❌ AndroidManifest.xml not found at the specified path.");
|
|
265
|
+
}
|
|
266
|
+
} else {
|
|
267
|
+
console.log("\x1b[33m%s\x1b[0m", "⚠️ No admob found, so permission.AD_ID is not added");
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
checkCommonFileStoreId();
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
if (_isADMOB_ENABLED)
|
|
286
|
+
{
|
|
287
|
+
checkIsTestingInAdmob();
|
|
288
|
+
checkIsAdsDisableByReturnStatement()
|
|
289
|
+
|
|
290
|
+
await addPermission_AD_ID()
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
const { playstore, samsung, amazon } = (_isADMOB_ENABLED && admobConfig.IAP) ? admobConfig.IAP : { playstore: false, samsung: false, amazon: false };
|
|
299
|
+
console.log(`ℹ️ IAP Configurations - PlayStore: ${playstore}, Samsung: ${samsung}, Amazon: ${amazon}`);
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
// Get the store ID from the command line arguments
|
|
307
|
+
const storeIdArg = process.argv[2]; // Get the store ID from the command line
|
|
308
|
+
const storeIds = storeIdArg ? [storeIdArg] : ["1", "2", "7"]; // If a specific ID is provided, use it; otherwise, use all store IDs
|
|
309
|
+
|
|
310
|
+
// Store the original minSdkVersion globally
|
|
311
|
+
let originalMinSdkVersion;
|
|
312
|
+
|
|
313
|
+
// Remove any existing AAB files before starting the build process
|
|
314
|
+
const aabDirectory = join("android", "app", "build", "outputs", "bundle", "release");
|
|
315
|
+
if (existsSync(aabDirectory)) {
|
|
316
|
+
const files = readdirSync(aabDirectory).filter(file => file.endsWith('.aab'));
|
|
317
|
+
files.forEach(file => {
|
|
318
|
+
const filePath = join(aabDirectory, file);
|
|
319
|
+
unlinkSync(filePath);
|
|
320
|
+
console.log(`ℹ️ Deleted existing AAB file: ${file}`);
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const aabOutputDir = join("AAB");
|
|
325
|
+
if (!existsSync(aabOutputDir)) {
|
|
326
|
+
mkdirSync(aabOutputDir);
|
|
327
|
+
console.log(`Created directory: ${aabOutputDir}`);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (existsSync(aabOutputDir)) {
|
|
331
|
+
const files = readdirSync(aabOutputDir).filter(file => file.endsWith('.aab'));
|
|
332
|
+
files.forEach(file => {
|
|
333
|
+
const filePath = join(aabOutputDir, file);
|
|
334
|
+
unlinkSync(filePath);
|
|
335
|
+
console.log(`Deleted existing AAB file: ${file}`);
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
// Extract version code and version name from build.gradle
|
|
341
|
+
const gradleFilePath = join("android", "app", "build.gradle");
|
|
342
|
+
const gradleContent = readFileSync(gradleFilePath, 'utf8');
|
|
343
|
+
|
|
344
|
+
const versionCodeMatch = gradleContent.match(/versionCode\s+(\d+)/);
|
|
345
|
+
const versionNameMatch = gradleContent.match(/versionName\s+"([^"]+)"/);
|
|
346
|
+
|
|
347
|
+
const versionCode = versionCodeMatch ? versionCodeMatch[1] : '';
|
|
348
|
+
const versionName = versionNameMatch ? versionNameMatch[1] : '';
|
|
349
|
+
|
|
350
|
+
// Display the current versionCode and versionName
|
|
351
|
+
console.log(`Current versionCode: ${versionCode}`);
|
|
352
|
+
console.log(`Current versionName: ${versionName}`);
|
|
353
|
+
|
|
354
|
+
// Create an interface for user input
|
|
355
|
+
const rl = createInterface({
|
|
356
|
+
input: process.stdin,
|
|
357
|
+
output: process.stdout
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// Ask for new versionCode
|
|
361
|
+
rl.question('Enter new versionCode (press enter to keep current): ', (newVersionCode) => {
|
|
362
|
+
const finalVersionCode = newVersionCode || versionCode; // Use existing if no input
|
|
363
|
+
|
|
364
|
+
// Ask for new versionName
|
|
365
|
+
rl.question('Enter new versionName (press enter to keep current): ', (newVersionName) => {
|
|
366
|
+
const finalVersionName = newVersionName || versionName; // Use existing if no input
|
|
367
|
+
|
|
368
|
+
// Log the final version details
|
|
369
|
+
console.log(`📦 Final versionCode: ${finalVersionCode}`);
|
|
370
|
+
console.log(`📝 Final versionName: ${finalVersionName}`);
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
// Update build.gradle with the new version details
|
|
375
|
+
let updatedGradleContent = gradleContent
|
|
376
|
+
.replace(/versionCode\s+\d+/, `versionCode ${finalVersionCode}`)
|
|
377
|
+
.replace(/versionName\s+"[^"]+"/, `versionName "${finalVersionName}"`);
|
|
378
|
+
|
|
379
|
+
// Check if resConfigs "en" already exists
|
|
380
|
+
const resConfigsLine = ' resConfigs "en"';
|
|
381
|
+
if (!updatedGradleContent.includes(resConfigsLine)) {
|
|
382
|
+
// Add resConfigs "en" below versionName
|
|
383
|
+
updatedGradleContent = updatedGradleContent.replace(/versionName\s+"[^"]+"/, `versionName "${finalVersionName}"\n${resConfigsLine}`);
|
|
384
|
+
} else {
|
|
385
|
+
console.log('ℹ️ resConfigs "en" already exists in build.gradle.');
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
if (/minifyEnabled\s+false/.test(updatedGradleContent)) {
|
|
394
|
+
updatedGradleContent = updatedGradleContent.replace(/minifyEnabled\s+false/, 'minifyEnabled true');
|
|
395
|
+
console.log('Replaced minifyEnabled false with true.');
|
|
396
|
+
} else if (!/minifyEnabled\s+true/.test(updatedGradleContent)) {
|
|
397
|
+
// Only insert if minifyEnabled (true or false) is NOT present
|
|
398
|
+
if (/buildTypes\s*{[\s\S]*?release\s*{/.test(updatedGradleContent)) {
|
|
399
|
+
updatedGradleContent = updatedGradleContent.replace(
|
|
400
|
+
/(buildTypes\s*{[\s\S]*?release\s*{)/,
|
|
401
|
+
'$1\n minifyEnabled true'
|
|
402
|
+
);
|
|
403
|
+
console.log('✅ Inserted minifyEnabled true into release block.');
|
|
404
|
+
} else {
|
|
405
|
+
console.log('⚠️ Warning: buildTypes > release block not found. minifyEnabled was not added.');
|
|
406
|
+
}
|
|
407
|
+
} else {
|
|
408
|
+
console.log('ℹ️ minifyEnabled true already present. No change needed.');
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
// Write the updated gradle content back to build.gradle
|
|
417
|
+
writeFileSync(gradleFilePath, updatedGradleContent, 'utf8');
|
|
418
|
+
console.log(`✅ Updated build.gradle with versionCode: ${finalVersionCode}, versionName: ${finalVersionName}, resConfigs "en" and "minifyEnabled true"`);
|
|
419
|
+
|
|
420
|
+
storeIds.forEach((id) => {
|
|
421
|
+
console.log(`ℹ️ Building for Store ID ${id}`);
|
|
422
|
+
|
|
423
|
+
// Set the environment variable for store ID
|
|
424
|
+
process.env.VITE_STORE_ID = id;
|
|
425
|
+
|
|
426
|
+
// Conditionally set the new file name
|
|
427
|
+
let newFileName;
|
|
428
|
+
let storeName = storeNames[id];
|
|
429
|
+
|
|
430
|
+
managePackages(storeName);
|
|
431
|
+
|
|
432
|
+
if (storeName === "SamsungStore") {
|
|
433
|
+
// For SamsungStore, rename to versionCode value only
|
|
434
|
+
newFileName = `${finalVersionCode}.aab`;
|
|
435
|
+
} else {
|
|
436
|
+
// For other stores, use the standard naming format
|
|
437
|
+
newFileName = `app-release-signed-${storeName}-b${finalVersionCode}-v${finalVersionName}.aab`;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
//storeName="amazon"
|
|
441
|
+
const checkFullPath = join("AAB", newFileName); // Update to point to the new AAB directory
|
|
442
|
+
|
|
443
|
+
// Modify minSdkVersion in variables.gradle for SamsungStore
|
|
444
|
+
const variablesGradleFilePath = join("android", "variables.gradle");
|
|
445
|
+
let variablesGradleContent = readFileSync(variablesGradleFilePath, 'utf8');
|
|
446
|
+
|
|
447
|
+
// Extract the current minSdkVersion
|
|
448
|
+
const minSdkVersionMatch = variablesGradleContent.match(/minSdkVersion\s*=\s*(\d+)/);
|
|
449
|
+
const currentMinSdkVersion = minSdkVersionMatch ? parseInt(minSdkVersionMatch[1], 10) : null;
|
|
450
|
+
|
|
451
|
+
// Store the original minSdkVersion (only on the first iteration)
|
|
452
|
+
if (!originalMinSdkVersion) {
|
|
453
|
+
originalMinSdkVersion = currentMinSdkVersion;
|
|
454
|
+
}
|
|
455
|
+
try {
|
|
456
|
+
// Modify the minSdkVersion based on the store
|
|
457
|
+
if (storeName === "SamsungStore" || storeName === "PlayStore") {
|
|
458
|
+
if (currentMinSdkVersion !== 24) {
|
|
459
|
+
variablesGradleContent = variablesGradleContent.replace(/minSdkVersion\s*=\s*\d+/, 'minSdkVersion = 24');
|
|
460
|
+
console.log('minSdkVersion updated to 24 for SamsungStore & PlayStore');
|
|
461
|
+
writeFileSync(variablesGradleFilePath, variablesGradleContent);
|
|
462
|
+
}
|
|
463
|
+
} else {
|
|
464
|
+
// For PlayStore and AmazonStore, ensure minSdkVersion is originalMinSdkVersion
|
|
465
|
+
//if (currentMinSdkVersion !== originalMinSdkVersion) {
|
|
466
|
+
variablesGradleContent = variablesGradleContent.replace(/minSdkVersion\s*=\s*\d+/, `minSdkVersion = ${amazonMinSdkVersion}`);
|
|
467
|
+
console.log(`minSdkVersion reverted to ${amazonMinSdkVersion} for ${storeName}`);
|
|
468
|
+
writeFileSync(variablesGradleFilePath, variablesGradleContent);
|
|
469
|
+
//}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
// Run the Node.js script to modify plugin.xml
|
|
475
|
+
if (isAdmobFound) {
|
|
476
|
+
execSync('node buildCodeplay/modify-plugin-xml.js', { stdio: 'inherit' });
|
|
477
|
+
} else {
|
|
478
|
+
console.log("\x1b[33m%s\x1b[0m", "Seems to Pro Version [No ads found]");
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Run the Vite build
|
|
482
|
+
execSync(`npm run build:storeid${id}`, { stdio: 'inherit' });
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
// Copy the built files to the appropriate folder
|
|
487
|
+
const src = join("www", "*");
|
|
488
|
+
const dest = join("android", "app", "src", "main", "assets", "public");
|
|
489
|
+
|
|
490
|
+
// Use 'xcopy' command for Windows
|
|
491
|
+
execSync(`xcopy ${src} ${dest} /E /I /Y`, { stdio: 'inherit' });
|
|
492
|
+
|
|
493
|
+
// Build Android AAB file
|
|
494
|
+
//child_process.execSync('cd android && ./gradlew bundleRelease', { stdio: 'inherit' });
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
// Build Android AAB file with Capacitor
|
|
498
|
+
execSync('npx cap sync android', { stdio: 'inherit' });
|
|
499
|
+
execSync('npx cap build android --androidreleasetype=AAB', { stdio: 'inherit' });
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
variablesGradleContent = variablesGradleContent.replace(/minSdkVersion\s*=\s*\d+/, 'minSdkVersion = 24');
|
|
504
|
+
console.log('minSdkVersion revert to 24 (default)');
|
|
505
|
+
writeFileSync(variablesGradleFilePath, variablesGradleContent);
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
// Rename the output AAB file
|
|
509
|
+
const oldFilePath = join(aabDirectory, "app-release-signed.aab");
|
|
510
|
+
if (existsSync(oldFilePath)) {
|
|
511
|
+
renameSync(oldFilePath, checkFullPath);
|
|
512
|
+
console.log(`✅ Renamed output AAB file to: ${newFileName}`);
|
|
513
|
+
} else {
|
|
514
|
+
console.error("❌ AAB file not found after build.");
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
} catch (error) {
|
|
518
|
+
console.error(`❌ Error during build for Store ID ${id}:`, error);
|
|
519
|
+
process.exit(1);
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
rl.close(); // Close the readline interface after all operations
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
function managePackages(store) {
|
|
532
|
+
console.log(`IAP Configurations - PlayStore: ${playstore}, Samsung: ${samsung}, Amazon: ${amazon}`);
|
|
533
|
+
|
|
534
|
+
let install = "";
|
|
535
|
+
let uninstall = "";
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
let manifestContent = readFileSync(androidManifestPath, 'utf-8');
|
|
540
|
+
|
|
541
|
+
const permissionsToRemove = [
|
|
542
|
+
'com.android.vending.BILLING',
|
|
543
|
+
'com.samsung.android.iap.permission.BILLING'
|
|
544
|
+
];
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
permissionsToRemove.forEach(permission => {
|
|
548
|
+
const permissionRegex = new RegExp(`^\\s*<uses-permission\\s+android:name="${permission}"\\s*/?>\\s*[\r\n]?`, 'm');
|
|
549
|
+
if (permissionRegex.test(manifestContent)) {
|
|
550
|
+
manifestContent = manifestContent.replace(permissionRegex, '');
|
|
551
|
+
console.log(`✅ Removed <uses-permission android:name="${permission}" /> from AndroidManifest.xml`);
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
// Write the updated content back to the file
|
|
556
|
+
writeFileSync(androidManifestPath, manifestContent, 'utf-8');
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
if ((playstore && store === "PlayStore") || (amazon && store === "AmazonStore")) {
|
|
561
|
+
install = '@revenuecat/purchases-capacitor';
|
|
562
|
+
uninstall = 'cordova-plugin-samsungiap';
|
|
563
|
+
|
|
564
|
+
// Update AndroidManifest.xml for PlayStore
|
|
565
|
+
if(playstore)
|
|
566
|
+
updateAndroidManifest(store,
|
|
567
|
+
'<uses-permission android:name="com.android.vending.BILLING" />');
|
|
568
|
+
|
|
569
|
+
} else if (samsung && store === "SamsungStore") {
|
|
570
|
+
install = 'cordova-plugin-samsungiap';
|
|
571
|
+
uninstall = '@revenuecat/purchases-capacitor';
|
|
572
|
+
|
|
573
|
+
// Update AndroidManifest.xml for SamsungStore
|
|
574
|
+
updateAndroidManifest(store,
|
|
575
|
+
'<uses-permission android:name="com.samsung.android.iap.permission.BILLING" />');
|
|
576
|
+
|
|
577
|
+
} else {
|
|
578
|
+
console.log("No valid store specified or no configurations found. Both plugins will be uninstalled.");
|
|
579
|
+
try {
|
|
580
|
+
execSync(`npm uninstall cordova-plugin-samsungiap`, { stdio: 'inherit' });
|
|
581
|
+
execSync(`npm uninstall @revenuecat/purchases-capacitor`, { stdio: 'inherit' });
|
|
582
|
+
console.log(`✅ Both plugins uninstalled successfully.`);
|
|
583
|
+
} catch (err) {
|
|
584
|
+
console.error("❌ Error uninstalling plugins:", err);
|
|
585
|
+
}
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
console.log(`⚠️ Installing ${install} and uninstalling ${uninstall} for ${store}...`);
|
|
590
|
+
try {
|
|
591
|
+
if (install) {
|
|
592
|
+
execSync(`npm install ${install}`, { stdio: 'inherit' });
|
|
593
|
+
}
|
|
594
|
+
if (uninstall) {
|
|
595
|
+
execSync(`npm uninstall ${uninstall}`, { stdio: 'inherit' });
|
|
596
|
+
}
|
|
597
|
+
console.log(`✅ ${install} installed and ${uninstall} uninstalled successfully.`);
|
|
598
|
+
} catch (err) {
|
|
599
|
+
console.error(`❌ Error managing packages for ${store}:`, err);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
function updateAndroidManifest(store, addPermission) {
|
|
606
|
+
try {
|
|
607
|
+
if (!existsSync(androidManifestPath)) {
|
|
608
|
+
console.error("❌ AndroidManifest.xml file not found!");
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Read the content of the AndroidManifest.xml
|
|
613
|
+
let manifestContent = readFileSync(androidManifestPath, 'utf-8');
|
|
614
|
+
|
|
615
|
+
// Normalize line endings to `\n` for consistent processing
|
|
616
|
+
manifestContent = manifestContent.replace(/\r\n/g, '\n');
|
|
617
|
+
|
|
618
|
+
// Check if the permission is already present
|
|
619
|
+
if (manifestContent.includes(addPermission.trim())) {
|
|
620
|
+
console.log(`${addPermission} is already in the AndroidManifest.xml. Skipping addition.`);
|
|
621
|
+
return; // Skip if the permission is already present
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// Insert the permission before the closing </manifest> tag
|
|
625
|
+
const closingTag = '</manifest>';
|
|
626
|
+
const formattedPermission = ` ${addPermission.trim()}\n`;
|
|
627
|
+
if (manifestContent.includes(closingTag)) {
|
|
628
|
+
manifestContent = manifestContent.replace(
|
|
629
|
+
closingTag,
|
|
630
|
+
`${formattedPermission}${closingTag}`
|
|
631
|
+
);
|
|
632
|
+
console.log(`✅ Added ${addPermission} before </manifest> tag.`);
|
|
633
|
+
} else {
|
|
634
|
+
console.warn(`⚠️ </manifest> tag not found. Adding ${addPermission} at the end of the file.`);
|
|
635
|
+
manifestContent += `\n${formattedPermission}`;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// Normalize line endings back to `\r\n` and write the updated content
|
|
639
|
+
manifestContent = manifestContent.replace(/\n/g, '\r\n');
|
|
640
|
+
writeFileSync(androidManifestPath, manifestContent, 'utf-8');
|
|
641
|
+
console.log(`✅ AndroidManifest.xml updated successfully for ${store}`);
|
|
642
|
+
} catch (err) {
|
|
643
|
+
console.error(`❌ Error updating AndroidManifest.xml for ${store}:`, err);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
/* function updateAndroidManifest1(store, addPermission) {
|
|
650
|
+
try {
|
|
651
|
+
if (!fs.existsSync(androidManifestPath)) {
|
|
652
|
+
console.error("AndroidManifest.xml file not found!");
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
let manifestContent = fs.readFileSync(androidManifestPath, 'utf-8');
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
// Add the required permission if not already present
|
|
661
|
+
if (!manifestContent.includes(addPermission)) {
|
|
662
|
+
const manifestLines = manifestContent.split('\n');
|
|
663
|
+
const insertIndex = manifestLines.findIndex(line => line.trim().startsWith('<application'));
|
|
664
|
+
if (insertIndex > -1) {
|
|
665
|
+
manifestLines.splice(insertIndex, 0, ` ${addPermission}`);
|
|
666
|
+
manifestContent = manifestLines.join('\n');
|
|
667
|
+
console.log(`Added ${addPermission} to AndroidManifest.xml`);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// Write the updated content back to the file
|
|
672
|
+
fs.writeFileSync(androidManifestPath, manifestContent, 'utf-8');
|
|
673
|
+
console.log(`AndroidManifest.xml updated successfully for ${store}`);
|
|
674
|
+
} catch (err) {
|
|
675
|
+
console.error(`Error updating AndroidManifest.xml for ${store}:`, err);
|
|
676
|
+
}
|
|
677
|
+
} */
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
|