2

I need to toggle data connection on my android device connected via usb to my system using C# code. Searching the web, I found madb and madbee libraries to manipulate devices from pc, but seems there is no such functionality in these libraries(I couldn't find straight-forward documentations).

Most examples are all about file operations and package management.

My questions:

1) Is it possible to toggle android data connection using my C# program??

2) Is there any shell-command to do this??

3) Are there any other libraries( in other languages) that are capable of this operation??

Any useful links can also be helpful.

Thanks in advance.

Efe
  • 800
  • 10
  • 32

2 Answers2

3

So from your Bounty text you want to switch Mobile Data on or off via USB connection from your Windows PC, using any library or something that will interface with C#.

Most languages on windows have some way to access terminal/command prompt commands. With that, you can run the following via ADB as long as you have a rooted device or a system app:

adb shell svc data enable
adb shell svc data disable

Unfortunately to do similar programmatically through an app using Telephony also requires the permission MODIFY_PHONE_STATE, which means non-system apps on non-rooted devices are not able to do it

If you don't want to create an app yourself, somebody has made an app just for this purpose using broadcast receivers. There is a blog post by the developer here detailing how to use it to receive the broadcast over adb:

adb shell am broadcast -a yp.data.handlebroadcast -n yp.data.handle/.DataChangeReceiver --ez "wifiEnable" "true" --ez "mobileDataEnable" "true"

The app does not specify, but root privileges should be required

Community
  • 1
  • 1
Nick Cardoso
  • 20,807
  • 14
  • 73
  • 124
  • 1
    Thanks a million. Your answer was really useful and I found the exact solution based on your detailed answer. In order for other visitors to get the fastes solution in stackoverflow, I marked mine as the answer and upvoted and awarded yours. I would honestly give all my points to you if that was possible, because you helped me solve a big problem this week. Thanks again – Efe Mar 19 '17 at 14:53
2

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.

Efe
  • 800
  • 10
  • 32