6/2/18

Xamarin Android Class Not Found Exception

The Class Not Found Exception is commonly raised when the class loader tries to find an activity or a broadcast receiver class listed on the app manifest, but it fails to find it. Common examples can be a splash activity with no layout to show an animation, or a broadcast receiver which should load after intent is received, like boot completed intent.

What is common on these cases is that these classes should be configured on the AndroidManifest.xml file as part of the build process, but during the application load lifecycle, these classes are not found. This indicates that there is missing metadata which affects the load process. Let’s review a common application manifest and class declaration and discuss the problem and solution.


AndroidManifest


<manifest package="com.ozkary.app"
<receiver       
        android:name=".BootReceiver"    
<intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />  
</intent-filter>

</receiver>
</manifest>


On the abbreviated manifest above, we can find the package name and the receiver class.  The receiver class name is relative to the package name which means that during the load time, the class loader will attempt to find a class with the name of com.ozkary.app.BootReceiver.

When the class not found exception is raised, we need to take a look at how our project metadata is getting created. This is where our class attributes become very important for our builds.


Class Metadata with Attributes

During the class implementation phase, we can leverage class attributes to add metadata information to our projects. For a Xamarin Android project, this is very important because this is the metadata that is added to the AndroidManifest file during the build cycle. With that knowledge in mind, let’s take a look at how we should properly declare our class.


[BroadcastReceiver(Name = "com.ozkary.BootReceiver]
[IntentFilter(new[] { Intent.ActionBootCompleted })]
public class BootReceiver : BroadcastReceiver


By looking at our abbreviated class declaration, we are setting the receiver class name properly as well as the intent. When we build the project, the metadata generated from our classes is merged with the Properties/AndroidManifest.xml file.  This is true for all classes including activities.

When encountering this Class Not Found Exception, we should review the content of the manifest file as well our class declarations, and we should find that there is probably not enough metadata added to the classes to prevent this error.


I hope this helps some of you with this problem.

Originally published by ozkary.com

5/19/18

Xamarin Android Build Java Exited with Code 1 ProGuard

When building a Xamarin Android app and using the option to Enable ProGuard, we may get the following error:


error MSB6006: "java.exe" exited with code 1


Note: Proguard is a file shrinker/optimizer which is often used on a release version. This can be found on the Android Options tab.



The error means that java is not able to build the application due to some an error that is raised during the build process. To find out what the error details, we need to set the MSBuild verbosity mode to Diagnostic which provides detail log on each step during the build. We can change the verbosity mode from Visual Studio Build and Run settings which can be found on the following menu option:

Tools->Options->Project and Solutions-Build and Run



Once this option is set, we should be able to compile again and see more detail about what is happening. If we look at the MSBuild output (output window on Visual Studio), we can find the error or exception that can provide more insight on the problem.

For this case, we can see that there is an error associated to the proguard tool. The error reads that there is an unknown option on the configuration file proguard.cfg.


proguard.ParseException: Unknown option '∩┐-dontwarn' in line 1 of file 'proguard.cfg', (TaskId:226)


If we look carefully, we can see that there is a funny character on the error message.  This leads us to think that there is some junk data in the proguard.cfg file, or there is an encoding problem.

Solution:

The proguard tool does not handle files that contain Byte Order Mark BOM. Visual Studio creates files with this information. The BOM is used to indicate the file encoding type. To see and remove that encoding, use a tool like Notepad++ and save the file without the BOM encoding which is a menu option when saving the file.

After removing the BOM from the file, we should be able to build the project again and see a successful build. Inspecting the log, we can also see that the proguard task completes with no errors:


Done executing task "Proguard". (TaskId:179)



Hopefully this can help solve similar errors when building Xamarin Android Apps.

Originally published by ozkary.com

5/5/18

Xamarin Android Device Mac and IP Address on a WebView JavaScript App

When using JavaScript applications with any framework, we cannot get access to some of the device information like the MAC and IP Address because JavaScript runs on an Isolated Sandbox due to security concerns.

When building hybrid applications using the WebView control on a Xamarin Android app, we can leverage the nature of the native app layer to provide the device information to the JavaScript layer. There are several ways to enable this interaction/bridge between the Native and JavaScript layers, but there is a more direct integration that can be used to handle this with less effort.

Browser UserAgent

All browsers provide a way to identify their information using the Navigator UserAgent property.  This property tells us the type of browser that is running the application like Internet Explorer, Safari, and Chrome etc.

When using the WebView control on a native app, we have more permission to control this information. This can enable our apps to set a UserAgent property that can provide the JavaScript application with device specific information.  Let’s review how that can be done by looking at a code sample with Xamarin Android project (C#) and JavaScript.

Xamarin Android Project

On the Xamarin Android project, we can set some of the WebView control properties on the OnCreate override of our activity as shown below:


private void SetWebView()
{
    WebView view = FindViewById<WebView>(Resource.Id.webView1);
    view.Settings.JavaScriptEnabled = true;
    view.Settings.UserAgentString = GetDeviceInfo();
}

private static string GetDeviceInfo()
{
    string mac = string.Empty;
    string ip = string.Empty;

    foreach (var netInterface in NetworkInterface.GetAllNetworkInterfaces())
    {
        if (netInterface.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 ||
            netInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
        {
            var address = netInterface.GetPhysicalAddress();
            mac = BitConverter.ToString(address.GetAddressBytes());

            IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName());                   
            if (addresses != null && addresses[0] != null)
            {
                ip = addresses[0].ToString();
                break;
            }                 

        }
    }



The code loads the reference to the control. This enables us to set the control settings to enable the JavaScript functionality to run on and set the user agent with the device information.

Notice that on the GetDeviceInfo function, we get both the MAC and IP address and return the information as a delimited string similar to the format used by most browsers. This enables us to parse the information and display/use it as needed.

JavaScript Code

When navigating to the web page on the WebView control, we can now query the windows user agent property and request the information that is set by the native code as shown below:


var device = window.navigator.userAgent;
console.log(device);              
 

The console log should print out the content of the string with a pattern similar to aa-bb-cc-dd/100.10.0.0 which represents the MAC and IP address of the device.

Using this approach, we can easily provide device information to the JavaScript app to enable it to display the device MAC and IP address which is usually hidden from the JavaScript layer due to security concerns on the device.

Originally published by ozkary.com

4/21/18

Complex Joins .NET Core 2.0 Entity Framework and SQL Server

With this article, we take a look at building a console application using .NET Core 2.0 and Entity Framework (EF). The goal is to show how to start a project with .Net core, install the dependencies and run a small test to extract data from a SQL Server database using a complex join.
We start by creating a Console Application using the .NET Core project template.  Make sure to target the .NET Core 2.0 framework.

Install Dependencies

We can install the necessary Entity Framework dependencies using the NuGet Package Manager Console.  We are only targeting SQL Server as our data platform, so we need to install that dependency as well.

On the console, type the following:


Install-Package Microsoft.EntityFrameworkCore.SqlServer

Install-Package Microsoft.EntityFrameworkCore.Tools


Defining the Database

Our database Entity Relation Diagram (ERD) is shown below. We want to query task information with the extended properties like status, type, severity and priority.



Defining the Models

We want to be able to join all those entities, so we need to define a model for each entity shown on the ERD: Task, TaskType, TaskStatus, TaskPriority, TaskSeverity.

   
    public class Task
    {
        public int TaskId { get; set; }
        public string Description { get; set; }
    }

    public class TaskStatus
    {
        public int TaskStatusId { get; set; }
        public string Name { get; set; }      
    }

    public class TaskType
    {
        public int TaskTypeId { get; set; }
        public string Name { get; set; }
    }

    public class TaskPriority
    {
        public int TaskPriorityId { get; set; }
        public string Name { get; set; }
    }

    public class TaskSeverity
    {
        public int TaskSeverityId { get; set; }
        public string Name { get; set; }
    }
   

Since we are joining all these tables, we want to create a model that can define the result of our join. Therefore, we add the TaskDetail model. This is basically a view model for the result we want which does not need to bind to physical table.


    public class TaskDetail
    {
        public int TaskId { get; set; }
        public string Description { get; set; }
        public string Status { get; set; }
        public string Severity { get; set; }
        public string Priority { get; set; }
        public string Type { get; set; }
    }



Defining the Database Context

We need to get data to our models, so we need to define the DbContext with a DbSet property to map to each entity. This is what we can use to make queries from our database.


    public class TaskContext : DbContext
    {
        public TaskContext(DbContextOptions<TaskContext> options)
            : base(options)
        { }

        public DbSet<Task> Tasks { get; set; }
        public DbSet<TaskStatus> TaskStatus { get; set; }
        public DbSet<TaskType> TaskTypes { get; set; }
        public DbSet<TaskSeverity> TaskSeverity { get; set; }
        public DbSet<TaskPriority> TaskPriority { get; set; }
    }


Doing the Work

We are ready to test our approach using our console application.  The logic is to execute a SQL statement with inner joins with the look up tables to get extended task information. We want to return a view model that brings all the relevant properties of a task.


var connection = @"Server=.;Database=dev;Trusted_Connection=True;";

var optionsBuilder = new DbContextOptionsBuilder<TaskContext>();
optionsBuilder.UseSqlServer(connection);

using (TaskContext context = new TaskContext(optionsBuilder.Options))
{

  var results = from task in context.Tasks
    join status in context.TaskStatus
            on task.TaskStatusId equals status.TaskStatusId
    join type in context.TaskTypes
            on task.TaskTypeId equals type.TaskTypeId
    join severity in context.TaskSeverity
            on task.TaskSeverityId equals severity.TaskSeverityId
    join priority in context.TaskPriority
            on task.TaskPriorityId equals priority.TaskPriorityId
    select new TaskDetail
    {

        TaskId = task.TaskId,
        Description = task.Description,
        Status = status.Name,
        Type = type.Name,
        Severity = severity.Name,
        Priority = priority.Name
    };              

foreach (var task in results)
{
    Console.WriteLine($" {task.TaskId}, {task.Description}, {task.Priority}, " +
        $"{task.Status}, {task.Type}, {task.Severity}," +
        $" {task.Priority}");
}

Console.WriteLine($"Total Records {results.Count()}");


The join is done using the primary keys for each entity which maps to a foreign key constraint on the task entity. We then just return the task description and names from each of the look up tables using our view model, TaskDetail.

Conclusion

We can create complex joins using EF and LINQ, and we can also define views models that can help us abstract the complexity of the database entities for our apps. There are also other strategies to get this done like creating a view on the database or executing a raw SQL statement and build the view model without defining each entity model.

Check this article for a Single Model from a Multi-Join Query .NET Core Entity Framework SQL Server

It really depends on the approach and coding standards that you need to follow. I hope this can provide a simple way to do complex join using .Net Entity Framework

Originally published by ozkary.com

4/7/18

Single Model from a Multi-Join Query .NET Core Entity Framework SQL Server

When building data solutions with Entity Framework (EF), we tend to create entity models for each table that we need.  For instances when we need to join multiple tables, we either create a SQL Server view and bound EF Model or join the data entities using LINQ.
In this article, we take a look at creating a single EF model which maps to a raw query with multiple joins executed on the backend using .NET Entity Framework

Defining the Database

Our challenge is to obtain task information using the ERD below.  There is the Task main table and four look up tables for the different properties like status, type, severity and priority.



Defining the SQL Statement

The SQL query to get that information is just a simple multi-join statement with all the lookup tables. The resulting data is useful in defining the model that we need to map the results.


select t.taskid,[description]
       ,ts.name as status
       ,tt.name type
       , tsv.name as severity
       , tp.name as priority
from [bi].task t (NOLOCK)
inner join [bi].[TaskStatus] ts (NOLOCK) on t.taskstatusid= ts.taskstatusid
inner join [bi].[TaskType] tt (NOLOCK) on t.tasktypeid= tt.tasktypeid
inner join [bi].[TaskSeverity] tsv (NOLOCK) on t.taskseverityid= tsv.taskseverityid
inner join [bi].[TaskPriority] tp (NOLOCK) on t.taskpriorityid= tp.taskpriorityid



Defining the Model

Since we only need to one entity with all the lookup values, we can define a simple model which we can use to map the results of our query.


   public class Task
    {
        public int TaskId { get; set; }
        public string Description { get; set; }
        public string Status { get; set; }
        public string Severity { get; set; }
        public string Priority { get; set; }
        public string Type { get; set; }
    }


We can move on to do the EF implementation.

Defining the Database Context

Now that we have our model, we need the DbContext with a DbSet property map to our Task model. This is what we can use to fetch the data from our database.


    public class TaskContext : DbContext
    {
        public TaskContext(DbContextOptions<TaskContext> options)
            : base(options)
        { }

        public DbSet<Task> Tasks { get; set; }      
    }



Doing the Work

We are  ready to test our approach using a simple console application.  The main logic is shown below:


var connection = @"Server=.\sqlexpress;Database=dev;Trusted_Connection=True";

var optionsBuilder = new DbContextOptionsBuilder<TaskContext>();
optionsBuilder.UseSqlServer(connection);
           
using (TaskContext context = new TaskContext(optionsBuilder.Options))
{             
    string sql = @" select t.taskid,[description]
       ,ts.name as status
       ,tt.name type
       , tsv.name as severity
       , tp.name as priority
  from [bi].task t (NOLOCK)
  inner join [bi].[TaskStatus] ts (NOLOCK) on t.taskstatusid= ts.taskstatusid
  inner join [bi].[TaskType] tt (NOLOCK) on t.tasktypeid= tt.tasktypeid
  inner join [bi].[TaskSeverity] tsv (NOLOCK) on t.taskseverityid= tsv.taskseverityid
  inner join [bi].[TaskPriority] tp (NOLOCK) on t.taskpriorityid= tp.taskpriorityid";

List<Task> tasks = context.Tasks.FromSql<Task>(sql).ToList();

foreach(var task in tasks)
{
    Console.WriteLine($" {task.TaskId}, {task.Description},
    {task.Priority}, {task.Status}, {task.Type},
    {task.Severity}, {task.Priority}");
}


We first set the connection string using a DbContextOptionsBuilder. Next, we instantiate the TaskContext object and execute our SQL query with the statement we defined previously.   The result of the query is then mapped to our entity.

Now that we have the result on a list, we can display the result on the console.

Conclusion

The ideal solution to handle these cases would be to create the views or tables that have all the data that is required to read. This however may not be an option due to some constraint, so we need to take an approach that can provide the same service on the middleware.

I hope this can provide a simple way to do complicated join using .NET Entity Framework.

Originally published by ozkary.com