Search Unity

Unity + MetaioSDK + Split Application Binary (.obb)

Discussion in 'Editor & General Support' started by MarioPinto_BInteractive, Mar 27, 2015.

  1. MarioPinto_BInteractive

    MarioPinto_BInteractive

    Joined:
    Apr 16, 2014
    Posts:
    4
    Hello everybody,

    We've developed an application in Unity (4.6.3p4) with Metaio (6.0.2) that required the "Split Application Binary" option activated (the application is >200mb) and we've faced some problems getting it to work on Android so we've decided to share our solution.

    Apparently, when this option is active, metaio SDK is not capable of getting the information from the "StreamingAssets" folder by himself. We've developed a workaround to solve this while this is not fixed in the SDK.

    We've followed the solution presented here, but without results. However, using that solution as a base, we've managed to solve the issue for our project.

    The following changes should be done in the "AssetManager.cs" file (can be found at Assets/metaio/Classes/).

    Add this three static variables in the begining of the file:

    Code (CSharp):
    1. // Name of the files in the StreamingAssets folder to be extracted from the obb file on Android
    2. static string[] assetsToExtract = new string[] {
    3.     "/MetaioSDKLicense.xml",
    4.     "/Metaio/TrackingData.zip"
    5. };
    6.  
    7. static string[] assetsNames;
    8. static string[] assetsFolders;
    On the "assetsToExtract" variable you should put all the files present on the "StreamingAssets" folder that are used by Metaio. I've only needed the "metaioSDKLicence" and the "trackingData" zip files. If you use other formats for the trackingData, all files names should be included.

    Then, on the "extractAssets" method, you should replace the "UNITY_ANDROID" code for by the following code:
    Code (CSharp):
    1.    publicstaticbool extractAssets(bool overrideAssets){
    2. #if UNITY_ANDROID && !UNITY_EDITOR
    3.  
    4.    //Initialize variables
    5.     assetsNames =newstring[assetsToExtract.Length];
    6.     assetsFolders =newstring[assetsToExtract.Length];
    7.  
    8.     for(int i =0; i < assetsToExtract.Length;++i){
    9.         assetsNames[i]= assetsToExtract[i].Substring(assetsToExtract[i].LastIndexOf('/')+1);
    10.         assetsFolders[i]= assetsToExtract[i].Substring(0,assetsToExtract[i].LastIndexOf('/'))+"/";
    11.     }
    12.  
    13.     //Duplicate the StreamingAssets directories on persistentDataPath (if necessary)
    14.     foreach(string directory in assetsFolders){
    15.         if(directory.Length>1){//If the directory is the StramingAssets folder, no need to create
    16.             string directoryPath =Application.persistentDataPath + directory;
    17.             Debug.Log("Creating Directory: "+ directoryPath);
    18.             Directory.CreateDirectory(directoryPath);
    19.         }
    20.     }
    21.  
    22.     //Extract files to persistentDataPath
    23.     for(int i =0; i < assetsToExtract.Length;++i){
    24.         string sourcePath =Application.streamingAssetsPath +
    25.                             assetsFolders[i]+
    26.                             assetsNames[i];
    27.  
    28.         Debug.Log("Extracting file from: "+ sourcePath);
    29.         WWW www =new WWW(sourcePath);
    30.  
    31.         // this is bad but shouldn't take too long!
    32.         while(!www.isDone){;}
    33.  
    34.         string destPath =   Application.persistentDataPath +
    35.                             assetsFolders[i]+
    36.                             assetsNames[i];
    37.  
    38.         Debug.Log("Extracting to: "+ destPath);
    39.         File.WriteAllBytes(destPath, www.bytes);
    40.     }
    41.  
    42.     //Old Code    
    43.     //Use Java AssetsManager class on Android
    44.     //AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    45.     //AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
    46.     //AndroidJavaClass cls = new AndroidJavaClass("com.metaio.tools.io.AssetsManager");
    47.     //String parentPath = "";
    48.     //String[] ignoreList = {"bin", "libs", "webkit", "sounds", "images"};
    49.     //object[] args = {jo, parentPath, ignoreList, overrideAssets};
    50.  
    51.     //cls.CallStatic("extractAllAssets", args);
    52. #elif UNITY_IPHONE || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_EDITOR
    53.  
    ...

    This creates the necessary directories on the persistentDataPath folder and copies the "assetsToExtract" files, making them accessible.

    Finaly, in the "getAssetPath" method, you should replace the "UNITY_ANDROID" code for by the following code:
    Code (CSharp):
    1. publicstaticString getAssetPath(String filename){
    2.     Debug.Log("AssetsManager.getAssetPath: "+ filename);
    3.  
    4.     filename = filename.Replace('/',Path.DirectorySeparatorChar);
    5.     String assetPath =null;
    6. #if UNITY_ANDROID && !UNITY_EDITOR
    7.  
    8.    //Set the asset data path
    9.     for(int i =0; i < assetsToExtract.Length;++i){
    10.         if(assetsNames[i].Contains(filename)){
    11.             assetPath =Application.persistentDataPath + assetsFolders[i]+ assetsNames[i];
    12.         }
    13.     }
    14.  
    15.     // Use Java AssetsManager class on Android
    16.     //AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    17.     //AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
    18.     //AndroidJavaObject context = jo.Call<AndroidJavaObject>("getApplicationContext");
    19.     //AndroidJavaClass cls = new AndroidJavaClass("com.metaio.tools.io.AssetsManager");
    20.     //object[] args = {context, filename};
    21.     //assetPath = cls.CallStatic<String>("getAssetPath", args);
    22. #elif UNITY_IPHONE || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_EDITOR
    23.  
    ...

    This manages to create the correct path for the files so the metaiosSDK can access them.

    For this fix you will also need to grant permissions to read/writo on the SD Card. To do this, on the Unity3d Build Settings -> Other Settings, change the "Write Access" setting to "External (SDCard)".

    Regarding the load of the obb file, we used the "Google OBB Downloader" Instructions can be found here.

    This fixed the problem for our application, hope it helps!
     
  2. cbigas

    cbigas

    Joined:
    Mar 16, 2015
    Posts:
    5
    Thanks a lot for this solution. It helped me.