Skip to content

Commit

Permalink
split apk support
Browse files Browse the repository at this point in the history
  • Loading branch information
qimiko committed Dec 21, 2023
1 parent beee008 commit 74ac7f5
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 5 deletions.
52 changes: 48 additions & 4 deletions app/src/main/java/com/geode/launcher/GeometryDashActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.ActivityInfo
import android.content.pm.PackageInfo
import android.os.Build
import android.os.Bundle
import android.os.Environment
Expand Down Expand Up @@ -44,7 +45,6 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
private var mHasWindowFocus = false
private var mReceiver: BroadcastReceiver? = null

@SuppressLint("UnsafeDynamicallyLoadedCode")
override fun onCreate(savedInstanceState: Bundle?) {
setupUIState()

Expand All @@ -57,7 +57,6 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
}

val gdPackageInfo = packageManager.getPackageInfo(Constants.PACKAGE_NAME, 0)
val gdNativeLibraryPath = "${gdPackageInfo.applicationInfo.nativeLibraryDir}/"

try {
LaunchUtils.addAssetsFromPackage(assets, gdPackageInfo)
Expand Down Expand Up @@ -86,8 +85,8 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
Cocos2dxHelper.init(this, this)
GeodeUtils.setContext(this)

System.load("$gdNativeLibraryPath/lib${Constants.FMOD_LIB_NAME}.so")
System.load("$gdNativeLibraryPath/lib${Constants.COCOS_LIB_NAME}.so")
tryLoadLibrary(gdPackageInfo, Constants.FMOD_LIB_NAME)
tryLoadLibrary(gdPackageInfo, Constants.COCOS_LIB_NAME)

if (getLoadTesting()) {
loadTestingLibraries()
Expand All @@ -114,6 +113,51 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
}
}

@SuppressLint("UnsafeDynamicallyLoadedCode")
private fun tryLoadLibrary(packageInfo: PackageInfo, libraryName: String) {
try {
val nativeDir = packageInfo.applicationInfo.nativeLibraryDir
System.load("$nativeDir/lib$libraryName.so")
} catch (ule: UnsatisfiedLinkError) {
loadLibraryFromAssets(libraryName)
}
}

@SuppressLint("UnsafeDynamicallyLoadedCode")
private fun loadLibraryFromAssets(libraryName: String) {
// loads a library loaded in assets
// this currently requires copying the library to a non-compressed directory
// ideally a better solution would be found, but i'm out of ideas

val libraryCopy = File(cacheDir, "lib$libraryName.so")
if (libraryCopy.exists()) {
// don't force a copy on each load
// (you will have to clear cache if the library updates, so maybe remove this check)
System.load(libraryCopy.path)
return
}

// find the first instance of the library in preferred abi order
val libraryFd = Build.SUPPORTED_ABIS.asSequence()
.mapNotNull {
try {
assets.openNonAssetFd("lib/$it/lib$libraryName.so")
} catch (_: Exception) {
null
}
}
.firstOrNull() ?: throw UnsatisfiedLinkError("Could not find library lib$libraryName.so")

// copy the library to a path we can access
// there doesn't seem to be a way to load a library from a file descriptor
val libraryOutput = libraryCopy.outputStream()
copyFile(libraryFd.createInputStream(), libraryOutput)

System.load(libraryCopy.path)

return
}

@SuppressLint("UnsafeDynamicallyLoadedCode")
private fun loadGeodeLibrary(): Boolean {
// Load Geode if exists
Expand Down
5 changes: 4 additions & 1 deletion app/src/main/java/com/geode/launcher/utils/LaunchUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.res.AssetManager
import android.content.Context
import com.geode.launcher.utils.Constants
import java.io.File

object LaunchUtils {
Expand Down Expand Up @@ -45,6 +44,10 @@ object LaunchUtils {
// (the source recommends replacing with AssetManager.setApkAssets(ApkAssets[], boolean) lol)
val clazz = assetManager.javaClass
val aspMethod = clazz.getDeclaredMethod("addAssetPath", String::class.java)

aspMethod.invoke(assetManager, packageInfo.applicationInfo.sourceDir)
packageInfo.applicationInfo.splitSourceDirs?.forEach {
aspMethod.invoke(assetManager, it)
}
}
}

0 comments on commit 74ac7f5

Please sign in to comment.