示例#1
0
        private BundletoolHelper.BuildBundleConfigParams CreateBuildBundleConfigParams(CreateBundleOptions options)
        {
            var configParams = new BundletoolHelper.BuildBundleConfigParams
            {
                defaultTcfSuffix = TextureTargetingTools.GetBundleToolTextureCompressionFormatName(
                    options.AssetPackConfig.DefaultTextureCompressionFormat),
                minSdkVersion                = _minSdkVersion,
                compressionOptions           = options.CompressionOptions ?? new CompressionOptions(),
                containsInstallTimeAssetPack = options.AssetPackConfig.SplitBaseModuleAssets
            };

            var assetPacks = options.AssetPackConfig.DeliveredAssetPacks;

            foreach (var entry in assetPacks)
            {
                var assetPackName = entry.Key;
                var assetPack     = entry.Value;

                configParams.enableTcfTargeting           |= assetPack.CompressionFormatToAssetBundleFilePath != null;
                configParams.enableTcfTargeting           |= assetPack.CompressionFormatToAssetPackDirectoryPath != null;
                configParams.containsInstallTimeAssetPack |=
                    assetPack.DeliveryMode == AssetPackDeliveryMode.InstallTime;
            }

            configParams.containsInstallTimeAssetPack |= options.AssetPackConfig.SplitBaseModuleAssets;


            return(configParams);
        }
示例#2
0
        private static string GetCompressionFormatSuffix(MobileTextureSubtarget subtarget)
        {
            var format = GetCompressionFormat(subtarget);

            return(TextureTargetingTools.GetTargetingSuffix(format));
        }
        private bool CreateAssetPackModule(
            string assetPackName, AssetPack assetPack, DirectoryInfo assetPackDirectoryInfo)
        {
            var androidManifestXmlPath     = Path.Combine(assetPackDirectoryInfo.FullName, AndroidManifestFileName);
            var assetPackManifestXDocument =
                CreateAssetPackManifestXDocument(assetPackName, assetPack.DeliveryMode);

            assetPackManifestXDocument.Save(androidManifestXmlPath);

            // Use aapt2 link to make a bundletool compatible module
            var sourceDirectoryInfo = assetPackDirectoryInfo.CreateSubdirectory("source");
            var aaptErrorMessage    =
                _androidAssetPackagingTool.Link(androidManifestXmlPath, sourceDirectoryInfo.FullName);

            if (aaptErrorMessage != null)
            {
                DisplayBuildError("aapt2 link " + assetPackName, aaptErrorMessage);
                return(false);
            }

            var destinationDirectoryInfo = GetDestinationSubdirectory(assetPackDirectoryInfo);

            ArrangeFilesForAssetPack(sourceDirectoryInfo, destinationDirectoryInfo);

            // Copy all assets to an "assets" subdirectory in the destination folder.
            var destinationAssetsDirectory = destinationDirectoryInfo.CreateSubdirectory(AssetsDirectoryName);

            if (assetPack.AssetBundleFilePath != null)
            {
                // Copy AssetBundle files into the module's "assets" folder, inside an "assetpack" folder.
                var outputDirectory = destinationAssetsDirectory.CreateSubdirectory(AssetPackFolder).FullName;
                File.Copy(assetPack.AssetBundleFilePath, Path.Combine(outputDirectory, assetPackName));
            }
            else if (assetPack.CompressionFormatToAssetBundleFilePath != null)
            {
                // Copy the AssetBundle files into the module's "assets" folder, inside an "assetpack#tcf_xxx" folder.
                foreach (var compressionAndFilePath in assetPack.CompressionFormatToAssetBundleFilePath)
                {
                    var targetedAssetsFolderName =
                        AssetPackFolder + TextureTargetingTools.GetTargetingSuffix(compressionAndFilePath.Key);
                    var outputDirectory = destinationAssetsDirectory.CreateSubdirectory(targetedAssetsFolderName);
                    File.Copy(compressionAndFilePath.Value, Path.Combine(outputDirectory.FullName, assetPackName));
                }
            }
            else if (assetPack.AssetPackDirectoryPath != null)
            {
                var sourceAssetsDirectory = new DirectoryInfo(assetPack.AssetPackDirectoryPath);
                if (!sourceAssetsDirectory.Exists)
                {
                    // TODO: check this earlier.
                    DisplayBuildError("Missing directory for " + assetPackName, sourceAssetsDirectory.FullName);
                    return(false);
                }

                // Copy asset pack files into the module's "assets" folder, inside an "assetpack" folder.
                var outputDirectory = destinationAssetsDirectory.CreateSubdirectory(AssetPackFolder);
                CopyFilesRecursively(sourceAssetsDirectory, outputDirectory);
            }
            else
            {
                throw new InvalidOperationException("Missing asset pack files: " + assetPackName);
            }

            return(true);
        }
        /// <summary>
        /// Synchronously builds an Android App Bundle at the specified path using the specified Android Player.
        /// </summary>
        /// <returns>True if the build succeeded, false if it failed or was cancelled.</returns>
        public bool CreateBundle(string aabFilePath, string androidPlayerFilePath, AssetPackConfig assetPackConfig)
        {
            if (_buildStatus != BuildStatus.Running)
            {
                throw new Exception("Unexpected call to CreateBundle() with status: " + _buildStatus);
            }

            var moduleDirectoryList = new List <DirectoryInfo>();
            var workingDirectory    = new DirectoryInfo(_workingDirectoryPath);
            var configParams        = new BundletoolHelper.BuildBundleConfigParams
            {
                defaultTcfSuffix = TextureTargetingTools.GetBundleToolTextureCompressionFormatName(
                    assetPackConfig.DefaultTextureCompressionFormat),
                minSdkVersion = _minSdkVersion
            };

            // Create asset pack module directories.
            var index      = 0;
            var assetPacks = assetPackConfig.DeliveredAssetPacks;

            foreach (var entry in assetPacks)
            {
                DisplayProgress(
                    string.Format("Processing asset pack {0} of {1}", index + 1, assetPacks.Count),
                    Mathf.Lerp(0.1f, ProgressCreateBaseModule, (float)index / assetPacks.Count));
                index++;

                var assetPackName = entry.Key;
                var assetPack     = entry.Value;
                configParams.enableTcfTargeting           |= assetPack.CompressionFormatToAssetBundleFilePath != null;
                configParams.containsInstallTimeAssetPack |=
                    assetPack.DeliveryMode == AssetPackDeliveryMode.InstallTime;

                var assetPackDirectoryInfo = workingDirectory.CreateSubdirectory(assetPackName);
                if (!CreateAssetPackModule(assetPackName, assetPack, assetPackDirectoryInfo))
                {
                    return(false);
                }

                moduleDirectoryList.Add(assetPackDirectoryInfo);
            }

            // Create base module directory.
            var            baseDirectory = workingDirectory.CreateSubdirectory(AndroidAppBundle.BaseModuleName);
            IList <string> bundleMetadata;

            if (!CreateBaseModule(baseDirectory, androidPlayerFilePath, out bundleMetadata))
            {
                return(false);
            }

            moduleDirectoryList.Add(baseDirectory);

            // Create a ZIP file for each module directory.
            var moduleFiles = new List <string>();
            var numModules  = moduleDirectoryList.Count;

            for (var i = 0; i < numModules; i++)
            {
                if (numModules == 1)
                {
                    DisplayProgress("Processing base module", ProgressProcessModules);
                }
                else
                {
                    DisplayProgress(
                        string.Format("Processing module {0} of {1}", i + 1, numModules),
                        Mathf.Lerp(ProgressProcessModules, ProgressRunBundletool, (float)i / numModules));
                }

                var moduleDirectoryInfo      = moduleDirectoryList[i];
                var destinationDirectoryInfo = GetDestinationSubdirectory(moduleDirectoryInfo);

                // Create ZIP file path, for example /path/to/files/base becomes /path/to/files/base/base.zip
                var zipFilePath     = Path.Combine(moduleDirectoryInfo.FullName, moduleDirectoryInfo.Name + ".zip");
                var zipErrorMessage = _zipUtils.CreateZipFile(zipFilePath, destinationDirectoryInfo.FullName, ".");
                if (zipErrorMessage != null)
                {
                    DisplayBuildError("Zip creation", zipErrorMessage);
                    return(false);
                }

                moduleFiles.Add(zipFilePath);
            }

            // If the .aab file exists, EditorUtility.SaveFilePanel() has already prompted for whether to overwrite.
            // Therefore, prevent Bundletool from throwing an IllegalArgumentException that "File already exists."
            File.Delete(aabFilePath);

            DisplayProgress("Running bundletool", ProgressRunBundletool);
            var buildBundleErrorMessage =
                _bundletool.BuildBundle(aabFilePath, moduleFiles, bundleMetadata, configParams);

            if (buildBundleErrorMessage != null)
            {
                DisplayBuildError("bundletool", buildBundleErrorMessage);
                return(false);
            }

            DisplayProgress("Signing bundle", 0.9f);
            var signingErrorMessage = _apkSigner.SignZip(aabFilePath);

            if (signingErrorMessage != null)
            {
                DisplayBuildError("Signing", signingErrorMessage);
                return(false);
            }

            Debug.LogFormat("Finished building app bundle: {0}", aabFilePath);
            _finishedAabFilePath = aabFilePath;
            _buildStatus         = BuildStatus.Succeeding;
            return(true);
        }
示例#5
0
        /// <summary>
        /// Synchronously builds an AAB given the specified options and existing Android Player on disk.
        /// </summary>
        /// <returns>An error message if there was an error, or null if successful.</returns>
        public string CreateBundle(string aabFilePath, AssetPackConfig assetPackConfig)
        {
            if (_buildStatus != BuildStatus.Running)
            {
                throw new Exception("Unexpected call to CreateBundle() with status: " + _buildStatus);
            }

            var moduleDirectoryList = new List <DirectoryInfo>();
            var workingDirectory    = new DirectoryInfo(_workingDirectoryPath);
            var configParams        = new BundletoolHelper.BuildBundleConfigParams
            {
                defaultTcfSuffix = TextureTargetingTools.GetBundleToolTextureCompressionFormatName(
                    assetPackConfig.DefaultTextureCompressionFormat),
                minSdkVersion = _minSdkVersion
            };

            // Create asset pack module directories.
            var index      = 0;
            var assetPacks = assetPackConfig.DeliveredAssetPacks;

            foreach (var entry in assetPacks)
            {
                DisplayProgress(
                    string.Format("Processing asset pack {0} of {1}", index + 1, assetPacks.Count),
                    Mathf.Lerp(0.1f, ProgressCreateBaseModule, (float)index / assetPacks.Count));
                index++;

                var assetPackName = entry.Key;
                var assetPack     = entry.Value;
                configParams.enableTcfTargeting           |= assetPack.CompressionFormatToAssetBundleFilePath != null;
                configParams.enableTcfTargeting           |= assetPack.CompressionFormatToAssetPackDirectoryPath != null;
                configParams.containsInstallTimeAssetPack |=
                    assetPack.DeliveryMode == AssetPackDeliveryMode.InstallTime;

                var assetPackDirectoryInfo = workingDirectory.CreateSubdirectory(assetPackName);
                var assetPackErrorMessage  = CreateAssetPackModule(assetPackName, assetPack, assetPackDirectoryInfo);
                if (assetPackErrorMessage != null)
                {
                    // Already displayed the error.
                    return(assetPackErrorMessage);
                }

                moduleDirectoryList.Add(assetPackDirectoryInfo);
            }

            // Create base module directory.
            var            baseDirectory = workingDirectory.CreateSubdirectory(AndroidAppBundle.BaseModuleName);
            IList <string> bundleMetadata;
            var            baseErrorMessage = CreateBaseModule(baseDirectory, out bundleMetadata);

            if (baseErrorMessage != null)
            {
                // Already displayed the error.
                return(baseErrorMessage);
            }

            moduleDirectoryList.Add(baseDirectory);

            // Create a ZIP file for each module directory.
            var moduleFiles = new List <string>();
            var numModules  = moduleDirectoryList.Count;

            for (var i = 0; i < numModules; i++)
            {
                if (numModules == 1)
                {
                    DisplayProgress("Processing base module", ProgressProcessModules);
                }
                else
                {
                    DisplayProgress(
                        string.Format("Processing module {0} of {1}", i + 1, numModules),
                        Mathf.Lerp(ProgressProcessModules, ProgressRunBundletool, (float)i / numModules));
                }

                var moduleDirectoryInfo      = moduleDirectoryList[i];
                var destinationDirectoryInfo = GetDestinationSubdirectory(moduleDirectoryInfo);

                // Create ZIP file path, for example /path/to/files/base becomes /path/to/files/base/base.zip
                var zipFilePath     = Path.Combine(moduleDirectoryInfo.FullName, moduleDirectoryInfo.Name + ".zip");
                var zipErrorMessage = _zipUtils.CreateZipFile(zipFilePath, destinationDirectoryInfo.FullName, ".");
                if (zipErrorMessage != null)
                {
                    return(DisplayBuildError("Zip creation", zipErrorMessage));
                }

                moduleFiles.Add(zipFilePath);
            }

            DisplayProgress("Running bundletool", ProgressRunBundletool);
            var buildBundleErrorMessage =
                _bundletool.BuildBundle(aabFilePath, moduleFiles, bundleMetadata, configParams);

            if (buildBundleErrorMessage != null)
            {
                return(DisplayBuildError("Bundletool", buildBundleErrorMessage));
            }

            // Only sign the .aab if a custom keystore is configured.
            if (_jarSigner.UseCustomKeystore)
            {
                DisplayProgress("Signing bundle", 0.9f);
                var signingErrorMessage = _jarSigner.Sign(aabFilePath);
                if (signingErrorMessage != null)
                {
                    return(DisplayBuildError("Signing", signingErrorMessage));
                }
            }
            else
            {
                Debug.LogFormat("Skipped signing since a Custom Keystore isn't configured in Android Player Settings");
            }

            MoveSymbolsZipFile(aabFilePath);

            Debug.LogFormat("Finished building app bundle: {0}", aabFilePath);
            _finishedAabFilePath = aabFilePath;
            _buildStatus         = BuildStatus.Succeeding;
            return(null);
        }
示例#6
0
        private string CreateAssetPackModule(
            string assetPackName, AssetPack assetPack, DirectoryInfo assetPackDirectoryInfo)
        {
            var aaptErrorMessage =
                CreateAssetPackWithManifest(assetPackDirectoryInfo, assetPackName, assetPack.DeliveryMode);

            if (aaptErrorMessage != null)
            {
                // Already displayed the error.
                return(aaptErrorMessage);
            }

            // Copy all assets to an "assets" subdirectory in the destination folder.
            var destinationAssetsDirectory =
                GetDestinationSubdirectory(assetPackDirectoryInfo).CreateSubdirectory(AssetsDirectoryName);

            if (assetPack.AssetBundleFilePath != null)
            {
                // Copy AssetBundle files into the module's "assets" folder, inside an "assetpack" folder.
                var outputDirectory = destinationAssetsDirectory.CreateSubdirectory(AssetPackFolder).FullName;
                File.Copy(assetPack.AssetBundleFilePath, Path.Combine(outputDirectory, assetPackName));
            }
            else if (assetPack.CompressionFormatToAssetBundleFilePath != null)
            {
                // Copy the AssetBundle files into the module's "assets" folder, inside an "assetpack#tcf_xxx" folder.
                foreach (var compressionAndFilePath in assetPack.CompressionFormatToAssetBundleFilePath)
                {
                    var targetedAssetsFolderName =
                        AssetPackFolder + TextureTargetingTools.GetTargetingSuffix(compressionAndFilePath.Key);
                    var outputDirectory = destinationAssetsDirectory.CreateSubdirectory(targetedAssetsFolderName);
                    File.Copy(compressionAndFilePath.Value, Path.Combine(outputDirectory.FullName, assetPackName));
                }
            }
            else if (assetPack.AssetPackDirectoryPath != null)
            {
                var sourceAssetsDirectory = new DirectoryInfo(assetPack.AssetPackDirectoryPath);
                if (!sourceAssetsDirectory.Exists)
                {
                    // TODO: check this earlier.
                    return(DisplayBuildError("Missing directory for " + assetPackName, sourceAssetsDirectory.FullName));
                }

                // Copy asset pack files into the module's "assets" folder, inside an "assetpack" folder.
                var outputDirectory = destinationAssetsDirectory.CreateSubdirectory(AssetPackFolder);
                CopyFilesRecursively(sourceAssetsDirectory, outputDirectory);
            }
            else if (assetPack.CompressionFormatToAssetPackDirectoryPath != null)
            {
                // Copy asset pack files into the module's "assets" folder, inside an "assetpack#tcf_xxx" folder.
                foreach (var compressionAndDirectoryPath in assetPack.CompressionFormatToAssetPackDirectoryPath)
                {
                    var sourceAssetsDirectory = new DirectoryInfo(compressionAndDirectoryPath.Value);
                    if (!sourceAssetsDirectory.Exists)
                    {
                        // TODO: check this earlier.
                        return(DisplayBuildError(
                                   "Missing directory for " + assetPackName, sourceAssetsDirectory.FullName));
                    }

                    var targetedAssetsFolderName =
                        AssetPackFolder + TextureTargetingTools.GetTargetingSuffix(compressionAndDirectoryPath.Key);
                    var outputDirectory = destinationAssetsDirectory.CreateSubdirectory(targetedAssetsFolderName);
                    CopyFilesRecursively(sourceAssetsDirectory, outputDirectory);
                }
            }
            else
            {
                throw new InvalidOperationException("Missing asset pack files: " + assetPackName);
            }

            return(null);
        }
示例#7
0
        /// <summary>
        /// BundleTool config optimized for Unity-based apps.
        /// </summary>
        public static BundletoolConfig.Config MakeConfig(
            BuildBundleConfigParams configParams, string streamingAssetsPath)
        {
            var config = new BundletoolConfig.Config();

            // APK download size is smaller when native libraries are uncompressed. uncompressNativeLibraries sets
            // android:extractNativeLibs="false" in the manifest, which also reduces on-disk for Android 6.0+ devices.
            config.optimizations.uncompressNativeLibraries.enabled = true;
            config.compression.uncompressedGlob.AddRange(UnityUncompressedGlob);

            var compressionOptions = configParams.compressionOptions;

            if (compressionOptions.UncompressedGlobs != null)
            {
                config.compression.uncompressedGlob.AddRange(compressionOptions.UncompressedGlobs);
            }

            if (!compressionOptions.CompressStreamingAssets)
            {
                config.compression.uncompressedGlob.AddRange(GetStreamingAssetsFileGlobs(streamingAssetsPath));
            }

            if (compressionOptions.CompressInstallTimeAssetPacks)
            {
                config.compression.installTimeAssetModuleDefaultCompression = BundletoolConfig.Compressed;
            }

            var dimensions = config.optimizations.splitsConfig.splitDimension;

            // Split on ABI so only one set of native libraries (armeabi-v7a, arm64-v8a, or x86) is sent to a device.
            dimensions.Add(new BundletoolConfig.SplitDimension {
                value = BundletoolConfig.Abi, negate = false
            });
            // Do not split on LANGUAGE since Unity games don't store localized strings in the typical Android manner.
            dimensions.Add(new BundletoolConfig.SplitDimension {
                value = BundletoolConfig.Language, negate = true
            });
            // Do not split on SCREEN_DENSITY since Unity games don't have per-density resources other than app icons.
            dimensions.Add(new BundletoolConfig.SplitDimension {
                value = BundletoolConfig.ScreenDensity, negate = true
            });
            if (configParams.enableTcfTargeting)
            {
                dimensions.Add(new BundletoolConfig.SplitDimension
                {
                    value           = BundletoolConfig.TextureCompressionFormat,
                    negate          = false,
                    suffixStripping =
                    {
                        enabled       = true,
                        defaultSuffix = configParams.defaultTcfSuffix
                    }
                });
            }



            // Bundletool requires the below standaloneConfig when supporting install-time asset packs for pre-Lollipop.
            if (configParams.containsInstallTimeAssetPack &&
                TextureTargetingTools.IsSdkVersionPreLollipop(configParams.minSdkVersion))
            {
                config.optimizations.standaloneConfig.splitDimension.Add(new BundletoolConfig.SplitDimension
                {
                    value = BundletoolConfig.Abi, negate = true
                });

                config.optimizations.standaloneConfig.splitDimension.Add(new BundletoolConfig.SplitDimension
                {
                    value = BundletoolConfig.Language, negate = true
                });

                config.optimizations.standaloneConfig.splitDimension.Add(new BundletoolConfig.SplitDimension
                {
                    value = BundletoolConfig.ScreenDensity, negate = true
                });

                config.optimizations.standaloneConfig.splitDimension.Add(new BundletoolConfig.SplitDimension
                {
                    value = BundletoolConfig.TextureCompressionFormat, negate = true
                });

                config.optimizations.standaloneConfig.strip64BitLibraries = true;
            }

            return(config);
        }