Marcin Drobik

software journeyman notes

About Me

I am

... a Software Engineer that likes to program everything - from simple custom tools to enterprise class systems.

Apart from technical aspects of programming, I'm is also interested in the dynamics of team-work and human motivation.

I created commercial software for various markets: finance, insurance, access control and others. Currently, at Future Processing, I'm supporting other teams in defining their development process, maintaining high quality code, choosing tools and designing software architecture.

Catch me on:

You could see me at:

 

Blog

Recent Posts

Entity Framework Core InMemory

Entity Framework Core has support for InMemory database which is great help when writing tests against database.

However currently the setup of InMemory database is somewhat unobvious. To make it more readable I use class similar to this:

public class InMemoryDatabaseInstance<TContext> where TContext : DbContext
{
    public DbContextOptions<TContext> DbContextOptions { get; }

    public InMemoryDatabaseInstance()
    {
        DbContextOptions = new DbContextOptionsBuilder<TContext>()
            .UseInMemoryDatabase()
            .UseInternalServiceProvider(
                new ServiceCollection().AddEntityFrameworkInMemoryDatabase().BuildServiceProvider())
            .Options;
    }

    public static implicit operator DbContextOptions<TContext>(InMemoryDatabaseInstance<TContext> instance) => instance.DbContextOptions;
}

Thanks to implicit operator it's fairly easy to use it:

public void ShouldRetrieveNotices()
{
    var instance = new InMemoryDatabaseInstance<MyContext>();
    using (var db = new MyContext(instance))
    {
        db.Notices.Add(new Notice()
        {
            Title = "Test Notice",
            Deadline = DateTime.Now.AddDays(2)
        });

        db.SaveChanges();
    }

    using (var db = new MyContext(instance))
    {
        var notice = db.Notices.Single();
        Assert.Equal("Test Notice", notice.Title);
        Assert.Equal(DateTime.Now.AddDays(2), notice.Deadline);
    }
}

public class MyContext : DbContext
{
    public MyContext(DbContextOptions<MyContext> dbOptions) : base(dbOptions)
    {
    }

    // ...
}

Scanning WiFi networks with Xamarin Android

For my WiFi Locator project I need an app to gather WiFi signal data in different locations. First step is to list IDs of all available networks. Finished app looks like this:

(Screen is updated every couple of seconds with latest data)

Xamarin

I decided to build it with Xamarin - It comes bundled with Visual Studio 2015 installer and has been recently made available to use with all Visual Studio licenses which makes it simple for me to start with.

Activity

First we need an activity that will be our app's starting point:

[Activity(Label = "Wifi Monitor", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        SetContentView(Resource.Layout.Wifi);

Network scanning is asynchronous, so to handle the results Android requires registered broadcast receiver. WifiMonitor is custom made class described later:

        RegisterReceiver(new WifiMonitor(this), new IntentFilter(WifiManager.ScanResultsAvailableAction));    
        ((WifiManager)GetSystemService(WifiService)).StartScan();
    }


    public void DisplayText(string text)
    {
        FindViewById<TextView>(Resource.Id.txtScanResults).Text = "Wifi networks: \r\n" + text;
    }
}

BroadcastReceiver

WifiMonitor will be called when network scan is completed and it's responsible for formating the result and passing it back to MainActivity:

public class WifiMonitor : BroadcastReceiver
{

Reminder: be careful when creating async void methods

    public override async void OnReceive(Context context, Intent intent)
    {
        var mainActivity = (MainActivity)context;

Scan results hold (among other data) identifiers and measured signal levels of available networks:

        var wifiManager = (WifiManager)mainActivity.GetSystemService(Context.WifiService);
        var message = string.Join("\r\n", wifiManager.ScanResults
            .Select(r => $"{r.Bssid} - {r.Level} dB"));

        mainActivity.DisplayText(message);

With use of .NET's async/await it's easy to reschedule another scan after some time:

        await Task.Delay(TimeSpan.FromSeconds(1));    
        wifiManager.StartScan();
    }
}

Layout

The layout is plain simple - it's just TextView used to display the message generated by the WifiMonitor. The only real adjustment I made is change the font to monospace and added small margin:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minWidth="25px"
    android:minHeight="25px">

  <TextView
      android:text="Scanning for networks..."
      android:textAppearance="?android:attr/textAppearanceMedium"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_margin="10dp"
      android:id="@+id/txtScanResults"
      android:typeface="monospace" />
</LinearLayout>

Older Posts