fix DYNAMIC_RECEIVER error by fixing ManifestPatcher
Add automatic <uses-permission> entries for declared/custom permissions (eg. names ending with _PERMISSION or containing DYNAMIC_RECEIVER). Ensure MANAGE_EXTERNAL_STORAGE is added after READ_EXTERNAL_STORAGE when needed. Improve handling of permission/provider name replacements, targetSdk and application attribute injection (debuggable, legacy storage, embedded dex, extractNativeLibs) and add manager metadata entry. Also minor formatting and visitor restructuring.
This commit is contained in:
parent
3754456213
commit
5dde2de6c9
2 changed files with 382 additions and 158 deletions
|
|
@ -24,8 +24,8 @@ android {
|
|||
defaultConfig {
|
||||
minSdk = 28
|
||||
targetSdk = 36
|
||||
versionCode = 10_00_00
|
||||
versionName = "1.0.0"
|
||||
versionCode = 10_00_20
|
||||
versionName = "1.0.2"
|
||||
|
||||
vectorDrawables {
|
||||
useSupportLibrary = true
|
||||
|
|
|
|||
|
|
@ -43,181 +43,399 @@ object ManifestPatcher {
|
|||
val reader = AxmlReader(manifestBytes)
|
||||
val writer = AxmlWriter()
|
||||
|
||||
reader.accept(object : AxmlVisitor(writer) {
|
||||
override fun ns(prefix: String?, uri: String?, ln: Int) {
|
||||
val realUri = uri ?: ANDROID_NAMESPACE
|
||||
super.ns(prefix, realUri, ln)
|
||||
}
|
||||
reader.accept(
|
||||
object : AxmlVisitor(writer) {
|
||||
override fun ns(prefix: String?, uri: String?, ln: Int) {
|
||||
val realUri = uri ?: ANDROID_NAMESPACE
|
||||
super.ns(prefix, realUri, ln)
|
||||
}
|
||||
|
||||
override fun child(ns: String?, name: String?) =
|
||||
object : ReplaceAttrsVisitor(
|
||||
super.child(ns, name),
|
||||
buildMap {
|
||||
packageName?.let { put(PACKAGE, it) }
|
||||
compileSdkVersion?.let { put(COMPILE_SDK_VERSION, it) }
|
||||
compileSdkVersionCodename?.let { put(COMPILE_SDK_VERSION_CODENAME, it) }
|
||||
}
|
||||
) {
|
||||
private var shouldAddExternalStoragePerm = false
|
||||
|
||||
override fun child(ns: String?, name: String): NodeVisitor {
|
||||
val nv = super.child(ns, name)
|
||||
|
||||
// Add MANAGE_EXTERNAL_STORAGE when necessary
|
||||
if (shouldAddExternalStoragePerm && addManageExternalStorage == true) {
|
||||
super
|
||||
.child(null, "uses-permission")
|
||||
.attr(ANDROID_NAMESPACE, "name", android.R.attr.name, TYPE_STRING, Manifest.permission.MANAGE_EXTERNAL_STORAGE)
|
||||
shouldAddExternalStoragePerm = false
|
||||
}
|
||||
|
||||
return when (name) {
|
||||
"uses-permission" -> if (modifyPermissions != false) {
|
||||
object : NodeVisitor(nv) {
|
||||
override fun attr(ns: String?, name: String?, resourceId: Int, type: Int, value: Any?) {
|
||||
if (name != "maxSdkVersion") {
|
||||
super.attr(ns, name, resourceId, type, value)
|
||||
}
|
||||
|
||||
// Set the add external storage permission to be added after WRITE_EXTERNAL_STORAGE (which is after read)
|
||||
if (name == "name" && value == Manifest.permission.READ_EXTERNAL_STORAGE) {
|
||||
shouldAddExternalStoragePerm = true
|
||||
}
|
||||
}
|
||||
override fun child(ns: String?, name: String?) =
|
||||
object :
|
||||
ReplaceAttrsVisitor(
|
||||
super.child(ns, name),
|
||||
buildMap {
|
||||
packageName?.let { put(PACKAGE, it) }
|
||||
compileSdkVersion?.let {
|
||||
put(COMPILE_SDK_VERSION, it)
|
||||
}
|
||||
} else nv
|
||||
|
||||
"uses-sdk" -> if (targetSdkVersion != null) {
|
||||
object : NodeVisitor(nv) {
|
||||
override fun attr(ns: String?, name: String?, resourceId: Int, type: Int, value: Any?) {
|
||||
if (name == "targetSdkVersion") {
|
||||
super.attr(ns, name, resourceId, type, targetSdkVersion)
|
||||
} else {
|
||||
super.attr(ns, name, resourceId, type, value)
|
||||
}
|
||||
}
|
||||
compileSdkVersionCodename?.let {
|
||||
put(COMPILE_SDK_VERSION_CODENAME, it)
|
||||
}
|
||||
} else nv
|
||||
}
|
||||
) {
|
||||
private var shouldAddExternalStoragePerm = false
|
||||
private val shouldAddUsesForDeclaredPermissions = mutableListOf<String>()
|
||||
|
||||
"permission" -> if (modifyPermissions != false && packageName != null) {
|
||||
object : NodeVisitor(nv) {
|
||||
override fun attr(ns: String?, name: String, resourceId: Int, type: Int, value: Any?) {
|
||||
super.attr(
|
||||
ns, name, resourceId, type,
|
||||
when (name) {
|
||||
"name" -> (value as String).replace("com.discord", packageName)
|
||||
else -> value
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
} else nv
|
||||
override fun child(ns: String?, name: String): NodeVisitor {
|
||||
val nv = super.child(ns, name)
|
||||
|
||||
"application" -> object : ReplaceAttrsVisitor(
|
||||
nv,
|
||||
buildMap {
|
||||
appName?.let { put(LABEL, it) }
|
||||
debuggable?.let { put(DEBUGGABLE, it) }
|
||||
requestLegacyExternalStorage?.let { put(REQUEST_LEGACY_EXTERNAL_STORAGE, it) }
|
||||
vmSafeMode?.let { put(VM_SAFE_MODE, it) }
|
||||
useEmbeddedDex?.let { put(USE_EMBEDDED_DEX, it) }
|
||||
extractNativeLibs?.let { put(EXTRACT_NATIVE_LIBS, !it) } // Inverted since we set to false originally
|
||||
}
|
||||
// Add MANAGE_EXTERNAL_STORAGE when necessary
|
||||
if (shouldAddExternalStoragePerm &&
|
||||
addManageExternalStorage == true
|
||||
) {
|
||||
private var shouldAddDebuggable = debuggable ?: false
|
||||
private var shouldAddLegacyStorage = requestLegacyExternalStorage ?: false
|
||||
private var shouldAddUseEmbeddedDex = useEmbeddedDex ?: false
|
||||
private var shouldAddExtractNativeLibs = extractNativeLibs ?: false
|
||||
private var shouldAddMetadata = addManagerMetadata ?: false
|
||||
super.child(null, "uses-permission")
|
||||
.attr(
|
||||
ANDROID_NAMESPACE,
|
||||
"name",
|
||||
android.R.attr.name,
|
||||
TYPE_STRING,
|
||||
Manifest.permission.MANAGE_EXTERNAL_STORAGE
|
||||
)
|
||||
shouldAddExternalStoragePerm = false
|
||||
}
|
||||
|
||||
override fun attr(ns: String?, name: String, resourceId: Int, type: Int, value: Any?) {
|
||||
if (name == NETWORK_SECURITY_CONFIG) return
|
||||
if (name == REQUEST_LEGACY_EXTERNAL_STORAGE) shouldAddLegacyStorage = false
|
||||
if (name == USE_EMBEDDED_DEX) shouldAddUseEmbeddedDex = false
|
||||
if (name == EXTRACT_NATIVE_LIBS) shouldAddExtractNativeLibs = false
|
||||
if (name == DEBUGGABLE) shouldAddDebuggable = false
|
||||
super.attr(ns, name, resourceId, type, value)
|
||||
// If any declared permissions were detected that should also be
|
||||
// exposed as <uses-permission/>, add them here (keeps declaration + usage).
|
||||
if (shouldAddUsesForDeclaredPermissions.isNotEmpty()) {
|
||||
for (perm in shouldAddUsesForDeclaredPermissions) {
|
||||
super.child(null, "uses-permission")
|
||||
.attr(
|
||||
ANDROID_NAMESPACE,
|
||||
"name",
|
||||
android.R.attr.name,
|
||||
TYPE_STRING,
|
||||
perm
|
||||
)
|
||||
}
|
||||
shouldAddUsesForDeclaredPermissions.clear()
|
||||
}
|
||||
|
||||
override fun child(ns: String?, name: String): NodeVisitor {
|
||||
val visitor = super.child(ns, name)
|
||||
|
||||
if (shouldAddMetadata && addManagerMetadata == true) {
|
||||
shouldAddMetadata = false
|
||||
super.child(ANDROID_NAMESPACE, "meta-data").apply {
|
||||
attr(
|
||||
ANDROID_NAMESPACE,
|
||||
"name",
|
||||
android.R.attr.name,
|
||||
TYPE_STRING,
|
||||
"isShiggy" /* originally "isAliucord" */
|
||||
)
|
||||
attr(ANDROID_NAMESPACE, "value", android.R.attr.value, TYPE_INT_BOOLEAN, 1)
|
||||
}
|
||||
}
|
||||
|
||||
return when (name) {
|
||||
"activity" -> if (modifyActivities != false && appName != null) {
|
||||
ReplaceAttrsVisitor(visitor, mapOf("label" to appName))
|
||||
} else visitor
|
||||
|
||||
"provider" -> if (modifyProviders != false && packageName != null) {
|
||||
object : NodeVisitor(visitor) {
|
||||
override fun attr(ns: String?, name: String, resourceId: Int, type: Int, value: Any?) {
|
||||
return when (name) {
|
||||
"uses-permission" ->
|
||||
if (modifyPermissions != false) {
|
||||
object : NodeVisitor(nv) {
|
||||
override fun attr(
|
||||
ns: String?,
|
||||
name: String?,
|
||||
resourceId: Int,
|
||||
type: Int,
|
||||
value: Any?
|
||||
) {
|
||||
if (name != "maxSdkVersion") {
|
||||
super.attr(
|
||||
ns, name, resourceId, type,
|
||||
if (name == "authorities") {
|
||||
(value as String).replace("com.discord", packageName)
|
||||
} else {
|
||||
value
|
||||
}
|
||||
ns,
|
||||
name,
|
||||
resourceId,
|
||||
type,
|
||||
value
|
||||
)
|
||||
}
|
||||
|
||||
// Set the add external storage
|
||||
// permission to be added after
|
||||
// WRITE_EXTERNAL_STORAGE (which is
|
||||
// after read)
|
||||
if (name == "name" &&
|
||||
value ==
|
||||
Manifest.permission
|
||||
.READ_EXTERNAL_STORAGE
|
||||
) {
|
||||
shouldAddExternalStoragePerm = true
|
||||
}
|
||||
}
|
||||
}
|
||||
} else nv
|
||||
|
||||
"uses-sdk" ->
|
||||
if (targetSdkVersion != null) {
|
||||
object : NodeVisitor(nv) {
|
||||
override fun attr(
|
||||
ns: String?,
|
||||
name: String?,
|
||||
resourceId: Int,
|
||||
type: Int,
|
||||
value: Any?
|
||||
) {
|
||||
if (name == "targetSdkVersion") {
|
||||
super.attr(
|
||||
ns,
|
||||
name,
|
||||
resourceId,
|
||||
type,
|
||||
targetSdkVersion
|
||||
)
|
||||
} else {
|
||||
super.attr(
|
||||
ns,
|
||||
name,
|
||||
resourceId,
|
||||
type,
|
||||
value
|
||||
)
|
||||
}
|
||||
}
|
||||
} else visitor
|
||||
}
|
||||
} else nv
|
||||
|
||||
else -> visitor
|
||||
}
|
||||
}
|
||||
"permission" ->
|
||||
if (modifyPermissions != false &&
|
||||
packageName != null
|
||||
) {
|
||||
object : NodeVisitor(nv) {
|
||||
override fun attr(
|
||||
ns: String?,
|
||||
name: String,
|
||||
resourceId: Int,
|
||||
type: Int,
|
||||
value: Any?
|
||||
) {
|
||||
val newVal = when (name) {
|
||||
"name" ->
|
||||
(value as String)
|
||||
.replace(
|
||||
"com.discord",
|
||||
packageName
|
||||
)
|
||||
|
||||
override fun end() {
|
||||
if (shouldAddLegacyStorage && Build.VERSION.SDK_INT >= 29 && requestLegacyExternalStorage == true) {
|
||||
super.attr(
|
||||
ANDROID_NAMESPACE,
|
||||
REQUEST_LEGACY_EXTERNAL_STORAGE,
|
||||
android.R.attr.requestLegacyExternalStorage,
|
||||
TYPE_INT_BOOLEAN,
|
||||
1
|
||||
)
|
||||
}
|
||||
if (shouldAddDebuggable && debuggable == true) {
|
||||
super.attr(ANDROID_NAMESPACE, DEBUGGABLE, android.R.attr.debuggable, TYPE_INT_BOOLEAN, 1)
|
||||
else -> value
|
||||
}
|
||||
|
||||
super.attr(
|
||||
ns,
|
||||
name,
|
||||
resourceId,
|
||||
type,
|
||||
newVal
|
||||
)
|
||||
|
||||
// If this permission looks like a runtime/receiver permission
|
||||
// or is a custom declared permission, also add a corresponding
|
||||
// <uses-permission/> entry so other apps / the system can request it.
|
||||
if (name == "name" && newVal is String) {
|
||||
if (newVal.endsWith("_PERMISSION") || newVal.contains("DYNAMIC_RECEIVER")) {
|
||||
shouldAddUsesForDeclaredPermissions.add(newVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else nv
|
||||
|
||||
"application" ->
|
||||
object :
|
||||
ReplaceAttrsVisitor(
|
||||
nv,
|
||||
buildMap {
|
||||
appName?.let { put(LABEL, it) }
|
||||
debuggable?.let {
|
||||
put(DEBUGGABLE, it)
|
||||
}
|
||||
requestLegacyExternalStorage
|
||||
?.let {
|
||||
put(
|
||||
REQUEST_LEGACY_EXTERNAL_STORAGE,
|
||||
it
|
||||
)
|
||||
}
|
||||
vmSafeMode?.let {
|
||||
put(VM_SAFE_MODE, it)
|
||||
}
|
||||
useEmbeddedDex?.let {
|
||||
put(USE_EMBEDDED_DEX, it)
|
||||
}
|
||||
extractNativeLibs?.let {
|
||||
put(
|
||||
EXTRACT_NATIVE_LIBS,
|
||||
!it
|
||||
)
|
||||
} // Inverted since we set to
|
||||
// false originally
|
||||
}
|
||||
) {
|
||||
private var shouldAddDebuggable =
|
||||
debuggable ?: false
|
||||
private var shouldAddLegacyStorage =
|
||||
requestLegacyExternalStorage ?: false
|
||||
private var shouldAddUseEmbeddedDex =
|
||||
useEmbeddedDex ?: false
|
||||
private var shouldAddExtractNativeLibs =
|
||||
extractNativeLibs ?: false
|
||||
private var shouldAddMetadata =
|
||||
addManagerMetadata ?: false
|
||||
|
||||
override fun attr(
|
||||
ns: String?,
|
||||
name: String,
|
||||
resourceId: Int,
|
||||
type: Int,
|
||||
value: Any?
|
||||
) {
|
||||
if (name == NETWORK_SECURITY_CONFIG) return
|
||||
if (name == REQUEST_LEGACY_EXTERNAL_STORAGE)
|
||||
shouldAddLegacyStorage = false
|
||||
if (name == USE_EMBEDDED_DEX)
|
||||
shouldAddUseEmbeddedDex = false
|
||||
if (name == EXTRACT_NATIVE_LIBS)
|
||||
shouldAddExtractNativeLibs = false
|
||||
if (name == DEBUGGABLE)
|
||||
shouldAddDebuggable = false
|
||||
super.attr(
|
||||
ns,
|
||||
name,
|
||||
resourceId,
|
||||
type,
|
||||
value
|
||||
)
|
||||
}
|
||||
|
||||
override fun child(
|
||||
ns: String?,
|
||||
name: String
|
||||
): NodeVisitor {
|
||||
val visitor = super.child(ns, name)
|
||||
|
||||
if (shouldAddMetadata &&
|
||||
addManagerMetadata == true
|
||||
) {
|
||||
shouldAddMetadata = false
|
||||
super.child(
|
||||
ANDROID_NAMESPACE,
|
||||
"meta-data"
|
||||
)
|
||||
.apply {
|
||||
attr(
|
||||
ANDROID_NAMESPACE,
|
||||
"name",
|
||||
android.R.attr.name,
|
||||
TYPE_STRING,
|
||||
"isShiggy" /* originally "isAliucord" */
|
||||
)
|
||||
attr(
|
||||
ANDROID_NAMESPACE,
|
||||
"value",
|
||||
android.R
|
||||
.attr
|
||||
.value,
|
||||
TYPE_INT_BOOLEAN,
|
||||
1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return when (name) {
|
||||
"activity" ->
|
||||
if (modifyActivities != false &&
|
||||
appName != null
|
||||
) {
|
||||
ReplaceAttrsVisitor(
|
||||
visitor,
|
||||
mapOf(
|
||||
"label" to
|
||||
appName
|
||||
)
|
||||
)
|
||||
} else visitor
|
||||
|
||||
"provider" ->
|
||||
if (modifyProviders != false &&
|
||||
packageName !=
|
||||
null
|
||||
) {
|
||||
object :
|
||||
NodeVisitor(
|
||||
visitor
|
||||
) {
|
||||
override fun attr(
|
||||
ns: String?,
|
||||
name: String,
|
||||
resourceId: Int,
|
||||
type: Int,
|
||||
value: Any?
|
||||
) {
|
||||
super.attr(
|
||||
ns,
|
||||
name,
|
||||
resourceId,
|
||||
type,
|
||||
if (name ==
|
||||
"authorities"
|
||||
) {
|
||||
(value as
|
||||
String)
|
||||
.replace(
|
||||
"com.discord",
|
||||
packageName
|
||||
)
|
||||
} else {
|
||||
value
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
} else visitor
|
||||
|
||||
else -> visitor
|
||||
}
|
||||
}
|
||||
|
||||
override fun end() {
|
||||
if (shouldAddLegacyStorage &&
|
||||
Build.VERSION.SDK_INT >=
|
||||
29 &&
|
||||
requestLegacyExternalStorage ==
|
||||
true
|
||||
) {
|
||||
super.attr(
|
||||
ANDROID_NAMESPACE,
|
||||
REQUEST_LEGACY_EXTERNAL_STORAGE,
|
||||
android.R
|
||||
.attr
|
||||
.requestLegacyExternalStorage,
|
||||
TYPE_INT_BOOLEAN,
|
||||
1
|
||||
)
|
||||
}
|
||||
if (shouldAddDebuggable &&
|
||||
debuggable == true
|
||||
) {
|
||||
super.attr(
|
||||
ANDROID_NAMESPACE,
|
||||
DEBUGGABLE,
|
||||
android.R.attr.debuggable,
|
||||
TYPE_INT_BOOLEAN,
|
||||
1
|
||||
)
|
||||
}
|
||||
|
||||
// Disable AOT (Necessary for AOSP Android
|
||||
// 15)
|
||||
if (Build.VERSION.SDK_INT >= 29 &&
|
||||
shouldAddUseEmbeddedDex &&
|
||||
useEmbeddedDex == true
|
||||
) {
|
||||
super.attr(
|
||||
ANDROID_NAMESPACE,
|
||||
USE_EMBEDDED_DEX,
|
||||
android.R.attr.useEmbeddedDex,
|
||||
TYPE_INT_BOOLEAN,
|
||||
1
|
||||
)
|
||||
}
|
||||
|
||||
if (shouldAddExtractNativeLibs &&
|
||||
extractNativeLibs == false
|
||||
) {
|
||||
super.attr(
|
||||
ANDROID_NAMESPACE,
|
||||
EXTRACT_NATIVE_LIBS,
|
||||
android.R
|
||||
.attr
|
||||
.extractNativeLibs,
|
||||
TYPE_INT_BOOLEAN,
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
super.end()
|
||||
}
|
||||
}
|
||||
|
||||
// Disable AOT (Necessary for AOSP Android 15)
|
||||
if (Build.VERSION.SDK_INT >= 29 && shouldAddUseEmbeddedDex && useEmbeddedDex == true) {
|
||||
super.attr(ANDROID_NAMESPACE, USE_EMBEDDED_DEX, android.R.attr.useEmbeddedDex, TYPE_INT_BOOLEAN, 1)
|
||||
}
|
||||
|
||||
if (shouldAddExtractNativeLibs && extractNativeLibs == false) {
|
||||
super.attr(
|
||||
ANDROID_NAMESPACE,
|
||||
EXTRACT_NATIVE_LIBS,
|
||||
android.R.attr.extractNativeLibs,
|
||||
TYPE_INT_BOOLEAN,
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
super.end()
|
||||
}
|
||||
else -> nv
|
||||
}
|
||||
|
||||
else -> nv
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
return writer.toByteArray()
|
||||
}
|
||||
|
|
@ -230,7 +448,13 @@ object ManifestPatcher {
|
|||
val replace = attrs.containsKey(name)
|
||||
val newValue = attrs[name]
|
||||
|
||||
super.attr(ns, name, resourceId, if (newValue is String) TYPE_STRING else type, if (replace) newValue else value)
|
||||
super.attr(
|
||||
ns,
|
||||
name,
|
||||
resourceId,
|
||||
if (newValue is String) TYPE_STRING else type,
|
||||
if (replace) newValue else value
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue