Search Unity

Vuforia Android build, split(obb) apk BUG. [SOLVED]

Discussion in 'Vuforia' started by skdev3, Feb 15, 2018.

  1. skdev3

    skdev3

    Joined:
    Jul 15, 2015
    Posts:
    64
    Hi Vuforia community.
    Im find Vuforia split(obb) application bug in Android.
    Vuforia version 6 and 7. Unity 2017.x.x.

    Repro steps:
    1.
    Added Databases in VuforiaConfiguration.
    2. Make Android build without split application option - Work Fine.
    3. Enable split application option and make Android build for Google Play.
    Vuforia Does not work. Cause, сan not find Databases.


    The correct solution to the problem From the Vuforia team side:
    Vuforia team should add to the Vuforia SDK search Databases support in OBB files.

    The correct solution to the problem From the Unity team side:
    Need added option selecting location "StreamingAssets" choice of APP / OBB file.

    My HotFix solution:
    Steps:
    1. Enable split application option and make Android build for Google Play.
    2. Decode APP file:
    java -jar apktool.jar decode MyApp_split.apk

    3. Added "assets\Vuforia" in decoded APP folder and added files database.dat, database.xml.
    4. Build decoded APP folder:
    java -jar apktool.jar build MyApp_split

    5. Sign APP file:
    jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 -keystore <MyKeys>.keystore -storepass <MyKeystorePass> -keypass <MyAliasPass> MyApp_split.apk <MyAlias>

    6. Zip aligned App:
    zipalign -p 4 MyApp_split.apk MyApp_split-aligned.apk

    7. Push to Google Play.

    Non-working solutions:
    Copy files Application.streamingAssetsPath to Application.persistentDataPath;
    AddExternalDatasetSearchDir(DatabasesPath);
    Connecting the Database after initialization Vuforia.
     
  2. Vuforia-Strasza

    Vuforia-Strasza

    Official Vuforia Employee Vuforia

    Joined:
    Jun 13, 2017
    Posts:
    548
  3. skdev3

    skdev3

    Joined:
    Jul 15, 2015
    Posts:
    64
    This solution is out of date... QCAR folder is not used in new versions Vuforia. You need to enable the option "Delayed Initialization" for work of this solution. This is not always convenient, Vuforia 7 init camera in start App...

    Why this problem can not be fixed in Vuforia side?
     
  4. skdev3

    skdev3

    Joined:
    Jul 15, 2015
    Posts:
    64
    How soon will this problem be fixed?
     
  5. Vuforia-Strasza

    Vuforia-Strasza

    Official Vuforia Employee Vuforia

    Joined:
    Jun 13, 2017
    Posts:
    548
    The QCAR folder is no longer used, but you can switch the references to that folder to the "Vuforia" folder that is also within the StreamingAssets folder. This is where the datasets exist now. You do not need to use delayed initialization, but you will need to run this script before loading into a scene that is using your targets.

    Thanks
     
  6. developer6DLAB

    developer6DLAB

    Joined:
    Oct 31, 2016
    Posts:
    4
    Script attached doesn't work.
    I have an error here

    in "Save" Method
    File.WriteAllBytes (outputPath, <a href="<a href=" http://www.bytes "> http: // www.bytes </a> "> <a href = "http: //www.bytes </a>"> www.bytes </a> </a>);

    also Script need to add "using System.IO;"
     
  7. skdev3

    skdev3

    Joined:
    Jul 15, 2015
    Posts:
    64
    1. Vuforia database initialized before the scene load...
    2. Even when copying through a script, the solution ( https://developer.vuforia.com/forum/android/load-dataset-android-split-binary-obb ) does not work on Vuforia 7...

    Use:
    Code (csharp):
    1. File.WriteAllBytes(outputPath, www.bytes);
     
    developer6DLAB likes this.
  8. Vuforia-Strasza

    Vuforia-Strasza

    Official Vuforia Employee Vuforia

    Joined:
    Jun 13, 2017
    Posts:
    548
    It's not clear to me what you mean by this in this context. How is your project set up to load and activate Vuforia datasets?

    I've confirmed that the script from that link still works in Vuforia 7 (I also updated it yesterday to reflect Vuforia changes). I did this by adding it into a scene at the beginning of the core samples and checking the split binary option in the Player Settings. The only things in this scene are an ARCamera and this script. The script runs and then changes to the splash screen to initialize the samples. All targets work as expected when doing this.
     
  9. Cognetic

    Cognetic

    Joined:
    Jun 15, 2017
    Posts:
    9
    Hi, I have posted this on the Vuforia forum too and to answer what was said re: "vuforia intialized before the scene load" -
    I have followed the sticky instructions by creating a pre-loading scene to load the required xml and .dat files pre-vuforia initialization.

    No matter what i try I can't prevent Vuforia from initializing before any other code executes.

    To try stop the initializing, I have been through the typical solution:
    • delayed initialization selected,
    • attach a vuforia behaviour to the camera and deactivate it.
    It all works fine in the unity editor, with the code executing in the right order (i.e. files copied and then vuforia initialized). Also, if the android application is not split, Vuforia does not initialize (as expected), however when split, Vuforia always initializes, regardless of the settings.

    I have tried this on an empty scene with a single camera in it, I have also downloaded the vuforia test demo as you state works but I simply can't find a way to prevent Vuforia from starting up

    the android build seems to be ignoring the delayed initilization tag.

    I've tried the last two official releases of unity (currently 2017.3.1.f1 and Vuforia 7.0.47) with no luck.
     
  10. theolagendijk

    theolagendijk

    Joined:
    Nov 12, 2014
    Posts:
    117
    I can confirm that the approach explained in https://developer.vuforia.com/forum/android/load-dataset-android-split-binary-obb works properly with Vuforia SDK 7. We use it in this ( Dutch ) game ; http://projects.platipussoftwareinside.com/project/flardinga-1018/

    But we made one simple addition to the example code because we want to keep one code base for both iOS and Android;

    Code (CSharp):
    1. if( Application.platform == RuntimePlatform.Android )
    2.     StartCoroutine( ExtractObbDatasets() );
    3. else
    4.     StartCoroutine( LoadMainMenuAsync() );
     
    Mr-Shackle and Vuforia-Strasza like this.
  11. skdev3

    skdev3

    Joined:
    Jul 15, 2015
    Posts:
    64
    there is one more solution:
    Fixes an issue when building Apk and OBB
    You need to place VuforiaBuildProcessor.cs script in the folder "Editor"

    Code (csharp):
    1.  
    2. #if UNITY_ANDROID
    3. using UnityEngine;
    4. using UnityEditor;
    5. using UnityEditor.Build;
    6. using System.IO;
    7.  
    8. class VuforiaBuildProcessor : MonoBehaviour, IProcessScene, IPreprocessBuild, IPostprocessBuild
    9. {
    10.     public int callbackOrder { get { return 0; } }
    11.  
    12.     // OnPreprocessBuild -> OnProcessScene -> OnPostprocessBuild
    13.     public void OnPreprocessBuild(BuildTarget target, string path)
    14.     {
    15.  
    16.         if (PlayerSettings.Android.useAPKExpansionFiles == true)
    17.         {
    18.             string oldPath = Application.streamingAssetsPath + "/Vuforia";
    19.             string newPath = Application.streamingAssetsPath + "/../VuforiaTemp";
    20.  
    21.             DirectoryInfo dirInfo = new DirectoryInfo(oldPath);
    22.             if (dirInfo.Exists && Directory.Exists(newPath) == false)
    23.             {
    24.                 Debug.Log("Preparation, transfer StreamingAssets/Vuforia to Assets/VuforiaTemp");
    25.                 dirInfo.MoveTo(newPath);
    26.             }
    27.         }
    28.     }
    29.  
    30.     public void OnProcessScene(UnityEngine.SceneManagement.Scene scene)
    31.     {
    32.         if (PlayerSettings.Android.useAPKExpansionFiles == true)
    33.         {
    34.             string oldPath = Application.streamingAssetsPath + "/../VuforiaTemp";
    35.             string newPath = Application.streamingAssetsPath + "/../../Temp/StagingArea/assets/Vuforia";
    36.  
    37.             Debug.Log("Copy Assets/VuforiaStreamingAssets to " + newPath);
    38.  
    39.             DirectoryCopy(oldPath, newPath, true);
    40.         }
    41.     }
    42.  
    43.     public void OnPostprocessBuild(BuildTarget target, string path)
    44.     {
    45.         if (PlayerSettings.Android.useAPKExpansionFiles == true)
    46.         {
    47.             string oldPath = Application.streamingAssetsPath + "/../VuforiaTemp";
    48.             string newPath = Application.streamingAssetsPath + "/Vuforia";
    49.  
    50.             DirectoryInfo dirInfo = new DirectoryInfo(oldPath);
    51.             if (dirInfo.Exists && Directory.Exists(newPath) == false)
    52.             {
    53.                 Debug.Log("Returning folder Assets/VuforiaTemp back to StreamingAssets/Vuforia");
    54.                 dirInfo.MoveTo(newPath);
    55.             }
    56.         }
    57.     }
    58.  
    59.     private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
    60.     {
    61.         // Get the subdirectories for the specified directory.
    62.         DirectoryInfo dir = new DirectoryInfo(sourceDirName);
    63.         if (!dir.Exists)
    64.         {
    65.             throw new DirectoryNotFoundException(
    66.                 "Source directory does not exist or could not be found: "
    67.                 + sourceDirName);
    68.         }
    69.  
    70.         DirectoryInfo[] dirs = dir.GetDirectories();
    71.         // If the destination directory doesn't exist, create it.
    72.         if (!Directory.Exists(destDirName))
    73.         {
    74.             Directory.CreateDirectory(destDirName);
    75.         }
    76.  
    77.         // Get the files in the directory and copy them to the new location.
    78.         FileInfo[] files = dir.GetFiles();
    79.         foreach (FileInfo file in files)
    80.         {
    81.             if (!file.Name.Contains(".meta"))
    82.             {
    83.                 string temppath = Path.Combine(destDirName, file.Name);
    84.                 file.CopyTo(temppath, false);
    85.             }
    86.         }
    87.  
    88.         // If copying subdirectories, copy them and their contents to new location.
    89.         if (copySubDirs)
    90.         {
    91.             foreach (DirectoryInfo subdir in dirs)
    92.             {
    93.                 string temppath = Path.Combine(destDirName, subdir.Name);
    94.                 DirectoryCopy(subdir.FullName, temppath, copySubDirs);
    95.             }
    96.         }
    97.     }
    98.  
    99. }
    100. #endif //UNITY_ANDROID
    101.  
    102.  
    103.  
     
    Last edited: Mar 27, 2018
    dynamer likes this.
  12. skdev3

    skdev3

    Joined:
    Jul 15, 2015
    Posts:
    64
    OnProcessScene warning fix:

    Code (CSharp):
    1.  
    2. #if UNITY_ANDROID
    3. using UnityEngine;
    4. using UnityEditor;
    5. using UnityEditor.Build;
    6. using System.IO;
    7.  
    8. class VuforiaBuildProcessor : MonoBehaviour, IProcessScene, IPreprocessBuild, IPostprocessBuild
    9. {
    10.     public int callbackOrder { get { return 0; } }
    11.  
    12.     static bool IsRunBuild = false;
    13.  
    14.     // OnPreprocessBuild -> OnProcessScene -> OnPostprocessBuild
    15.     public void OnPreprocessBuild(BuildTarget target, string path)
    16.     {
    17.         IsRunBuild = true;
    18.         if (PlayerSettings.Android.useAPKExpansionFiles == true)
    19.         {
    20.             string oldPath = Application.streamingAssetsPath + "/Vuforia";
    21.             string newPath = Application.streamingAssetsPath + "/../VuforiaTemp";
    22.  
    23.             DirectoryInfo dirInfo = new DirectoryInfo(oldPath);
    24.             if (dirInfo.Exists && Directory.Exists(newPath) == false)
    25.             {
    26.                 Debug.Log("Preparation, transfer StreamingAssets/Vuforia to Assets/VuforiaTemp");
    27.                 dirInfo.MoveTo(newPath);
    28.             }
    29.         }
    30.     }
    31.  
    32.     public void OnProcessScene(UnityEngine.SceneManagement.Scene scene)
    33.     {
    34.         if (IsRunBuild)
    35.         {
    36.             if (PlayerSettings.Android.useAPKExpansionFiles == true)
    37.             {
    38.                 string oldPath = Application.streamingAssetsPath + "/../VuforiaTemp";
    39.                 string newPath = Application.streamingAssetsPath + "/../../Temp/StagingArea/assets/Vuforia";
    40.  
    41.                 Debug.Log("Copy Assets/VuforiaTemp to " + newPath);
    42.  
    43.                 DirectoryCopy(oldPath, newPath, true);
    44.             }
    45.         }
    46.     }
    47.  
    48.     public void OnPostprocessBuild(BuildTarget target, string path)
    49.     {
    50.         if (PlayerSettings.Android.useAPKExpansionFiles == true)
    51.         {
    52.             string oldPath = Application.streamingAssetsPath + "/../VuforiaTemp";
    53.             string newPath = Application.streamingAssetsPath + "/Vuforia";
    54.  
    55.             DirectoryInfo dirInfo = new DirectoryInfo(oldPath);
    56.             if (dirInfo.Exists && Directory.Exists(newPath) == false)
    57.             {
    58.                 Debug.Log("Returning folder Assets/VuforiaTemp back to StreamingAssets/Vuforia");
    59.                 dirInfo.MoveTo(newPath);
    60.             }
    61.         }
    62.         IsRunBuild = false;
    63.     }
    64.  
    65.  
    66.     private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
    67.     {
    68.         // Get the subdirectories for the specified directory.
    69.         DirectoryInfo dir = new DirectoryInfo(sourceDirName);
    70.         if (!dir.Exists)
    71.         {
    72.             throw new DirectoryNotFoundException(
    73.                 "Source directory does not exist or could not be found: "
    74.                 + sourceDirName);
    75.         }
    76.  
    77.         DirectoryInfo[] dirs = dir.GetDirectories();
    78.         // If the destination directory doesn't exist, create it.
    79.         if (!Directory.Exists(destDirName))
    80.         {
    81.             Directory.CreateDirectory(destDirName);
    82.         }
    83.  
    84.         // Get the files in the directory and copy them to the new location.
    85.         FileInfo[] files = dir.GetFiles();
    86.         foreach (FileInfo file in files)
    87.         {
    88.             if (!file.Name.Contains(".meta"))
    89.             {
    90.                 string temppath = Path.Combine(destDirName, file.Name);
    91.                 file.CopyTo(temppath, false);
    92.             }
    93.         }
    94.  
    95.         // If copying subdirectories, copy them and their contents to new location.
    96.         if (copySubDirs)
    97.         {
    98.             foreach (DirectoryInfo subdir in dirs)
    99.             {
    100.                 string temppath = Path.Combine(destDirName, subdir.Name);
    101.                 DirectoryCopy(subdir.FullName, temppath, copySubDirs);
    102.             }
    103.         }
    104.     }
    105.  
    106. }
    107. #endif //UNITY_ANDROID
    108.  
     
  13. sam598

    sam598

    Joined:
    Sep 21, 2014
    Posts:
    60
    I'm getting errors with this script, one per scene, and my vuforia targets are missing from streaming assets.

    IOException: /Users/Sam/Desktop/UnityApp/Temp/StagingArea/assets/Vuforia/MyDataset.dat already exists
     
    Last edited: Apr 14, 2018
  14. oliver_Random42

    oliver_Random42

    Joined:
    Oct 13, 2016
    Posts:
    10
    Hi @sam598 - didyou manage to fix these errors? Having the same issue.

    Cheers

    Oliver
     
  15. oliver_Random42

    oliver_Random42

    Joined:
    Oct 13, 2016
    Posts:
    10
    @skdev3 I am experiencing the same issues as @sam598
    I am using Unity 2017.4.1f1

    My errors are as follows:

    Code (CSharp):
    1. IOException: D:\Dropbox\_Projects\Unity\VR360\OBBAccessSerializedVideos\VRInOutTest - 2017.4 - AR\Temp\StagingArea\assets\Vuforia\Target-HSW-AR-test.dat already exists
    2. System.IO.File.Copy (System.String sourceFileName, System.String destFileName, Boolean overwrite) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/File.cs:115)
    3. System.IO.File.Copy (System.String sourceFileName, System.String destFileName) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/File.cs:86)
    4. System.IO.FileInfo.CopyTo (System.String destFileName, Boolean overwrite) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/FileInfo.cs:259)
    5. (wrapper remoting-invoke-with-check) System.IO.FileInfo:CopyTo (string,bool)
    6. VuforiaBuildProcessor.DirectoryCopy (System.String sourceDirName, System.String destDirName, Boolean copySubDirs) (at Assets/Editor/Vuforia/VuforiaBuildProcessor.cs:90)
    7. VuforiaBuildProcessor.OnProcessScene (Scene scene) (at Assets/Editor/Vuforia/VuforiaBuildProcessor.cs:42)
    8. UnityEditor.Build.BuildPipelineInterfaces.OnSceneProcess (Scene scene, Boolean strict) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs:304)
    9. UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
     
  16. oliver_Random42

    oliver_Random42

    Joined:
    Oct 13, 2016
    Posts:
    10
    @sam598 , @skdev3 , and for anybody else experiencing the same issue - I managed to solve it by navigating to my
    \Temp\StagingArea\assets\Vuforia\ and deleting all unused target .dat and .xml files.

    I also deleted all unsuded target .dat and .xml files fomrt he unity proejct and it compiled with a split application binary
     
    Vuforia-Strasza likes this.
  17. theolagendijk

    theolagendijk

    Joined:
    Nov 12, 2014
    Posts:
    117
    Vuforia-Strasza likes this.
  18. augivision

    augivision

    Joined:
    Mar 27, 2018
    Posts:
    14

    I cannot seem to get any of the above to work at all. Any suggestions?
     
  19. theolagendijk

    theolagendijk

    Joined:
    Nov 12, 2014
    Posts:
    117
    Can you be a bit more specific about what fails?
    Here's one suggestions; folder and filenames are case sensitive on Android.
     
  20. Gian1989

    Gian1989

    Joined:
    Mar 16, 2017
    Posts:
    1
    Hi @theolagendijk,

    I've the exactly same issue of @oliver_Random42, but I couldn't resolve simply by deleting those files in Temp folder.
    I'm always getting the same error code and I couldn't find a way to fix it.

    Also the other solution by @Vuforia-Strasza make my app crash every time I open a scene with ARCamera.

    Please someone could help me to solve this problem?

    I'm on Unity 2017.2.2f1 with Vuforia 6.5.25

    Thanks in advance
     
  21. theolagendijk

    theolagendijk

    Joined:
    Nov 12, 2014
    Posts:
    117
    I would advise to go with @Vuforia-Strasza 's solution. Can you share your apps crash log?
     
    Vuforia-Strasza likes this.
  22. Hiverlab

    Hiverlab

    Joined:
    Jul 10, 2015
    Posts:
    5
    Hello people, I am working on the same thing (Android vuforia obb) with Unity 2018.2.6, Vuforia version 7.2.23

    I am also trying to use the solution at https://developer.vuforia.com/forum/faq/load-dataset-android-split-binary-obb . However , my code always get stuck at the www.error part and im at my wits end.

    Am i doing my uri wrongly?


    Code (CSharp):
    1. //mainPath = "/storage/emulated/0/Android/obb/com.Hiverlab.ARTC/main.39.com.Hiverlab.ARTC.obb"
    2.         string[] filesInOBB = { "/ARTCDatabase.dat", "/ARTCDatabase.xml" };
    3.         foreach (string i in filesInOBB)
    4.         {
    5.             string uri = Application.streamingAssetsPath + "/Vuforia" + i;    //404 not found
    6. //            string uri = mainPath;                                            //java.net.ConnectException: Connection refused
    7. //            string uri = mainPath + "/Vuforia" + i;                            //java.net.ConnectException: Connection refused
    8. //            string uri = mainPath + "/StreamingAssets/Vuforia" + i;            //java.net.ConnectException: Connection refused
    9. //            string targetPath = "file://"+Application.persistentDataPath + "/Vuforia";
    10. //            string targetPath = Application.persistentDataPath + "/Vuforia";
    11.             string targetPath = GetAndroidFriendlyFilesPath () + "/Vuforia";
    12.  
    13.             Debug.Log ("FF = " + uri);
    14.             Debug.Log ("GG = " + targetPath);
    15.             if (!Directory.Exists (Path.GetDirectoryName (targetPath)))
    16.             {
    17.                 Debug.Log ("HH");
    18.                 Directory.CreateDirectory (Path.GetDirectoryName (targetPath));
    19.             }
    20.             targetPath += i;
    21.  
    22.             WWW www = new WWW (uri);
    23.             yield return www;
    24.  
    25.             Debug.Log ("JJ");
    26.             if (!string.IsNullOrEmpty (www.error)) {
    27.                 Debug.LogWarning (name + " www error: " + www.error);        //code always end here
    28.                 yield break;
    29.             }
    30.             else
    31.             {
    32.                 File.WriteAllBytes (targetPath, www.bytes);
    33.                 if( File.Exists( targetPath ) )
    34.                     Debug.Log (name + " file written: " + targetPath);
    35.                 else
    36.                     Debug.Log( "Failure!! - File does not exist at: " + targetPath );  
    37.             }
    38.  
    39.             Debug.Log ("KK");
    40.             yield return new WaitForEndOfFrame ();
    41.         }
    42.  
    43. //        Vuforia.DataSet.StorageType = Vuforia.DataSet.StorageType.STORAGE_ABSOLUTE;
    44.  
    45.         UnityEngine.SceneManagement.SceneManager.LoadScene (1);
    46.     }
    47.  
    48.     string GetAndroidFriendlyFilesPath()
    49.     {
    50.         #if UNITY_ANDROID
    51.         AndroidJavaClass up = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    52.         AndroidJavaObject currentActivity = up.GetStatic<AndroidJavaObject>("currentActivity");
    53.         AndroidJavaObject applicationContext = currentActivity.Call<AndroidJavaObject>("getApplicationContext");
    54.         AndroidJavaObject path = applicationContext.Call<AndroidJavaObject>("getFilesDir");
    55.         string filesPath = path.Call<string>("getCanonicalPath");
    56.         return filesPath;
    57.         #endif
    58.         return Application.persistentDataPath;
    59.     }
     
    BKSurveily likes this.
  23. cgydev

    cgydev

    Joined:
    Oct 2, 2015
    Posts:
    15
    Hi,

    I have tried this solution in which the XML/DAT files did manage to load correctly but before that happens while being in my Empty Scene I get the following error,

    The Vuforia Developer Agreement needs to be accepted before using Vuforia in an application.

    Did you encounter any such problem, if yes how did you get around it ?

    Thanks.
     
  24. lrb

    lrb

    Joined:
    Jun 21, 2014
    Posts:
    28
    Same issue here now!
    We used to work fine with Vuforia and OBB files, but now upgrading to 2019.3.x we start getting this same error as cgydev said. If the app is not splitted then works fine but it's not possible to publish.

    Any help here is really appreciated.
    Thanks.
     
  25. cgydev

    cgydev

    Joined:
    Oct 2, 2015
    Posts:
    15
    I don't know if this was the correct way of solving the problem or not. But I changed the package name to get problem fixed.
    Initially my package name was com.company.product.variation which I changed back to com.company.productvariation. Can't be sure but if the extra '.' may be cause the OBB file to not read correctly during the loading process ?

    This allowed me to test the OBB routine locally as well as worked correctly when uploaded to store for Beta testing.