Skip to content

Instantly share code, notes, and snippets.

@stek29
Last active May 27, 2025 19:39
Show Gist options
  • Save stek29/492fea961726953dbdb002f2b1d909b4 to your computer and use it in GitHub Desktop.
Save stek29/492fea961726953dbdb002f2b1d909b4 to your computer and use it in GitHub Desktop.
multiple copies of beatsaber app on quest

Here's how you can have multiple versions of beat saber at the same time by having different package names.
Unfortunately, BMBF is hardcoded to use original BeatSaber package id, so it's not possible to have completely unmodded version with BMBF modded version.
If BMBF starts using this method, it would be possible to have unmodded beat saber from oculus store with multiplayer support and modded BMBF version.

I made this because BMBF modded version used to crash time to time, and I prefer to have choice between stable game and custom songs.

You'd need apktool, zipalign, apksigner – I'm on mac, so I've installed apktool from brew and used Docker for other tools: fopina/dedroid.

Grab the APK

If you don't have APK already, you can pull it from device with adb:

adb pull $(adb shell pm path com.beatgames.beatsaber | cut -d: -f2) BeatSaber.apk

Extract

apktool d BeatSaber.apk -o BeatXaber

APK would be extracted to BeatXaber directory

Patch: Rename

  1. Edit apktool.yaml: replace renameManifestPackage: null with renameManifestPackage: com.beatgames.beatxaber
  2. Edit AndroidManifest.xml: replace android:label="Beat Saber" with android:label="Beat Xaber"
  3. Rename smali/com/beatgames/beatsaber to smali/com/beatgames/beatxaber
  4. Change Saber to Xaber in res/values/strings.xml (app_name)
  5. Replace all occurencies of com/beatgames/beatsaber with com/beatgames/beatxaber in smali/com/beatgames/beatxaber
  6. Replace com.beatgames.beatsaber with com.beatgames.beatxaber in smali/com/beatgames/beatxaber/BuildConfig.smali (APPLICATION_ID)

Patch: Resource ID hack

Renaming everything wasn't enough – for some reason resource lookup was broken: game was crashing with android.content.res.Resources$NotFoundException: String resource ID #0x0 on start, so I had to patch it out:

Open file smali/com/unity3d/player/UnityPlayer.smali, find UnityPlayer;->GetGlViewContentDescription: remove invoke-direct and move-result-object p1 and replace it with const-string p1, "Game view":

- invoke-direct {p0, p1}, Lcom/unity3d/player/UnityPlayer;->GetGlViewContentDescription(Landroid/content/Context;)Ljava/lang/String;
- move-result-object p1
+ const-string p1, "Game view"

Build

# build apk
apktool b BeatXaber -o BeatXaber-unaligned.apk
# docker run --rm -v $PWD:/work -it fopina/dedroid bash # if you prefer docker too

# generate signing key
keytool -genkeypair -v -keystore ./BeatXaber.keystore \
    -alias BeatXaber -keyalg RSA -keysize 2048 \
    -validity 10000 -dname "CN=BeatXaber, OU=BeatXaber, O=BeatXaber, L=BeatXaber, ST=BeatXaber, C=US" \
    -storepass password -keypass password

# align
zipalign -p -f -v 4 BeatXaber-unaligned.apk BeatXaber.apk

# sign
apksigner sign --ks ./BeatXaber.keystore --ks-key-alias BeatXaber --ks-pass pass:password BeatXaber.apk

Install

adb install -r -d BeatXaber.apk (SideQuest sideloading might work too)

App Beat Xaber should now appear in unknown sources

Managing saves/DLCs

saves can be copied from/to /sdcard/Android/data/com.beatgames.beatsaber and /sdcard/Android/data/com.beatgames.beatxaber

DLCs for patched version are loaded from /sdcard/Android/obb/com.beatgames.beatxaber

@PatrickJoshua
Copy link

I always have this issue with Beat Saber when changing the package name where it crashes after a few minutes (around 5 minutes). This has been happening since I started installing duplicate beat saber copies in my Quest (since v1.13). The original game (BMBF-modded) is working fine. Do you also encounter this?

@stek29
Copy link
Author

stek29 commented Jun 15, 2021

@PatrickJoshua nope, never had that. Try attaching logcat and waiting for crash to know what causes it

@ItsVRK
Copy link

ItsVRK commented Nov 29, 2023

@stek29 this process doesn't appear to work anymore, it starts to load and then crashes after the loading splash screen

@mrsolarius
Copy link

mrsolarius commented May 27, 2025

When I load the apk like you said I have this error that show up in logcat :

2025-05-27 21:33:05.784 32002-32111 Unity                   com.beatgames.beatxaber              E  RemoteProviderException : TextDataProvider : unable to load from url : jar:file:///data/app/~~i9FqUy3C7eG33OSF7Qkg_w==/com.beatgames.beatxaber-rVoLrWjJT7caUK2YauQDaw==/base.apk!/assets/aa/settings.json
UnityWebRequest result : ProtocolError : HTTP/1.1 404 Not Found
ResponseCode : 404, Method : GET
url : jar:file:///data/app/~~i9FqUy3C7eG33OSF7Qkg_w==/com.beatgames.beatxaber-rVoLrWjJT7caUK2YauQDaw==/base.apk!/assets/aa/settings.json

UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, Exception, Boolean)
UnityEngine.ResourceManagement.ResourceProviders.ProvideHandle:Complete(T, Boolean, Exception)
UnityEngine.ResourceManagement.ResourceProviders.InternalOp:CompleteOperation(String, Exception)
UnityEngine.ResourceManagement.ResourceProviders.InternalOp:RequestOperation_completed(AsyncOperation)
UnityEngine.AsyncOperation:InvokeCompletionEvent()
2025-05-27 21:33:05.788 32002-32111 Unity                   com.beatgames.beatxaber              E  RuntimeData is null.  Please ensure you have built the correct Player Content.
UnityEngine.ResourceManagement.AsyncOperations.InitalizationObjectsOperation:Execute()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
UnityEngine.ResourceManagement.AsyncOperations.<>c__DisplayClass57_0:<add_CompletedTypeless>b__0(AsyncOperationHandle`1)
System.Action`1:Invoke(T)
DelegateList`1:Invoke(T)
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
UnityEngine.ResourceManagement.ResourceManager:Update(Single)
2025-05-27 21:33:05.789 32002-32111 Unity                   com.beatgames.beatxaber              W  Addressables - Unable to load runtime data at location UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1[[UnityEngine.AddressableAssets.Initialization.ResourceManagerRuntimeData, Unity.Addressables, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]].
UnityEngine.AddressableAssets.Initialization.InitializationOperation:Execute()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
UnityEngine.ResourceManagement.AsyncOperations.<>c__DisplayClass57_0:<add_CompletedTypeless>b__0(AsyncOperationHandle`1)
System.Action`1:Invoke(T)
DelegateList`1:Invoke(T)
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, Exception, Boolean)
UnityEngine.ResourceManagement.AsyncOperations.InitalizationObjectsOperation:Execute()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
UnityEngine.ResourceManagement.Asy
2025-05-27 21:33:05.790 32002-32111 Unity                   com.beatgames.beatxaber              E  OperationException : Addressables - Unable to load runtime data at location UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1[[UnityEngine.AddressableAssets.Initialization.ResourceManagerRuntimeData, Unity.Addressables, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]].
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, Exception, Boolean)
UnityEngine.AddressableAssets.Initialization.InitializationOperation:Execute()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
UnityEngine.ResourceManagement.AsyncOperations.<>c__DisplayClass57_0:<add_CompletedTypeless>b__0(AsyncOperationHandle`1)
System.Action`1:Invoke(T)
DelegateList`1:Invoke(T)
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObje
2025-05-27 21:33:05.819 32002-32111 Unity                   com.beatgames.beatxaber              E  UnityEngine.AddressableAssets.InvalidKeyException: Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown. No Location found for Key=AppInit
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, Exception, Boolean)
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Start(ResourceManager, AsyncOperationHandle, DelegateList`1)
UnityEngine.ResourceManagement.ResourceManager:StartOperation(AsyncOperationBase`1, AsyncOperationHandle)
UnityEngine.ResourceManagement.ResourceManager:CreateCompletedOperationInternal(TObject, Boolean, Exception, Boolean)
UnityEngine.ResourceManagement.ResourceManager:CreateCompletedOperationWithException(TObject, Exception)
UnityEngine.AddressableAssets.AddressablesImpl:LoadSceneAsync(Object, LoadSceneMode, Boolean, Int
2025-05-27 21:33:05.847 32002-32111 Unity                   com.beatgames.beatxaber              E  OperationException : ChainOperation failed because dependent operation failed
UnityEngine.AddressableAssets.InvalidKeyException: Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown. No Location found for Key=AppInit
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, Exception, Boolean)
System.Action`1:Invoke(T)
DelegateList`1:Invoke(T)
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()
UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()
UnityEngine.ResourceManagement.ResourceManager:Update(Single)
2025-05-27 21:33:05.921 32002-32111 Unity                   com.beatgames.beatxaber              E  NullReferenceException: Object reference not set to an instance of an object.
  at GameLoader.Start () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.Run () [0x00000] in <00000000000000000000000000000000>:0 
  at UnityEngine.UnitySynchronizationContext+WorkRequest.Invoke () [0x00000] in <00000000000000000000000000000000>:0 
  at UnityEngine.UnitySynchronizationContext.Exec () [0x00000] in <00000000000000000000000000000000>:0 
--- End of stack trace from previous location where exception was thrown ---

  at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) [0x00000] in <00000000000000000000000000000000>:0 

It looks like settings.json and other player data is not in jar have you any idea to how bypass this ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment