public static bool UninstallAPK() { OVRBundleTool.PrintLog("Uninstalling Application . . ."); OVRADBTool adbTool = new OVRADBTool(OVRConfig.Instance.GetAndroidSDKPath()); if (adbTool.isReady) { string output, error; string appPackagename = PlayerSettings.GetApplicationIdentifier(BuildTargetGroup.Android) + GetTransitionApkOptionalIdentifier(); string[] appStartCommand = { "-d shell", "pm uninstall", appPackagename }; if (adbTool.RunCommand(appStartCommand, null, out output, out error) == 0) { OVRBundleTool.PrintSuccess(); OVRBundleTool.PrintLog("App package " + appPackagename + " is uninstalled."); return(true); } OVRBundleTool.PrintError("Failed to uninstall APK."); } else { OVRBundleTool.PrintError(ADB_TOOL_INITIALIZE_ERROR); } return(false); }
public static void DeleteRemoteAssetBundles() { OVRADBTool adbTool = new OVRADBTool(OVRConfig.Instance.GetAndroidSDKPath()); if (adbTool.isReady) { bool failure = false; string fileExistsError = "No such file or directory"; OVRBundleTool.PrintLog("Deleting device bundles . . . "); string output, error; string[] deleteBundleCommand = { "-d shell", "rm -r", externalSceneCache }; if (adbTool.RunCommand(deleteBundleCommand, null, out output, out error) != 0) { if (!(output.Contains(fileExistsError) || error.Contains(fileExistsError))) { failure = true; } } if (failure) { OVRBundleTool.PrintError(string.IsNullOrEmpty(error) ? output : error); OVRBundleTool.PrintError("Failed to delete scene bundle cache directory."); } else { OVRBundleTool.PrintSuccess(); } } else { OVRBundleTool.PrintError(ADB_TOOL_INITIALIZE_ERROR); } }
public static bool LaunchApplication() { OVRBundleTool.PrintLog("Launching Application . . . "); OVRADBTool adbTool = new OVRADBTool(OVRConfig.Instance.GetAndroidSDKPath()); if (adbTool.isReady) { string output, error; string appPackagename = PlayerSettings.GetApplicationIdentifier(BuildTargetGroup.Android) + GetTransitionApkOptionalIdentifier(); string playerActivityName = "\"" + appPackagename + "/com.unity3d.player.UnityPlayerActivity\""; string[] appStartCommand = { "-d shell", "am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -S -f 0x10200000 -n", playerActivityName }; if (adbTool.RunCommand(appStartCommand, null, out output, out error) == 0) { OVRBundleTool.PrintSuccess(); OVRBundleTool.PrintLog("App package " + appPackagename + " is launched."); return(true); } string completeError = "Failed to launch application. Try launching it manually through the device.\n" + (string.IsNullOrEmpty(error) ? output : error); OVRBundleTool.PrintError(completeError); } else { OVRBundleTool.PrintError(ADB_TOOL_INITIALIZE_ERROR); } return(false); }
public static bool UninstallAPK() { OVRBundleTool.PrintLog("Uninstalling Application . . ."); OVRADBTool adbTool = new OVRADBTool(OVRConfig.Instance.GetAndroidSDKPath()); if (adbTool.isReady) { string output, error; string packageName = Application.identifier + ".transition"; string[] appStartCommand = { "-d shell", "pm uninstall", packageName }; if (adbTool.RunCommand(appStartCommand, null, out output, out error) == 0) { OVRBundleTool.PrintSuccess(); return(true); } OVRBundleTool.PrintError("Failed to uninstall APK."); } else { OVRBundleTool.PrintError(ADB_TOOL_INITIALIZE_ERROR); } return(false); }
public static string[] ListRemoteAssetBundleNames() { OVRADBTool adbTool = new OVRADBTool(OVRConfig.Instance.GetAndroidSDKPath()); if (adbTool.isReady) { externalSceneCache = EXTERNAL_STORAGE_PATH + "/" + PlayerSettings.GetApplicationIdentifier(BuildTargetGroup.Android) + GetTransitionApkOptionalIdentifier() + "/cache/scenes"; string output, error; string[] listBundlesCommand = { "-d shell", "ls", externalSceneCache }; if (adbTool.RunCommand(listBundlesCommand, null, out output, out error) == 0) { return(output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)); } } return(null); }
public static void DeleteRemoteAssetBundles() { OVRADBTool adbTool = new OVRADBTool(OVRConfig.Instance.GetAndroidSDKPath()); if (adbTool.isReady) { externalSceneCache = EXTERNAL_STORAGE_PATH + "/" + PlayerSettings.GetApplicationIdentifier(BuildTargetGroup.Android) + GetTransitionApkOptionalIdentifier() + "/cache/scenes"; bool failure = false; string fileExistsError = "No such file or directory"; OVRBundleTool.PrintLog("Deleting device bundles . . . "); string output, error; string[] deleteBundleCommand = { "-d shell", "rm -r", externalSceneCache }; if (adbTool.RunCommand(deleteBundleCommand, null, out output, out error) != 0) { if (!(output.Contains(fileExistsError) || error.Contains(fileExistsError))) { failure = true; } } if (failure) { OVRBundleTool.PrintError(string.IsNullOrEmpty(error) ? output : error); OVRBundleTool.PrintError("Failed to delete scene bundle cache directory."); } else { OVRBundleTool.PrintSuccess(); } } else { OVRBundleTool.PrintError(ADB_TOOL_INITIALIZE_ERROR); } }
private static void CheckForTransitionAPK() { OVRADBTool adbTool = new OVRADBTool(OVRConfig.Instance.GetAndroidSDKPath()); if (adbTool.isReady) { string matchedPackageList, error; var transitionPackageName = PlayerSettings.applicationIdentifier; if (useOptionalTransitionApkPackage) { transitionPackageName += ".transition"; } string[] packageCheckCommand = new string[] { "-d shell pm list package", transitionPackageName }; if (adbTool.RunCommand(packageCheckCommand, null, out matchedPackageList, out error) == 0) { if (string.IsNullOrEmpty(matchedPackageList)) { currentApkStatus = ApkStatus.NOT_INSTALLED; } else { // adb "list package" command returns all package names that contains the given query package name // Need to check if the transition package name is matched exactly if (matchedPackageList.Contains("package:" + transitionPackageName + "\r\n")) { if (useOptionalTransitionApkPackage) { // If optional package name is used, it is deterministic that the transition apk is installed currentApkStatus = ApkStatus.OK; } else { // get package info to check for TRANSITION_APK_VERSION_NAME string[] dumpPackageInfoCommand = new string[] { "-d shell dumpsys package", transitionPackageName }; string packageInfo; if (adbTool.RunCommand(dumpPackageInfoCommand, null, out packageInfo, out error) == 0 && !string.IsNullOrEmpty(packageInfo) && packageInfo.Contains(OVRBundleManager.TRANSITION_APK_VERSION_NAME)) { // Matched package name found, and the package info contains TRANSITION_APK_VERSION_NAME currentApkStatus = ApkStatus.OK; } else { currentApkStatus = ApkStatus.NOT_INSTALLED; } } } else { // No matached package name returned currentApkStatus = ApkStatus.NOT_INSTALLED; } } } else if (error.Contains("no devices found")) { currentApkStatus = ApkStatus.DEVICE_NOT_CONNECTED; } else { currentApkStatus = ApkStatus.UNKNOWN; } } }
private static bool TransferSceneBundles(OVRADBTool adbTool, string absoluteTempPath, string externalSceneCache) { List <string> bundlesToTransfer = new List <string>(); List <string> bundlesToDelete = new List <string>(); string manifestFilePath = externalSceneCache + "/" + BUNDLE_MANAGER_MASTER_BUNDLE; string[] pullManifestCommand = { "-d pull", "\"" + manifestFilePath + "\"", "\"" + absoluteTempPath + "\"" }; string output, error; if (adbTool.RunCommand(pullManifestCommand, null, out output, out error) == 0) { // An existing manifest file was found on device. Load hashes and upload bundles that have changed hashes. Debug.Log("[OVRBundleManager] - Scene bundle manifest file found. Decoding changes . . ."); // Load hashes from remote manifest AssetBundle remoteBundle = AssetBundle.LoadFromFile(Path.Combine(absoluteTempPath, BUNDLE_MANAGER_MASTER_BUNDLE)); if (remoteBundle == null) { OVRBundleTool.PrintError("Failed to load remote asset bundle manifest file."); return(false); } AssetBundleManifest remoteManifest = remoteBundle.LoadAsset <AssetBundleManifest>("AssetBundleManifest"); Dictionary <string, Hash128> remoteBundleToHash = new Dictionary <string, Hash128>(); if (remoteManifest != null) { string[] assetBundles = remoteManifest.GetAllAssetBundles(); foreach (string bundleName in assetBundles) { remoteBundleToHash[bundleName] = remoteManifest.GetAssetBundleHash(bundleName); } } remoteBundle.Unload(true); // Load hashes from local manifest AssetBundle localBundle = AssetBundle.LoadFromFile(BUNDLE_MANAGER_OUTPUT_PATH + "\\" + BUNDLE_MANAGER_MASTER_BUNDLE + "\\" + BUNDLE_MANAGER_MASTER_BUNDLE); if (localBundle == null) { OVRBundleTool.PrintError("<color=red>Failed to load local asset bundle manifest file.\n</color>"); return(false); } AssetBundleManifest localManifest = localBundle.LoadAsset <AssetBundleManifest>("AssetBundleManifest"); if (localManifest != null) { Hash128 zeroHash = new Hash128(0, 0, 0, 0); // Build a list of dirty bundles that will have to be transfered string relativeSceneBundlesPath = Path.Combine(BUNDLE_MANAGER_OUTPUT_PATH, BUNDLE_MANAGER_MASTER_BUNDLE); bundlesToTransfer.Add(Path.Combine(relativeSceneBundlesPath, BUNDLE_MANAGER_MASTER_BUNDLE)); string[] assetBundles = localManifest.GetAllAssetBundles(); foreach (string bundleName in assetBundles) { if (!remoteBundleToHash.ContainsKey(bundleName)) { bundlesToTransfer.Add(Path.Combine(relativeSceneBundlesPath, bundleName)); } else { if (remoteBundleToHash[bundleName] != localManifest.GetAssetBundleHash(bundleName)) { bundlesToTransfer.Add(Path.Combine(relativeSceneBundlesPath, bundleName)); } remoteBundleToHash[bundleName] = zeroHash; } } OVRBundleTool.PrintLog(bundlesToTransfer.Count + " dirty bundle(s) will be transfered.\n"); } } else { if (output.Contains("does not exist") || output.Contains("No such file or directory")) { // Fresh install of asset bundles, transfer all asset bundles OVRBundleTool.PrintLog("Manifest file not found. Transfering all bundles . . . "); string[] mkdirCommand = { "-d shell", "mkdir -p", "\"" + externalSceneCache + "\"" }; if (adbTool.RunCommand(mkdirCommand, null, out output, out error) == 0) { string absoluteSceneBundlePath = Path.Combine(Path.Combine(Application.dataPath, ".."), Path.Combine(BUNDLE_MANAGER_OUTPUT_PATH, BUNDLE_MANAGER_MASTER_BUNDLE)); string[] assetBundlePaths = Directory.GetFiles(absoluteSceneBundlePath); if (assetBundlePaths.Length != 0) { foreach (string path in assetBundlePaths) { if (!path.Contains(".manifest")) { bundlesToTransfer.Add(path); } } } else { OVRBundleTool.PrintError("Failed to locate scene bundles to transfer."); return(false); } } } } // If any adb error occured during manifest calculation, print it and return false if (!string.IsNullOrEmpty(error) || output.Contains("error")) { OVRBundleTool.PrintError(string.IsNullOrEmpty(error) ? output : error); return(false); } // Transfer bundles to device DateTime transferStart = DateTime.Now; foreach (string bundle in bundlesToTransfer) { string absoluteBundlePath = Path.Combine(Path.Combine(Application.dataPath, ".."), bundle); string[] pushBundleCommand = { "-d push", "\"" + absoluteBundlePath + "\"", "\"" + externalSceneCache + "\"" }; adbTool.RunCommandAsync(pushBundleCommand, null); } Debug.Log("[OVRBundleManager] - Transfer took " + (DateTime.Now - transferStart).TotalSeconds + " seconds."); // Delete stale bundles on device if (bundlesToDelete.Count > 0) { foreach (string bundle in bundlesToDelete) { string bundlePath = externalSceneCache + "/" + bundle; string[] deleteBundleCommand = { "-d shell", "rm", "\"" + bundlePath + "\"" }; adbTool.RunCommandAsync(deleteBundleCommand, null); } OVRBundleTool.PrintLog("Deleted " + bundlesToDelete.Count + " bundle(s) that were stale"); } return(true); }
private static bool DeploySceneBundles(List <OVRBundleTool.EditorSceneInfo> sceneList) { // Create Temp directory on local machine if it does not exist string tempDirectory = Path.Combine(BUNDLE_MANAGER_OUTPUT_PATH, "Temp"); if (!Directory.Exists(tempDirectory)) { Directory.CreateDirectory(tempDirectory); } string absoluteTempPath = Path.Combine(Path.Combine(Application.dataPath, ".."), tempDirectory); OVRBundleTool.PrintLog("Deploying scene bundles to device . . . "); OVRADBTool adbTool = new OVRADBTool(OVRConfig.Instance.GetAndroidSDKPath()); if (adbTool.isReady) { DateTime transferStart = DateTime.Now; for (int i = 0; i < sceneList.Count; ++i) { if (!sceneList[i].shouldDeploy) { continue; } OVRBundleTool.UpdateSceneBuildStatus(OVRBundleTool.SceneBundleStatus.TRANSFERRING, i); } // Transfer all scene bundles that are relavent if (!TransferSceneBundles(adbTool, absoluteTempPath, externalSceneCache)) { return(false); } for (int i = 0; i < sceneList.Count; ++i) { if (!sceneList[i].shouldDeploy) { continue; } OVRBundleTool.UpdateSceneBuildStatus(OVRBundleTool.SceneBundleStatus.DEPLOYED, i); } // Create file to tell transition scene APK which scene to load and push it to the device string sceneLoadDataPath = Path.Combine(tempDirectory, OVRSceneLoader.sceneLoadDataName); if (File.Exists(sceneLoadDataPath)) { File.Delete(sceneLoadDataPath); } StreamWriter writer = new StreamWriter(sceneLoadDataPath, true); // Write version and scene names long unixTime = (int)(DateTimeOffset.UtcNow.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds; writer.WriteLine(unixTime.ToString()); for (int i = 0; i < sceneList.Count; i++) { if (!sceneList[i].shouldDeploy) { continue; } writer.WriteLine(Path.GetFileNameWithoutExtension(sceneList[i].scenePath)); } writer.Close(); string absoluteSceneLoadDataPath = Path.Combine(absoluteTempPath, OVRSceneLoader.sceneLoadDataName); string[] pushCommand = { "-d push", "\"" + absoluteSceneLoadDataPath + "\"", "\"" + externalSceneCache + "\"" }; string output, error; if (adbTool.RunCommand(pushCommand, null, out output, out error) == 0) { Debug.Log("[OVRBundleManager] Scene Load Data Pushed to Device."); return(true); } OVRBundleTool.PrintError(string.IsNullOrEmpty(error) ? output : error); } else { OVRBundleTool.PrintError(ADB_TOOL_INITIALIZE_ERROR); } return(false); }
public static bool DeployAPK() { // Create new instance of ADB Tool var adbTool = new OVRADBTool(androidSdkPath); if (adbTool.isReady) { string apkPathLocal; string gradleExportFolder = Path.Combine(Path.Combine(gradleExport, productName), "build\\outputs\\apk\\debug"); // Check to see if gradle output directory exists gradleExportFolder = gradleExportFolder.Replace("/", "\\"); if (!Directory.Exists(gradleExportFolder)) { UnityEngine.Debug.LogError("Could not find the gradle project at the expected path: " + gradleExportFolder); return(false); } // Search for output APK in gradle output directory apkPathLocal = Path.Combine(gradleExportFolder, productName + "-debug.apk"); if (!System.IO.File.Exists(apkPathLocal)) { UnityEngine.Debug.LogError(string.Format("Could not find {0} in the gradle project.", productName + "-debug.apk")); return(false); } string output, error; DateTime timerStart; // Ensure that the Oculus temp directory is on the device by making it IncrementProgressBar("Making Temp directory on device"); string[] mkdirCommand = { "-d shell", "mkdir -p", REMOTE_APK_PATH }; if (adbTool.RunCommand(mkdirCommand, null, out output, out error) != 0) { return(false); } // Push APK to device, also time how long it takes timerStart = System.DateTime.Now; IncrementProgressBar("Pushing APK to device . . ."); string[] pushCommand = { "-d push", "\"" + apkPathLocal + "\"", REMOTE_APK_PATH }; if (adbTool.RunCommand(pushCommand, null, out output, out error) != 0) { return(false); } // Calculate the transfer speed and determine if user is using USB 2.0 or 3.0 TimeSpan pushTime = System.DateTime.Now - timerStart; FileInfo apkInfo = new System.IO.FileInfo(apkPathLocal); double transferSpeed = (apkInfo.Length / pushTime.TotalSeconds) / BYTES_TO_MEGABYTES; bool informLog = transferSpeed < USB_TRANSFER_SPEED_THRES; UnityEngine.Debug.Log("OVRADBTool: Push Success"); // Install the APK package on the device IncrementProgressBar("Installing APK . . ."); string apkPath = REMOTE_APK_PATH + "/" + productName + "-debug.apk"; apkPath = apkPath.Replace(" ", "\\ "); string[] installCommand = { "-d shell", "pm install -r", apkPath }; timerStart = System.DateTime.Now; if (adbTool.RunCommand(installCommand, null, out output, out error) != 0) { return(false); } TimeSpan installTime = System.DateTime.Now - timerStart; UnityEngine.Debug.Log("OVRADBTool: Install Success"); // Start the application on the device IncrementProgressBar("Launching application on device . . ."); #if UNITY_2019_3_OR_NEWER string playerActivityName = "\"" + applicationIdentifier + "/com.unity3d.player.UnityPlayerActivity\""; #else string playerActivityName = "\"" + applicationIdentifier + "/" + applicationIdentifier + ".UnityPlayerActivity\""; #endif string[] appStartCommand = { "-d shell", "am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -S -f 0x10200000 -n", playerActivityName }; if (adbTool.RunCommand(appStartCommand, null, out output, out error) != 0) { return(false); } UnityEngine.Debug.Log("OVRADBTool: Application Start Success"); // Send back metrics on push and install steps OVRPlugin.AddCustomMetadata("transfer_speed", transferSpeed.ToString()); OVRPlugin.SendEvent("build_step_push_apk", pushTime.TotalSeconds.ToString(), "ovrbuild"); OVRPlugin.SendEvent("build_step_install_apk", installTime.TotalSeconds.ToString(), "ovrbuild"); IncrementProgressBar("Success!"); // If the user is using a USB 2.0 cable, inform them about improved transfer speeds and estimate time saved if (informLog) { var usb3Time = apkInfo.Length / (USB_3_TRANSFER_SPEED * BYTES_TO_MEGABYTES); UnityEngine.Debug.Log(string.Format("OVRBuild has detected slow transfer speeds. A USB 3.0 cable is recommended to reduce the time it takes to deploy your project by approximatly {0:0.0} seconds", pushTime.TotalSeconds - usb3Time)); return(true); } } else { UnityEngine.Debug.LogError("Could not find the ADB executable in the specified Android SDK directory."); } return(false); }
public static bool DeployAPK() { // Create new instance of ADB Tool var adbTool = new OVRADBTool(androidSdkPath); if (adbTool.isReady) { string apkPathLocal; string buildFlavor = isDevelopmentBuild ? "debug" : "release"; string gradleExportFolder = Path.Combine(gradleExport, productName, $"build\\outputs\\apk\\{buildFlavor}"); // Check to see if gradle output directory exists gradleExportFolder = gradleExportFolder.Replace("/", "\\"); if (!Directory.Exists(gradleExportFolder)) { UnityEngine.Debug.LogError("Could not find the gradle project at the expected path: " + gradleExportFolder); return(false); } // Search for output APK in gradle output directory apkPathLocal = Path.Combine(gradleExportFolder, productName + $"-{buildFlavor}.apk"); if (!System.IO.File.Exists(apkPathLocal)) { UnityEngine.Debug.LogError(string.Format("Could not find {0} in the gradle project.", productName + $"-{buildFlavor}.apk")); return(false); } string output, error; DateTime timerStart; // Ensure that the Oculus temp directory is on the device by making it IncrementProgressBar("Making Temp directory on device"); string[] mkdirCommand = { "-d shell", "mkdir -p", REMOTE_APK_PATH }; if (adbTool.RunCommand(mkdirCommand, null, out output, out error) != 0) { return(false); } // Push APK to device, also time how long it takes timerStart = System.DateTime.Now; IncrementProgressBar("Pushing APK to device . . ."); string[] pushCommand = { "-d push", "\"" + apkPathLocal + "\"", REMOTE_APK_PATH }; if (adbTool.RunCommand(pushCommand, null, out output, out error) != 0) { return(false); } // Calculate the transfer speed and determine if user is using USB 2.0 or 3.0 // Only bother informing the user on non-trivial transfers, as for very short // periods of time, things like process creation overhead can dwarf the actual // transfer time. TimeSpan pushTime = System.DateTime.Now - timerStart; bool trivialPush = pushTime.TotalSeconds < TRANSFER_SPEED_CHECK_THRESHOLD; long? apkSize = (trivialPush ? (long?)null : new System.IO.FileInfo(apkPathLocal).Length); double? transferSpeed = (apkSize / pushTime.TotalSeconds) / BYTES_TO_MEGABYTES; bool informLog = transferSpeed.HasValue && transferSpeed.Value < USB_TRANSFER_SPEED_THRES; UnityEngine.Debug.Log("OVRADBTool: Push Success"); // Install the APK package on the device IncrementProgressBar("Installing APK . . ."); string apkPath = REMOTE_APK_PATH + "/" + productName + "-debug.apk"; apkPath = apkPath.Replace(" ", "\\ "); string[] installCommand = { "-d shell", "pm install -r", apkPath }; timerStart = System.DateTime.Now; if (adbTool.RunCommand(installCommand, null, out output, out error) != 0) { return(false); } TimeSpan installTime = System.DateTime.Now - timerStart; UnityEngine.Debug.Log("OVRADBTool: Install Success"); // Start the application on the device IncrementProgressBar("Launching application on device . . ."); #if UNITY_2019_3_OR_NEWER string playerActivityName = "\"" + applicationIdentifier + "/com.unity3d.player.UnityPlayerActivity\""; #else string playerActivityName = "\"" + applicationIdentifier + "/" + applicationIdentifier + ".UnityPlayerActivity\""; #endif string[] appStartCommand = { "-d shell", "am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -S -f 0x10200000 -n", playerActivityName }; if (adbTool.RunCommand(appStartCommand, null, out output, out error) != 0) { return(false); } UnityEngine.Debug.Log("OVRADBTool: Application Start Success"); IncrementProgressBar("Success!"); // If the user is using a USB 2.0 cable, inform them about improved transfer speeds and estimate time saved if (informLog) { float usb3Time = apkSize.Value / (USB_3_TRANSFER_SPEED * BYTES_TO_MEGABYTES); // `informLog` can't be true if `apkSize` is null. UnityEngine.Debug.Log(string.Format("OVRBuild has detected slow transfer speeds. A USB 3.0 cable is recommended to reduce the time it takes to deploy your project by approximatly {0:0.0} seconds", pushTime.TotalSeconds - usb3Time)); return(true); } } else { UnityEngine.Debug.LogError("Could not find the ADB executable in the specified Android SDK directory."); } return(false); }