68#define EXECBUFSIZE 4096
75 SECURITY_ATTRIBUTES sa;
79 sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
80 sa.bInheritHandle = TRUE;
81 sa.lpSecurityDescriptor = NULL;
108 BOOL bSuccess = FALSE;
118 CloseHandle(piProcInfo.hProcess);
119 CloseHandle(piProcInfo.hThread);
131 PROCESS_INFORMATION piProcInfo;
132 STARTUPINFO siStartInfo;
135 ZeroMemory(&piProcInfo,
sizeof(PROCESS_INFORMATION));
139 ZeroMemory(&siStartInfo,
sizeof(STARTUPINFO));
140 siStartInfo.cb =
sizeof(STARTUPINFO);
143 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
146 bSuccess = CreateProcess(NULL,
151 NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,
165void ReadExecFromPipe(PROCESS_INFORMATION piProcInfo, std::string &output, std::string &err)
169 BOOL bSuccess = FALSE;
175 if( ! bSuccess || dwRead == 0 )
break;
177 std::string s(chBuf, dwRead);
184 if( ! bSuccess || dwRead == 0 )
break;
186 std::string s(chBuf, dwRead);
192void addDirToArchive(zip_t *archive,
const boost::filesystem::path &srcdir,
const boost::filesystem::path &inputdir)
194 std::string outputdir = inputdir.generic_string().substr(srcdir.parent_path().generic_string().length() + 1);
195 if (zip_dir_add(archive, outputdir.c_str(), 0) < 0)
196 throw std::runtime_error(
"Failed to add directory to archive: " + std::string(zip_strerror(archive)));
198 boost::filesystem::directory_iterator dirIter(inputdir);
199 boost::filesystem::directory_iterator end;
200 while (dirIter != end)
202 if (boost::filesystem::is_directory(dirIter->path()))
206 zip_source_t *source = zip_source_file(archive, dirIter->path().generic_string().c_str(), 0, 0);
208 throw std::runtime_error(
"Failed to add file to archive: " + std::string(zip_strerror(archive)));
210 std::string outputfile = outputdir +
"/" + dirIter->path().filename().generic_string();
211 if (zip_file_add(archive, outputfile.c_str(), source, 0) < 0)
213 zip_source_free(source);
214 throw std::runtime_error(
"Failed to add file to archive: " + std::string(zip_strerror(archive)));
238 MMechostr(MSKDEBUG,
"_MAKEandroidUnsignedAPK\n");
240 boost::system::error_code ec;
242 int imanifestPath = MMpull(m);
243 int iname = MMget(m, 0);
245 if (imanifestPath == NIL || iname == NIL)
247 MMechostr(MSKDEBUG,
"error: manifest path or name is NIL\n");
253 boost::filesystem::path manifestPath = MMstartstr(m, MTOP(imanifestPath));
254 boost::filesystem::path basePath = manifestPath;
255 basePath.remove_filename();
256 std::string name = MMstartstr(m, MTOP(iname));
257 std::string cmd =
"";
258 std::string cmdargs =
"";
264 std::string errmsg(std::string(
"error: ") +
toolsPathBox.
exe_aapt2Path.generic_string() + std::string(
" doesn't exist !"));
265 MMechostr(MSKDEBUG,
"_MAKEandroidUnsignedAppBundle : %s\n", errmsg.c_str());
271 boost::filesystem::path unsignedAppBundle = projectPathBox.
binPath / (name +
".unsigned.aab");
274 if (boost::filesystem::exists(unsignedAppBundle))
275 boost::filesystem::remove(unsignedAppBundle, ec);
279 std::string res_arg =
" -R";
280 if (boost::filesystem::exists(projectPathBox.
resPath) && boost::filesystem::is_directory(projectPathBox.
resPath))
282 boost::filesystem::create_directory(projectPathBox.
tmpPath);
283 boost::filesystem::recursive_directory_iterator resDirIter(projectPathBox.
resPath);
284 boost::filesystem::recursive_directory_iterator end;
286 while (resDirIter != end)
288 if (!boost::filesystem::is_directory(resDirIter->path()))
291 +
" compile \"" + resDirIter->path().string() +
"\""
292 +
" -o \"" + projectPathBox.
tmpPath.generic_string() +
"\"";
296 MMechostr(MSKDEBUG,
"error running aapt2 compile : %s\n", output.c_str());
298 Mpushstrbloc(m, (
char*)output.c_str());
308 boost::filesystem::directory_iterator compResDirIter(projectPathBox.
tmpPath);
309 boost::filesystem::directory_iterator compResEnd;
310 while (compResDirIter != compResEnd)
312 res_arg +=
" \"" + compResDirIter->path().string() +
"\"";
321 +
" -o \"" + projectPathBox.
projectArchive.generic_string() +
"\""
323 +
" --manifest \"" + projectPathBox.
manifestPath.generic_string() +
"\""
325 +
" --auto-add-overlay";
328 MMechostr(MSKRUNTIME,
"_MAKEandroidUnsignedAppBundle command: %s\n", cmd.c_str());
332 MMechostr(MSKDEBUG,
"error running aapt2 link : %s\n", output.c_str());
334 Mpushstrbloc(m, (
char*)output.c_str());
342 zip_error_t ziperror;
347 archive = zip_open(projectPathBox.
projectArchive.generic_string().c_str(), 0, &errorp);
350 zip_error_init_with_code(&ziperror, errorp);
351 throw std::runtime_error(
"Failed to open archive " + projectPathBox.
projectArchive.generic_string() +
": " + zip_error_strerror(&ziperror));
355 zip_uint64_t index = zip_name_locate(archive,
"AndroidManifest.xml", 0);
356 if (index < 0 || zip_dir_add(archive,
"manifest", 0) < 0 || zip_file_rename(archive, index,
"manifest/AndroidManifest.xml", 0) < 0)
357 throw std::runtime_error(
"Failed to move manifest inside archive " + projectPathBox.
projectArchive.generic_string() +
": " + zip_error_strerror(&ziperror));
365 catch(std::exception e)
369 MMechostr(MSKDEBUG,
"error packaging archive : %s\n", e.what());
371 Mpushstrbloc(m, (
char*)e.what());
378 boost::filesystem::create_directory(projectPathBox.
binPath);
383 +
" --modules=\"" + projectPathBox.
projectArchive.generic_string() +
"\""
384 +
" --output=\"" + unsignedAppBundle.generic_string() +
"\"";
389 MMechostr(MSKDEBUG,
"error running bundletool : %s\n", output.c_str());
391 Mpushstrbloc(m, (
char*)output.c_str());
397 if (boost::filesystem::exists(unsignedAppBundle))
400 Mpushstrbloc(m, (
char*)unsignedAppBundle.generic_string().c_str());
401 Mpushstrbloc(m, (
char*)output.c_str());
408 Mpushstrbloc(m, (
char*)output.c_str());
414 MMechostr(MSKDEBUG,
"end _MAKEandroidUnsignedAppBundle\n");
431 MMechostr(MSKDEBUG,
"_MAKEandroidUnsignedAPK\n");
434 boost::system::error_code ec;
435 int imanifestPath = MMpull(m);
436 int iname = MMget(m, 0);
438 if (imanifestPath == NIL || iname == NIL)
440 MMechostr(MSKDEBUG,
"error: manifest path or name is NIL\n");
446 boost::filesystem::path manifestPath = MMstartstr(m, MTOP(imanifestPath));
447 boost::filesystem::path basePath = manifestPath;
448 basePath.remove_filename();
449 std::string name = MMstartstr(m, MTOP(iname));
450 std::string cmdargs =
"";
454 std::string errmsg(std::string(
"error: ") +
toolsPathBox.
exe_aaptPath.generic_string() + std::string(
" doesn't exist !"));
455 MMechostr(MSKDEBUG,
"_MAKEandroidUnsignedAPK : %s\n", errmsg.c_str());
461 boost::filesystem::path unsignedApk = projectPathBox.
binPath / (name +
".unsigned.apk");
464 if(boost::filesystem::exists(unsignedApk))
465 boost::filesystem::remove(unsignedApk, ec);
468 cmdargs +=
"package";
469 cmdargs +=
" -M \"" + projectPathBox.
manifestPath.generic_string() +
"\"";
471 cmdargs +=
" -F \"" + unsignedApk.generic_string() +
"\"";
472 cmdargs +=
" -S \"" + projectPathBox.
resPath.generic_string() +
"\"";
473 cmdargs +=
" \"" + projectPathBox.
dexPath.generic_string() +
"\"";
474 cmdargs +=
" \"" + projectPathBox.
packagePath.generic_string() +
"\"";
477 boost::filesystem::create_directory(projectPathBox.
binPath);
482 MMechostr(MSKRUNTIME,
"_MAKEandroidUnsignedAPK command: %s\n", cmd.c_str());
507 MMechostr(MSKDEBUG,
"error running aapt : %s\n", output.c_str());
509 Mpushstrbloc(m, (
char*)output.c_str());
515 if (boost::filesystem::exists(unsignedApk))
518 Mpushstrbloc(m, (
char*)unsignedApk.generic_string().c_str());
519 Mpushstrbloc(m, (
char*)output.c_str());
526 Mpushstrbloc(m, (
char*)output.c_str());
532 MMechostr(MSKDEBUG,
"end _MAKEandroidUnsignedAPK\n");
551 MMechostr(MSKDEBUG,
"_ENCRYPTandroidSigningKey\n");
553 boost::system::error_code ec;
555 int ibundlePath = MMpull(m);
556 int ikeyAlias = MMpull(m);
557 int ikeyPassword = MMpull(m);
558 int ikeystorePath = MMget(m, 0);
560 if (ikeystorePath == NIL || ikeyPassword == NIL || ikeyAlias == NIL)
562 MMechostr(MSKDEBUG,
"error: destination path, application name, password or key alias are NIL\n");
568 boost::filesystem::path keystorePath = MMstartstr(m, MTOP(ikeystorePath));
569 boost::filesystem::path encryptedKeyPath = MMstartstr(m, MTOP(ibundlePath));
570 encryptedKeyPath.remove_filename();
571 encryptedKeyPath /= boost::filesystem::change_extension(keystorePath.filename(),
"keystore.encrypted");
572 std::string keyPassword = MMstartstr(m, MTOP(ikeyPassword));
573 std::string keyAlias = MMstartstr(m, MTOP(ikeyAlias));
578 std::string errmsg(std::string(
"error: ") +
toolsPathBox.
jar_pepkPath.generic_string() + std::string(
" doesn't exist !"));
579 MMechostr(MSKDEBUG, errmsg.c_str());
585 if (boost::filesystem::exists(encryptedKeyPath))
586 boost::filesystem::remove(encryptedKeyPath, ec);
590 bool result =
execProcess(
"java --version", output);
593 MMechostr(MSKDEBUG,
"error : Java is not available\n");
595 Mpushstrbloc(m,
"Java is not available on your computer. You must install Java in order to create and sign an Android App bundle");
602 cmd =
"echo Encryption of the store key to upload to the Play Store & echo Please enter your store key password twice (the password will not appear as you type, that is the normal behaviour) & java -jar \"" +
toolsPathBox.
jar_pepkPath.generic_string() +
"\""
603 +
" --keystore=\"" + keystorePath.generic_string() +
"\""
604 +
" --alias=\"" + keyAlias +
"\""
605 +
" --output=\"" + encryptedKeyPath.generic_string() +
"\""
606 +
" --encryptionkey=\"eb10fe8f7c7c9df715022017b00c6471f8ba8170b13049a11e6c09ffe3056a104a3bbe4ac5a955f4ba4fe93fc8cef27558a3eb9d2a529a2092761fb833b656cd48b9de6a\""
611 int res = system(cmd.c_str());
614 MMechostr(MSKRUNTIME,
"_ENCRYPTandroidSigningKey : error running pepk : %s\n", output.c_str());
616 Mpushstrbloc(m, (
char*)output.c_str());
622 if (boost::filesystem::exists(encryptedKeyPath))
625 Mpushstrbloc(m, (
char*)encryptedKeyPath.generic_string().c_str());
626 Mpushstrbloc(m, (
char*)output.c_str());
632 MMechostr(MSKRUNTIME,
"_ENCRYPTandroidSigningKey : error running pepk : %s\n", cmd.c_str());
634 Mpushstrbloc(m, (
char*)output.c_str());
640 MMechostr(MSKDEBUG,
"end _ENCRYPTandroidSigningKey\n");
659 MMechostr(MSKDEBUG,
"_MAKEandroidSigningKey\n");
661 boost::system::error_code ec;
663 int iadditional = MMpull(m);
664 int ikeyAlias = MMpull(m);
665 int ikeyPassword = MMpull(m);
666 int ikeystorePath = MMget(m, 0);
668 if (ikeystorePath == NIL || ikeyPassword == NIL || ikeyAlias == NIL)
670 MMechostr(MSKDEBUG,
"error: destination path, application name, password or key alias are NIL\n");
676 boost::filesystem::path keystorePath = MMstartstr(m, MTOP(ikeystorePath));
677 std::string keyPassword = MMstartstr(m, MTOP(ikeyPassword));
678 std::string keyAlias = MMstartstr(m, MTOP(ikeyAlias));
679 std::string cmdargs =
"-J-Duser.language=en ";
684 MMechostr(MSKDEBUG, errmsg.c_str());
690 if(boost::filesystem::exists(keystorePath))
691 boost::filesystem::remove(keystorePath, ec);
698 std::string dname =
"";
699 while(iadditional != NIL)
701 q = MMfetch(m, MTOP(iadditional), 0);
704 ikey = MMfetch(m, MTOP(q), 0);
705 ivalue = MMfetch(m, MTOP(q), 1);
710 std::string skey = MMstartstr(m, MTOP(ikey));
711 std::string svalue =
"";
713 svalue = MMstartstr(m, MTOP(ivalue));
716 if (!svalue.empty() && ((skey ==
"CN") || (skey ==
"OU") || (skey ==
"O") || (skey ==
"L") || (skey ==
"S") || (skey ==
"C")))
721 dname += skey +
"=" + svalue;
725 iadditional = MMfetch(m, MTOP(iadditional), 1);
728 cmdargs +=
"-genkeypair";
729 cmdargs +=
" -validity 20000 ";
731 cmdargs +=
" -dname \"" + dname +
"\"";
733 cmdargs +=
" -dname \"C=AQ\"";
735 cmdargs +=
" -keystore \"" + keystorePath.generic_string() +
"\"";
736 cmdargs +=
" -storepass " + keyPassword;
737 cmdargs +=
" -keypass " + keyPassword;
738 cmdargs +=
" -alias " + keyAlias;
739 cmdargs +=
" -keyalg RSA";
740 cmdargs +=
" -keysize 2048";
766 MMechostr(MSKRUNTIME,
"_MAKEandroidSigningKey : error running keytool : %s\n", output.c_str());
768 Mpushstrbloc(m, (
char*)output.c_str());
776 if (boost::filesystem::exists(keystorePath))
779 Mpushstrbloc(m, (
char*)keystorePath.generic_string().c_str());
780 Mpushstrbloc(m, (
char*)output.c_str());
786 MMechostr(MSKRUNTIME,
"_MAKEandroidSigningKey : error running keytool : %s\n", cmd.c_str());
788 Mpushstrbloc(m, (
char*)output.c_str());
794 MMechostr(MSKDEBUG,
"end _MAKEandroidSigningKey\n");
813 MMechostr(MSKDEBUG,
"_SIGNandroidAppBundle\n");
815 boost::system::error_code ec;
817 int ikeyAlias = MMpull(m);
818 int ikeyPassword = MMpull(m);
819 int ikeystorePath = MMpull(m);
820 int iunsignedAppBundlepath = MMget(m, 0);
823 if (ikeyAlias == NIL || ikeyPassword == NIL || ikeystorePath == NIL || iunsignedAppBundlepath == NIL)
825 MMechostr(MSKDEBUG,
"_SIGNandroidAppBundle : error: manifest path, keystore path, key password or key alias are NIL\n");
833 MMechostr(MSKDEBUG,
"_SIGNandroidAppBundle : %s\n", errmsg.c_str());
839 boost::filesystem::path unsignedAppBundlePath = MMstartstr(m, MTOP(iunsignedAppBundlepath));
840 boost::filesystem::path keystorePath = MMstartstr(m, MTOP(ikeystorePath));
841 std::string password = MMstartstr(m, MTOP(ikeyPassword));
842 std::string alias = MMstartstr(m, MTOP(ikeyAlias));
843 std::string cmdargs =
"-J-Duser.language=en ";
846 boost::filesystem::path appBundlePath(unsignedAppBundlePath);
847 appBundlePath = boost::filesystem::change_extension(appBundlePath,
"");
848 int lastindex = appBundlePath.generic_string().find_last_of(
".");
849 appBundlePath = appBundlePath.generic_string().substr(0, lastindex);
851 boost::filesystem::path finalAppBundlePath = appBundlePath.generic_string() +
".aab";
854 if (boost::filesystem::exists(finalAppBundlePath))
855 boost::filesystem::remove(finalAppBundlePath, ec);
857 cmdargs +=
"-tsa http://timestamp.digicert.com";
858 cmdargs +=
" -keystore \"" + keystorePath.generic_string() +
"\"";
859 cmdargs +=
" -storepass " + password;
860 cmdargs +=
" -keypass " + password;
861 cmdargs +=
" -sigalg SHA1withRSA";
862 cmdargs +=
" -digestalg SHA1";
863 cmdargs +=
" -signedjar \"" + finalAppBundlePath.generic_string() +
"\"";
864 cmdargs +=
" \"" + unsignedAppBundlePath.generic_string() +
"\"";
865 cmdargs +=
" " + alias;
872 if (!result || !boost::filesystem::exists(finalAppBundlePath))
874 MMechostr(MSKDEBUG,
"_SIGNandroidAppBundle : error running jarsigner : %s\n", output.c_str());
876 Mpushstrbloc(m, (
char*)output.c_str());
884 if (boost::filesystem::exists(unsignedAppBundlePath))
885 boost::filesystem::remove(unsignedAppBundlePath, ec);
887 if (boost::filesystem::exists(finalAppBundlePath))
890 Mpushstrbloc(m, (
char*)finalAppBundlePath.generic_string().c_str());
891 Mpushstrbloc(m, (
char*)output.c_str());
898 Mpushstrbloc(m, (
char*)output.c_str());
904 MMechostr(MSKDEBUG,
"end _SIGNandroidAppBundle\n");
923 MMechostr(MSKDEBUG,
"_SIGNandroidAPK\n");
925 boost::system::error_code ec;
927 int ikeyAlias = MMpull(m);
928 int ikeyPassword = MMpull(m);
929 int ikeystorePath = MMpull(m);
930 int iunsignedAPKpath = MMget(m, 0);
933 if (ikeyAlias == NIL || ikeyPassword == NIL || ikeystorePath == NIL || iunsignedAPKpath == NIL)
935 MMechostr(MSKDEBUG,
"_SIGNandroidAPK : error: manifest path, keystore path, key password or key alias are NIL\n");
943 MMechostr(MSKDEBUG,
"_SIGNandroidAPK : %s\n", errmsg.c_str());
949 boost::filesystem::path unsignedAPKPath = MMstartstr(m, MTOP(iunsignedAPKpath));
950 boost::filesystem::path keystorePath = MMstartstr(m, MTOP(ikeystorePath));
951 std::string password = MMstartstr(m, MTOP(ikeyPassword));
952 std::string alias = MMstartstr(m, MTOP(ikeyAlias));
953 std::string cmdargs =
"";
957 boost::filesystem::path apkPath(unsignedAPKPath);
958 apkPath = boost::filesystem::change_extension(apkPath,
"");
959 int lastindex = apkPath.generic_string().find_last_of(
".");
960 apkPath = apkPath.generic_string().substr(0, lastindex);
962 boost::filesystem::path alignedAPKPath = apkPath.generic_string() +
".aligned.apk";
963 boost::filesystem::path finalAPKPath = apkPath.generic_string() +
".apk";
966 if(boost::filesystem::exists(alignedAPKPath))
967 boost::filesystem::remove(alignedAPKPath, ec);
969 if(boost::filesystem::exists(finalAPKPath))
970 boost::filesystem::remove(finalAPKPath, ec);
973 cmdargs +=
"\"" + unsignedAPKPath.generic_string() +
"\" ";
974 cmdargs +=
"\"" + alignedAPKPath.generic_string() +
"\" ";
1000 MMechostr(MSKDEBUG,
"_SIGNandroidAPK : error running zipalign : %s\n", output.c_str());
1002 Mpushstrbloc(m, (
char*)output.c_str());
1010 +
" --ks \"" + keystorePath.generic_string() +
"\""
1011 +
" --ks-pass \"pass:" + password +
"\""
1012 +
" --v1-signing-enabled true"
1013 +
" --v2-signing-enabled true"
1014 +
" --out \"" + finalAPKPath.generic_string() +
"\""
1015 +
" \"" + alignedAPKPath.generic_string() +
"\"";
1020 MMechostr(MSKDEBUG,
"error running apksigner : %s\n", output.c_str());
1022 Mpushstrbloc(m, (
char*)output.c_str());
1029 if(boost::filesystem::exists(unsignedAPKPath))
1030 boost::filesystem::remove(unsignedAPKPath, ec);
1032 if(boost::filesystem::exists(alignedAPKPath))
1033 boost::filesystem::remove(alignedAPKPath, ec);
1035 if (boost::filesystem::exists(finalAPKPath))
1038 Mpushstrbloc(m, (
char*)finalAPKPath.generic_string().c_str());
1039 Mpushstrbloc(m, (
char*)output.c_str());
1046 Mpushstrbloc(m, (
char*)output.c_str());
1052 MMechostr(MSKDEBUG,
"end _SIGNandroidAPK\n");
1068 MMechostr(MSKDEBUG,
"_INSTALLandroidAPK\n");
1071 int iAPKPath = MMget(m, 0);
1073 if (iAPKPath == NIL)
1075 MMechostr(MSKDEBUG,
"error: APK path is NIL\n");
1082 std::string errmsg(std::string(
"error: ") +
toolsPathBox.
exe_adbPath.generic_string() + std::string(
" doesn't exist !"));
1083 MMechostr(MSKDEBUG, errmsg.c_str());
1088 boost::filesystem::path APKPath = MMstartstr(m, MTOP(iAPKPath));
1091 std::string cmd =
"\"\"" +
toolsPathBox.
exe_adbPath.generic_string() +
"\" install -r \"" + APKPath.generic_string() +
"\"\"";
1092 int res = system(cmd.c_str());
1095 MMechostr(MSKDEBUG,
"error running adb : %s\n", cmd.c_str());
1096 system(
"cd %__LASTDIR%");
1101 MMset(m, 0, ITOM(0));
1104 MMechostr(MSKDEBUG,
"end _INSTALLandroidAPK\n");
1151 MMechostr(MSKDEBUG,
" > Loading Android Deployer\n");
1153 MMechostr(MSKDEBUG,
" > Successfully Loaded\n\n");
int LoadAndroidDeployer(mmachine m)
Load the packages in Scol virtual machine.
HANDLE g_hChildStd_OUT_Wr
HANDLE g_hChildStd_ERR_Rd
HANDLE g_hChildStd_ERR_Wr
bool execProcess(std::string cmd, std::string &output)
void ReadExecFromPipe(PROCESS_INFORMATION, std::string &, std::string &)
PROCESS_INFORMATION CreateExecChildProcess(std::string, BOOL &)
void addDirToArchive(zip_t *archive, const boost::filesystem::path &srcdir, const boost::filesystem::path &inputdir)
NativeDefinition base_android_deployer[]
HANDLE g_hChildStd_OUT_Rd
ToolsPathBox toolsPathBox
boost::filesystem::path binPath
boost::filesystem::path libPath
boost::filesystem::path resPath
boost::filesystem::path packagePath
boost::filesystem::path projectArchive
boost::filesystem::path dexPath
boost::filesystem::path manifestPath
boost::filesystem::path tmpPath
boost::filesystem::path assetsPath
int _CHECKandroidTools(mmachine m)
_CHECKandroidTools : This function test if the android tools are available
int _INSTALLandroidAPK(mmachine m)
_INSTALLandroidAPK : This function signs and
int _ENCRYPTandroidSigningKey(mmachine m)
_ENCRYPTandroidSigningKey : This function encrypts a signing key (.keystore) so it can be sent to the...
int _SIGNandroidAPK(mmachine m)
_SIGNandroidAPK : This function signs and zips align an APK file
int _MAKEandroidUnsignedAppBundle(mmachine m)
_MAKEandroidUnsignedAppBundle : This function creates an unsigned App Bundle from files contained in ...
int _MAKEandroidSigningKey(mmachine m)
_MAKEandroidSigningKey : This function creates a signing key (.keystore) used to sign Android APKs
int _MAKEandroidUnsignedAPK(mmachine m)
_MAKEandroidUnsignedAPK : This function creates an unsigned apk from files contained in the same fold...
int _SIGNandroidAppBundle(mmachine m)
_SIGNandroidAppBundle : This function signs and zips align an app bundle file