Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
AndroidAdbUtilities.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.IO;
5 using System.Linq;
6 using Paradox.Framework.Diagnostics;
7 using Paradox.Framework.Serialization;
8 
9 namespace Paradox.BuildEngine
10 {
11  public static class AndroidAdbUtilities
12  {
13  private static readonly string AdbExecutable = FindAdbExecutable();
14 
15  public static string GetExternalStoragePath(string device)
16  {
17  var sdcardPath = RunAdb(device, "shell \"echo $EXTERNAL_STORAGE\"");
18  return sdcardPath[0];
19  }
20 
21  public static string[] GetDevices()
22  {
23  var devices = RunAdb(null, "devices");
24 
25  // Skip first line "List of devices attached",
26  // and then take first part of string (device id).
27  return devices.Skip(1).Select(x => x.Split(' ', '\t').First()).ToArray();
28  }
29 
30  /// <summary>
31  /// Synchronizes files to an android device.
32  /// </summary>
33  /// <param name="logger">The logger.</param>
34  /// <param name="device">The device.</param>
35  /// <param name="fileMapping">The file mapping (relative target path, source HDD filename).</param>
36  /// <param name="androidPath">The android path.</param>
37  /// <param name="cacheFile">The cache file.</param>
38  public static void Synchronize(Logger logger, string device, Dictionary<string, string> fileMapping, string androidPath, string cacheFile)
39  {
40  // Ensure android path ends up with directory separator
41  if (!androidPath.EndsWith("/"))
42  androidPath = androidPath + "/";
43 
44  // Search files
45  var currentVersions = fileMapping
46  .ToDictionary(x => x.Key, x => new FileVersion(x.Value));
47 
48  // Try to read previous cache file
49  var previousVersions = new Dictionary<string, FileVersion>();
50  try
51  {
52  using (var file = File.OpenRead(cacheFile))
53  {
54  var binaryReader = new BinarySerializationReader(file);
55  binaryReader.Serialize(ref previousVersions, ArchiveMode.Deserialize);
56  }
57  }
58  catch (IOException)
59  {
60  }
61 
62  var filesToRemove = new List<string>();
63  var filesToUpload = new List<string>();
64 
65  // Remove unecessary files (in previousVersions but not in currentVersions)
66  foreach (var file in previousVersions.Where(x => !currentVersions.ContainsKey(x.Key)))
67  {
68  filesToRemove.Add(file.Key);
69  }
70 
71  // Upload files that are either not uploaded yet, or not up to date
72  foreach (var file in currentVersions)
73  {
74  FileVersion fileVersion;
75  if (!previousVersions.TryGetValue(file.Key, out fileVersion)
76  || fileVersion.FileSize != file.Value.FileSize
77  || fileVersion.LastModifiedDate != file.Value.LastModifiedDate)
78  {
79  filesToUpload.Add(file.Key);
80  }
81  }
82 
83  // Upload files
84  foreach (var file in filesToUpload)
85  {
86  if (logger != null)
87  logger.Verbose("Copying file {0}", file);
88  RunAdb(device, string.Format("push \"{0}\" \"{1}\"", fileMapping[file], androidPath + file.Replace('\\', '/')));
89  }
90 
91  // Remove files
92  foreach (var file in filesToRemove)
93  {
94  if (logger != null)
95  logger.Verbose("Deleting file {0}", file);
96  RunAdb(device, string.Format("shell \"rm {0}\"", androidPath + file.Replace('\\', '/')));
97  }
98 
99  // Write new cache file
100  using (var file = File.Create(cacheFile))
101  {
102  var binaryWriter = new BinarySerializationWriter(file);
103  binaryWriter.Write(currentVersions);
104  }
105  }
106 
107  private static string FindAdbExecutable()
108  {
109  var androidSdkDir = Environment.GetEnvironmentVariable("ANDROID_SDK");
110  var androidAdbExecutable = androidSdkDir != null ? androidSdkDir + @"\platform-tools\adb" : "adb";
111 
112  return androidAdbExecutable;
113  }
114 
115  private static string[] RunAdb(string device, string arguments)
116  {
117  // Add device to argument list if necessary
118  if (device != null)
119  arguments = "-s " + device + ' ' + arguments;
120 
121  var processStartInfo = new ProcessStartInfo()
122  {
123  FileName = AdbExecutable,
124  Arguments = arguments,
125  UseShellExecute = false,
126  CreateNoWindow = true,
127  RedirectStandardOutput = true,
128  };
129 
130  var lines = new List<string>();
131 
132  var adbProcess = Process.Start(processStartInfo);
133  adbProcess.OutputDataReceived += (sender, args) =>
134  {
135  if (!string.IsNullOrEmpty(args.Data))
136  {
137  lock (adbProcess)
138  {
139  lines.Add(args.Data);
140  }
141  }
142  };
143  adbProcess.BeginOutputReadLine();
144  adbProcess.WaitForExit();
145 
146  return lines.ToArray();
147  }
148 
149  [Serializable]
150  public struct FileVersion
151  {
152  public DateTime LastModifiedDate;
153  public long FileSize;
154 
155  public FileVersion(string fileName)
156  {
157  LastModifiedDate = DateTime.MinValue;
158  FileSize = -1;
159 
160  if (File.Exists(fileName))
161  {
162  var fileInfo = new FileInfo(fileName);
163  LastModifiedDate = fileInfo.LastWriteTime;
164  FileSize = fileInfo.Length;
165  }
166  }
167  }
168  }
169 }
static string GetExternalStoragePath(string device)
static void Synchronize(Logger logger, string device, Dictionary< string, string > fileMapping, string androidPath, string cacheFile)
Synchronizes files to an android device.
System.IO.File File