Compare commits

...

9 Commits
v2.9 ... v2.9.1

Author SHA1 Message Date
William Swartwood
c607d1a2fd aapt badging added to get actual release name for new games, duplicate code put in to ask for whitelist first cuz im dumb. 2021-08-25 02:57:08 -04:00
harryeffinpotter
81c1e61d8b Merge pull request #83 from konqiDAM/master
I haven't tried to get an empty list, if rclone fails maybe it gives a null pointer
2021-08-24 18:09:31 -04:00
konqi
1dc0e38865 . 2021-08-24 23:55:16 +02:00
konqi
19dcacfbbe ask every 24h for game list 2021-08-24 23:52:11 +02:00
konqi
10d8498f1b add whitelist and ask for games 2021-08-24 23:21:53 +02:00
konqi
d3620bf033 happy pmow noises 2021-08-24 22:20:46 +02:00
konqi
467041825c not read header 2021-08-24 22:03:31 +02:00
William Swartwood
fa380c75f7 RSL 2.9.0 2021-08-24 04:17:15 -04:00
William Swartwood
2882737958 2.9 2021-08-24 03:35:54 -04:00
12 changed files with 523 additions and 281 deletions

4
ADB.cs
View File

@@ -368,12 +368,12 @@ namespace AndroidSideloader
}
public static ProcessOutput Sideload(string path = "", string packagename = "")
public static ProcessOutput Sideload(string path, string packagename = "")
{
WakeDevice();
ProcessOutput ret = new ProcessOutput();
ret += RunAdbCommandToString($"install -g -r \"{path}\"");
ret += RunAdbCommandToString($"install -g \"{path}\"");
string out2 = ret.Output + ret.Error;
if (out2.Contains("failed"))
{

View File

@@ -167,6 +167,9 @@
<setting name="GlobalUsername" serializeAs="String">
<value />
</setting>
<setting name="lastTimeShared" serializeAs="String">
<value />
</setting>
</AndroidSideloader.Properties.Settings>
<AndroidADB.Sideloader.Properties.Settings>
<setting name="checkForUpdates" serializeAs="String">

View File

@@ -1,4 +1,82 @@
-----BEGIN PGP SIGNED MESSAGE-----
RSL 2.9.0
= Hotfix to remove errant entry from GamesList
that would crash the program.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
RSL 2.9
+ Updated ADB zip on repo and added a verification
text file to ensure all users are on newest ADB,
this should fix most obb issues. Upon first launch
after this update Rookie will automatically obtain
the latest ADB via this zip (7MB).
+ Added AAPT to repo along with a timer + logic to
detect packagename for automatic reinstall when drag
and dropped installs fail.
+ Implemented Size(MB) column to see app size prior
to clicking Download and Install.
= Cleaned up automatic reinstall on apk installation
failure for Download and Install, it should work for
most users now.
= Adjusted code for mirror switching, should fix failure
to load gameslist whatsoever on dead mirrors.
= Fixed issue where after installing a game RSL would
ask user to donate same clean files again. RSL will now
only ask once per program load, as intended.
- - Removed filesize confirmation dialog when clicking
download and install.
- - Removed columns that were useless to users.
HFP
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCAAdFiEEKjgtlwMyrpVu4TGfx/Rql1VoczcFAmEkn0oACgkQx/Rql1Vo
czf7Mg//cU+DnFex+on9JBI5+K2bRfmp6RUhYHQKXD7V/od4vMxWP2jXt7F6ebat
32KI9GeQfCubRuFEJKBRQ5BfsZXqZtWbLoYtSfrPsk6fz5JzK5PfzAayRLEmS3nV
+3Gu7w7wxlseo+IzN95mvEZOYOaFnv7rieGJsXoEUVh0xZnCF7CzTe6MZ6JSdpCY
LUWOiZ2Krxc8W/tD45JLGSxHkMpFlnZO9DLISyN65SdkvjcridbpTWSMiQJPh5KA
jTiOM4PzOZo6YCoTsIWy4rvhkIqhdNJdJZK4qb0vN40wvqgbFI7c7yh/rcb/xi7R
Ruva6Z2zIJi122lEsohG9TfeNODxIuPGR0rLAJDuSPpri0ukxLMIHPg0ViBQ2Z7D
jPmDnEQDKPfaj1gbvAXuk5qd8ogOM3CCpBoaHt3tMFhuCUgxPYx5RxMPjdn8bOvR
fjkEfMdvS55pI04seQued6KIlYnkkUGntIcSbBJfVhW8pev2iPxICC3Rn4ejSAnM
J3fIjLsUbHxM501HgM8ttWjniEb5ExGFUI/PvF7rNw2WjYT8wJltv8PUWNZoQYy/
Upif9IzLVORN9TsrnbxUQBtOZgmvfbCbj+rotYhvj6igo1C3ZX8t001CknljNBCU
/9Y18yJRWJ7BpbEbzYpKBofphZzaWI9GN2hM6wV18An8sMEbb4A=
=kVMl
-----END PGP SIGNATURE-----
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCAAdFiEEKjgtlwMyrpVu4TGfx/Rql1VoczcFAmEkntYACgkQx/Rql1Vo
czdB/g/9FHUbQt4tTHitnCBjfKmxRY5qcmmvSQM1LRKxoWqOMgl6wmX/oJQFnR1/
DL+zc5nf1Qmjll7OyLEZbft2p0+KnGuGNCcB4aB36VcsMEED6j6L63OZeI045KY6
cMAmcyR0A/OcfsiqaHjXVOyp8yI4RCGa/M2HwBvZOypxbdTKlftdQEOQ9bVFxV8p
1L0NuhHpfewnke1WG3MRjiXlu44athOYh6fACO0/+TTJwmtD6w9A9fc+0A70jqp6
pz9WVKzrnVFnq5CbHSQIrmDoQfiqyIxUEmrMKcZipjHfkVa0ZZ5Jjp9QuIozEskp
rLxoCawe2NmfHhe4frxF6ngRCVD0Xcn8YmgQAbts+5+PqnvK+DyL0C53BkONUeCp
ODAqiTjqWWfsILkpphPDQI4/WWjKURLTKFbse5jboBHNeF810y9gfBC0xHS8MeGO
k//02mbJ7gHonRBpuNy0ba80tRHYtzr4OL/gd9YUyVd2AYP/GEptIoWM7ESqR1Hy
g7oxD8JGR/WgLIJD1stYC3eh2Fy36J6oJPUvT85EUbPznY7UIL+upT/9wrXPzZqd
iI4o8DkPq/9yMEWBwV8cikgllx+KXWgwHbG8lY0uvuxPX26UscGyY1bNytb/WMfG
lJaztf9Yo7uBrSIdicEeED1BN+/q/QmsNzR9mpFrqfrqyDB91yA=
=z7JR
-----END PGP SIGNATURE-----
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
RSL 2.8.7

2
MainForm.Designer.cs generated
View File

@@ -242,7 +242,7 @@
this.getApkButton.Padding = new System.Windows.Forms.Padding(23, 0, 0, 0);
this.getApkButton.Size = new System.Drawing.Size(218, 28);
this.getApkButton.TabIndex = 2;
this.getApkButton.Text = "Upload Selected App";
this.getApkButton.Text = "Share Selected App";
this.getApkButton.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.getApkButton.UseVisualStyleBackColor = false;
this.getApkButton.Click += new System.EventHandler(this.getApkButton_Click);

View File

@@ -107,51 +107,21 @@ namespace AndroidSideloader
private string oldTitle = "";
public static bool updatesnotified;
public static bool updatesnotified = false;
private async void Form1_Load(object sender, EventArgs e)
{
updatesnotified = false;
string adbFile = "C:\\RSL\\2.8.2\\adb\\adb.exe";
string adbDir = "C:\\RSL\\2.8.2\\adb";
string fileName = "";
string destFile = "";
string date_time = DateTime.Now.ToString("dddd, MMMM dd @ hh:mmtt (UTC)");
Logger.Log($"\n\n##############\n##############\n##############\n\nAPP LAUNCH DATE/TIME: " + date_time + "\n\n##############\n##############\n##############\n\n");
Properties.Settings.Default.MainDir = Environment.CurrentDirectory;
Properties.Settings.Default.Save();
if (!File.Exists(adbFile))
{
Directory.CreateDirectory(adbDir);
if (System.IO.Directory.Exists($"{Environment.CurrentDirectory}\\adb"))
{
string[] ADBfiles = System.IO.Directory.GetFiles($"{Properties.Settings.Default.MainDir}\\adb");
// Copy the files and overwrite destination files if they already exist.
foreach (string s in ADBfiles)
{
fileName = System.IO.Path.GetFileName(s);
destFile = System.IO.Path.Combine(adbDir, fileName);
System.IO.File.Copy(s, destFile, true);
}
}
}
ADB.RunAdbCommandToString("kill-server");
Properties.Settings.Default.ADBPath = adbFile;
Properties.Settings.Default.Save();
if (!String.IsNullOrEmpty(Properties.Settings.Default.IPAddress))
ADB.RunAdbCommandToString(Properties.Settings.Default.IPAddress);
CheckForInternet();
if (HasInternet == true)
Sideloader.downloadFiles();
else
FlexibleMessageBox.Show("Cannot connect to google dns, your internet may be down, won't use rclone or online features!");
await Task.Delay(100);
ADB.RunAdbCommandToString("kill-server");
if (!String.IsNullOrEmpty(Properties.Settings.Default.IPAddress))
ADB.RunAdbCommandToString(Properties.Settings.Default.IPAddress);
if (!Directory.Exists(BackupFolder))
Directory.CreateDirectory(BackupFolder);
@@ -258,21 +228,19 @@ namespace AndroidSideloader
ChangeTitle("Initializing Mirrors");
initMirrors(true);
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
t.Interval = 35000; // 35 seconds before switching mirror
t.Tick += new EventHandler(timer_Tick5);
t.Start();
ChangeTitle("Initializing Games");
SideloaderRCLONE.initGames(currentRemote);
t.Stop();
//ChangeTitle("Syncing Game Photos");
//ChangeTitle("Updating list of needed clean apps...");
//ChangeTitle("Checking for Updates on server...");
});
t1.SetApartmentState(ApartmentState.STA);
t1.IsBackground = true;
if (HasInternet)
t1.Start();
while (t1.IsAlive)
await Task.Delay(100);
Thread t2 = new Thread(() =>
{
SideloaderRCLONE.UpdateGameNotes(currentRemote);
@@ -296,12 +264,11 @@ namespace AndroidSideloader
t4.IsBackground = true;
if (HasInternet)
{
t1.Start();
t2.Start();
t3.Start();
t4.Start();
}
while (t1.IsAlive || t2.IsAlive || t3.IsAlive || t4.IsAlive)
while (t2.IsAlive || t3.IsAlive || t4.IsAlive)
await Task.Delay(100);
ChangeTitle("Loaded");
@@ -365,12 +332,6 @@ namespace AndroidSideloader
ADB.RunAdbCommandToString("shell input keyevent KEYCODE_WAKEUP");
}
void timer_Tick5(object sender, EventArgs e)
{
SwitchMirrors();
SideloaderRCLONE.initGames(currentRemote);
}
void timer_Tick2(object sender, EventArgs e)
{
keyheld = false;
@@ -770,7 +731,7 @@ namespace AndroidSideloader
line[i] = line[i].Remove(0, 8);
line[i] = line[i].Remove(line[i].Length - 1);
foreach (var game in SideloaderRCLONE.games)
if (line[i].Length > 0 && game[3].Contains(line[i]))
if (line[i].Length > 0 && game[2].Contains(line[i]))
line[i] = game[0];
}
}
@@ -926,7 +887,7 @@ namespace AndroidSideloader
}
private async void sideloadFolderButton_Click(object sender, EventArgs e)
{
{
ADB.WakeDevice();
var dialog = new FolderSelectDialog
@@ -984,157 +945,285 @@ namespace AndroidSideloader
ADB.WakeDevice();
ADB.DeviceID = GetDeviceID();
progressBar.Style = ProgressBarStyle.Marquee;
Thread t1 = new Thread(() =>
CurrPCKG = "";
string[] datas = (string[])e.Data.GetData(DataFormats.FileDrop);
foreach (string data in datas)
{
string[] datas = (string[])e.Data.GetData(DataFormats.FileDrop);
foreach (string data in datas)
string directory = Path.GetDirectoryName(data);
//if is directory
string dir = Path.GetDirectoryName(data);
string path = $"{dir}\\Install.txt";
if (Directory.Exists(data))
{
string directory = Path.GetDirectoryName(data);
//if is directory
string dir = Path.GetDirectoryName(data);
string path = $"{dir}\\Install.txt";
if (Directory.Exists(data))
Program.form.ChangeTitle($"Copying {data} to device...");
Thread t1 = new Thread(() =>
{
Program.form.ChangeTitle($"Copying {data} to device...");
output += ADB.CopyOBB(data);
Program.form.ChangeTitle($"");
string extension = Path.GetExtension(data);
if (extension == ".apk")
});
t1.IsBackground = true;
t1.Start();
while (t1.IsAlive)
await Task.Delay(100);
Program.form.ChangeTitle($"");
string extension = Path.GetExtension(data);
if (extension == ".apk")
{
if (File.Exists($"{Environment.CurrentDirectory}\\Install.txt"))
{
if (File.Exists($"{Environment.CurrentDirectory}\\Install.txt"))
DialogResult dialogResult = FlexibleMessageBox.Show("Special instructions have been found with this file, would you like to run them automatically?", "Special Instructions found!", MessageBoxButtons.OKCancel);
if (dialogResult == DialogResult.Cancel)
return;
else
ChangeTitle("Sideloading custom install.txt automatically.");
Thread t2 = new Thread(() =>
{
DialogResult dialogResult = FlexibleMessageBox.Show("Special instructions have been found with this file, would you like to run them automatically?", "Special Instructions found!", MessageBoxButtons.OKCancel);
if (dialogResult == DialogResult.Cancel)
return;
else
ChangeTitle("Sideloading custom install.txt automatically.");
output += Sideloader.RunADBCommandsFromFile(path);
Logger.Log($"Sideloading {path}");
if (output.Error.Contains("mkdir"))
output.Error = "";
if (output.Error.Contains("reserved"))
output.Output = "";
ChangeTitle("");
}
}
string[] files = Directory.GetFiles(data);
foreach (string file2 in files)
{
if (File.Exists(file2))
{
if (file2.EndsWith(".apk"))
{
string pathname = Path.GetDirectoryName(data);
string filename = file2.Replace($"{pathname}\\", "");
ChangeTitle($"Installing {filename} (If this hangs, uninstall app first then install again)");
output += ADB.Sideload(file2);
}
if (file2.EndsWith(".zip") && Properties.Settings.Default.BMBFchecked)
{
string datazip = file2;
string zippath = Path.GetDirectoryName(data);
datazip = datazip.Replace(zippath, "");
datazip = Utilities.StringUtilities.RemoveEverythingAfterFirst(datazip, ".");
datazip = datazip.Replace(".", "");
string command2 = $"\"{Properties.Settings.Default.MainDir}\\7z.exe\" e \"{file2}\" -o\"{zippath}\\{datazip}\\\"";
ADB.RunCommandToString(command2, file2);
output += ADB.RunAdbCommandToString($"push \"{zippath}\\{datazip}\" /sdcard/ModData/com.beatgames.beatsaber/Mods/SongLoader/CustomLevels/");
Directory.Delete($"{zippath}\\{datazip}", true);
}
}
}
string[] folders = Directory.GetDirectories(data);
foreach (string folder in folders)
{
Program.form.ChangeTitle($"Copying {folder} to device...");
output += ADB.CopyOBB(folder);
Program.form.ChangeTitle("");
Properties.Settings.Default.CurrPckg = dir;
Properties.Settings.Default.Save();
});
t2.IsBackground = true;
t2.Start();
while (t2.IsAlive)
await Task.Delay(100);
Logger.Log($"Sideloading {path}");
if (output.Error.Contains("mkdir"))
output.Error = "";
if (output.Error.Contains("reserved"))
output.Output = "";
ChangeTitle("");
}
}
//if it's a file
else if (File.Exists(data))
string[] files = Directory.GetFiles(data);
foreach (string file2 in files)
{
string extension = Path.GetExtension(data);
if (extension == ".apk")
if (File.Exists(file2))
{
if (File.Exists($"{dir}\\Install.txt"))
{
DialogResult dialogResult = FlexibleMessageBox.Show("Special instructions have been found with this file, would you like to run them automatically?", "Special Instructions found!", MessageBoxButtons.OKCancel);
if (dialogResult == DialogResult.Cancel)
return;
else
{
ChangeTitle("Sideloading custom install.txt automatically.");
output += Sideloader.RunADBCommandsFromFile(path);
ChangeTitle("");
}
}
else
if (file2.EndsWith(".apk"))
{
string pathname = Path.GetDirectoryName(data);
string dataname = data.Replace($"{pathname}\\", "");
ChangeTitle($"Installing {dataname} (If this hangs, uninstall app first then install again)");
output += ADB.Sideload(data);
string filename = file2.Replace($"{pathname}\\", "");
string cmd = $"\"{Properties.Settings.Default.MainDir}\\adb\\aapt.exe\" dump badging \"{data}\" | findstr -i \"package: name\"";
string cmdout = ADB.RunCommandToString(cmd, file2).Output;
cmdout = Utilities.StringUtilities.RemoveEverythingBeforeFirst(cmdout, "=");
cmdout = Utilities.StringUtilities.RemoveEverythingAfterFirst(cmdout, " ");
cmdout = cmdout.Replace("'", "");
cmdout = cmdout.Replace("=", "");
CurrPCKG = cmdout;
CurrAPK = file2;
System.Windows.Forms.Timer t3 = new System.Windows.Forms.Timer();
t3.Interval = 150000; // 180 seconds to fail
t3.Tick += timer_Tick4;
t3.Start();
Program.form.ChangeTitle($"Sideloading apk...");
Thread t2 = new Thread(() =>
{
output += ADB.Sideload(file2);
});
t2.IsBackground = true;
t2.Start();
while (t2.IsAlive)
await Task.Delay(100);
t3.Stop();
}
if (file2.EndsWith(".zip") && Properties.Settings.Default.BMBFchecked)
{
string datazip = file2;
string zippath = Path.GetDirectoryName(data);
datazip = datazip.Replace(zippath, "");
datazip = Utilities.StringUtilities.RemoveEverythingAfterFirst(datazip, ".");
datazip = datazip.Replace(".", "");
string command2 = $"\"{Properties.Settings.Default.MainDir}\\7z.exe\" e \"{file2}\" -o\"{zippath}\\{datazip}\\\"";
Thread t2 = new Thread(() =>
{
ADB.RunCommandToString(command2, file2);
output += ADB.RunAdbCommandToString($"push \"{zippath}\\{datazip}\" /sdcard/ModData/com.beatgames.beatsaber/Mods/SongLoader/CustomLevels/");
});
t2.IsBackground = true;
t2.Start();
while (t2.IsAlive)
await Task.Delay(100);
Directory.Delete($"{zippath}\\{datazip}", true);
}
}
}
string[] folders = Directory.GetDirectories(data);
foreach (string folder in folders)
{
Program.form.ChangeTitle($"Copying {folder} to device...");
Thread t2 = new Thread(() =>
{
output += ADB.CopyOBB(folder);
});
t2.IsBackground = true;
t2.Start();
while (t2.IsAlive)
await Task.Delay(100);
Program.form.ChangeTitle("");
Properties.Settings.Default.CurrPckg = dir;
Properties.Settings.Default.Save();
}
}
//if it's a file
else if (File.Exists(data))
{
string extension = Path.GetExtension(data);
if (extension == ".apk")
{
if (File.Exists($"{dir}\\Install.txt"))
{
DialogResult dialogResult = FlexibleMessageBox.Show("Special instructions have been found with this file, would you like to run them automatically?", "Special Instructions found!", MessageBoxButtons.OKCancel);
if (dialogResult == DialogResult.Cancel)
return;
else
{
ChangeTitle("Sideloading custom install.txt automatically.");
Thread t1 = new Thread(() =>
{
output += Sideloader.RunADBCommandsFromFile(path);
});
t1.IsBackground = true;
t1.Start();
while (t1.IsAlive)
await Task.Delay(100);
ChangeTitle("");
}
}
//If obb is dragged and dropped alone onto Rookie, Rookie will recreate its obb folder automatically with this code.
else if (extension == ".obb")
else
{
string filename = Path.GetFileName(data);
string foldername = filename.Substring(filename.IndexOf('.') + 1);
foldername = foldername.Substring(foldername.IndexOf('.') + 1);
foldername = foldername.Replace(".obb", "");
foldername = Environment.CurrentDirectory + "\\" + foldername;
Directory.CreateDirectory(foldername);
File.Copy(data, foldername + "\\" + filename);
path = foldername;
output += ADB.CopyOBB(path);
Directory.Delete(foldername, true);
ChangeTitle("");
}
// BMBF Zip extraction then push to BMBF song folder on Quest.
else if (extension == ".zip" && Properties.Settings.Default.BMBFchecked)
{
string datazip = data;
string zippath = Path.GetDirectoryName(data);
datazip = datazip.Replace(zippath, "");
datazip = Utilities.StringUtilities.RemoveEverythingAfterFirst(datazip, ".");
datazip = datazip.Replace(".", "");
string pathname = Path.GetDirectoryName(data);
string dataname = data.Replace($"{pathname}\\", "");
string cmd = $"\"{Properties.Settings.Default.MainDir}\\adb\\aapt.exe\" dump badging \"{data}\" | findstr -i \"package: name\"";
string cmdout = ADB.RunCommandToString(cmd, data).Output;
cmdout = Utilities.StringUtilities.RemoveEverythingBeforeFirst(cmdout, "=");
cmdout = Utilities.StringUtilities.RemoveEverythingAfterFirst(cmdout, " ");
cmdout = cmdout.Replace("'", "");
cmdout = cmdout.Replace("=", "");
CurrPCKG = cmdout;
CurrAPK = data;
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Interval = 150000; // 150 seconds to fail
timer.Tick += timer_Tick4;
timer.Start();
ChangeTitle($"Installing {dataname}...");
Thread t1 = new Thread(() =>
{
output += ADB.Sideload(data);
});
t1.IsBackground = true;
t1.Start();
while (t1.IsAlive)
await Task.Delay(100);
timer.Stop();
string command = $"\"{Properties.Settings.Default.MainDir}\\7z.exe\" e \"{data}\" -o\"{zippath}\\{datazip}\\\"";
ADB.RunCommandToString(command, data);
output += ADB.RunAdbCommandToString($"push \"{zippath}\\{datazip}\" /sdcard/ModData/com.beatgames.beatsaber/Mods/SongLoader/CustomLevels/");
Directory.Delete($"{zippath}\\{datazip}", true);
}
else if (extension == ".txt")
{
ChangeTitle("Sideloading custom install.txt automatically.");
output += Sideloader.RunADBCommandsFromFile(path);
ChangeTitle("");
}
}
}
});
t1.IsBackground = true;
t1.Start();
//If obb is dragged and dropped alone onto Rookie, Rookie will recreate its obb folder automatically with this code.
else if (extension == ".obb")
{
string filename = Path.GetFileName(data);
string foldername = filename.Substring(filename.IndexOf('.') + 1);
foldername = foldername.Substring(foldername.IndexOf('.') + 1);
foldername = foldername.Replace(".obb", "");
foldername = Environment.CurrentDirectory + "\\" + foldername;
Directory.CreateDirectory(foldername);
File.Copy(data, foldername + "\\" + filename);
path = foldername;
while (t1.IsAlive)
await Task.Delay(100);
Thread t1 = new Thread(() =>
{
output += ADB.CopyOBB(path);
});
t1.IsBackground = true;
t1.Start();
while (t1.IsAlive)
await Task.Delay(100);
Directory.Delete(foldername, true);
ChangeTitle("");
}
// BMBF Zip extraction then push to BMBF song folder on Quest.
else if (extension == ".zip" && Properties.Settings.Default.BMBFchecked)
{
string datazip = data;
string zippath = Path.GetDirectoryName(data);
datazip = datazip.Replace(zippath, "");
datazip = Utilities.StringUtilities.RemoveEverythingAfterFirst(datazip, ".");
datazip = datazip.Replace(".", "");
string command = $"\"{Properties.Settings.Default.MainDir}\\7z.exe\" e \"{data}\" -o\"{zippath}\\{datazip}\\\"";
Thread t1 = new Thread(() =>
{
ADB.RunCommandToString(command, data);
output += ADB.RunAdbCommandToString($"push \"{zippath}\\{datazip}\" /sdcard/ModData/com.beatgames.beatsaber/Mods/SongLoader/CustomLevels/");
});
t1.IsBackground = true;
t1.Start();
while (t1.IsAlive)
await Task.Delay(100);
Directory.Delete($"{zippath}\\{datazip}", true);
}
else if (extension == ".txt")
{
ChangeTitle("Sideloading custom install.txt automatically.");
Thread t1 = new Thread(() =>
{
output += Sideloader.RunADBCommandsFromFile(path);
});
t1.IsBackground = true;
t1.Start();
while (t1.IsAlive)
await Task.Delay(100);
ChangeTitle("");
}
}
}
progressBar.Style = ProgressBarStyle.Continuous;
@@ -1144,7 +1233,6 @@ namespace AndroidSideloader
ShowPrcOutput(output);
listappsbtn();
initListView();
}
@@ -1163,6 +1251,7 @@ namespace AndroidSideloader
ChangeTitle("");
}
List<String> newGamesList = new List<string>();
List<String> newGamesToUploadList = new List<string>();
private List<UploadGame> gamesToUpload = new List<UploadGame>();
private List<UpdateGameData> gamesToAskForUpdate = new List<UpdateGameData>();
private async void initListView()
@@ -1182,10 +1271,15 @@ namespace AndroidSideloader
char[] delims = new[] { '\r', '\n' };
string[] packageList = result.Split(delims, StringSplitOptions.RemoveEmptyEntries);
string[] blacklist = new string[] { };
string[] whitelist = new string[] { };
if (File.Exists($"{Properties.Settings.Default.MainDir}\\nouns\\blacklist.txt"))
{
blacklist = File.ReadAllLines($"{Properties.Settings.Default.MainDir}\\nouns\\blacklist.txt");
}
if(File.Exists($"{Properties.Settings.Default.MainDir}\\nouns\\whitelist.txt"))
{
whitelist = File.ReadAllLines($"{Properties.Settings.Default.MainDir}\\nouns\\whitelist.txt");
}
List<ListViewItem> GameList = new List<ListViewItem>();
List<String> rookieList = new List<String>();
foreach (string[] game in SideloaderRCLONE.games)
@@ -1194,20 +1288,24 @@ namespace AndroidSideloader
}
List<String> installGames = packageList.ToList();
List<String> blacklistItems = blacklist.ToList();
List<String> whitelistItems = whitelist.ToList();
//This is for black list, but temporarly will be whitelist
newGamesList = installGames.Except(rookieList).Except(blacklistItems).ToList();
//this list has games that we are actually going to upload
newGamesToUploadList = whitelistItems.Intersect(installGames).ToList();
foreach (string[] release in SideloaderRCLONE.games)
{
ListViewItem Game = new ListViewItem(release);
if (gamesListView.Columns.Count > 0)
{
gamesListView.Columns[5].Width = 0;
gamesListView.Columns[2].Width = 0;
gamesListView.Columns[3].Width = 102;
gamesListView.Columns[4].Width = 94;
gamesListView.Columns[6].Width = 98;
gamesListView.Columns[1].Width = 280;
gamesListView.Columns[1].Width = 265;
gamesListView.Columns[5].Width = 59;
gamesListView.Columns[2].Width = 100;
gamesListView.Columns[3].Width = 50;
gamesListView.Columns[4].Width = 100;
gamesListView.Columns[5].Text = "Size (MB)";
}
foreach (string packagename in packageList)
{
@@ -1244,6 +1342,8 @@ namespace AndroidSideloader
bool dontget = false;
if (blacklist.Contains(packagename))
dontget = true;
if (!dontget)
Game.BackColor = Color.FromArgb(20, 20, 20);
string RlsName = Sideloader.PackageNametoGameName(packagename);
string GameName = Sideloader.gameNameToSimpleName(RlsName);
@@ -1266,30 +1366,49 @@ namespace AndroidSideloader
GameList.Add(Game);
}
ListViewItem[] arr = GameList.ToArray();
gamesListView.BeginUpdate();
gamesListView.Items.AddRange(arr);
gamesListView.EndUpdate();
//This is for games that we already have on rookie and user has an update
foreach(UpdateGameData gameData in gamesToAskForUpdate)
foreach (UpdateGameData gameData in gamesToAskForUpdate)
{
DialogResult dialogResult = FlexibleMessageBox.Show($"You have a newer version of:\n\n{gameData.GameName}\n\nRSL can AUTOMATICALLY UPLOAD the clean files to a shared drive in the background,\nthis is the only way to keep the apps up to date for everyone.\n\nNOTE: Rookie will only extract the APK/OBB which contain NO personal information whatsoever.", "CONTRIBUTE CLEAN FILES?", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
if (!updatesnotified)
{
await extractAndPrepareGameToUploadAsync(gameData.GameName, gameData.Packagename, gameData.InstalledVersionInt);
DialogResult dialogResult = FlexibleMessageBox.Show($"You have a newer version of:\n\n{gameData.GameName}\n\nRSL can AUTOMATICALLY UPLOAD the clean files to a shared drive in the background,\nthis is the only way to keep the apps up to date for everyone.\n\nNOTE: Rookie will only extract the APK/OBB which contain NO personal information whatsoever.", "CONTRIBUTE CLEAN FILES?", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
await extractAndPrepareGameToUploadAsync(gameData.GameName, gameData.Packagename, gameData.InstalledVersionInt);
}
}
}
//This is for games that are not blacklisted and we dont have on rookie
/*foreach (string newGamesToUpload in newGamesList)
//This is for WhiteListed Games, they will be asked for first, if we don't get many bogus prompts we can remove this entire duplicate section.
foreach (string newGamesToUpload in newGamesToUploadList)
{
string RlsName = Sideloader.PackageNametoGameName(newGamesToUpload);
//start of code to get official Release Name from APK by first extracting APK then running AAPT on it.
string apppath = ADB.RunAdbCommandToString($"shell pm path {newGamesToUpload}").Output;
apppath = Utilities.StringUtilities.RemoveEverythingBeforeFirst(apppath, "/");
apppath = Utilities.StringUtilities.RemoveEverythingAfterFirst(apppath, "\r\n");
if (File.Exists($"C:\\RSL\\2.8.2\\ADB\\base.apk"))
File.Delete($"C:\\RSL\\2.8.2\\ADB\\base.apk");
ADB.RunAdbCommandToString($"pull \"{apppath}\"");
string cmd = $"\"{Properties.Settings.Default.MainDir}\\adb\\aapt.exe\" dump badging \"C:\\RSL\\2.8.2\\ADB\\base.apk\" | findstr -i \"application-label\"";
string workingpath = $"{Properties.Settings.Default.MainDir}\\adb\\aapt.exe";
string ReleaseName = ADB.RunCommandToString(cmd, workingpath).Output;
ReleaseName = Utilities.StringUtilities.RemoveEverythingBeforeFirst(ReleaseName, "'");
ReleaseName = Utilities.StringUtilities.RemoveEverythingAfterFirst(ReleaseName, "\r\n");
ReleaseName = ReleaseName.Replace("'", "");
File.Delete($"C:\\RSL\\2.8.2\\ADB\\base.apk");
//end
string GameName = Sideloader.gameNameToSimpleName(RlsName);
Logger.Log(newGamesToUpload);
if (!updatesnotified)
{
DialogResult dialogResult = FlexibleMessageBox.Show($"You have a new game:\n\n{GameName}\n\nRSL can AUTOMATICALLY UPLOAD the clean files to a shared drive in the background,\nthis is the only way to keep the apps up to date for everyone.\n\nNOTE: Rookie will only extract the APK/OBB which contain NO personal information whatsoever.", "CONTRIBUTE CLEAN FILES?", MessageBoxButtons.YesNo);
DialogResult dialogResult = FlexibleMessageBox.Show($"You have an in demand game:\n\n{ReleaseName}\n\nRSL can AUTOMATICALLY UPLOAD the clean files to a shared drive in the background,\nthis is the only way to keep the apps up to date for everyone.\n\nNOTE: Rookie will only extract the APK/OBB which contain NO personal information whatsoever.", "CONTRIBUTE CLEAN FILES?", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
string InstalledVersionCode;
@@ -1297,13 +1416,57 @@ namespace AndroidSideloader
InstalledVersionCode = Utilities.StringUtilities.RemoveEverythingBeforeFirst(InstalledVersionCode, "versionCode=");
InstalledVersionCode = Utilities.StringUtilities.RemoveEverythingAfterFirst(InstalledVersionCode, " ");
ulong installedVersionInt = UInt64.Parse(Utilities.StringUtilities.KeepOnlyNumbers(InstalledVersionCode));
await uploadGameAsync(GameName, newGamesToUpload, installedVersionInt);
await extractAndPrepareGameToUploadAsync(GameName, newGamesToUpload, installedVersionInt);
}
else
{
}
}
}
//This is for games that are not blacklisted and we dont have on rookie
foreach (string newGamesToUpload in newGamesList)
{
string RlsName = Sideloader.PackageNametoGameName(newGamesToUpload);
//start of code to get official Release Name from APK by first extracting APK then running AAPT on it.
string apppath = ADB.RunAdbCommandToString($"shell pm path {newGamesToUpload}").Output;
apppath = Utilities.StringUtilities.RemoveEverythingBeforeFirst(apppath, "/");
apppath = Utilities.StringUtilities.RemoveEverythingAfterFirst(apppath, "\r\n");
if (File.Exists($"C:\\RSL\\2.8.2\\ADB\\base.apk"))
File.Delete($"C:\\RSL\\2.8.2\\ADB\\base.apk");
ADB.RunAdbCommandToString($"pull \"{apppath}\"");
string cmd = $"\"{Properties.Settings.Default.MainDir}\\adb\\aapt.exe\" dump badging \"C:\\RSL\\2.8.2\\ADB\\base.apk\" | findstr -i \"application-label\"";
string workingpath = $"{Properties.Settings.Default.MainDir}\\adb\\aapt.exe";
string ReleaseName = ADB.RunCommandToString(cmd, workingpath).Output;
ReleaseName = Utilities.StringUtilities.RemoveEverythingBeforeFirst(ReleaseName, "'");
ReleaseName = Utilities.StringUtilities.RemoveEverythingAfterFirst(ReleaseName, "\r\n");
ReleaseName = ReleaseName.Replace("'", "");
File.Delete($"C:\\RSL\\2.8.2\\ADB\\base.apk");
//end
newGamesList.Clear();*/
string GameName = Sideloader.gameNameToSimpleName(RlsName);
Logger.Log(newGamesToUpload);
if (!updatesnotified)
{
DialogResult dialogResult = FlexibleMessageBox.Show($"You have a new game:\n\n{ReleaseName}\n\nRSL can AUTOMATICALLY UPLOAD the clean files to a shared drive in the background,\nthis is the only way to keep the apps up to date for everyone.\n\nNOTE: Rookie will only extract the APK/OBB which contain NO personal information whatsoever.", "CONTRIBUTE CLEAN FILES?", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
string InstalledVersionCode;
InstalledVersionCode = ADB.RunAdbCommandToString($"shell \"dumpsys package {newGamesToUpload} | grep versionCode -F\"").Output;
InstalledVersionCode = Utilities.StringUtilities.RemoveEverythingBeforeFirst(InstalledVersionCode, "versionCode=");
InstalledVersionCode = Utilities.StringUtilities.RemoveEverythingAfterFirst(InstalledVersionCode, " ");
ulong installedVersionInt = UInt64.Parse(Utilities.StringUtilities.KeepOnlyNumbers(InstalledVersionCode));
await extractAndPrepareGameToUploadAsync(GameName, newGamesToUpload, installedVersionInt);
} else
{
}
}
}
updatesnotified = true;
if (!isworking && gamesToUpload.Count > 0)
{
ChangeTitle("Uploading to shared drive, you can continue to use Rookie while it uploads in the background.");
@@ -1562,11 +1725,14 @@ without him none of this would be possible
if (reset)
{
remotesList.SelectedIndex--;
SideloaderRCLONE.initGames(currentRemote);
initListView();
}
if (remotesList.Items.Count > remotesList.SelectedIndex && !reset)
{
remotesList.SelectedIndex++;
SideloaderRCLONE.initGames(currentRemote);
initListView();
steps++;
}
});
@@ -1580,7 +1746,6 @@ without him none of this would be possible
string namebox = gamesListView.SelectedItems[0].ToString();
string nameboxtranslated = Sideloader.gameNameToSimpleName(namebox);
ChangeTitle($"Checking filesize of {nameboxtranslated}...");
long selectedGamesSize = 0;
int count = 0;
string[] gamesToDownload;
@@ -1592,7 +1757,6 @@ without him none of this would be possible
gamesToDownload[i] = gamesListView.SelectedItems[i].SubItems[SideloaderRCLONE.ReleaseNameIndex].Text;
}
else return;
bool HadError = false;
Thread gameSizeThread = new Thread(() =>
{
@@ -1626,13 +1790,6 @@ without him none of this would be possible
{
game = "the selected games";
}
DialogResult dialogResult = FlexibleMessageBox.Show($"Are you sure you want to download {game}? The size is {String.Format("{0:0.00}", (double)selectedGamesSize)} MB", "Are you sure?", MessageBoxButtons.YesNo);
ChangeTitle($"");
if (dialogResult != DialogResult.Yes)
{
ChangeTitle("");
return;
}
isinstalling = true;
//Add games to the queue
for (int i = 0; i < gamesToDownload.Length; i++)
@@ -1800,7 +1957,7 @@ without him none of this would be possible
CurrAPK = file;
CurrPCKG = packagename;
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
t.Interval = 180000; // 180 seconds to fail
t.Interval = 150000; // 150 seconds to fail
t.Tick += new EventHandler(timer_Tick4);
t.Start();
Thread apkThread = new Thread(() =>
@@ -1845,11 +2002,10 @@ without him none of this would be possible
gamesQueueList.RemoveAt(0);
gamesQueListBox.DataSource = null;
gamesQueListBox.DataSource = gamesQueueList;
ChangeTitlebarToDevice();
showAvailableSpace();
ChangeTitle("");
}
ChangeTitle("");
}
}
progressBar.Style = ProgressBarStyle.Continuous;
etaLabel.Text = "ETA: Finished Queue";
@@ -1872,7 +2028,6 @@ without him none of this would be possible
{
timerticked = true;
bool isinstalled = false;
if (Properties.Settings.Default.InstalledApps.Contains(CurrPCKG))
{
isinstalled = true;
@@ -1888,10 +2043,8 @@ without him none of this would be possible
ADB.RunAdbCommandToString("devices");
ADB.RunAdbCommandToString($"pull /sdcard/Android/data/{CurrPCKG} \"{Environment.CurrentDirectory}\"");
ADB.RunAdbCommandToString($"shell pm uninstall {CurrPCKG}");
output += ADB.RunAdbCommandToString($"install -g -r \"{CurrAPK}\"");
output += ADB.RunAdbCommandToString($"install -g \"{CurrAPK}\"");
ADB.RunAdbCommandToString($"push \"{Environment.CurrentDirectory}\\{CurrPCKG}\" /sdcard/Android/data/");
listappsbtn();
initListView();
timerticked = false;
if (Directory.Exists($"{Environment.CurrentDirectory}\\{CurrPCKG}"))
@@ -1921,6 +2074,14 @@ without him none of this would be possible
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//Even if the user has already uploaded the game list, we will ask once every 24h
if (Properties.Settings.Default.lastTimeShared != null && Properties.Settings.Default.UploadedGameList)
{
if((DateTime.Now - Properties.Settings.Default.lastTimeShared).TotalDays > 1)
{
Properties.Settings.Default.UploadedGameList = false;
}
}
if (isinstalling)
{
var res1 = FlexibleMessageBox.Show(this, "There are downloads and/or installations in progress,\nif you exit now you'll have to start the entire process over again.\nAre you sure you want to exit?", "Still downloading/installing.",
@@ -1958,6 +2119,7 @@ without him none of this would be possible
FlexibleMessageBox.Show("Upload done! Thank for your colaboration!");
File.Delete(fileName);
Properties.Settings.Default.UploadedGameList = true;
Properties.Settings.Default.lastTimeShared = DateTime.Now;
Properties.Settings.Default.Save();
RCLONE.killRclone();
ADB.RunAdbCommandToString("kill-server");
@@ -1974,6 +2136,7 @@ without him none of this would be possible
RCLONE.killRclone();
ADB.RunAdbCommandToString("kill-server");
}
}
private void ADBWirelessDisable_Click(object sender, EventArgs e)
@@ -2083,7 +2246,7 @@ without him none of this would be possible
else
{
lvwColumnSorter.SortColumn = e.Column;
if (e.Column == 6)
if (e.Column == 4)
{
lvwColumnSorter.Order = SortOrder.Descending;
}
@@ -2245,28 +2408,7 @@ without him none of this would be possible
Properties.Settings.Default.Save();
}
}
if (keyData == (Keys.F11))
if (File.Exists($"{Properties.Settings.Default.CurrentLogPath}"))
{
RCLONE.runRcloneCommand($"copy \"{Properties.Settings.Default.CurrentLogPath}\" RSL-debuglogs:DebugLogs");
FlexibleMessageBox.Show($"Your debug log has been copied to the server. Please mention your DebugLog ID ({Properties.Settings.Default.CurrentLogName}) to the Mods (it has been automatically copied to your clipboard).");
Clipboard.SetText(Properties.Settings.Default.CurrentLogName);
}
if (keyData == (Keys.F12))
{
if (File.Exists($"{Properties.Settings.Default.CurrentCrashPath}"))
{
RCLONE.runRcloneCommand($"copy \"{Properties.Settings.Default.CurrentCrashPath}\" RSL-debuglogs:CrashLogs");
FlexibleMessageBox.Show($"Your CrashLog has been copied to the server. Please mention your DebugLog ID ({Properties.Settings.Default.CurrentCrashName}) to the Mods (it has been automatically copied to your clipboard).");
Clipboard.SetText(Properties.Settings.Default.CurrentCrashName);
}
else
FlexibleMessageBox.Show("No CrashLog found in Rookie directory.");
}

View File

@@ -646,5 +646,16 @@ namespace AndroidSideloader.Properties {
this["GlobalUsername"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public global::System.DateTime lastTimeShared {
get {
return ((global::System.DateTime)(this["lastTimeShared"]));
}
set {
this["lastTimeShared"] = value;
}
}
}
}

View File

@@ -158,5 +158,8 @@
<Setting Name="GlobalUsername" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="lastTimeShared" Type="System.DateTime" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>

View File

@@ -242,11 +242,11 @@ And all of them added to PATH, without ANY of them, the spoofer won't work!";
{
if (!File.Exists("Sideloader Launcher.exe"))
client.DownloadFile("https://github.com/nerdunit/androidsideloader/raw/master/Sideloader%20Launcher.exe", "Sideloader Launcher.exe");
if (!Directory.Exists(ADB.adbFolderPath)) //if there is no adb folder, download and extract
if (!File.Exists($"{Properties.Settings.Default.MainDir}\\adb\\aug2021.txt") || !File.Exists("C:\\RSL\\2.8.2\\ADB\\aug2021.txt")) //if adb is not updated, download and auto extract
{
client.DownloadFile("https://github.com/nerdunit/androidsideloader/raw/master/adb.7z", "adb.7z");
Utilities.Zip.ExtractFile(Environment.CurrentDirectory + "\\adb.7z", Environment.CurrentDirectory);
Utilities.Zip.ExtractFile(Environment.CurrentDirectory + "\\adb.7z", "C:\\RSL\\2.8.2\\");
File.Delete("adb.7z");
}

View File

@@ -26,9 +26,9 @@ namespace AndroidSideloader
public static int GameNameIndex = 0;
public static int ReleaseNameIndex = 1;
public static int ReleaseAPKPathIndex = 2;
public static int PackageNameIndex = 3;
public static int VersionCodeIndex = 4;
public static int PackageNameIndex = 2;
public static int VersionCodeIndex = 3;
public static int ReleaseAPKPathIndex = 4;
public static int VersionNameIndex = 5;
public static List<string> gameProperties = new List<string>();
@@ -85,49 +85,26 @@ namespace AndroidSideloader
{
gameProperties.Clear();
games.Clear();
string tempGameList = RCLONE.runRcloneCommand($"cat \"{remote}:{RcloneGamesFolder}/GameList.txt\"").Output;
string tempGameList = RCLONE.runRcloneCommand($"cat \"{remote}:{RcloneGamesFolder}/VRP-GameList.txt\"").Output;
if (MainForm.debugMode)
{
File.WriteAllText("GamesList.txt", tempGameList);
File.WriteAllText("VRP-GamesList.txt", tempGameList);
}
string gamePropertiesLine = Utilities.StringUtilities.RemoveEverythingAfterFirst(tempGameList, "\n");
string[] gameListSplited = tempGameList.Split(new[] { '\n' }, 2);
foreach (string gameProperty in gamePropertiesLine.Split(';'))
foreach (string gameProperty in gameListSplited[0].Split(';'))
{
gameProperties.Add(gameProperty);
}
gameProperties.Add("Last Updated");
tempGameList = Utilities.StringUtilities.RemoveEverythingBeforeFirst(tempGameList, "\n");
List<rcloneFolder> gameFolders = JsonConvert.DeserializeObject<List<rcloneFolder>>(RCLONE.runRcloneCommand($"lsjson \"{remote}:{RcloneGamesFolder}\"").Output);
if (gameFolders == null || gameFolders.Count < 1)
{
Program.form.SwitchMirrors();
gameFolders = JsonConvert.DeserializeObject<List<rcloneFolder>>(RCLONE.runRcloneCommand($"lsjson \"{remote}:{RcloneGamesFolder}\"").Output);
}
foreach (string game in tempGameList.Split('\n'))
foreach (string game in gameListSplited[1].Split('\n'))
{
if (game.Length > 1)
{
string[] splitGame = game.Split(';');
games.Add(splitGame);
//gameFolder.find();
Array.Resize(ref splitGame, splitGame.Length + 1);
var gameSynced = gameFolders.Exists((predicate) => predicate.Path == splitGame[1]);
if (gameSynced)
{
var gameFolder = gameFolders.Find((predicate) => predicate.Path == splitGame[1]);
//splitGame[6] = gameFolder.ModTime;
string gametime = Utilities.StringUtilities.RemoveEverythingAfterLast(gameFolder.ModTime, ":");
gametime = gametime.Replace("T", " ");
splitGame[splitGame.Length - 1] = gametime;
games.Add(splitGame);
}
}
}

View File

@@ -17,7 +17,7 @@ namespace AndroidSideloader
private static string RawGitHubUrl;
private static string GitHubUrl;
static readonly public string LocalVersion = "2.8.7";
static readonly public string LocalVersion = "2.9.1";
public static string currentVersion = string.Empty;
public static string changelog = string.Empty;
@@ -54,13 +54,14 @@ namespace AndroidSideloader
//Download new sideloader with version appended to file name so there is no chance of overwriting the current exe
try
{
RCLONE.killRclone();
ADB.RunAdbCommandToString("kill-server");
var fileClient = new WebClient();
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Logger.Log($"Downloading update from {RawGitHubUrl}/releases/download/v{currentVersion}/{AppName}.exe to {AppName} v{currentVersion}.exe");
fileClient.DownloadFile($"{GitHubUrl}/releases/download/v{currentVersion}/{AppName}.exe", $"{AppName} v{currentVersion}.exe");
fileClient.Dispose();
Logger.Log($"Starting {AppName} v{currentVersion}.exe");
Process.Start($"{AppName} v{currentVersion}.exe");
//Delete current version

View File

@@ -1,10 +1,37 @@
RSL 2.8.7
RSL 2.9.0
= Added code made by Ivan that makes
RSL load up much faster.
= Added confirmation dialog when using
Upload App button in case of accidental
misclicks.
= Hotfix to remove errant entry from app list
that would crash the program.
RSL 2.9
+ Updated ADB zip on repo and added a verification
text file to ensure all users are on newest ADB,
this should fix most obb issues. Upon first launch
after this update Rookie will automatically obtain
the latest ADB via this zip (7MB).
+ Added AAPT to repo along with a timer + logic to
detect packagename for automatic reinstall when drag
and dropped installs fail.
+ Implemented Size(MB) column to see app size prior
to clicking Download and Install.
= Cleaned up automatic reinstall on apk installation
failure for Download and Install, it should work for
most users now.
= Adjusted code for mirror switching, should fix failure
to load gameslist whatsoever on dead mirrors.
= Fixed issue where after installing a game RSL would
ask user to donate same clean files again. RSL will now
only ask once per program load, as intended.
- Removed filesize confirmation dialog when clicking
download and install.
- Removed columns that were useless to users.
HFP

View File

@@ -1 +1 @@
2.8.7
2.9.0