Skip to content

Instantly share code, notes, and snippets.

@Xiaoy312
Created April 8, 2019 18:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xiaoy312/ae922076588795a0a70e456f8726ee9b to your computer and use it in GitHub Desktop.
Save Xiaoy312/ae922076588795a0a70e456f8726ee9b to your computer and use it in GitHub Desktop.
Linqpad script to manage apps on android devices
<Query Kind="Program">
<Namespace>LINQPad.Controls</Namespace>
<Namespace>System.Threading.Tasks</Namespace>
</Query>
#define YOLO_NO_CONFIRM
void Main()
{
Util.AutoScrollResults = false;
var searchLabel = new Label("Find:");
searchTextBox = new TextBox(onTextInput: _ => UpdateResults());
useRegexCheckBox = new CheckBox("Regex", true, onClick: _ => UpdateResults());
filterMiscAppsCheckBox = new CheckBox("Filter platform/manufacturer/misc apps", true, onClick: _ => UpdateResults());
promoteKnownAppsCheckBox = new CheckBox("todo: sort nventive(tm) apps on top", false, onClick: _ => UpdateResults()) { Enabled = false, Visible = false };
var refreshButton = new Button("refresh", onClick: _ => UpdateResults());
new WrapPanel(searchLabel, searchTextBox, useRegexCheckBox).Dump();
new WrapPanel(refreshButton, filterMiscAppsCheckBox, promoteKnownAppsCheckBox).Dump();
results = new DumpContainer(GetResults()).Dump("Packages");
}
TextBox searchTextBox;
CheckBox useRegexCheckBox;
CheckBox filterMiscAppsCheckBox, promoteKnownAppsCheckBox;
DumpContainer results;
// Define other methods and classes here
void UpdateResults()
{
results.Content = GetResults();
}
object GetResults()
{
try
{
// see: http://adbshell.com/commands/adb-shell-pm-list-packages
const string ThirdPartyOnlyOption = "-3";
var packages = Util.Cmd($"adb shell pm list packages {ThirdPartyOnlyOption}", quiet: true)
.Where(x => !string.IsNullOrEmpty(x))
.ToArray();
if (packages.Any(x => !x.StartsWith("package:")))
{
packages.Dump();
throw new InvalidOperationException("expected 'package:' to be found on every line");
}
return packages
.Select(x => x.Substring("package:".Length))
.Where(GetSearchMatcher())
.Where(GetMiscAppsFilter())
.OrderBy(x => x)
.Select(x => new
{
PackageName = x,
Actions = Util.HorizontalRun(true,
new Hyperlinq(() => StartApp(x), "Start"),
new Hyperlinq(() => KillApp(x), "Kill"),
new Hyperlinq(() => CleanApp(x), "Clear Data"),
new Hyperlinq(() => UninstallApp(x), "Uninstall")
)
});
}
catch (Exception ex)
{
return ex;
}
}
Func<string, bool> GetSearchMatcher()
{
if (string.IsNullOrEmpty(searchTextBox.Text)) return x => true;
return useRegexCheckBox.Checked
? (Func<string, bool>)new Regex(searchTextBox.Text).IsMatch
: x => x.Contains(searchTextBox.Text);
}
Func<string, bool> GetMiscAppsFilter()
{
return filterMiscAppsCheckBox.Checked
? (Func<string, bool>)FilterMiscApps
: x => true;
}
bool FilterMiscApps(string packageName)
{
if (packageName == "android") return false;
if (packageName.StartsWith("com.android")) return false;
if (packageName.StartsWith("com.sec")) return false;
if (packageName.StartsWith("com.google")) return false;
if (packageName.StartsWith("com.microsoft")) return false;
if (packageName.StartsWith("com.samsung")) return false;
if (packageName.StartsWith("com.qualcomm")) return false;
// other common apps
if (packageName.StartsWith("Mono.Android")) return false;
if (packageName.StartsWith("com.monotype")) return false;
if (packageName.StartsWith("com.amazon")) return false;
if (packageName.StartsWith("com.facebook")) return false;
return true;
}
string[] ExecuteCommand(string command, bool quiet = false)
{
Util.Metatext($"> {command}").Dump();
return Util.Cmd(command, quiet);
}
async Task ConfirmAction(string prompt, Action action, bool useBrain = false)
{
#if !YOLO_NO_CONFIRM
var challenge = GenerateChallenge();
if (await Util.ReadLineAsync($"{prompt} {challenge.Question}") == challenge.Answer)
{
action();
}
#else
action();
#endif
(string Question, string Answer) GenerateChallenge()
{
if (useBrain)
{
var random = new Random(Guid.NewGuid().GetHashCode());
var leftOperand = random.Next(0, 10);
var rightOperand = random.Next(0, 10);
return ($"(enter sum of {leftOperand} and {rightOperand})", (leftOperand + rightOperand).ToString());
}
else
{
return ("(enter y to continue)", "y");
}
}
}
void StartApp(string packageName) => ExecuteCommand($"adb shell monkey -p {packageName} 1"); // see: https://stackoverflow.com/a/25398877
void KillApp(string packageName) => ExecuteCommand($"adb shell am force-stop {packageName}");
void CleanApp(string packageName) => ExecuteCommand($"adb shell pm clear {packageName}"); // kill & clean slate see: https://stackoverflow.com/a/3117310
void UninstallApp(string packageName) => ConfirmAction($"uninstall `{packageName}`?", () => ExecuteCommand($"adb uninstall {packageName}"));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment