SharpAdb / AdvancedSharpAdbClient

AdvancedSharpAdbClient is a .NET library that allows .NET, Mono and Unity applications to communicate with Android devices. It's improved version of SharpAdbClient.
https://sharpadb.github.io
Apache License 2.0
199 stars 54 forks source link

Async listen to client #83

Open davidlip123 opened 1 year ago

davidlip123 commented 1 year ago

What can we do for you?

Hi, thanks for your aweomse library! I need some help in async listening to the device connection... this is my code:

public MainWindow()
{
    InitializeComponent();

    StartAdbServer();

    var deviceMonitor = new DeviceMonitor(new AdbSocket("127.0.0.1", 62001));
    deviceMonitor.DeviceConnected += OnDeviceConnected;
    deviceMonitor.Start();
}

private void StartAdbServer()
{
    if (!AdbServer.Instance.GetStatus().IsRunning)
    {
        AdbServer server = new AdbServer();
        StartServerResult result = server.StartServer(@"C:\Users\Itamar\AppData\Local\Android\Sdk\platform-tools\adb.exe", false);
        if (result != StartServerResult.Started)
        {
            MessageBox.Show("Can't start adb server");
        }
        else
        {
            MessageBox.Show("started adb server");
        }
    }
}

But I'm getting error with that.... No connection could be made because the target machine actively refused it.

And there is device connected indeed...can you give me a clue about what I need to do?

wherewhere commented 1 year ago

This is my code

using AdvancedSharpAdbClient;
using System;
using System.Collections.Generic;
using System.Net;

StartServerResult startServerResult = await AdbServer.Instance.StartServerAsync(@"C:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe", false, default);
Console.WriteLine(startServerResult);

await using DeviceMonitor deviceMonitor = new(new AdbSocket(new IPEndPoint(IPAddress.Loopback, AdbClient.AdbServerPort)));
deviceMonitor.DeviceConnected += (sender, e) => Console.WriteLine($"Device connected: {e.Device}");
deviceMonitor.DeviceDisconnected += (sender, e) => Console.WriteLine($"Device disconnected: {e.Device}");
deviceMonitor.DeviceChanged += (sender, e) => Console.WriteLine($"Device state changed: {e.Device} {e.OldState} -> {e.NewState}");
await deviceMonitor.StartAsync();

Console.Write("Press any key to exit...");
Console.ReadKey(true);

await AdbServer.Instance.StopServerAsync(default);

And synchronous one

using AdvancedSharpAdbClient;
using System;
using System.Collections.Generic;
using System.Net;

StartServerResult startServerResult = AdbServer.Instance.StartServer(@"C:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe", false);
Console.WriteLine(startServerResult);

using DeviceMonitor deviceMonitor = new(new AdbSocket(new IPEndPoint(IPAddress.Loopback, AdbClient.AdbServerPort)));
deviceMonitor.DeviceConnected += (sender, e) => Console.WriteLine($"Device connected: {e.Device}");
deviceMonitor.DeviceDisconnected += (sender, e) => Console.WriteLine($"Device disconnected: {e.Device}");
deviceMonitor.DeviceChanged += (sender, e) => Console.WriteLine($"Device state changed: {e.Device} {e.OldState} -> {e.NewState}");
deviceMonitor.Start();

Console.Write("Press any key to exit...");
Console.ReadKey(true);

AdbServer.Instance.StopServer();
davidlip123 commented 1 year ago

@wherewhere thank you so much for response man ;)

I'm using this code:

public MainWindow()
{
    InitializeComponent();

    Start();
}

public async Task Start()
{
    StartServerResult startServerResult = await AdbServer.Instance.StartServerAsync(@"C:\Users\Itamar\AppData\Local\Android\Sdk\platform-tools\adb.exe", false, CancellationToken.None);
    Trace.WriteLine(startServerResult);

    await using DeviceMonitor deviceMonitor = new(new AdbSocket(new IPEndPoint(IPAddress.Loopback, AdbClient.AdbServerPort)));
    deviceMonitor.DeviceConnected += (sender, e) => Trace.WriteLine($"Device connected: {e.Device}"); // never reaches here
    deviceMonitor.DeviceDisconnected += (sender, e) => Trace.WriteLine($"Device disconnected: {e.Device}");
    deviceMonitor.DeviceChanged += (sender, e) => Trace.WriteLine($"Device state changed: {e.Device} {e.OldState} -> {e.NewState}");
    await deviceMonitor.StartAsync();

    // await AdbServer.Instance.StopServerAsync(default);
}

The server indeed starts,but it never triggers the DeviceConnected method..... tried few times...and nothing..... any idea what's wrong here?

Using this sample,indeed works...but as I said I need to listen in the background and handle incoming connections...:

public static void getConnectedDevice()
{
    client = new AdbClient();
    client.ConnectAsync("127.0.0.1:62001");
    device = client.GetDevices().FirstOrDefault();

    Trace.WriteLine(device.Model);
}
wherewhere commented 1 year ago

I don't know. Are you connected device by USB? Why connected by localhost IP?

https://github.com/SharpAdb/AdvancedSharpAdbClient/assets/27689196/aabe6f3d-119b-4728-af71-408441be8db1

davidlip123 commented 1 year ago

@wherewhere I used the localhost ip because this is the example you provided...in the github home page.... of course I'm using usb. Look,i've used nuget pm to install the AdvancedSharpAdbClient,maybe I need to clone the project and add it to my project,since there were changes from the last release?maybe it will solve the problem...?

edit:can you confirm that this code work for you, and the events indeed trigers....?

public MainWindow()
{
    InitializeComponent();

    Start();
}

public async Task Start()
{
    StartServerResult startServerResult = await AdbServer.Instance.StartServerAsync(@"C:\Users\Itamar\AppData\Local\Android\Sdk\platform-tools\adb.exe", false, CancellationToken.None);
    Trace.WriteLine(startServerResult); // result is already running

    await using DeviceMonitor deviceMonitor = new(new AdbSocket(new IPEndPoint(IPAddress.Loopback, AdbClient.AdbServerPort)));
    deviceMonitor.DeviceConnected += (sender, e) => Trace.WriteLine($"Device connected: {e.Device}"); // never reaches here
    deviceMonitor.DeviceDisconnected += (sender, e) => Trace.WriteLine($"Device disconnected: {e.Device}");
    deviceMonitor.DeviceChanged += (sender, e) => Trace.WriteLine($"Device state changed: {e.Device} {e.OldState} -> {e.NewState}");
    await deviceMonitor.StartAsync();

    // await AdbServer.Instance.StopServerAsync(default);
}
wherewhere commented 1 year ago

Remove the using of DeviceMonitor. You just disposed it when Start method is done.

yungd1plomat commented 1 year ago

What device are you using an emulator or a real device?

davidlip123 commented 12 months ago

@wherewhere @yungd1plomat ,I'm using real usb connected device...tried on few devices....different chipsets and android versions....and none....

I tried to create a console app in visual studio , and your code indeed works....but When I try to add it to my wpf app....there are no results at all..... what the hell is wrong here? And another question,When I try to get the device name/ model when in the console app when the DeviceConnectedevent triggers...I'm getting blank output.... why is it?

deviceMonitor.DeviceConnected += (sender, e) => Trace.WriteLine($"Device connected: {e.Device.Name}");
yungd1plomat commented 12 months ago

@wherewhere @yungd1plomat ,I'm using real usb connected device...tried on few devices....different chipsets and android versions....and none....

I tried to create a console app in visual studio , and your code indeed works....but When I try to add it to my wpf app....there are no results at all..... what the hell is wrong here? And another question,When I try to get the device name/ model when in the console app when the DeviceConnectedevent triggers...I'm getting blank output.... why is it?

deviceMonitor.DeviceConnected += (sender, e) => Trace.WriteLine($"Device connected: {e.Device.Name}");

Because track-devices only sends the device serial. If you want to get the device model and name you can use:

var client = new AdbClient();
await using DeviceMonitor deviceMonitor = new(
    new AdbSocket(new IPEndPoint(IPAddress.Loopback, AdbClient.AdbServerPort)));
deviceMonitor.DeviceConnected += async (s, deviceData) =>
{
    var devices = await client.GetDevicesAsync();
    var device = devices.First(d => d.Serial == deviceData.Device.Serial);
    Trace.WriteLine($"Device connected: {device.Model}");
};
await deviceMonitor.StartAsync();

Or you can directly monitor when device connected like this:

var client = new AdbClient();
var devices = await client.GetDevicesAsync();
while (!devices.Any(x => x.State == DeviceState.Online)) 
{
    Trace.WriteLine("Waiting for device connection..");
    devices = await client.GetDevicesAsync();
    await Task.Delay(1000);
}
var device = devices.FirstOrDefault();
Trace.WriteLine($"Connected {device.Name}");

and you don't need to use client.ConnectAsync("127.0.0.1:62001"); because the real device is connected automatically

davidlip123 commented 11 months ago

@yungd1plomat @wherewhere hey guys, thanks for your response. This is the current and the only working solution for me:

public async Task Start()
{
    StartAdbServer();
    var client = new AdbClient();
    var devices = await client.GetDevicesAsync();
    while (!devices.Any(x => x.State == DeviceState.Online))
    {
         Trace.WriteLine("Waiting for device connection..");
         devices = await client.GetDevicesAsync();
         await Task.Delay(600);      
    }
    var device = devices.FirstOrDefault();
    String model = device.Model;
}

@yungd1plomat your first example, using the deviceMonitor.DeviceConnected event didn't work for me, and that event never triggers, feel free to try it yourself, in and wpf app (not in a console). I need to register a DeviceDisconnected event.... is there a solution for me? (Again, in wpf app :)) Thank you so so much for your kind response sir!

wherewhere commented 11 months ago

Mybe you need to know what's using and what's await...

davidlip123 commented 11 months ago

Mybe you need to know what's using and what's await...

I know sir...I'm developing few years in c#...I know await uses for async functions,and using is for resources managment.... it doesn't answer my question..... you are invited to try it yourself and see that I'm right.... :(

wherewhere commented 11 months ago
public async Task Start()
{
    StartServerResult startServerResult = await AdbServer.Instance.StartServerAsync(@"C:\Users\Itamar\AppData\Local\Android\Sdk\platform-tools\adb.exe", false, CancellationToken.None);
    Trace.WriteLine(startServerResult); // result is already running

    await using DeviceMonitor deviceMonitor = new(new AdbSocket(new IPEndPoint(IPAddress.Loopback, AdbClient.AdbServerPort)));
    deviceMonitor.DeviceConnected += (sender, e) => Trace.WriteLine($"Device connected: {e.Device}"); // never reaches here
    deviceMonitor.DeviceDisconnected += (sender, e) => Trace.WriteLine($"Device disconnected: {e.Device}");
    deviceMonitor.DeviceChanged += (sender, e) => Trace.WriteLine($"Device state changed: {e.Device} {e.OldState} -> {e.NewState}");
    await deviceMonitor.StartAsync();

    // await AdbServer.Instance.StopServerAsync(default);
}

So why you disposed the monitor?