public IAppInstance Run(IAppInstall App) { AndroidAppInstall DroidAppInstall = App as AndroidAppInstall; if (DroidAppInstall == null) { throw new Exception("AppInstance is of incorrect type!"); } // wake the device - we can install while its asleep but not run PowerOn(); // kill any currently running instance: KillRunningProcess(DroidAppInstall.AndroidPackageName); string LaunchActivity = AndroidPlatform.GetLaunchableActivityName(); Log.Info("Launching {0} on '{1}' ", DroidAppInstall.AndroidPackageName + "/" + LaunchActivity, ToString()); Log.Verbose("\t{0}", DroidAppInstall.CommandLine); // Clear the device's logcat in preparation for the test.. RunAdbDeviceCommand("logcat --clear"); // start the app on device! string CommandLine = "shell am start -W -S -n " + DroidAppInstall.AndroidPackageName + "/" + LaunchActivity; IProcessResult Process = RunAdbDeviceCommand(CommandLine, false, true); return(new AndroidAppInstance(this, DroidAppInstall, Process)); }
public IAppInstall InstallApplication(UnrealAppConfig AppConfig) { // todo - pass this through AndroidBuild Build = AppConfig.Build as AndroidBuild; // Ensure APK exists if (Build == null) { throw new AutomationException("Invalid build for Android!"); } // kill any currently running instance: KillRunningProcess(Build.AndroidPackageName); bool SkipDeploy = Globals.Params.ParseParam("SkipDeploy"); if (SkipDeploy == false) { // Establish remote directory locations string DeviceStorageQueryCommand = AndroidPlatform.GetStorageQueryCommand(); IProcessResult StorageQueryResult = RunAdbDeviceCommand(DeviceStorageQueryCommand); string StorageLocation = StorageQueryResult.Output.Trim(); // "/mnt/sdcard"; // remote dir used to save things string RemoteDir = StorageLocation + "/UE4Game/" + AppConfig.ProjectName; // if not a bulk/dev build, remote dir will be under /{StorageLocation}/Android/data/{PackageName} if ((Build.Flags & (BuildFlags.Bulk | BuildFlags.CanReplaceExecutable)) == 0) { RemoteDir = StorageLocation + "/Android/data/" + Build.AndroidPackageName + "/files/UE4Game/" + AppConfig.ProjectName; } string DependencyDir = RemoteDir + "/deps"; // device artifact path, always clear between runs DeviceArtifactPath = string.Format("{0}/{1}/Saved", RemoteDir, AppConfig.ProjectName); RunAdbDeviceCommand(string.Format("shell rm -r {0}", DeviceArtifactPath)); // path for OBB files string OBBRemoteDestination = string.Format("{0}/obb/{1}", StorageLocation, Build.AndroidPackageName); if (Globals.Params.ParseParam("cleandevice")) { Log.Info("Cleaning previous builds due to presence of -cleandevice"); // we need to ununstall then install the apk - don't care if it fails, may have been deleted Log.Info("Uninstalling {0}", Build.AndroidPackageName); RunAdbDeviceCommand(string.Format("uninstall {0}", Build.AndroidPackageName)); Log.Info("Removing {0}", RemoteDir); RunAdbDeviceCommand(string.Format("shell rm -r {0}", RemoteDir)); Log.Info("Removing {0}", OBBRemoteDestination); RunAdbDeviceCommand(string.Format("shell rm -r {0}", OBBRemoteDestination)); } // remote dir on the device, create it if it doesn't exist RunAdbDeviceCommand(string.Format("shell mkdir -p {0}/", RemoteDir)); IProcessResult AdbResult; string AdbCommand; // path to the APK to install. string ApkPath = Build.SourceApkPath; // check for a local newer executable if (Globals.Params.ParseParam("dev")) { //string ApkFileName = Path.GetFileName(ApkPath); string ApkFileName2 = UnrealHelpers.GetExecutableName(AppConfig.ProjectName, UnrealTargetPlatform.Android, AppConfig.Configuration, AppConfig.ProcessType, "apk"); string LocalAPK = Path.Combine(Environment.CurrentDirectory, AppConfig.ProjectName, "Binaries/Android", ApkFileName2); bool LocalFileExists = File.Exists(LocalAPK); bool LocalFileNewer = LocalFileExists && File.GetLastWriteTime(LocalAPK) > File.GetLastWriteTime(ApkPath); Log.Verbose("Checking for newer binary at {0}", LocalAPK); Log.Verbose("LocalFile exists: {0}. Newer: {1}", LocalFileExists, LocalFileNewer); if (LocalFileExists && LocalFileNewer) { ApkPath = LocalAPK; } } // first install the APK CopyFileToDevice(Build.AndroidPackageName, ApkPath, ""); // obb files need to be named based on APK version (grrr), so find that out. This should return something like // versionCode=2 minSdk=21 targetSdk=21 string PackageInfo = RunAdbDeviceCommand(string.Format("shell dumpsys package {0} | grep versionCode", Build.AndroidPackageName)).Output; var Match = Regex.Match(PackageInfo, @"versionCode=([\d\.]+)\s"); if (Match.Success == false) { throw new AutomationException("Failed to find version info for APK!"); } string PackageVersion = Match.Groups[1].ToString(); // Convert the files from the source to final destination names Dictionary <string, string> FilesToInstall = new Dictionary <string, string>(); Console.WriteLine("trying to copy files over."); if (AppConfig.FilesToCopy != null) { if (LocalDirectoryMappings.Count == 0) { Console.WriteLine("Populating Directory"); PopulateDirectoryMappings(DeviceArtifactPath); } Console.WriteLine("trying to copy files over."); foreach (UnrealFileToCopy FileToCopy in AppConfig.FilesToCopy) { string PathToCopyTo = Path.Combine(LocalDirectoryMappings[FileToCopy.TargetBaseDirectory], FileToCopy.TargetRelativeLocation); if (File.Exists(FileToCopy.SourceFileLocation)) { FileInfo SrcInfo = new FileInfo(FileToCopy.SourceFileLocation); SrcInfo.IsReadOnly = false; FilesToInstall.Add(FileToCopy.SourceFileLocation, PathToCopyTo.Replace("\\", "/")); Console.WriteLine("Copying {0} to {1}", FileToCopy.SourceFileLocation, PathToCopyTo); } else { Log.Warning("File to copy {0} not found", FileToCopy); } } } Build.FilesToInstall.Keys.ToList().ForEach(K => { string SrcPath = K; string DestPath = Build.FilesToInstall[K]; string DestFile = Path.GetFileName(DestPath); // If we installed a new APK we need to change the package version Match OBBMatch = Regex.Match(DestFile, @"main\.(\d+)\.com.*\.obb"); if (OBBMatch.Success) { string NewFileName = DestFile.Replace(OBBMatch.Groups[1].ToString(), PackageVersion); DestPath = DestPath.Replace(DestFile, NewFileName); } DestPath = Regex.Replace(DestPath, "%STORAGE%", StorageLocation, RegexOptions.IgnoreCase); FilesToInstall.Add(SrcPath, DestPath); }); // get a list of files in the destination OBB directory AdbResult = RunAdbDeviceCommand(string.Format("shell ls {0}", OBBRemoteDestination)); // if != 0 then no folder exists if (AdbResult.ExitCode == 0) { IEnumerable <string> CurrentRemoteFileList = AdbResult.Output.Replace("\r\n", "\n").Split('\n'); IEnumerable <string> NewRemoteFileList = FilesToInstall.Values.Select(F => Path.GetFileName(F)); // delete any files that should not be there foreach (string FileName in CurrentRemoteFileList) { if (FileName.StartsWith(".") || FileName.Length == 0) { continue; } if (NewRemoteFileList.Contains(FileName) == false) { RunAdbDeviceCommand(string.Format("shell rm {0}/{1}", OBBRemoteDestination, FileName)); } } } foreach (var KV in FilesToInstall) { string LocalFile = KV.Key; string RemoteFile = KV.Value; CopyFileToDevice(Build.AndroidPackageName, LocalFile, RemoteFile); } // create a tempfile, insert the command line, and push it over string TmpFile = Path.GetTempFileName(); CommandLineFilePath = string.Format("{0}/UE4CommandLine.txt", RemoteDir); // I've seen a weird thing where adb push truncates by a byte, so add some padding... File.WriteAllText(TmpFile, AppConfig.CommandLine + " "); AdbCommand = string.Format("push {0} {1}", TmpFile, CommandLineFilePath); RunAdbDeviceCommand(AdbCommand); File.Delete(TmpFile); } else { Log.Info("Skipping install of {0} (-skipdeploy)", Build.AndroidPackageName); } AndroidAppInstall AppInstall = new AndroidAppInstall(this, AppConfig.ProjectName, Build.AndroidPackageName, AppConfig.CommandLine); return(AppInstall); }
public AndroidAppInstance(TargetDeviceAndroid InDevice, AndroidAppInstall InInstall, IProcessResult InProcess) { AndroidDevice = InDevice; Install = InInstall; LaunchProcess = InProcess; }