I went through DaReign’s tutorial and now the pop-up successfully appears in my app upon first starting it, and after I click “allow”, storage access shows as “enabled” in Settings → apps, but the OBB is still not loaded. Strangely, in previous builds of the app, when I MANUALLY enable storage access in settings, the OBB is loaded. Anyone know why this might be the case?
I SOLVED IT ! I ~think~ it may have been that because I’m making a Google Cardboard App, I just needed to modify the manifest file “AndroidManifest-Cardboard” instead of the AndroidManifest as in DaReign’s tutorial. Upon startup, I allow access to the SD card, and my first (menu scene) is reloaded. Once I click through it to start the next scene, which uses assets from the OBB file, it’s all gravy ![]()
Hello, im desperate trying to make OBB work as we have our game stuck on Android (IOS working and waiting for Review). It’s a racing game. Can i ask how did you managed to Restart the App? Im not proeficient in Java PendingIntent or similar. I think im stuck with the same issue. I can read the OBB Scenes (the names for them), the OBB is there in Internal Storage, but it doesn’t want to load my first scene and this is a nightmare. I’ve tried restarting, same.
Galaxy J1 prime, Android 6.0.1
Im using DownloaderOBB, API 19 , all published in Beta in Google, asking for Permissions at Runtime and Manifest has READ_EXTERNAL_STORAGE (im adding now as i write WRITE_EXTERNAL_STORAGE too).
Please help! ![]()
![]()
@DBarlok I don’t believe you can force the device to restart, our solution tries to resolve it using permissions, then we test to see if something can be loaded from the OBB (I think from memory we try and load a prefab that only exists in the OBB). If this fails, we then display to the user a message something like ‘This is a known Android bug, please restart the device and reopen this application. If the problem persists contact us on blah blah.’
Hello jason_yak, nice to meet you.
Sure. That sounds good. I did that checking if an Scene exist too.
I will check my code to see if i didn’t commented that part. For now, i didn’t
tested on Oreo, so, i think will be safer if i test that asap. Thank you!
Update: I will think about checking against a prefab too. You are super pro!!
You saved my game from Google Bug i think! ![]()
Hello everyone,
I have been dealing with this obb issue for over a week now getting quite depressive :(, I have added the:
in my android manifest and have tried @DaReign solution, it got me until the ask for permission and once I press accept button, which is suppose to trigger the android dialog to get pop up(the allow/deny UI), nothing happen, I can press the accept button endlessly, it just seem to do nothing with it, the accept button call for the OnGrantButtonPress().
Image of my UI:
Here are all my line of codes:
[code=CSharp]
//UI to access android dialogue permission
public GameObject requestpermission;
//UI to acess button to load the next scene
public GameObject loadnextscene;
private const string STORAGE_PERMISSION = "android.permission.READ_EXTERNAL_STORAGE";
void Start () {
requestpermission.SetActive (false);
loadnextscene.SetActive (false);
CheckPermissions();
}
//load next scene
public void shownextscene(){
SceneManager.LoadScene ("start page normal");
}
//close application if user refuse access
public void hideaccess(){
Application.Quit();
}
private bool MyCheckPermissions(){
if (Application.platform != RuntimePlatform.Android)
{
return true;
}
return AndroidPermissionsManager.IsPermissionGranted(STORAGE_PERMISSION);
}
public void CheckPermissions(){
if (!MyCheckPermissions ()) {
requestpermission.SetActive (true); //pop UI with accept or refuse button
}
}
//if user press accept button, this method get called
public void OnGrantButtonPress()
{
AndroidPermissionsManager.RequestPermission(new []{STORAGE_PERMISSION}, new AndroidPermissionCallback(
grantedPermission =>
{
// The permission was successfully granted, restart the change avatar routine
requestpermission.SetActive (false); //close UI
loadnextscene.SetActive (true); //pop button
},
deniedPermission =>
{
// The permission was denied
hideaccess();
},
deniedPermissionAndDontAskAgain =>
{
//honestly dont care about this at this point
// The permission was denied, and the user has selected "Don't ask again"
}));
}
}
}[/code]
Also restarting the device make no difference.
The device I am testing on is LG G5 version 8.0 with Unity 2017.1.1.f1 It seem like I cant reach the Obb file no matter what I do.
Any help would be greatly appreciated :).
Thank you
-Phoenixrider
A bit late, but I think “Force Internal” inside ProjectSettings->Player is the way to bypass this particular issue.
Also, in your case specifically, you will probably need to get rid of the
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
maybe from this as well (try to see):
<meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true"/>
that you currently had (if you had) in your custom manifest file, and thus, let unity decide, while it builds.
“Forcing internal” helped me in that the obb is found, though only after a device restart…
Once you have that, you should be able to do this
Checking if obb is available on the first launch is done as this post suggests:
or as these people suggest (and I think so too) trying to load an asset via Resources.Load() will do the job. Quoting unity:
When the Split Application Binary option is enabled the player executable and data will be split up, with a generated .apk (main application binary) consisting only of the executable (Java, Native) code (around 10MB), any and all script / plugin code, and the data for the first scene. Everything else (all additional scenes, resources, streaming assets …) will be serialized separately to a APK Expansion File (.obb).
Your initial scene should probably be super-tiny (I called mine “Pre-welcome scene”), which is the first one to launch. It should have an index of zero. It should only have 1 script that checks for obb, and can show a message. If your welcome scene has pictures, you might fail to display such a message, as parts of it might get placed in obb …i’m not sure though ))
For the same reason don’t use TextMeshPro in this Pre-welcom-scene, as I think parts of it are placed into .obb; Just use the usual text. Don’t use any fonts other than Arial. Don’t use any sprites other than ‘UISprite’ - the default one provided by unity.
My starting scene has no camera, just a simple canvas, set to “screen overlay” mode.
My code looks like this:
Code
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class AndroidInstall_VerifyHasObb : MonoBehaviour{
[SerializeField] GameObject _message_pannel = null;
[SerializeField] Button _confirmButton = null;
bool _firstUpdateInvoked = false;
// Update is called once per frame
void Update(){
if(_firstUpdateInvoked){ return; }
_firstUpdateInvoked = true;
OnFirstUpdate();
}
void OnFirstUpdate(){
GameObject go = Resources.Load("PreWelcomeScene_ObbVerifying_Prefab") as GameObject;
if(go == null){
//the obb wasn't loaded!
//tell the user about this Google-bug, and tell them to restart the phone.
// https://discussions.unity.com/t/661270 page-2#post-4132885
_message_pannel.SetActive(true);//displays the message
_confirmButton.onClick.AddListener( onConfirmButtonClicked );
return;
}
//otherwise, everything is ok. Load the scene:
UnityEngine.SceneManagement.SceneManager.LoadSceneAsync( 1, UnityEngine.SceneManagement.LoadSceneMode.Single );//load the "Welcome Scene" (with company logo, etc).
}
void onConfirmButtonClicked(){
Debug.Log("quitting");
Application.Quit();
}
}
Here is a bit more on dangers of WRITE_EXTERNAL_STORAGE:
https://web.archive.org/web/20180613050320/http://www.supersegfault.com:80/unity-on-android-save-data-pitfall
Hi everyone,
Recently there’s been some developments on Google Play which I believe might finally be the answer to all of these Obb file issues. Google have opened the door to effectively remove the of Obb expansion files through a couple of different means which completely side steps all of the related issues the Obb files have.
Firstly using the Android App Bundle delivery format it is possible to organise your assets in a way that they’d eventually be split and delivered to users as a series of apk files. At the moment these apk files have a 100mb size limit which means that you still have a primary apk installed with extra resources ending up in other secondary apks, which fundamentally isn’t that much different to Obb files, but would take some massaging to get your compiler setup to support this new format. I haven’t tried this format yet, so don’t quote me, but I think another difference might be that secondary apks might need to be downloaded by the app at runtime, which means that if a user installed the primary apk, lost internet (say in on a plane in aeroplane mode) would not be able to download the remaining apk resouce files. But, at least no Obb file and no bugs associated with them. I think the AAB format is supported from Android 5.0 and up.
All that said there’s another potential option. Google have announced that they’re increasing the size limit of self contained apk’s to 500mb, and for us this is the real solution. Users trying to download an apk over 100mb will be shown a popup warming that the app is a large size, do they want to wait until on wifi or continue using mobile data. I believe you need to put in a request to be whitelisted, you’d need to talk to you google account manager as the feature is currently in early access only.
All content included on the first scene on build settings will be placed at the .APK, and the rest on .OBB:
How data is split between the APK and OBB
When the Split Application Binary option is enabled, the app is split the following way:
- APK - Consists of the executables (Java and native), plug-ins, scripts, and the data for the first Scene (with the index 0).
- OBB - Contains everything else, including all of the remaining Scenes, resources, and streaming Assets
Same issue here.
I made some tests with a helpful user.
His device is: HUAWEI CAM-L23
The default install location of his device is set to external.
Android version 6
Unity version 2018.2.21f1
I tried with different build setting combinations, the result is the same.
Install Location: Force Internal
Permission: Internal
Install Location: Automatic
Permission: Internal
Install Location: Automatic
Permission: External
Manifest file:
READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
(Test build settings)
Install Storage: Automatic
Permission: Internal
Steps:
1- Install the app from Google Play Store
2- Launch the first scene.
3- Check if external storage is readable, if it is not, ask permission => storage was readable
4- Check if obb file exists => returns True.
(if returns false, ask write_external_storage permission, start downloading obb)
5- Check if Application.dataPath equals to obb path. => Not equal
Application.dataPath returns this path: /data/app/com.company.package-1/base.apk
instead of Obb location. (Unity - Scripting API: Application.dataPath))
6- The second scene won’t load.
7- Ask the user to restart his device and re-launch the game.
8- Now Application.dataPath equals to obb path
9- Everything is working.
I wonder whether asking the user for write_external_storage permission in step 5 may solve the issue. I could not test it because it is too difficult to communicate with the user who is speaking Spanish.
Edit: I just figurated it out that asking runtime permission after obb is has mounted won’t solve the issue
.
“Pausing/resuming the unity activity AFTER the user has clicked “accept” in the permission dialog”
Is there anyone who has tried this way?
This is really old thread but reading it. It seems that no one considered that you can restart app programmically which will bypass the issue.
Once obb download is finished try:
public void restartApplication()
{
Intent mStartActivity = new Intent(UnityPlayer.currentActivity, UnityPlayer.currentActivity.getClass());
int mPendingIntentId = 123456;
PendingIntent mPendingIntent = PendingIntent.getActivity(UnityPlayer.currentActivity, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager)UnityPlayer.currentActivity.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 200, mPendingIntent);
UnityPlayer.currentActivity.finish();
/* Clean but does not work with obb
Context context = UnityPlayer.currentActivity.getApplicationContext();
Intent intent = new Intent(context, UnityPlayer.currentActivity.getClass());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
Runtime.getRuntime().exit(0);
*/
}
This snippet works most of cases but there are cases where some devices fails to restart the app. Yet default behaviour for users is to reopen crashed app so it works. Fail case might be fixable by increasing delay of the alarm which restarts the app. The default 200ms delay restarts the app seamlessly on devices that are fast enough.