Compare commits
No commits in common. "007ca4ef0f397277eeedc89159f7292b65e22205" and "9d6aaccc0c11ef6a7ffbbb483d024121c7f352d2" have entirely different histories.
007ca4ef0f
...
9d6aaccc0c
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,4 +1,3 @@
|
|||||||
.idea/
|
.idea/
|
||||||
obj/
|
obj/
|
||||||
bin/
|
bin/
|
||||||
/.DS_Store
|
|
BIN
DemoAndroid/.DS_Store
vendored
BIN
DemoAndroid/.DS_Store
vendored
Binary file not shown.
@ -1,21 +1,11 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using Android.Content;
|
|
||||||
using Android.Hardware.Biometrics;
|
|
||||||
using Android.OS;
|
|
||||||
using Java.Lang;
|
|
||||||
|
|
||||||
namespace DemoAndroid;
|
namespace DemoAndroid;
|
||||||
|
|
||||||
[Activity(Label = "@string/app_name", MainLauncher = true, Theme = "@style/Default")]
|
[Activity(Label = "WakeOnLanActivity")]
|
||||||
public class WakeOnLanActivity : Activity
|
public class WakeOnLanActivity : Activity
|
||||||
{
|
{
|
||||||
private const int BiometricStrong = 0x0000000f;
|
|
||||||
private const int BiometricWeak = 0x000000ff;
|
|
||||||
private const int DeviceCredential = 0x00008000;
|
|
||||||
|
|
||||||
private bool _authenticated = false;
|
|
||||||
|
|
||||||
protected override void OnCreate(Bundle? savedInstanceState)
|
protected override void OnCreate(Bundle? savedInstanceState)
|
||||||
{
|
{
|
||||||
base.OnCreate(savedInstanceState);
|
base.OnCreate(savedInstanceState);
|
||||||
@ -26,51 +16,25 @@ public class WakeOnLanActivity : Activity
|
|||||||
var button = FindViewById<Button>(Resource.Id.btnWakeOnLan);
|
var button = FindViewById<Button>(Resource.Id.btnWakeOnLan);
|
||||||
button.Click += (sender, args) =>
|
button.Click += (sender, args) =>
|
||||||
{
|
{
|
||||||
OnlyAuthenticated(WakePc);
|
WakePc();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnlyAuthenticated(Action action)
|
|
||||||
{
|
|
||||||
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();
|
|
||||||
|
|
||||||
var cancellation = new CancellationSignal();
|
|
||||||
|
|
||||||
prompt.Authenticate(cancellation, MainExecutor, callback);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
action();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WakePc()
|
private void WakePc()
|
||||||
{
|
{
|
||||||
byte[] macAddress = [0x2c, 0x4d, 0x54, 0x4d, 0x10, 0x0f];
|
byte[] macAddress = { 0x2c, 0x4d, 0x54, 0x4d, 0x10, 0x0f };
|
||||||
var magicPacket = new byte[102];
|
byte[] magicPacket = new byte[102];
|
||||||
|
|
||||||
// Fill first 6 bytes with 0xFF
|
// Fill first 6 bytes with 0xFF
|
||||||
for (var i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
magicPacket[i] = 0xFF;
|
magicPacket[i] = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repeat MAC address 16 times
|
// Repeat MAC address 16 times
|
||||||
for (var i = 1; i <= 16; i++)
|
for (int i = 1; i <= 16; i++)
|
||||||
{
|
{
|
||||||
for (var j = 0; j < 6; j++)
|
for (int j = 0; j < 6; j++)
|
||||||
{
|
{
|
||||||
magicPacket[i * 6 + j] = macAddress[j];
|
magicPacket[i * 6 + j] = macAddress[j];
|
||||||
}
|
}
|
||||||
@ -80,49 +44,10 @@ public class WakeOnLanActivity : Activity
|
|||||||
client.EnableBroadcast = true;
|
client.EnableBroadcast = true;
|
||||||
var endpoint = new IPEndPoint(IPAddress.Broadcast, 9); // 255.255.255.255 port 9
|
var endpoint = new IPEndPoint(IPAddress.Broadcast, 9); // 255.255.255.255 port 9
|
||||||
|
|
||||||
for (var i = 0; i < 5; i++)
|
for (int i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
// Try 5 times
|
// Try 5 times
|
||||||
client.Send(magicPacket, magicPacket.Length, endpoint);
|
client.Send(magicPacket, magicPacket.Length, endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,6 +3,4 @@
|
|||||||
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:label="@string/app_name" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true">
|
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:label="@string/app_name" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true">
|
||||||
</application>
|
</application>
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
|
||||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
|
||||||
</manifest>
|
</manifest>
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0-android</TargetFramework>
|
<TargetFramework>net8.0-android</TargetFramework>
|
||||||
<SupportedOSPlatformVersion>30</SupportedOSPlatformVersion>
|
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
@ -12,10 +12,11 @@
|
|||||||
<!-- With AOT, our app is crashing in Release mode -->
|
<!-- With AOT, our app is crashing in Release mode -->
|
||||||
<RunAOTCompilation>False</RunAOTCompilation>
|
<RunAOTCompilation>False</RunAOTCompilation>
|
||||||
<PublishAot>False</PublishAot>
|
<PublishAot>False</PublishAot>
|
||||||
<TargetFrameworkVersion>v13.0</TargetFrameworkVersion>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="QRCoder-ImageSharp" Version="0.10.0" />
|
<PackageReference Include="QRCoder-ImageSharp" Version="0.10.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Activities\" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -4,7 +4,7 @@ using QRCoder; // QRCoder-ImageSharp else it crashes
|
|||||||
|
|
||||||
namespace DemoAndroid;
|
namespace DemoAndroid;
|
||||||
|
|
||||||
[Activity(Label = "@string/app_name", MainLauncher = false)]
|
[Activity(Label = "@string/app_name", MainLauncher = true)]
|
||||||
public class MainActivity : Activity
|
public class MainActivity : Activity
|
||||||
{
|
{
|
||||||
private string _text = "";
|
private string _text = "";
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
# Android Native C# readme
|
|
||||||
|
|
||||||
1. AOT makes release versions crash sometimes, so it is disabled
|
|
||||||
2. Project created with
|
|
||||||
```bash
|
|
||||||
dotnet new android
|
|
||||||
```
|
|
||||||
3. New activities can be created with
|
|
||||||
```bash
|
|
||||||
dotnet new android-activity -n MyNewActivity
|
|
||||||
```
|
|
||||||
4. Avoid NuGet packages that are not built for non-Windows environments (e.g. depend on System.Drawing)
|
|
||||||
|
|
||||||
If the app crashes directly in Release, before reverting all your changes try to clean /bin and /obj
|
|
||||||
Also, if you reverted some changes, clean /bin and /obj again before thinking it still doesn't work
|
|
@ -2,19 +2,18 @@
|
|||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:layout_margin="5pt">
|
|
||||||
|
|
||||||
<TextView android:layout_width="match_parent"
|
<TextView android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Start de computer met Wake-On-Lan door op de knop hieronder te klikken" />
|
android:text="Start PC by tapping button below" />
|
||||||
|
|
||||||
<Button android:id="@+id/btnWakeOnLan"
|
<Button android:id="@+id/btnWakeOnLan"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Start de computer"
|
android:text="Start PC"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:background="@color/green"
|
android:background="@color/blue"
|
||||||
android:height="20pt"
|
android:height="15pt"
|
||||||
android:layout_margin="10pt"/>
|
android:layout_margin="10pt"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -2,5 +2,4 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<color name="blue">#4287f5</color>
|
<color name="blue">#4287f5</color>
|
||||||
<color name="white">#FFFFFF</color>
|
<color name="white">#FFFFFF</color>
|
||||||
<color name="green">#2abf39</color>
|
|
||||||
</resources>
|
</resources>
|
@ -1,4 +1,4 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Goofjes</string>
|
<string name="app_name">DemoAndroid</string>
|
||||||
<string name="app_text">Hello, Android!</string>
|
<string name="app_text">Hello, Android!</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<style name="Default" parent="@android:style/Theme.Material.Light.DarkActionBar">
|
|
||||||
|
|
||||||
</style>
|
|
||||||
<style name="NoActionBar" parent="@android:style/Theme.Material.Light.DarkActionBar">
|
|
||||||
<item name="android:windowActionBar">false</item>
|
|
||||||
<item name="android:windowNoTitle">true</item>
|
|
||||||
<item name="android:windowFullscreen">true</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
|
Loading…
Reference in New Issue
Block a user