This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
package org.autojs.autojs.annotation
|
||||
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FIELD, AnnotationTarget.FUNCTION)
|
||||
annotation class SerializedNameCompatible(vararg val with: With) {
|
||||
annotation class With(val value: String, val target: Array<String> = ["AutoJs6"], val isReversed: Boolean = false)
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import android.content.pm.PackageManager.ApplicationInfoFlags
|
||||
import android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES
|
||||
import android.content.res.AssetManager
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import com.mcal.apksigner.ApkSigner
|
||||
@@ -13,7 +12,6 @@ import com.reandroid.arsc.chunk.TableBlock
|
||||
import org.apache.commons.io.FileUtils.copyFile
|
||||
import org.apache.commons.io.FileUtils.copyInputStreamToFile
|
||||
import org.autojs.autojs.apkbuilder.keystore.AESUtils
|
||||
import org.autojs.autojs.apkbuilder.keystore.KeyStore
|
||||
import org.autojs.autojs.app.GlobalAppContext
|
||||
import org.autojs.autojs.engine.encryption.AdvancedEncryptionStandard
|
||||
import org.autojs.autojs.pio.PFiles
|
||||
@@ -35,7 +33,6 @@ import java.io.FileNotFoundException
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
/**
|
||||
* Created by Stardust on Oct 24, 2017.
|
||||
@@ -49,7 +46,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File
|
||||
private var mInitVector: String? = null
|
||||
private var mKey: String? = null
|
||||
|
||||
private lateinit var mAppConfig: AppConfig
|
||||
private lateinit var mProjectConfig: ProjectConfig
|
||||
|
||||
private val mApkPackager = ApkPackager(apkInputStream, workspacePath)
|
||||
|
||||
@@ -59,6 +56,9 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File
|
||||
private var mAssetsFileIncludes = Libs.defaultAssetFilesToInclude.toMutableList()
|
||||
private var mAssetsDirExcludes = Libs.defaultAssetDirsToExclude.toMutableList()
|
||||
|
||||
private var mSplashThemeId = 0
|
||||
private var mNoSplashThemeId = 0
|
||||
|
||||
private val mManifestFile
|
||||
get() = File(workspacePath, "AndroidManifest.xml")
|
||||
|
||||
@@ -105,7 +105,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File
|
||||
srcChildFile.copyTo(File(destDirFile, srcChildFile.name), true)
|
||||
}
|
||||
} else {
|
||||
if (!mAppConfig.ignoredDirs.contains(srcChildFile)) {
|
||||
if (!mProjectConfig.ignoredDirs.contains(srcChildFile)) {
|
||||
copyDir(srcChildFile, PFiles.join(relativeDestPath, srcChildFile.name + File.separator))
|
||||
}
|
||||
}
|
||||
@@ -141,10 +141,27 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun withConfig(config: AppConfig) = also {
|
||||
config.also { mAppConfig = it }.run {
|
||||
fun withConfig(config: ProjectConfig) = also {
|
||||
config.also { mProjectConfig = it }.run {
|
||||
if (!launchConfig.isSplashVisible) {
|
||||
try {
|
||||
val tableBlock = TableBlock.load(mResourcesArscFile)
|
||||
val packageName = "${GlobalAppContext.get().packageName}.inrt"
|
||||
val packageBlock = tableBlock.getOrCreatePackage(0x7f, packageName).also {
|
||||
tableBlock.currentPackage = it
|
||||
}
|
||||
packageBlock.getEntry("", "style", "AppTheme.Splash")?.let {
|
||||
mSplashThemeId = it.resourceId
|
||||
}
|
||||
packageBlock.getEntry("", "style", "AppTheme.SevereTransparent")?.let {
|
||||
mNoSplashThemeId = it.resourceId
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
mManifestEditor = editManifest()
|
||||
.setAppName(appName)
|
||||
.setAppName(name)
|
||||
.setVersionName(versionName)
|
||||
.setVersionCode(versionCode)
|
||||
.setPackageName(packageName)
|
||||
@@ -160,32 +177,32 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File
|
||||
@Throws(FileNotFoundException::class)
|
||||
fun editManifest(): ManifestEditor = ManifestEditorWithAuthorities(FileInputStream(mManifestFile)).also { mManifestEditor = it }
|
||||
|
||||
private fun updateProjectConfig(appConfig: AppConfig) {
|
||||
private fun updateProjectConfig(config: ProjectConfig) {
|
||||
val projectConfig = when {
|
||||
!PFiles.isDir(appConfig.sourcePath) -> null
|
||||
else -> ProjectConfig.fromProjectDir(appConfig.sourcePath)?.also {
|
||||
!PFiles.isDir(config.sourcePath) -> null
|
||||
else -> ProjectConfig.fromProjectDir(config.sourcePath)?.also {
|
||||
val buildNumber = it.buildInfo.buildNumber
|
||||
it.buildInfo = BuildInfo.generate(buildNumber + 1)
|
||||
PFiles.write(ProjectConfig.configFileOfDir(appConfig.sourcePath), it.toJson())
|
||||
PFiles.write(ProjectConfig.configFileOfDir(config.sourcePath), it.toJson())
|
||||
}
|
||||
} ?: ProjectConfig()
|
||||
.setMainScriptFile("main.js")
|
||||
.setName(appConfig.appName)
|
||||
.setPackageName(appConfig.packageName)
|
||||
.setVersionName(appConfig.versionName)
|
||||
.setVersionCode(appConfig.versionCode)
|
||||
.also { config ->
|
||||
config.buildInfo = BuildInfo.generate(appConfig.versionCode.toLong())
|
||||
.setName(config.name)
|
||||
.setPackageName(config.packageName)
|
||||
.setVersionName(config.versionName)
|
||||
.setVersionCode(config.versionCode)
|
||||
.also { newProjectConfig ->
|
||||
newProjectConfig.buildInfo = BuildInfo.generate(newProjectConfig.versionCode.toLong())
|
||||
File(workspacePath, "assets/project/${ProjectConfig.CONFIG_FILE_NAME}").also { file ->
|
||||
file.parentFile?.let { parent -> if (!parent.exists()) parent.mkdirs() }
|
||||
}.writeText(config.toJson())
|
||||
}.writeText(newProjectConfig.toJson())
|
||||
}
|
||||
|
||||
projectConfig.run {
|
||||
mKey = MD5Utils.md5(packageName + versionName + mainScriptFile)
|
||||
mInitVector = MD5Utils.md5(buildInfo.buildId + name).substring(0, 16)
|
||||
Libs.entries.forEach { entry ->
|
||||
if (appConfig.libs.contains(entry.label)) {
|
||||
if (config.libs.contains(entry.label)) {
|
||||
mLibsIncludes += entry.libsToInclude.toSet()
|
||||
mAssetsFileIncludes += entry.assetFilesToInclude.toSet()
|
||||
mAssetsDirExcludes -= entry.assetDirsToExclude.toSet()
|
||||
@@ -197,7 +214,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File
|
||||
@Throws(Exception::class)
|
||||
fun build() = also {
|
||||
mProgressCallback?.let { callback -> GlobalAppContext.post { callback.onBuild(this) } }
|
||||
mAppConfig.icon?.let { callable ->
|
||||
mProjectConfig.iconBitmapGetter?.let { callable ->
|
||||
runCatching {
|
||||
val tableBlock = TableBlock.load(mResourcesArscFile)
|
||||
val packageName = "${GlobalAppContext.get().packageName}.inrt"
|
||||
@@ -264,17 +281,17 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File
|
||||
|
||||
val signer = ApkSigner(outApkFile, tmpOutputApk)
|
||||
signer.useDefaultSignatureVersion = false
|
||||
signer.v1SigningEnabled = mAppConfig.signatureSchemes.contains("V1")
|
||||
signer.v2SigningEnabled = mAppConfig.signatureSchemes.contains("V2")
|
||||
signer.v3SigningEnabled = mAppConfig.signatureSchemes.contains("V3")
|
||||
signer.v4SigningEnabled = mAppConfig.signatureSchemes.contains("V4")
|
||||
signer.v1SigningEnabled = mProjectConfig.signatureSchemes.contains("V1")
|
||||
signer.v2SigningEnabled = mProjectConfig.signatureSchemes.contains("V2")
|
||||
signer.v3SigningEnabled = mProjectConfig.signatureSchemes.contains("V3")
|
||||
signer.v4SigningEnabled = mProjectConfig.signatureSchemes.contains("V4")
|
||||
|
||||
var keyStoreFile = defaultKeyStoreFile
|
||||
var password = "AutoJs6"
|
||||
var alias = "AutoJs6"
|
||||
var aliasPassword = "AutoJs6"
|
||||
|
||||
mAppConfig.keyStore?.let {
|
||||
mProjectConfig.keyStore?.let {
|
||||
keyStoreFile = File(it.absolutePath)
|
||||
password = AESUtils.decrypt(it.password)
|
||||
alias = it.alias
|
||||
@@ -324,76 +341,14 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File
|
||||
|
||||
}
|
||||
|
||||
class AppConfig {
|
||||
|
||||
var appName: String? = null
|
||||
private set
|
||||
var versionName: String? = null
|
||||
private set
|
||||
var versionCode = 0
|
||||
private set
|
||||
var sourcePath: String? = null
|
||||
private set
|
||||
var packageName: String? = null
|
||||
private set
|
||||
var ignoredDirs = ArrayList<File>()
|
||||
var icon: Callable<Bitmap>? = null
|
||||
private set
|
||||
var abis: List<String> = emptyList()
|
||||
private set
|
||||
var libs: List<String> = emptyList()
|
||||
private set
|
||||
var keyStore: KeyStore? = null
|
||||
private set
|
||||
var signatureSchemes: String = "V1 + V2"
|
||||
private set
|
||||
var permissions: List<String> = emptyList()
|
||||
private set
|
||||
|
||||
fun ignoreDir(dir: File) = also { ignoredDirs.add(dir) }
|
||||
|
||||
fun setAppName(appName: String?) = also { appName?.let { this.appName = it } }
|
||||
|
||||
fun setVersionName(versionName: String?) = also { versionName?.let { this.versionName = it } }
|
||||
|
||||
fun setVersionCode(versionCode: Int?) = also { versionCode?.let { this.versionCode = it } }
|
||||
|
||||
fun setSourcePath(sourcePath: String?) = also { sourcePath?.let { this.sourcePath = it } }
|
||||
|
||||
fun setPackageName(packageName: String?) = also { packageName?.let { this.packageName = it } }
|
||||
|
||||
fun setIcon(icon: Callable<Bitmap>?) = also { icon?.let { this.icon = it } }
|
||||
|
||||
fun setIcon(iconPath: String?) = also { iconPath?.let { this.icon = Callable { BitmapFactory.decodeFile(it) } } }
|
||||
|
||||
fun setAbis(abis: List<String>) = also { this.abis = abis }
|
||||
|
||||
fun setLibs(libs: List<String>) = also { this.libs = libs }
|
||||
|
||||
fun setKeyStore(keyStore: KeyStore?) = also { this.keyStore = keyStore }
|
||||
|
||||
fun setSignatureSchemes(signatureSchemes: String) = also { this.signatureSchemes = signatureSchemes }
|
||||
|
||||
fun setPermissions(permissions: List<String>) = also { this.permissions = permissions }
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun fromProjectConfig(projectDir: String?, projectConfig: ProjectConfig) = AppConfig()
|
||||
.setAppName(projectConfig.name)
|
||||
.setPackageName(projectConfig.packageName)
|
||||
.ignoreDir(File(projectDir, projectConfig.buildDir))
|
||||
.setVersionCode(projectConfig.versionCode)
|
||||
.setVersionName(projectConfig.versionName)
|
||||
.setSourcePath(projectDir)
|
||||
.setIcon(projectConfig.icon?.let { File(projectDir, it).path })
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ManifestEditorWithAuthorities(manifestInputStream: InputStream?) : ManifestEditor(manifestInputStream) {
|
||||
override fun onAttr(attr: AxmlWriter.Attr) {
|
||||
attr.apply {
|
||||
if (!mProjectConfig.launchConfig.isSplashVisible && mSplashThemeId != 0 && value == mSplashThemeId) {
|
||||
value = mNoSplashThemeId
|
||||
}
|
||||
if (name.data == "authorities" && value is StringItem) {
|
||||
(value as StringItem).data = "${mAppConfig.packageName}.fileprovider"
|
||||
(value as StringItem).data = "${mProjectConfig.packageName}.fileprovider"
|
||||
} else {
|
||||
super.onAttr(this)
|
||||
}
|
||||
@@ -401,11 +356,11 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File
|
||||
}
|
||||
|
||||
override fun isPermissionRequired(permissionName: String): Boolean {
|
||||
return mAppConfig.permissions.contains(permissionName)
|
||||
return mProjectConfig.permissions.contains(permissionName)
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyLibrariesByConfig(config: AppConfig) {
|
||||
private fun copyLibrariesByConfig(config: ProjectConfig) {
|
||||
|
||||
// @Hint by SuperMonster003 on Dec 11, 2023.
|
||||
// ! The list contains only abi names not matching the canonical name itself.
|
||||
@@ -461,6 +416,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File
|
||||
|
||||
}
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
enum class Libs(
|
||||
@JvmField val label: String,
|
||||
@JvmField val aliases: List<String> = emptyList(),
|
||||
|
||||
@@ -10,10 +10,11 @@ import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import org.autojs.autojs.inrt.autojs.AutoJs
|
||||
import org.autojs.autojs.inrt.launch.GlobalProjectLauncher
|
||||
import org.autojs.autojs.project.ProjectConfig
|
||||
import org.autojs.autojs.ui.splash.SplashActivity.Companion.INIT_TIMEOUT
|
||||
import org.autojs.autojs6.R
|
||||
import org.autojs.autojs6.databinding.ActivitySplashInrtBinding
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
@@ -24,14 +25,29 @@ import kotlin.concurrent.thread
|
||||
class SplashActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setContentView(R.layout.activity_splash_inrt)
|
||||
val binding = ActivitySplashInrtBinding.inflate(layoutInflater)
|
||||
binding.slug.typeface = Typeface.createFromAsset(assets, "roboto_medium.ttf")
|
||||
val binding = ActivitySplashInrtBinding.inflate(layoutInflater).apply {
|
||||
setContentView(root)
|
||||
}
|
||||
val handler = Handler(Looper.myLooper()!!)
|
||||
val projectConfig = ProjectConfig.fromAssets(this, ProjectConfig.configFileOfDir("project"))
|
||||
var timeout = INIT_TIMEOUT
|
||||
|
||||
if (!projectConfig.launchConfig.isSplashVisible) {
|
||||
timeout = 0L
|
||||
} else {
|
||||
handler.post {
|
||||
binding.slug.typeface = Typeface.createFromAsset(assets, "roboto_medium.ttf")
|
||||
binding.slug.isVisible = true
|
||||
binding.icon.isVisible = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!Pref.isFirstUsing) {
|
||||
main()
|
||||
} else {
|
||||
Handler(Looper.myLooper()!!).postDelayed({ this@SplashActivity.main() }, INIT_TIMEOUT)
|
||||
handler.postDelayed({ this@SplashActivity.main() }, timeout)
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ open class AssetsProjectLauncher(private val mAssetsProjectDir: String, private
|
||||
|
||||
fun launch(activity: Activity) {
|
||||
// 如果需要隐藏日志界面, 则直接运行脚本
|
||||
if (mProjectConfig.launchConfig.shouldHideLogs() || Pref.shouldHideLogs()) {
|
||||
if (!mProjectConfig.launchConfig.isLogsVisible || Pref.shouldHideLogs()) {
|
||||
runScript(activity)
|
||||
} else {
|
||||
// 如果不隐藏日志界面
|
||||
|
||||
@@ -6,13 +6,13 @@ import java.util.zip.CRC32;
|
||||
|
||||
public class BuildInfo {
|
||||
|
||||
@SerializedName("build_time")
|
||||
@SerializedName(value = "buildTime", alternate = {"build_time"})
|
||||
private long mBuildTime;
|
||||
|
||||
@SerializedName("build_id")
|
||||
@SerializedName(value = "buildId", alternate = {"build_id"})
|
||||
private String mBuildId;
|
||||
|
||||
@SerializedName("build_number")
|
||||
@SerializedName(value = "buildNumber", alternate = {"build_number"})
|
||||
private long mBuildNumber;
|
||||
|
||||
public long getBuildNumber() {
|
||||
|
||||
@@ -1,21 +1,57 @@
|
||||
package org.autojs.autojs.project;
|
||||
package org.autojs.autojs.project
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import org.autojs.autojs.annotation.SerializedNameCompatible
|
||||
import org.autojs.autojs.annotation.SerializedNameCompatible.With
|
||||
import org.autojs.autojs.app.GlobalAppContext
|
||||
import org.autojs.autojs6.R
|
||||
|
||||
/**
|
||||
* Created by Stardust on Jan 25, 2018.
|
||||
* Modified by SuperMonster003 as of Jan 15, 2025.
|
||||
* Created by SuperMonster003 on Jan 15, 2025.
|
||||
*/
|
||||
public class LaunchConfig {
|
||||
class LaunchConfig {
|
||||
|
||||
@SerializedName("hideLogs")
|
||||
private boolean mHideLogs = false;
|
||||
@Transient
|
||||
private val mContext = GlobalAppContext.get()
|
||||
|
||||
public boolean shouldHideLogs() {
|
||||
return mHideLogs;
|
||||
}
|
||||
@SerializedName("logsVisible")
|
||||
@field:SerializedNameCompatible(
|
||||
With(value = "showLogs"),
|
||||
With(value = "hideLogs", target = ["AutoJs4", "AutoX"], isReversed = true),
|
||||
With(value = "displayLogs"),
|
||||
)
|
||||
var isLogsVisible = true
|
||||
|
||||
public void setHideLogs(boolean hideLogs) {
|
||||
mHideLogs = hideLogs;
|
||||
}
|
||||
@SerializedName("splashVisible")
|
||||
@field:SerializedNameCompatible(
|
||||
With(value = "showSplash"),
|
||||
With(value = "hideSplash", isReversed = true),
|
||||
With(value = "displaySplash", target = ["AutoX"]),
|
||||
)
|
||||
var isSplashVisible = true
|
||||
|
||||
@SerializedName("launcherVisible")
|
||||
@field:SerializedNameCompatible(
|
||||
With(value = "showLauncher"),
|
||||
With(value = "hideLauncher", target = ["AutoX"], isReversed = true),
|
||||
With(value = "displayLauncher"),
|
||||
)
|
||||
var isLauncherVisible = true
|
||||
|
||||
@SerializedName("slug")
|
||||
@field:SerializedNameCompatible(
|
||||
With(value = "slugText"),
|
||||
With(value = "splashText", target = ["AutoX"]),
|
||||
)
|
||||
var slug = mContext.getString(R.string.text_powered_by_autojs)
|
||||
|
||||
@SerializedName("permissions")
|
||||
@field:SerializedNameCompatible(
|
||||
With(value = "permission"),
|
||||
With(value = "permissionList"),
|
||||
)
|
||||
var permissions = emptyList<String>()
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package org.autojs.autojs.project;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.text.TextUtils;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.autojs.autojs.apkbuilder.keystore.KeyStore;
|
||||
import org.autojs.autojs.model.explorer.ExplorerPage;
|
||||
import org.autojs.autojs.pio.PFiles;
|
||||
import org.autojs.autojs.util.JsonUtils;
|
||||
@@ -20,6 +23,7 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -30,7 +34,9 @@ public class ProjectConfig {
|
||||
|
||||
public static final String CONFIG_FILE_NAME = "project.json";
|
||||
|
||||
private static final Gson sGson = new GsonBuilder().setPrettyPrinting().create();
|
||||
private static final Gson sGson = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
|
||||
@SerializedName("name")
|
||||
private String mName;
|
||||
@@ -52,13 +58,15 @@ public class ProjectConfig {
|
||||
private List<String> mAssets = new ArrayList<>();
|
||||
|
||||
@SerializedName("launchConfig")
|
||||
private LaunchConfig mLaunchConfig;
|
||||
private LaunchConfig mLaunchConfig = new LaunchConfig();
|
||||
|
||||
@SerializedName("build")
|
||||
private BuildInfo mBuildInfo = new BuildInfo();
|
||||
|
||||
@SerializedName("icon")
|
||||
private String mIcon;
|
||||
private String mIconPath;
|
||||
|
||||
private transient Callable<Bitmap> mIconBitmapGetter;
|
||||
|
||||
@Nullable
|
||||
@SerializedName(value = "abis", alternate = {"abi", "abiList"})
|
||||
@@ -68,12 +76,27 @@ public class ProjectConfig {
|
||||
@SerializedName(value = "libs", alternate = {"lib", "libList"})
|
||||
private List<String> mLibs = new ArrayList<>();
|
||||
|
||||
@SerializedName("permissions")
|
||||
private List<String> mPermissions = new ArrayList<>();
|
||||
|
||||
@SerializedName("signatureSchemes")
|
||||
private String mSignatureSchemes = "V1 + V2";
|
||||
|
||||
@Nullable
|
||||
private transient KeyStore mKeyStore = null;
|
||||
|
||||
@SerializedName("scripts")
|
||||
private final Map<String, ScriptConfig> mScriptConfigs = new HashMap<>();
|
||||
|
||||
@SerializedName(value = "useFeatures", alternate = {"useFeature", "useFeatureList"})
|
||||
private List<String> mFeatures = new ArrayList<>();
|
||||
|
||||
@SerializedName("ignoredDirs")
|
||||
private final List<File> mIgnoredDirs = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private transient String mSourcePath = null;
|
||||
|
||||
public static ProjectConfig fromJson(String json) {
|
||||
if (json == null) {
|
||||
return null;
|
||||
@@ -117,7 +140,7 @@ public class ProjectConfig {
|
||||
return fromJson(fileContents);
|
||||
} catch (Exception e1) {
|
||||
if (fileContents == null) return null;
|
||||
try {
|
||||
try {
|
||||
return fromJson(JsonUtils.repairJson(fileContents));
|
||||
} catch (Exception e2) {
|
||||
return tryReadCrucialData(fileContents, path);
|
||||
@@ -126,10 +149,9 @@ public class ProjectConfig {
|
||||
}
|
||||
|
||||
private static ProjectConfig tryReadCrucialData(String s, String jsonFilePath) {
|
||||
ProjectConfig config = new ProjectConfig();
|
||||
BuildInfo buildInfo = new BuildInfo();
|
||||
ScriptConfig scriptConfig = new ScriptConfig();
|
||||
ProjectConfig projectConfig = new ProjectConfig();
|
||||
LaunchConfig launchConfig = new LaunchConfig();
|
||||
BuildInfo buildInfo = new BuildInfo();
|
||||
|
||||
Pattern namePattern = Pattern.compile(stringPattern("name"));
|
||||
Pattern versionNamePattern = Pattern.compile(stringPattern("versionName"));
|
||||
@@ -147,40 +169,47 @@ public class ProjectConfig {
|
||||
Pattern buildNumberPattern = Pattern.compile(numberPattern("buildNumber"));
|
||||
Pattern buildIdPattern = Pattern.compile(stringPattern("buildId"));
|
||||
|
||||
Pattern launchConfigPattern = Pattern.compile(booleanPattern("hideLogs"));
|
||||
Pattern launchConfigHideLogsPattern = Pattern.compile(booleanPattern("hideLogs"));
|
||||
Pattern launchConfigLogsVisiblePattern = Pattern.compile(booleanPattern("logsVisible"));
|
||||
|
||||
Pattern scriptsUiModePattern = Pattern.compile(booleanPattern("uiMode"));
|
||||
Pattern launchConfigDisplaySplashPattern = Pattern.compile(booleanPattern("displaySplash"));
|
||||
Pattern launchConfigSplashVisiblePattern = Pattern.compile(booleanPattern("splashVisible"));
|
||||
|
||||
setFieldIfMatches(namePattern, s, config::setName);
|
||||
setFieldIfMatches(versionNamePattern, s, config::setVersionName);
|
||||
setFieldForIntIfMatches(versionCodePattern, s, config::setVersionCode);
|
||||
setFieldIfMatches(packageNamePattern, s, config::setPackageName);
|
||||
setFieldIfMatches(mainPattern, s, config::setMainScriptFile);
|
||||
setFieldIfMatches(iconPattern, s, config::setIcon);
|
||||
setFieldIfMatches(namePattern, s, projectConfig::setName);
|
||||
setFieldIfMatches(versionNamePattern, s, projectConfig::setVersionName);
|
||||
setFieldForIntIfMatches(versionCodePattern, s, projectConfig::setVersionCode);
|
||||
setFieldIfMatches(packageNamePattern, s, projectConfig::setPackageName);
|
||||
setFieldIfMatches(mainPattern, s, projectConfig::setMainScriptFile);
|
||||
setFieldIfMatches(iconPattern, s, projectConfig::setIconPath);
|
||||
|
||||
setListIfMatches(assetsPattern, s, config::setAssets);
|
||||
setListIfMatches(abisPattern, s, config::setAbis);
|
||||
setListIfMatches(libsPattern, s, config::setLibs);
|
||||
setListIfMatches(useFeaturesPattern, s, config::setFeatures);
|
||||
setListIfMatches(assetsPattern, s, projectConfig::setAssets);
|
||||
setListIfMatches(abisPattern, s, projectConfig::setAbis);
|
||||
setListIfMatches(libsPattern, s, projectConfig::setLibs);
|
||||
setListIfMatches(useFeaturesPattern, s, projectConfig::setFeatures);
|
||||
|
||||
setFieldForIntIfMatches(buildTimePattern, s, buildInfo::setBuildTime);
|
||||
setFieldForIntIfMatches(buildNumberPattern, s, buildInfo::setBuildNumber);
|
||||
setFieldIfMatches(buildIdPattern, s, buildInfo::setBuildId);
|
||||
|
||||
setFieldForBooleanIfMatches(launchConfigPattern, s, launchConfig::setHideLogs);
|
||||
setFieldForBooleanIfMatches(launchConfigHideLogsPattern, s, value -> launchConfig.setLogsVisible(!value));
|
||||
setFieldForBooleanIfMatches(launchConfigLogsVisiblePattern, s, launchConfig::setLogsVisible); /* 优先. */
|
||||
|
||||
setFieldForBooleanIfMatches(scriptsUiModePattern, s, scriptConfig::setUiMode);
|
||||
setFieldForBooleanIfMatches(launchConfigDisplaySplashPattern, s, launchConfig::setSplashVisible);
|
||||
setFieldForBooleanIfMatches(launchConfigSplashVisiblePattern, s, launchConfig::setSplashVisible); /* 优先. */
|
||||
|
||||
if (config.getName() == null || config.getName().isBlank()) {
|
||||
if (projectConfig.getName() == null || projectConfig.getName().isBlank()) {
|
||||
if (jsonFilePath.endsWith(CONFIG_FILE_NAME)) {
|
||||
File parentFile = new File(jsonFilePath).getParentFile();
|
||||
if (parentFile != null) {
|
||||
config.setName(parentFile.getName());
|
||||
projectConfig.setName(parentFile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
projectConfig.setBuildInfo(buildInfo);
|
||||
projectConfig.setLaunchConfig(launchConfig);
|
||||
|
||||
return projectConfig;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -350,13 +379,10 @@ public class ProjectConfig {
|
||||
}
|
||||
|
||||
public LaunchConfig getLaunchConfig() {
|
||||
if (mLaunchConfig == null) {
|
||||
mLaunchConfig = new LaunchConfig();
|
||||
}
|
||||
return mLaunchConfig;
|
||||
}
|
||||
|
||||
public void setLaunchConfig(LaunchConfig launchConfig) {
|
||||
public void setLaunchConfig(@NonNull LaunchConfig launchConfig) {
|
||||
mLaunchConfig = launchConfig;
|
||||
}
|
||||
|
||||
@@ -364,12 +390,23 @@ public class ProjectConfig {
|
||||
return sGson.toJson(this);
|
||||
}
|
||||
|
||||
public String getIcon() {
|
||||
return mIcon;
|
||||
public String getIconPath() {
|
||||
return mIconPath;
|
||||
}
|
||||
|
||||
public void setIcon(String icon) {
|
||||
mIcon = icon;
|
||||
public ProjectConfig setIconPath(String iconPath) {
|
||||
mIconPath = iconPath;
|
||||
mIconBitmapGetter = () -> BitmapFactory.decodeFile(iconPath);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Callable<Bitmap> getIconBitmapGetter() {
|
||||
return mIconBitmapGetter;
|
||||
}
|
||||
|
||||
public ProjectConfig setIconGetter(@Nullable Callable<Bitmap> getter) {
|
||||
mIconBitmapGetter = getter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> getAbis() {
|
||||
@@ -379,8 +416,9 @@ public class ProjectConfig {
|
||||
return mAbis;
|
||||
}
|
||||
|
||||
public void setAbis(@Nullable List<String> abis) {
|
||||
public ProjectConfig setAbis(@Nullable List<String> abis) {
|
||||
mAbis = abis;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> getLibs() {
|
||||
@@ -390,8 +428,9 @@ public class ProjectConfig {
|
||||
return mLibs;
|
||||
}
|
||||
|
||||
public void setLibs(@Nullable List<String> libs) {
|
||||
public ProjectConfig setLibs(@Nullable List<String> libs) {
|
||||
mLibs = libs;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getBuildDir() {
|
||||
@@ -427,4 +466,51 @@ public class ProjectConfig {
|
||||
config.setFeatures(features);
|
||||
return config;
|
||||
}
|
||||
|
||||
public List<File> getIgnoredDirs() {
|
||||
return mIgnoredDirs;
|
||||
}
|
||||
|
||||
public ProjectConfig ignoredDir(File ignoredDir) {
|
||||
mIgnoredDirs.add(ignoredDir);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getSourcePath() {
|
||||
return mSourcePath;
|
||||
}
|
||||
|
||||
public ProjectConfig setSourcePath(@Nullable String sourcePath) {
|
||||
mSourcePath = sourcePath;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> getPermissions() {
|
||||
return mPermissions;
|
||||
}
|
||||
|
||||
public ProjectConfig setPermissions(List<String> permissions) {
|
||||
mPermissions = permissions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getSignatureSchemes() {
|
||||
return mSignatureSchemes;
|
||||
}
|
||||
|
||||
public ProjectConfig setSignatureSchemes(String signatureSchemes) {
|
||||
mSignatureSchemes = signatureSchemes;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public KeyStore getKeyStore() {
|
||||
return mKeyStore;
|
||||
}
|
||||
|
||||
public ProjectConfig setKeyStore(@Nullable KeyStore keyStore) {
|
||||
mKeyStore = keyStore;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,14 @@ package org.autojs.autojs.project
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class ScriptConfig(
|
||||
@SerializedName("useFeatures") var features: List<String>,
|
||||
@SerializedName("uiMode") var uiMode: Boolean
|
||||
data class ScriptConfig @JvmOverloads constructor(
|
||||
@SerializedName("useFeatures") var features: List<String> = emptyList(),
|
||||
) {
|
||||
constructor() : this(emptyList(), false)
|
||||
|
||||
fun hasFeature(feature: String): Boolean {
|
||||
return features.contains(feature)
|
||||
}
|
||||
fun hasFeature(feature: String) = features.contains(feature)
|
||||
|
||||
companion object {
|
||||
const val FEATURE_CONTINUATION = "continuation"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -160,18 +160,18 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
put("moe.shizuku.manager.permission.API_V23", R.string.text_permission_shizuku);
|
||||
}};
|
||||
|
||||
EditText mSourcePath;
|
||||
View mSourcePathContainer;
|
||||
EditText mOutputPath;
|
||||
EditText mAppName;
|
||||
EditText mPackageName;
|
||||
TextInputLayout mPackageNameParent;
|
||||
EditText mVersionName;
|
||||
TextInputLayout mVersionNameParent;
|
||||
EditText mVersionCode;
|
||||
TextInputLayout mVersionCodeParent;
|
||||
ImageView mIcon;
|
||||
LinearLayout mAppConfig;
|
||||
EditText mSourcePathView;
|
||||
View mSourcePathContainerView;
|
||||
EditText mOutputPathView;
|
||||
EditText mAppNameView;
|
||||
EditText mPackageNameView;
|
||||
TextInputLayout mPackageNameParentView;
|
||||
EditText mVersionNameView;
|
||||
TextInputLayout mVersionNameParentView;
|
||||
EditText mVersionCodeView;
|
||||
TextInputLayout mVersionCodeParentView;
|
||||
ImageView mIconView;
|
||||
LinearLayout mAppConfigView;
|
||||
|
||||
private ProjectConfig mProjectConfig;
|
||||
private MaterialDialog mProgressDialog;
|
||||
@@ -209,24 +209,24 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
ActivityBuildBinding binding = ActivityBuildBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
mSourcePath = binding.sourcePath;
|
||||
mSourcePath.setOnKeyListener((v, keyCode, event) -> {
|
||||
mSourcePathView = binding.sourcePath;
|
||||
mSourcePathView.setOnKeyListener((v, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||
if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||
mOutputPath.requestFocus();
|
||||
mOutputPathView.requestFocus();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
mSourcePathContainer = binding.sourcePathContainer;
|
||||
mSourcePathContainerView = binding.sourcePathContainer;
|
||||
|
||||
mOutputPath = binding.outputPath;
|
||||
mOutputPath.setOnKeyListener((v, keyCode, event) -> {
|
||||
mOutputPathView = binding.outputPath;
|
||||
mOutputPathView.setOnKeyListener((v, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||
if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||
TextView nextField = (TextView) mOutputPath.focusSearch(View.FOCUS_DOWN);
|
||||
TextView nextField = (TextView) mOutputPathView.focusSearch(View.FOCUS_DOWN);
|
||||
if (nextField != null) {
|
||||
nextField.requestFocus();
|
||||
}
|
||||
@@ -236,30 +236,30 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
return false;
|
||||
});
|
||||
|
||||
mAppName = binding.appName;
|
||||
mAppNameView = binding.appName;
|
||||
|
||||
mPackageName = binding.packageName;
|
||||
mPackageName.setOnKeyListener((v, keyCode, event) -> {
|
||||
mPackageNameView = binding.packageName;
|
||||
mPackageNameView.setOnKeyListener((v, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||
if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||
mVersionName.requestFocus();
|
||||
mVersionNameView.requestFocus();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
mPackageNameParent = binding.packageNameParent;
|
||||
mPackageNameParentView = binding.packageNameParent;
|
||||
|
||||
mVersionName = binding.versionName;
|
||||
mVersionNameParent = binding.versionNameParent;
|
||||
mVersionCode = binding.versionCode;
|
||||
mVersionCodeParent = binding.versionCodeParent;
|
||||
mVersionNameView = binding.versionName;
|
||||
mVersionNameParentView = binding.versionNameParent;
|
||||
mVersionCodeView = binding.versionCode;
|
||||
mVersionCodeParentView = binding.versionCodeParent;
|
||||
|
||||
mIcon = binding.appIcon;
|
||||
mIcon.setVisibility(View.INVISIBLE);
|
||||
mIcon.setOnClickListener(v -> selectIcon());
|
||||
mIconView = binding.appIcon;
|
||||
mIconView.setVisibility(View.INVISIBLE);
|
||||
mIconView.setOnClickListener(v -> selectIcon());
|
||||
|
||||
mAppConfig = binding.appConfig;
|
||||
mAppConfigView = binding.appConfig;
|
||||
|
||||
mFlexboxAbis = binding.flexboxAbis;
|
||||
initAbisChildren();
|
||||
@@ -515,8 +515,8 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
if (dir != null && dir.startsWith(getFilesDir().getPath())) {
|
||||
dir = WorkingDirectoryUtils.getPath();
|
||||
}
|
||||
mOutputPath.setText(dir);
|
||||
mAppName.setText(file.getSimplifiedName());
|
||||
mOutputPathView.setText(dir);
|
||||
mAppNameView.setText(file.getSimplifiedName());
|
||||
|
||||
Observable.fromCallable(() -> {
|
||||
String packageNameSuffix = generatePackageNameSuffix(file);
|
||||
@@ -525,34 +525,34 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(packageName -> {
|
||||
mPackageName.setText(packageName);
|
||||
mPackageNameParent.setHint(R.string.text_package_name);
|
||||
mPackageNameView.setText(packageName);
|
||||
mPackageNameParentView.setHint(R.string.text_package_name);
|
||||
|
||||
SimpleVersionInfo nextVersionInfo = AppUtils.generateNextVersionInfo(packageName);
|
||||
if (nextVersionInfo != null) {
|
||||
mVersionName.setText(nextVersionInfo.versionName);
|
||||
mVersionCode.setText(nextVersionInfo.versionCodeString);
|
||||
mVersionNameView.setText(nextVersionInfo.versionName);
|
||||
mVersionCodeView.setText(nextVersionInfo.versionCodeString);
|
||||
} else {
|
||||
mVersionName.setText(R.string.default_build_apk_version_name);
|
||||
mVersionCode.setText(R.string.default_build_apk_version_code);
|
||||
mVersionNameView.setText(R.string.default_build_apk_version_name);
|
||||
mVersionCodeView.setText(R.string.default_build_apk_version_code);
|
||||
}
|
||||
mVersionNameParent.setHint(R.string.text_version_name);
|
||||
mVersionCodeParent.setHint(R.string.text_version_code);
|
||||
mVersionNameParentView.setHint(R.string.text_version_name);
|
||||
mVersionCodeParentView.setHint(R.string.text_version_code);
|
||||
|
||||
Drawable iconDrawable = AppUtils.getInstalledAppIcon(packageName);
|
||||
if (iconDrawable != null) {
|
||||
mIcon.setImageDrawable(iconDrawable);
|
||||
mIconView.setImageDrawable(iconDrawable);
|
||||
mIsDefaultIcon = false;
|
||||
}
|
||||
mIcon.setVisibility(View.VISIBLE);
|
||||
mIconView.setVisibility(View.VISIBLE);
|
||||
}, throwable -> {
|
||||
mPackageName.setText(getString(R.string.format_default_package_name, file.getSimplifiedName().toLowerCase(Language.getPrefLanguage().getLocale())));
|
||||
mVersionName.setText(R.string.default_build_apk_version_name);
|
||||
mVersionCode.setText(R.string.default_build_apk_version_code);
|
||||
mPackageNameParent.setHint(R.string.text_package_name);
|
||||
mVersionNameParent.setHint(R.string.text_version_name);
|
||||
mVersionCodeParent.setHint(R.string.text_version_code);
|
||||
mIcon.setVisibility(View.VISIBLE);
|
||||
mPackageNameView.setText(getString(R.string.format_default_package_name, file.getSimplifiedName().toLowerCase(Language.getPrefLanguage().getLocale())));
|
||||
mVersionNameView.setText(R.string.default_build_apk_version_name);
|
||||
mVersionCodeView.setText(R.string.default_build_apk_version_code);
|
||||
mPackageNameParentView.setHint(R.string.text_package_name);
|
||||
mVersionNameParentView.setHint(R.string.text_version_name);
|
||||
mVersionCodeParentView.setHint(R.string.text_version_code);
|
||||
mIconView.setVisibility(View.VISIBLE);
|
||||
});
|
||||
|
||||
setSource(file);
|
||||
@@ -579,7 +579,7 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
}
|
||||
|
||||
void selectSourceFilePath() {
|
||||
String initialDir = new File(mSourcePath.getText().toString()).getParent();
|
||||
String initialDir = new File(mSourcePathView.getText().toString()).getParent();
|
||||
new FileChooserDialogBuilder(this)
|
||||
.title(R.string.text_source_file_path)
|
||||
.dir(EnvironmentUtils.getExternalStoragePath(),
|
||||
@@ -590,7 +590,7 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
|
||||
private void setSource(File file) {
|
||||
if (!file.isDirectory()) {
|
||||
mSourcePath.setText(file.getPath());
|
||||
mSourcePathView.setText(file.getPath());
|
||||
return;
|
||||
}
|
||||
mProjectConfig = ProjectConfig.fromProjectDir(file.getPath());
|
||||
@@ -598,20 +598,20 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
return;
|
||||
}
|
||||
mIsProjectLevelBuilding = true;
|
||||
mOutputPath.setText(new File(mSource, mProjectConfig.getBuildDir()).getPath());
|
||||
mAppConfig.setVisibility(View.GONE);
|
||||
mSourcePathContainer.setVisibility(View.GONE);
|
||||
mOutputPathView.setText(new File(mSource, mProjectConfig.getBuildDir()).getPath());
|
||||
mAppConfigView.setVisibility(View.GONE);
|
||||
mSourcePathContainerView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
void selectOutputDirPath() {
|
||||
String initialDir = new File(mOutputPath.getText().toString()).exists()
|
||||
? mOutputPath.getText().toString()
|
||||
String initialDir = new File(mOutputPathView.getText().toString()).exists()
|
||||
? mOutputPathView.getText().toString()
|
||||
: WorkingDirectoryUtils.getPath();
|
||||
new FileChooserDialogBuilder(this)
|
||||
.title(R.string.text_output_apk_path)
|
||||
.dir(initialDir)
|
||||
.chooseDir()
|
||||
.singleChoice(dir -> mOutputPath.setText(dir.getPath()))
|
||||
.singleChoice(dir -> mOutputPathView.setText(dir.getPath()))
|
||||
.show();
|
||||
}
|
||||
|
||||
@@ -633,14 +633,14 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
|
||||
private boolean checkInputs() {
|
||||
if (mIsProjectLevelBuilding) {
|
||||
return checkNotEmpty(mOutputPath);
|
||||
return checkNotEmpty(mOutputPathView);
|
||||
}
|
||||
return checkNotEmpty(mSourcePath)
|
||||
& checkNotEmpty(mOutputPath)
|
||||
& checkNotEmpty(mAppName)
|
||||
& checkNotEmpty(mVersionCode)
|
||||
& checkNotEmpty(mVersionName)
|
||||
& checkPackageNameValid(mPackageName);
|
||||
return checkNotEmpty(mSourcePathView)
|
||||
& checkNotEmpty(mOutputPathView)
|
||||
& checkNotEmpty(mAppNameView)
|
||||
& checkNotEmpty(mVersionCodeView)
|
||||
& checkNotEmpty(mVersionNameView)
|
||||
& checkPackageNameValid(mPackageNameView);
|
||||
}
|
||||
|
||||
private boolean checkAbis() {
|
||||
@@ -773,12 +773,12 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
@SuppressLint("CheckResult")
|
||||
private void doBuildingApk() {
|
||||
ApkBuilder.AppConfig appConfig = createAppConfig();
|
||||
ProjectConfig projectConfig = determineProjectConfig();
|
||||
File tmpDir = new File(getCacheDir(), "build/");
|
||||
File outApk = new File(mOutputPath.getText().toString(),
|
||||
String.format("%s_v%s.apk", appConfig.getAppName(), appConfig.getVersionName()));
|
||||
File outApk = new File(mOutputPathView.getText().toString(),
|
||||
String.format("%s_v%s.apk", projectConfig.getName(), projectConfig.getVersionName()));
|
||||
showProgressDialog();
|
||||
Observable.fromCallable(() -> callApkBuilder(tmpDir, outApk, appConfig))
|
||||
Observable.fromCallable(() -> callApkBuilder(tmpDir, outApk, projectConfig))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(apkBuilder -> {
|
||||
@@ -790,32 +790,33 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
}, this::onBuildFailed);
|
||||
}
|
||||
|
||||
private ApkBuilder.AppConfig createAppConfig() {
|
||||
private ProjectConfig determineProjectConfig() {
|
||||
ArrayList<String> abis = collectCheckedItems(mFlexboxAbis);
|
||||
ArrayList<String> libs = collectCheckedItems(mFlexboxLibs);
|
||||
ArrayList<String> permissions = collectCheckedItems(mFlexboxPermissions);
|
||||
|
||||
ApkBuilder.AppConfig appConfig = mProjectConfig != null
|
||||
? ApkBuilder.AppConfig.fromProjectConfig(mSource, mProjectConfig)
|
||||
: new ApkBuilder.AppConfig()
|
||||
.setAppName(mAppName.getText().toString())
|
||||
.setSourcePath(mSourcePath.getText().toString())
|
||||
.setPackageName(mPackageName.getText().toString())
|
||||
.setVersionName(mVersionName.getText().toString())
|
||||
.setVersionCode(Integer.parseInt(mVersionCode.getText().toString()))
|
||||
.setIcon(mIsDefaultIcon ? null : () -> BitmapUtils.drawableToBitmap(mIcon.getDrawable()));
|
||||
|
||||
appConfig.setAbis(abis);
|
||||
appConfig.setLibs(libs);
|
||||
appConfig.setSignatureSchemes(mSignatureSchemes.getSelectedItem().toString());
|
||||
if (mVerifiedKeyStores.getSelectedItemPosition() > 0) {
|
||||
appConfig.setKeyStore((KeyStore) mVerifiedKeyStores.getSelectedItem());
|
||||
ProjectConfig projectConfig;
|
||||
if (mProjectConfig != null) {
|
||||
projectConfig = mProjectConfig
|
||||
.ignoredDir(new File(mSource, mProjectConfig.getBuildDir()))
|
||||
.setSourcePath(mSource)
|
||||
.setIconPath(mProjectConfig.getIconPath() == null ? null : new File(mSource, mProjectConfig.getIconPath()).getPath());
|
||||
} else {
|
||||
appConfig.setKeyStore(null);
|
||||
projectConfig = new ProjectConfig()
|
||||
.setName(mAppNameView.getText().toString())
|
||||
.setSourcePath(mSourcePathView.getText().toString())
|
||||
.setPackageName(mPackageNameView.getText().toString())
|
||||
.setVersionName(mVersionNameView.getText().toString())
|
||||
.setVersionCode(Integer.parseInt(mVersionCodeView.getText().toString()))
|
||||
.setIconGetter(mIsDefaultIcon ? null : () -> BitmapUtils.drawableToBitmap(mIconView.getDrawable()));
|
||||
}
|
||||
appConfig.setPermissions(permissions);
|
||||
|
||||
return appConfig;
|
||||
return projectConfig
|
||||
.setAbis(abis)
|
||||
.setLibs(libs)
|
||||
.setKeyStore(mVerifiedKeyStores.getSelectedItemPosition() > 0 ? (KeyStore) mVerifiedKeyStores.getSelectedItem() : null)
|
||||
.setSignatureSchemes(mSignatureSchemes.getSelectedItem().toString())
|
||||
.setPermissions(permissions);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -843,12 +844,12 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
return libs;
|
||||
}
|
||||
|
||||
private ApkBuilder callApkBuilder(File tmpDir, File outApk, ApkBuilder.AppConfig appConfig) throws Exception {
|
||||
private ApkBuilder callApkBuilder(File tmpDir, File outApk, ProjectConfig projectConfig) throws Exception {
|
||||
InputStream templateApk = getAssets().open(TEMPLATE_APK_NAME);
|
||||
return new ApkBuilder(templateApk, outApk, tmpDir.getPath())
|
||||
.setProgressCallback(BuildActivity.this)
|
||||
.prepare()
|
||||
.withConfig(appConfig)
|
||||
.withConfig(projectConfig)
|
||||
.build()
|
||||
.sign()
|
||||
.cleanWorkspace();
|
||||
@@ -920,7 +921,7 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(drawable -> {
|
||||
mIcon.setImageDrawable(drawable);
|
||||
mIconView.setImageDrawable(drawable);
|
||||
mIsDefaultIcon = false;
|
||||
}, Throwable::printStackTrace);
|
||||
}
|
||||
|
||||
@@ -122,12 +122,12 @@ class ProjectConfigActivity : BaseActivity() {
|
||||
} else {
|
||||
mAppName.setText(config.name)
|
||||
setToolbarAsBack(config.name)
|
||||
mVersionCode.setText(config.versionCode.toString())
|
||||
mVersionCode.setText(config.versionCode.coerceAtLeast(0).toString())
|
||||
mPackageName.setText(config.packageName)
|
||||
mVersionName.setText(config.versionName)
|
||||
mMainFileName.setText(config.mainScriptFile)
|
||||
mProjectLocationWrapper.visibility = View.GONE
|
||||
config.icon?.let { icon ->
|
||||
config.iconPath?.let { icon ->
|
||||
File(mDirectory, icon).takeIf { it.exists() }?.let { iconFile ->
|
||||
Glide.with(this)
|
||||
.load(iconFile)
|
||||
@@ -259,7 +259,7 @@ class ProjectConfigActivity : BaseActivity() {
|
||||
private fun saveIcon(b: Bitmap): Observable<String> {
|
||||
return Observable.just(b)
|
||||
.map { bitmap: Bitmap ->
|
||||
var iconPath = mProjectConfig!!.icon
|
||||
var iconPath = mProjectConfig!!.iconPath
|
||||
if (iconPath == null) {
|
||||
iconPath = "res/logo.png"
|
||||
}
|
||||
@@ -272,7 +272,7 @@ class ProjectConfigActivity : BaseActivity() {
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnNext { iconPath: String? -> mProjectConfig!!.icon = iconPath }
|
||||
.doOnNext { iconPath: String? -> mProjectConfig!!.iconPath = iconPath }
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
||||
@@ -1,27 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="128dp"
|
||||
android:layout_gravity="center|bottom"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="128dp"
|
||||
android:layout_gravity="center|bottom"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@mipmap/ic_launcher" />
|
||||
android:id="@+id/icon"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@mipmap/ic_launcher" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/slug"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="@string/text_powered_by_autojs"
|
||||
android:textColor="@color/day_night_full"
|
||||
android:textSize="16sp" />
|
||||
android:id="@+id/slug"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="@string/text_powered_by_autojs"
|
||||
android:textColor="@color/day_night_full"
|
||||
android:textSize="16sp" />
|
||||
|
||||
</LinearLayout>
|
||||
Reference in New Issue
Block a user