Special thanks to @Nick Cardoso for his detailed and useful answer(awarded below).
I found the solution which is working on both ROOTED and UNROOTED devices(without requiring to install any app on device).
Since MabBee library has some problems with x86 and x64 architectures (problem with MoreLinq library), I decided not to use MabBee and execute ShellCommands directly from adb.exe file using C# Process class(probably possible in other languages). The only three necessary files are adb.exe, AdbWinApi.dll and AdbWinUsbApi.dll(all exist in android sdk platform-tools folder)
I created two classes MyAdbManager.cs and MyDevice.cs as below:
MyAdbManager.cs
public class MyAdbManager
{
private string _adbFileName;
public MyAdbManager(string adbFileName)
{
_adbFileName = adbFileName;
}
public string ExecuteShellCommand(string command)
{
Process proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = _adbFileName,
Arguments = command,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
return proc.StandardOutput.ReadToEnd().Trim();
}
//this method skips unauthorized devices, becuase commands do not execute
//on unauthorized devices and we need to run adb kill-server, which
//doesnt solve the problem all the time.
public List<MyDevice> GetDevices()
{
string output = ExecuteShellCommand("devices");
List<string> serials = output.Split('\n').ToList();
serials = serials.GetRange(1, serials.Count - 1); //skip the first line of output
List<MyDevice> myDevices = new List<MyDevice>();
foreach (var item in serials)
{
if (item.Contains("device"))
{
myDevices.Add(new MyDevice(item.Split('\t')[0], _adbFileName));
}
}
return myDevices;
}
}
MyDevice.cs
public class MyDevice
{
private string _adbFileNme;
public string Serial { get; }
public string Model { get; }
public string Product { get; }
public MyDevice(string serial, string adbFileName)
{
_adbFileNme = adbFileName;
Serial = serial;
Model = GetSpecificProperty("ro.product.model");
Product = GetSpecificProperty("ro.build.product");
}
public override string ToString()
{
return $"Model: {Model}, Serial: {Serial}, Product: {Product}";
}
public string ExecuteShellCommand(string command)
{
Process proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = _adbFileNme,
Arguments = command,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
return proc.StandardOutput.ReadToEnd().Trim();
}
public string GetAllPropertirs()
{
return ExecuteShellCommand($"-s {Serial} shell getprop");
}
public string GetSpecificProperty(string propertyName)
{
return ExecuteShellCommand($"-s {Serial} shell getprop {propertyName}");
}
public void EnableData()
{
ExecuteShellCommand($"-s {Serial} shell svc data enable");
}
public void DisableData()
{
ExecuteShellCommand($"-s {Serial} shell svc data disable");
}
public void RestartData()
{
DisableData();
EnableData();
}
}
Having these classes, we can use simple code as below to toggle data connection on/off:
Usage:
MyAdbManager manager = new MyAdbManager("/path/to/adb.exe"); // with AdbWinApi.dll and AdbWinUsbApi.dll files in directory
myDevices = manager.GetDevices();
myDevices[0].EnableData();
myDevices[1].DisableData();
myDevices[2].RestartData();
We can execute raw shell commands on each device or with MyAdbManager. We can also extend this class to suite our needs like what I did for geting properties of device:
Other usages:
Console.WriteLine(myDevices[0].GetAllPropertirs());
Console.WriteLine(myDevices[0].GetSpecificProperty("ro.build.version.release"));
Console.WriteLine(myDevices[0].GetSpecificProperty("ro.build.version.incremental"));
Console.WriteLine(myDevices[0].GetSpecificProperty("vzw.os.rooted"));
Console.WriteLine(myDevices[0].GetSpecificProperty("wifi.interface"));
NOTE: Just enable usb debugging on your device and check "Always Allow usb debugging from this computer". Make sure that you get "device" state after the serial number. By running "adb devices" command from adb shell, you will get sth like this:
List of devices attached
48a4ce9f device //This device will work
de16d6b2 offline //This device will not work
g5e23f2a unauthorize //This device will not work
If you don't get "device" state(like second and third devices above), disconnect cable from device side and reconnect again.
That's all.
My special thanks to @Nick Cardoso again because this answer is based on his answer.