Reading OBB File

Is it possible to read or unzip obb file and can someone point me how to do that?
What exactly im trying to do , is to get vuforia image dataset for my ar camera. But since it is in obb file, i dont have idea how to reach it?

Bump, sry i have to. Im in rush…

This is a really good guide for accessing assets in your OBB:

http://labs.exoa.fr/tutorial-unity-4-apk-splitting-google-play-obb/

Thanks i followed tutorial and i got scene loaded from obb just like in example. But i cant figure out how to get files from StreamingAssets folder? Im pretty much depressed right now im working on this for 3 days and im stuck all that time…

I need to reach to:
StreamingAssets/QCAR/Tracker.xml
StreamingAssets/QCAR/Tracker.data
which is in obb i unziped it and checked it is there but cant get it in unity -.-

Update:
Application.streamingAssetsPath…How the hell i didnt saw this
Application.streamingAssetsPath + WWW Class + Binary Writing = Solution

Have you had any luck Marceta? I’m in exactly the same position as you, trying to get the Data Sets and Videos that are in the Streaming Assets folder.

Yes i did.
I used System.IO and unity WWW class to read obb file and get dataset files from it then i copy them from obb to application storage path on phone. After that you have to make tracker programmatically so it will read dataset from “extracted” location.
So my application works like this:

  1. User start app and it will show message that it is reading data from obb (and this happens only once per install)
  2. Then when it is done it will load tracker and start tracking.
  3. If user already had did this before, tracker will just check if dataset exist in app path and if it’s true it will load trackable if not it will do first step.

Thanks to WWW class i got acess to tracker.xml and tracker.data.
With File.WriteAllText i copied all text from tracker.xml to new tracker.xml wich will be in application path.
With File.WriteAllBytes i copied all bytes from tracker.data to new tracker.data wich will be in application path.
And now you can easy get your tracker data always

Some references:

1 Like

Could you post some info on how you exactly got to the correct file path and stuff like that. Been trying to load the xml and .DAT file without success on android.

Some code would be helpfull

Sorry for late response.

This is not the best way to do, when i wrote it again i got much faster read/write results, but i dont have that code anymore.
So when user download OBB data, i used this script on start of AR scene, to check if i have already extracted xml and data for tracking. If not it will do the job else it will just start tracking normally.

The is the “old code”:

using UnityEngine;
using System.Collections;
using System.IO;
public class SetupTrackers : MonoBehaviour, ITrackableEventHandler {

    private bool mLoaded = false;
    private DataSet mDataset = null;
    private bool canReadData;
    private bool doOnce = false;
    private bool doOnceData = false;
    private bool canLoadSceneXml = false;
    private bool canLoadSceneDat = false;
    private string logtxt;
    public UILabel Loading;
    public GameObject Story;
    public Story storyObj;

    void Start()
    {
        Time.timeScale = 0;
    }

    public void OnTrackableStateChanged(
        TrackableBehaviour.Status previousStatus,
        TrackableBehaviour.Status newStatus)
    {
        if (newStatus == TrackableBehaviour.Status.DETECTED ||
            newStatus == TrackableBehaviour.Status.TRACKED ||
            newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
        {
            foreach(Renderer mr in this.gameObject.GetComponentsInChildren<Renderer>())
            {
                mr.enabled = true;
            }
            foreach(AudioSource aus in this.gameObject.GetComponentsInChildren<AudioSource>())
            {
                aus.pitch = 1;
            }
            Time.timeScale= 1;
        }
        else
        {
            foreach(Renderer mr in this.gameObject.GetComponentsInChildren<Renderer>())
            {
                mr.enabled = false;
            }

            foreach(AudioSource aus in this.gameObject.GetComponentsInChildren<AudioSource>())
            {
                aus.pitch = 0;
            }
            Time.timeScale = 0;
        }
    }

    void Update()
    {
        if(!mLoaded)
        {
            Story.gameObject.SetActive(false);
            if (!doOnce) {
                if (!File.Exists (Application.persistentDataPath + "/MYAPP.xml"))
                {
                    string trackerXML= Application.streamingAssetsPath + "/QCAR/MYAPP.xml";
                    WWW wwwXML = new WWW (trackerXML);
                    if(wwwXML.isDone)
                    {
                        File.WriteAllText(Application.persistentDataPath + "/MYAPP.xml", wwwXML.text);
                        //File.WriteAllBytes(Application.persistentDataPath + "/MYAPP.xml", wwwXML.bytes);
                        //log ("ZAPISAN XML");
                        doOnce = true;
                    }
                    else
                    {
                        Loading.text = "LoadingTrackerXML...(Only first time)";
                    }
                }
            }
       
            if (doOnce  !doOnceData) {
                if (!File.Exists (Application.persistentDataPath + "/MYAPP.dat")) {
                    string trackerDATA= Application.streamingAssetsPath + "/QCAR/MYAPP.dat";
                    WWW wwwDATA = new WWW (trackerDATA);
                    if (wwwDATA.isDone) {
                        File.WriteAllBytes (Application.persistentDataPath + "/MYAPP.dat", wwwDATA.bytes);
                        //log ("ZAPISAN DATA");
                        Loading.text = "";
                        doOnceData = true;
                    }
                    else
                    {
                        Loading.text = "LoadingTrackerDATA...(Only first time)";
                    }
                }
            }

            if (File.Exists (Application.persistentDataPath + "/MYAPP.dat")) {
           
                string externalPathEx = Application.persistentDataPath + "/MYAPP.xml";
           
                if (mDataset == null) {
                    ImageTracker tracker = TrackerManager.Instance.GetTracker<ImageTracker> ();
                    mDataset = tracker.CreateDataSet ();
                }
           
                if (mDataset.Load (externalPathEx, DataSet.StorageType.STORAGE_ABSOLUTE)) {
                    ImageTracker apTracker= TrackerManager.Instance.GetTracker<ImageTracker> ();
                    apTracker.ActivateDataSet (mDataset);
                    Loading.text = "";
                    Story.gameObject.SetActive(true);
                    Time.timeScale = 1;
                    StateManager stateM = TrackerManager.Instance.GetStateManager();
                    foreach(TrackableBehaviour tb in stateM.GetTrackableBehaviours())
                    {
                        tb.RegisterTrackableEventHandler(this);
                    }
                    if(Application.loadedLevelName == "Story")
                    {
                        storyObj.PlaySounds();
                    }
                    mLoaded = true;
                } else {
                }
            }
        }
    }

        void log( string t )
    {
        logtxt += t + "\n";
        print("MYLOG " + t);
    }

    void OnGUI()
    {
        GUI.Label(new Rect(10, 10, Screen.width-10, Screen.height-10), logtxt );
    }

}
1 Like

Here’s my experience as I’ve been stuck on this while trying to read .mp4 video file from Streaming Assets using split option and Easy Movie For Android plugin.

As it’s not possible to easily extract file from Unity’s OBB (even if video with other stuff is visible using VLC), and as we cannot use Asset Bundle for a video file (that is not a Unity recognized type), I managed to generate the OBB myself and let Unity only build the APK without video file.

It’s very simple to embed every file you want in archive by using this command (OSX or Linux) to generate a zip file in storage mode (not compressed) : zip -n .mp4 main.zip video.mp4
Details here : http://blogmobile.itude.com/2013/09/11/creating-expansion-files-without-compression-obb/

You can then change the file extension to .obb and use a simple zip utility in unity to extract video file from archive to the persistent data path of device.

In my project, I let Google Play Downloader plugin retrieve the OBB file and then I do a File.WriteAllBytes to save obb in cache path as a .zip file. Then I could extract the video and remove unwanted zip file.

Hopes it could help someone.