2024-06-19 14:16:38 +00:00
|
|
|
using System.Net;
|
|
|
|
using System.Net.Sockets;
|
2024-06-19 17:02:44 +00:00
|
|
|
using Android.Content;
|
|
|
|
using Android.Hardware.Biometrics;
|
|
|
|
using Android.OS;
|
|
|
|
using Java.Lang;
|
2024-06-19 14:16:38 +00:00
|
|
|
|
|
|
|
namespace DemoAndroid;
|
|
|
|
|
2024-06-19 17:20:50 +00:00
|
|
|
[Activity(Label = "WakeOnLanActivity", MainLauncher = true, Theme = "@style/NoActionBar")]
|
2024-06-19 14:16:38 +00:00
|
|
|
public class WakeOnLanActivity : Activity
|
|
|
|
{
|
2024-06-19 17:02:44 +00:00
|
|
|
private const int BiometricStrong = 0x0000000f;
|
|
|
|
private const int BiometricWeak = 0x000000ff;
|
|
|
|
private const int DeviceCredential = 0x00008000;
|
|
|
|
|
|
|
|
private bool _authenticated = false;
|
|
|
|
|
2024-06-19 14:16:38 +00:00
|
|
|
protected override void OnCreate(Bundle? savedInstanceState)
|
|
|
|
{
|
|
|
|
base.OnCreate(savedInstanceState);
|
|
|
|
|
|
|
|
// Create your application here
|
|
|
|
SetContentView(Resource.Layout.activity_wakeonlan);
|
|
|
|
|
|
|
|
var button = FindViewById<Button>(Resource.Id.btnWakeOnLan);
|
|
|
|
button.Click += (sender, args) =>
|
|
|
|
{
|
2024-06-19 17:20:50 +00:00
|
|
|
OnlyAuthenticated(WakePc);
|
2024-06-19 14:16:38 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2024-06-19 17:20:50 +00:00
|
|
|
private void OnlyAuthenticated(Action action)
|
2024-06-19 17:02:44 +00:00
|
|
|
{
|
2024-06-19 17:20:50 +00:00
|
|
|
if (!_authenticated)
|
|
|
|
{
|
|
|
|
var callback = new BiometricCallback(this, () =>
|
|
|
|
{
|
|
|
|
_authenticated = true;
|
|
|
|
action();
|
|
|
|
});
|
|
|
|
|
|
|
|
var prompt = new BiometricPrompt.Builder(this)
|
|
|
|
.SetNegativeButton("Annuleren", MainExecutor, callback)
|
|
|
|
.SetTitle("Bewijs jezelf met je vingerafdruk")
|
|
|
|
.SetSubtitle("We willen zeker weten dat je niet Colinde bent")
|
|
|
|
.SetAllowedAuthenticators(BiometricStrong)
|
|
|
|
.Build();
|
2024-06-19 17:02:44 +00:00
|
|
|
|
2024-06-19 17:20:50 +00:00
|
|
|
var cancellation = new CancellationSignal();
|
2024-06-19 17:02:44 +00:00
|
|
|
|
2024-06-19 17:20:50 +00:00
|
|
|
prompt.Authenticate(cancellation, MainExecutor, callback);
|
|
|
|
return;
|
|
|
|
}
|
2024-06-19 17:02:44 +00:00
|
|
|
|
2024-06-19 17:20:50 +00:00
|
|
|
action();
|
2024-06-19 17:02:44 +00:00
|
|
|
}
|
|
|
|
|
2024-06-19 14:16:38 +00:00
|
|
|
private void WakePc()
|
|
|
|
{
|
2024-06-19 17:02:44 +00:00
|
|
|
byte[] macAddress = [0x2c, 0x4d, 0x54, 0x4d, 0x10, 0x0f];
|
|
|
|
var magicPacket = new byte[102];
|
2024-06-19 14:16:38 +00:00
|
|
|
|
|
|
|
// Fill first 6 bytes with 0xFF
|
2024-06-19 17:02:44 +00:00
|
|
|
for (var i = 0; i < 6; i++)
|
2024-06-19 14:16:38 +00:00
|
|
|
{
|
|
|
|
magicPacket[i] = 0xFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Repeat MAC address 16 times
|
2024-06-19 17:02:44 +00:00
|
|
|
for (var i = 1; i <= 16; i++)
|
2024-06-19 14:16:38 +00:00
|
|
|
{
|
2024-06-19 17:02:44 +00:00
|
|
|
for (var j = 0; j < 6; j++)
|
2024-06-19 14:16:38 +00:00
|
|
|
{
|
|
|
|
magicPacket[i * 6 + j] = macAddress[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
using var client = new UdpClient();
|
|
|
|
client.EnableBroadcast = true;
|
|
|
|
var endpoint = new IPEndPoint(IPAddress.Broadcast, 9); // 255.255.255.255 port 9
|
|
|
|
|
2024-06-19 17:02:44 +00:00
|
|
|
for (var i = 0; i < 5; i++)
|
2024-06-19 14:16:38 +00:00
|
|
|
{
|
|
|
|
// Try 5 times
|
|
|
|
client.Send(magicPacket, magicPacket.Length, endpoint);
|
|
|
|
}
|
2024-06-19 17:02:44 +00:00
|
|
|
|
2024-06-19 17:20:50 +00:00
|
|
|
Toast.MakeText(this, "Computer started!", ToastLength.Long)!.Show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Biometric authentication callbacks
|
|
|
|
/// https://developer.android.com/identity/sign-in/biometric-auth#java
|
|
|
|
/// </summary>
|
|
|
|
class BiometricCallback : BiometricPrompt.AuthenticationCallback, IDialogInterfaceOnClickListener
|
|
|
|
{
|
|
|
|
private Context _context;
|
|
|
|
private readonly Action _onSuccess;
|
|
|
|
|
|
|
|
public BiometricCallback(Context context, Action onSuccess)
|
|
|
|
{
|
|
|
|
_context = context;
|
|
|
|
_onSuccess = onSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void OnAuthenticationError(BiometricErrorCode errorCode, ICharSequence? errString)
|
|
|
|
{
|
|
|
|
Toast.MakeText(_context, $"Authenticatie mislukt: {errorCode}, {errString?.ToString()}", ToastLength.Long)!.Show();
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void OnAuthenticationSucceeded(BiometricPrompt.AuthenticationResult? result)
|
|
|
|
{
|
|
|
|
Toast.MakeText(_context, "Authentication succeeded!", ToastLength.Short)!.Show();
|
|
|
|
_onSuccess();
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void OnAuthenticationFailed()
|
|
|
|
{
|
|
|
|
Toast.MakeText(_context, "Authenticatie mislukt!", ToastLength.Long)!.Show();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnClick(IDialogInterface? dialog, int which)
|
|
|
|
{
|
|
|
|
Toast.MakeText(_context, "Geannuleerd!", ToastLength.Long)!.Show();
|
2024-06-19 14:16:38 +00:00
|
|
|
}
|
|
|
|
}
|