Tag Archive : Xamarin

/ Xamarin

If you create a button on Android and write its text in lowercase (“my text”), when you launch the app, you can see that the text is all uppercase (“MY TEXT”).This is not a bug but the standard style for Android.Sometimes we prefer to have our text in lowercase so here I’ll show you different methods to do it.First of all, consider a very easy Page:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"             
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"             
             xmlns:local="clr-namespace:Tutorial02"             
             x:Class="Tutorial02.MainPage">
    <Button Text="My Text!"            
            VerticalOptions="Center"            
            HorizontalOptions="Center" />
</ContentPage>

If we run the app on Android, we see that the button text will be : “MY TEXT!” all uppercase. Now let’s see how we can make it lowercase:

CUSTOM RENDERERS

First of all, create an empty class MyButton in you PCL/.NetStandard project:

public class MyButton : Button
{        
}

Now we have to replace the Button with MyButton:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"             
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"             
             xmlns:local="clr-namespace:Tutorial02"             
             x:Class="Tutorial02.MainPage">
    <local:MyButton Text="My Text!"    <- CHANGE HERE          
                    VerticalOptions="Center"            
                    HorizontalOptions="Center" />
</ContentPage>

The next step is to create the custom render, so inside the Android project, create the class MyButtonRenderer:

[assembly: ExportRenderer(typeof(MyButton), typeof(MyButtonRenderer))]
namespace YOURNAMESPACEHERE
{
    public class MyButtonRenderer : ButtonRenderer
    {
        public MyButtonRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);
            var button = this.Control;
            button.SetAllCaps(false);
        }
    }
}

It’s very important to add the first line[assembly: ExportRenderer(typeof(MyButton), typeof(MyButtonRenderer))]otherwise the Custom Renderer will not work.If we run the code, we see that now the button text is: “My Text!”.

EDIT THE STYLES.XML FILE

In your Android project open the styles.xml file inside the folder “Resources/values”, it will be something similar to:

<style name="MainTheme" parent="MainTheme.Base">  </style>
  <!-- Base theme applied no matter what API -->
  <style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
    <!--If you are using revision 22.1 please use just windowNoTitle. Without android:-->
    <item name="windowNoTitle">true</item>
    <!--We will be using the toolbar so no need to show ActionBar-->
    <item name="windowActionBar">false</item>
    <!-- Set theme colors from http://www.google.com/design/spec/style/color.html#color-color-palette -->
    <!-- colorPrimary is used for the default action bar background -->
    <item name="colorPrimary">#2196F3</item>
    <!-- colorPrimaryDark is used for the status bar -->
    <item name="colorPrimaryDark">#1976D2</item>
    <!-- colorAccent is used as the default value for colorControlActivated         which is used to tint widgets -->
    <item name="colorAccent">#FF4081</item>
    <!-- You can also set colorControlNormal, colorControlActivated         colorControlHighlight and colorSwitchThumbNormal. -->
    <item name="windowActionModeOverlay">true</item>
    <item name="android:datePickerDialogTheme">@style/AppCompatDialogStyle</item>
  </style>
  <style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
    <item name="colorAccent">#FF4081</item>
  </style>

To this file add these lines:

<style name="myTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="android:textAppearanceButton">@style/mybutton.text</item>
  </style>
  <style name="mybutton.text" parent="Base.TextAppearance.AppCompat.Button">
    <item name="textAllCaps">false</item>
    <item name="android:textAllCaps">false</item>
  </style>

so the your styles.xml file will be: 

<resources>
  <style name="MainTheme" parent="MainTheme.Base">  </style>
  <!-- Base theme applied no matter what API -->
  <style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
    <!--If you are using revision 22.1 please use just windowNoTitle. Without android:-->
    <item name="windowNoTitle">true</item>
    <!--We will be using the toolbar so no need to show ActionBar-->
    <item name="windowActionBar">false</item>
    <!-- Set theme colors from http://www.google.com/design/spec/style/color.html#color-color-palette -->
    <!-- colorPrimary is used for the default action bar background -->
    <item name="colorPrimary">#2196F3</item>
    <!-- colorPrimaryDark is used for the status bar -->
    <item name="colorPrimaryDark">#1976D2</item>
    <!-- colorAccent is used as the default value for colorControlActivated         which is used to tint widgets -->
    <item name="colorAccent">#FF4081</item>
    <!-- You can also set colorControlNormal, colorControlActivated         colorControlHighlight and colorSwitchThumbNormal. -->
    <item name="windowActionModeOverlay">true</item>
    <item name="android:datePickerDialogTheme">@style/AppCompatDialogStyle</item>
    <item name="android:textAppearanceButton">@style/mybutton.text</item>
  </style>
  <style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
    <item name="colorAccent">#FF4081</item>
  </style>
  <style name="myTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="android:textAppearanceButton">@style/mybutton.text</item>
  </style>
  <style name="mybutton.text" parent="Base.TextAppearance.AppCompat.Button">
    <item name="textAllCaps">false</item>
    <item name="android:textAllCaps">false</item>
  </style>
</resources>

USE AN EFFECT

In your Android project create the class ButtonEffect:

[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(Tutorial02.Droid.ButtonEffect), "ButtonEffect")]

namespace Tutorial02.Droid
{
    public class ButtonEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            try
            {
                var control = Control as Android.Widget.Button;
                control.SetAllCaps(false);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
            }
        }

        protected override void OnDetached()
        {
        }

        protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged(args);
        }
    }
}

In your PCL/.NetStandard project create the class ButtonEffect:

public class ButtonEffect : RoutingEffect
{
    public ButtonEffect() : base("MyCompany.ButtonEffect")
    {
    }
}

Now you need to change your ContentPage to attach the Effect to your button:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"             
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"             
             xmlns:local="clr-namespace:Tutorial02"             
             x:Class="Tutorial02.MainPage">
    <Button Text="My Text!"            
            VerticalOptions="Center"           
            HorizontalOptions="Center">
        <Button.Effects>
            <local:ButtonEffect />
        </Button.Effects>
    </Button>
</ContentPage>

Conclusion

We have seen three methods to remove the Uppercase from your Android button:

  • Custom Renderers
  • Styles
  • Effects

All the methods do the same thing so it’s up to you to decide which method to use. Remember that Custom Renderers and Effects are very important in Xamarin so it’s important to understand them very well.

Microsoft has released the version 15.6.3 of Visual Studio and it contains several fixes some of them for Xamarin.

Visual Studio
Visual Studio 2017

Visual Studio 2017 15.6.3 – Release note

  • Esc key doesn’t close Peek Definition Window.
  • wpp.targets file execution not working after update to version 15.6.
  • Project loaded via File->Open->CMake throws exception and CMake cache is not generated..
  • Version 15.6 update crashes Xamarin code with NullReferenceException with next scenario.
  • XCode Tools installation fails after version 15.6 update.
  • Anaconda 5.0.0 Completion DB is not up to date and hitting refresh fails.
  • Cannot run NUnit tests after version 15.6.1 update.
  • Visual Studio 2017 fails to launch from the command line when launched using 8.3 file name path.
  • Version 15.6.0 breaks when VisualStudio\\Telemetry\\TurnOffSwitch is set to 0.
  • Visual Studio Community 2017 auto closes after version 15.6 update..
  • CMake generation never stops after version 15.6.1 update.
  • Opening a solution with tests, and clicking any toolbar item in Test Explorer causes VS to crash.

I have highlighted the two bugs for Xamarin that now have been fixed.Those bugs are quite annoying so, especially if you use Xamarin, it’s very important to update Visual Studio to the  version 15.6.3 If you want to try the Visual Studio Preview Version, you can find it clicking here

Usually a desktop platform has a lot of available resources so many developers tend to avoid to improve the quality of their code.On a mobile platform the resources are quite limited and improving the code could make a huge difference. It can transform a slow and annoying app in a great fast and great one.Today, using the code I’ve written for one of my app Tv Series Time Manager, we are going to see how improving the code can make a huge difference in the loading time of your apps.

LINQ
LINQ

Improve your code – LINQ is your friend

Tv Series time manager allows you to keep track of your preferred tv series.It uses a public API to get information about all the TV Series created. As you can imagine there are thousands and thousands of Tv Series so we need to handle lists of thousands of items.Every time we launch the app, it searches online updated about the Tv Series you are following (new episodes, release dates, and so on). This can be a quite intensive task as the API we need to call returns a JSON file with more than 34000 items.The first time I’ve written the updated method I had this code:

var localTvShows = LocalData.GetAllTvShows(); 
var remoteUpdatedTime = await WsData.GetUpdatedShows(); 
foreach (var info in remoteUpdatedTime) 
{ 
    var show = localTvShows.FirstOrDefault(x => x.id == info.Key); 
    if (show != null && info.Value > show.updated) 
    { 
        updateRequired = true; 
        break; 
    } 
}

            if (UpdateRequired)
            {
                foreach (var info in remoteUpdatedTime)
                {
                    var show = localTvShows.FirstOrDefault(x => x.id == info.Key);
                    if (show != null && info.Value > show.updated)
                    {
                        var remoteserie = await WsData.GetShow(show.id);
                        SqlHelper.SyncSerie(show, remoteserie);
                        var episodeList = await WsData.GetEpisodes(show.id);
                        SqlHelper.SyncEpisodes(show.idLocal, episodeList);
                    }
                }
            }

I load the local Tv Show followed by the user and the remote Tv Series with the corresponding update time.Inside the first foreach I check if I need to update the local Tv Series.In case I have to update a Tv Series, I use a second foreach to update every local TV Series inside the local Sql database. (To add SQLite database to your app, you can read this tutorial)The code worked pretty well but I wasn’t satisfied by the loading time so I started to look for a way to improve the performances and here I discovered once more that LINQ is our friend.

The new code with LINQ

I decided to use LINQ to evaluate if I have to update a tv series, so I’ve written the code replacing the old one with this:

var seriesToUpdate = from remoteTime in remoteUpdatedTime
                join localShow in localTvShows 
                    on remoteTime.Key equals localShow.id
                where remoteTime.Key == localShow.id && remoteTime.Value > localShow.updated
                select localShow;

            if (seriesToUpdate.Any())
            {
                foreach (var show in seriesToUpdate)
                {
                    var remoteserie = await WsData.GetShow(show.id);
                    SqlHelper.SyncSerie(show, remoteserie);
                    var episodeList = await WsData.GetEpisodes(show.id);
                    SqlHelper.SyncEpisodes(show.idLocal, episodeList);
                }
            }

Speed Test

Now it’s time to see if the new code is really better than the first (Obviously it is 🙂 ). To do so, I’ve divided the code in two parts.

  • Evaluate if an update is required (Part A)
  • Update the Tv Series (Part B).

To give you the idea of how much time we can save, I’ve enclosed both the code in a for statement repeating the it for 100 times. These are the result:

Part A

  • OLD CODE:  Elapsed Time: 1077 ms
  • NEW CODE: Elapsed Time:   225 ms

Part B

  • OLD CODE:  Elapsed Time:  590 ms
  • NEW CODE: Elapsed Time:   122 ms

Total

  • OLD CODE:  Elapsed Time:  1667 ms
  • NEW CODE: Elapsed Time:    347 ms

Looking at the time spent by the old and new code we  went from 1667 ms to 347 ms, saving 1320 ms. The difference is HUGE.From the point of view of a user, saving almost 1.5 seconds makes a massive difference, maybe the difference between keeping your app or uninstalling it.

Conclusion

A mobile device has a limited amount of resources and users don’t like to spend time waiting in front of a loading screen. Even the most useful app, if not optimized will be uninstalled by the users. This is why it’s really important to optimize your code.Today we have seen that with a good use LINQ  we can massively reduce the time used by our code.If you like the article, comment and share it!

Microsoft has released a preview version 15.7 of Visual Studio 2017.

Visual Studio
Visual Studio 2017

There are few improvements around Xamarin so could be quite interesting to see the release notes.As it is a Preview release, you shouldn’t use if for production code.

Release Notes

Updates

  • IntelliTrace?s step-back debugging feature is now supported for debugging .NET Core projects.
  • Debugging large solutions with /Debug:fastlink PDBs is more robust.
  • Visual Studio Tools for Xamarin can now automatically install missing Android API levels required by Xamarin.Android projects.
  • We added a limited preview of a new Python debugger based on the popular open source pydevd debugger.
  • We have improved Kestrel HTTPs support during debugging.
  • The Windows 10 Insider Preview SDK Build 17110 can now be installed as an optional component with the Universal Windows Platform.
  • We added support for NuGet package signatures.

Bug Fixed

  • .NET Core failed due to dependency on Microsoft.VisualStudio.AspNetDiagnosticPack.Msi.
  • Update to Visual Studio 2017T15.4 generates multiple package errors.
  • Add Option to Disable format on paste for razor code in razor/cshtml files.
  • Visual Studio auto formatter breaks complex razor code.
  • Update error: PackageId:Microsoft.VisualStudio.AspNetDiagnosticPack.Msi;PackageAction:Uninstall;ReturnCode:1603;.

Xamarin

This release includes Xamarin.iOS 11.10 and Xamarin.Android 8.3.

Automatic Android SDK Management

When a Xamarin.Android project is loaded, Visual Studio can now determine if the Android API level used by the project is missing from your machine and automatically install it for you in the background. To enable this feature, go to Tools > Options > Xamarin > Android Settings > Auto Install Android SDKs.

Download

You can download the Preview version of Visual Studio 2017 from here: https://www.visualstudio.com/vs/preview/

If instead of the preview version you want to use a stable one, give a look here: http://www.xamarinexpert.it/2018/03/05/vs2017-version-15-6-just-released/

Xamarin.Forms is fantastic, you write your code once inside your PCL/.NetStandard project and it will run on many different platforms.However sometimes we need to access directly the native platform. To do so, we can use something called DependencyService.DependencyService allows us to use platform-specific functionality from shared code.To use the DependencyService we need:

  • An interface inside our shared code
  • An implementation for each platform
  • A registration

After the DependencyService is ready, then we can call it from our shared code.If we want to add a Sqlite database to our Xamarin.Forms project, because we cannot create it directly in our shared code, we need to use a DependencyService so in this tutorial we are going to see how to use the DependencyService to create and use a Sqlite database in our multi platform app.

TUTORIAL

First of all, let’s create an empty Xamarin.Forms project using a .NetStandard project. For a tutorial on how to create a Xamarin.Forms project, you can read this guide: http://www.xamarinexpert.it/2018/03/03/xamarin-forms-a-guide-for-beginners/

Empty Xamarin Project
Fig.1 Structure of an empty Xamarin.Forms Project

In the first image you can see the structure of a Xamarin.Forms project.As we said, the creation of a DependencyService consists of 3 steps.

First Step – The interface

Now the first step to do, is to create the Interface for our DependencyService.Let’s create and add an interface called ISql to our .NetStandard project:

public interface ISql
{
    SQLiteConnection GetConnection(string dbname = "database.db3");
    SQLiteAsyncConnection GetConnectionAsync(string dbname = "database.db3");
}

This interface exposes two methods:GetConnection: Get a connection for the Sqlite database.GetConnectionAsync: Get an async connection for the Sqlite database.Really easy. Don’t you think?

Second Step – The implementation

Inside this second step, we need to implement the interface in each platform. Let’s start with Android

Android

We need to create in Android a class the implements the ISql interface, let’s call this class SqlImplementation:

public class SqlImplementation : ISql
{
    public SQLiteConnection GetConnection(string dbname = "database.db3")
    {
        var sqliteFilename = dbname;
        string documentsPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Personal);
        // Documents folder
        var path = Path.Combine(documentsPath, sqliteFilename);
        var conn = new SQLiteConnection(path, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex);
        return conn;
    }

    public SQLiteAsyncConnection GetConnectionAsync(string dbname = "database.db3")
    {
        var sqliteFilename = dbname;
        string documentsPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder
        var path = Path.Combine(documentsPath, sqliteFilename);
        return new SQLiteAsyncConnection(path);
    }
}

We have basically implemented the two methods of our ISql interface. These two methods return the native connection to an Android Sqlite database.

iOS

Now we need to create the same class inside the native  iOS project:

public class SqlImplementation : ISql
{
    public SQLiteConnection GetConnection(string dbname = "database.db3")
    {
        var sqliteFilename = dbname;
        string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder

        var path = Path.Combine(documentsPath, sqliteFilename);
        var conn = new SQLiteConnection(path, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex);
        return conn;
    }

    public SQLiteAsyncConnection GetConnectionAsync(string dbname = "database.db3")
    {
        var sqliteFilename = dbname;
        string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder
        var path = Path.Combine(documentsPath, sqliteFilename);
        return new SQLiteAsyncConnection(path);
    }
}

As you can see the code is basically the same but it’s IMPORTANT to add the implementation to each platform you need to use, otherwise you’ll get an error.

UWP

Now it’s time to implement the interface for UWP:

public class SqlImplementation : ISql
{
    public SQLiteConnection GetConnection(string dbname = "database.db3")
    {
        var sqliteFilename = dbname;
        var path = Path.Combine(ApplicationData.Current.LocalFolder.Path, sqliteFilename);
        var conn = new SQLiteConnection(path, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex);
        return conn;
    }

    public SQLiteAsyncConnection GetConnectionAsync(string dbname = "database.db3")
    {
        var sqliteFilename = dbname;
        var path = Path.Combine(ApplicationData.Current.LocalFolder.Path, sqliteFilename);
        return new SQLiteAsyncConnection(path);
    }
}

and this concludes the second step.

Third Step – The registration

it’s extremely important to register the DependencyService otherwise it will not work.Don’t worry, this step is incredibly easy, the only thing you need to do is to add this line of code in each SqlImplementation class just before the namespace:

[assembly: Dependency(typeof(SqlImplementation))]

so for example the final code of your Android implementation will be:

[assembly: Dependency(typeof(SqlImplementation))]

namespace YOURNAMESPACE
{
    public class SqlImplementation : ISql
    {
        public SQLiteConnection GetConnection(string dbname = "database.db3")
        {
            var sqliteFilename = dbname;
            string documentsPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder
            var path = Path.Combine(documentsPath, sqliteFilename);
            var conn = new SQLiteConnection(path, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex);
            return conn;
        }

        public SQLiteAsyncConnection GetConnectionAsync(string dbname = "database.db3")
        {
            var sqliteFilename = dbname;
            string documentsPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder
            var path = Path.Combine(documentsPath, sqliteFilename);
            return new SQLiteAsyncConnection(path);
        }
    }
}

REMEMBER to add the assembly line to EACH of your SqlImplementation classes.

HOW TO USE IT

Now the DependencyService is ready, we just need to call use it. If we want to get the SqLite connection we just need to use a single line of code inside our share code:

SQLiteConnection database = DependencyService.Get<ISQLite>().GetConnection();

Now you have your sql connection in you shared code so you can start to use your SqLite database.

Sqlite Plugin

It’s extremely easy to use the DependencyService to add a Sqlite database to your Xamarin.Forms app, but if you want an already made solution, you can use my Sqlite plugin so after you install it, you can directly use your database with a single line of code:

SQLiteConnection conn = MTSql.Current.GetConnection("yourdatabasename.db3");

It cannot be easier than that.You can find a tutorial on how to use the plugin here: http://www.xamarinexpert.it/2018/03/01/sqlite-made-easy/The official page is here: http://www.xamarinexpert.it/plugins/mt-sqlite/You can find the nuget package here: https://www.nuget.org/packages/MarcTron.Sqlite

More

You have doubts about the DependencyService or Sql? You want to know more? Ask me adding a comment below this article.

Admob for Xamarin made easy

May 6, 2019 | Guide, Plugin, Tutorial | 23 Comments

In this tutorial I’ll show you how to monetize your Xamarin apps with AdMob using my MTAdmob plugin.

UPDATE: I’ve added on github the source code of a project to test this Admob plugin. You can find it here: https://github.com/marcojak/TestMTAdmob

To help you to speed up your Xamarin development, I’ve created a set of plugins, one of them is MTAdmob. Thanks to this plugin you can add Admob banners and Insterstitials in just few lines of code. It couldn’t be easier than that and I’ll show you.

Install the plugin

First of all, right click on your Xamarin solution and select “Manage Nuget packages for Solution”

manage nuget

Visual Studio will open a new screen where you can search and install one or more nuget packages. In this case we can search for the MTAdmob plugin. Searching for MarcTron will show you all my packages (I’m sure you can find other useful plugins that I’ve written), and we can select the MTAdmob plugin as showed in the next image.

It’s very important that you install the plugin in your PCL/.Net standard project and in your platform projects (Android, iOS, UWP).

After the Admob plugin is installed we can add banners and insterstitials to our projects.

Add Ads to our project

With version 1.0 the MTAdmob plugin supports banner and interstitials for Android and iOS. If you would like to see the plugin supporting also the UWP platform, let me now and I’ll add the support in a new version.

As I’ve said we can add Banners and Interstitials Admob ads to our project. Let’s start with the Banners

How to add an Admob Banner

An Admob banner is just a view inside our page. It means that we can add it using XAML or C#. First of all let’s see how to add an Admob banner using XAML.

Add an Admob Banner with XAML

In MTAdmob to use an Admob banner I’ve created a custom control called AdView, so to use it we can use this code:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:controls="clr-namespace:MarcTron.Plugin.Controls;assembly=Plugin.MtAdmob"
             x:Class="Test.MTAdmob.MainPage">

<StackLayout>
    <Label Text="Let's test an Admob Banner!" 
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand" />
    <!-- Place the Admob controls here -->
    <controls:AdView></controls:AdView>
</StackLayout>

In this example we have created a StackLayout with 2 controls: a label and an AdView (our Admob banner). Easy! Isn’t it???

The AdView control is basically a View so you can use all the properties you can think of like: HorizontalOptions, VerticalOptions, IsVisible…

In addition to these properties, I’ve added in AdView two other properties: AdsId and PersonalizedAds.

AdsId: Allows you to add the Banner Id (you can find it in your Admob account)

PersonalizedAds: This allow you to use non personalized ads. For example in case of GPDR. Of course it’s better to use personalized Ads.

To use these properties you can update the previous code to:

<controls:AdView PersonalizedAds="true" AdsId="xxxxxxxxxxxxxxxxxx"></controls:AdView>

Add an Admob Banner with C#

In case you don’t write your pages with XAML or you write your UI in C# or you want to add your view only in some cases, you can add your Admob Banner using this code:

using MarcTron.Plugin;
...
AdView ads = new AdView();

Of course you need to attach this View to your layout, but you know how to do it (If not, feel free to ask).

To use the custom properties you can change the previous code to:

...
AdView ads = new AdView();
ads.AdsId = "xxx";
ads.PersonalizedAds = true;

Also in this case, to add an Admob banner is INCREDIBILY EASY!!!

Global Custom Properties

As you have seen, the properties AdsId and PersonalizedAds belong to a single AdView. It means that you have to set them for every Admob Banner.

To make things even easier I’ve added the option to set these properties only once. To do so, you can use this C# code:

CrossMTAdmob.Current.UserPersonalizedAds = true;
CrossMTAdmob.Current.AdsId = "xxxxxxxxxxxxxxxx";

In this case all your Admob banner will show personalized ads and will have the same Id.

If you set local and global properties, the local ones will have higher priority.

Use of Banner Events

I’ve added 4 events to the Admob banner that you could find nice to have. These events are:

  • AdsClicked When a user clicks on the ads
  • AdsClosed When the user closes the ads
  • AdsImpression Called when an impression is recorded for an ad.
  • AdsOpened When the ads is opened

To use these events you can write this code:

AdView myAds = new AdView();
myAds.AdsClicked += MyAdsAdsClicked;
myAds.AdsClosed += MyAds_AdVClosed;
myAds.AdsImpression += MyAds_AdVImpression;
myAds.AdsOpened += MyAds_AdVOpened;

Of course you can use these events also if you have declared your AdView in your XAML code.

Admob Interstitials

Now that we know how to add Admob banners using my plugin MTAdmob, let’s see how we can add Admob Interstitials. If possible, to add an Admob interstitial is even easier. You just need a single line of code. Don’t you believe me? Look here how to show an Admob interstitial:

CrossMTAdmob.Current.ShowInterstitial("ca-app-pub-xxxxxxxxxxxxxxxx/xxxxxxxxxx");

I told you!!! That’s it!!! With that line of code you have just showed an Interstitial in you app. Of course you need to replace that string with the Insterstitial ID you can find in your Admob account.

Events for Interstitials

There 3 events that you can use with Interstitials:

OnInterstitialLoaded        When it's loaded
OnInterstitialOpened        When it's opened      
OnInterstitialClosed        When it's closed

Rewarded Video

From version 1.1 the plugin supports the amazing Rewarded Video too.

To show a rewarded video you just need a single line of code:

CrossMTAdmob.Current.ShowRewardedVideo("xx-xxx-xxx-xxxxxxxxxxxxxxxxx/xxxxxxxxxx");

Events for Rewarded videos

There are 7 events that you can use with the Rewarded video Ads:

OnRewarded                          When the user gets a reward
OnRewardedVideoAdClosed             When the ads is closed
OnRewardedVideoAdFailedToLoad       When the ads fails to load
OnRewardedVideoAdLeftApplication    When the users leaves the application
OnRewardedVideoAdLoaded             When the ads is loaded
OnRewardedVideoAdOpened             When the ads is opened
OnRewardedVideoStarted              When the ads starts

Initialization

Before you can use the Admob banners and Interstitials, you need to initialize it. You need to do it only once so it makes sense to initialize it onside the OnCreate method in Android and FinishedLaunching in iOS.

In your Android project add this line in your OnCreate method:

MobileAds.Initialize(ApplicationContext, "ca-app-pub-xxxxxxxxxxxxxxxx~xxxxxxxxxx");

In your iOS project add this line in your FinishedLaunching method:

MobileAds.Configure("ca-app-pub-xxxxxxxxxxxxxxxx~xxxxxxxxxx");

ANDROID PROJECT (IMPORTANT)

In your AndroidManifest you should add these lines:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<application android:label="Test.MTAdmob.Android">
    <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/>
    <activity android:name="com.google.android.gms.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" android:theme="@android:style/Theme.Translucent" />
</application>

Some useful links

Conclusion

This Admob MTAdmob plugin is incredibly easy to use but in case you need help, or you want to suggest a new feature or for any other reason, write me.

Xamarin has a long story of problematic releases where new features comes along with numerous bugs.For this reason is possible that you are still using an old version of Xamarin.Forms.But today you will see why you should really upgrade to Xamarin.Forms 2.5

Layout Compression

Sometimes to create the UI we want, we need to add several layouts that are not visible but are needed as container for other components.As you can imagine, all these layouts come with a cost and you can see it especially on older Android devices.Layout compression helps us to solve this problem reducing the number of views to render.Consider this basic example:

<StackLayout Orientation="Horizontal"                  
                 HorizontalOptions="CenterAndExpand"                  
                 VerticalOptions="CenterAndExpand">
        <Button Text="Yes"></Button>
        <Button Text="No"></Button>
    </StackLayout>

We have a StackLayout that contains two buttons, the only reason to have this layout is to add the two buttons at the same height.Even if we don’t see the layout, having it in our Page has a cost.With the Layout Compression we can keep the StackLayout and remove its cost.To enable the compression of the StackLayout we need to add the codeCompressedLayout.IsHeadless="true"so the previous example will be:

<StackLayout Orientation="Horizontal"                  
                 HorizontalOptions="CenterAndExpand"                  
                 VerticalOptions="CenterAndExpand"                 
                 CompressedLayout.IsHeadless="true">
        <Button Text="Yes"></Button>
        <Button Text="No"></Button>
    </StackLayout>

Easy. Isn’t it? You can enable the Layout compression on: StackLayout, AbsoluteLayout, Grid, RelativeLayout.Because the compression removes the renderer for the layout, candidates for the compression are layouts that don’t have:

  • Background color
  • Gestures
  • Transformations
  • etc.

Layout Compression is available on iOS and Android.

Fast Renderers

Ok this is not entirely a new feature (they arrived on Xamarin.Forms 2.4) but it’s definitely a feature you shouldn’t miss.We love Xamarin but we also know that sometimes, especially on Android the performances are not really amazing.Fast Renderers for Android will improve performances on your Xamarin.Forms applications.As this is still an experimental feature, to enable them you need to add this line

Forms.SetFlags("FastRenderers_Experimental");

to your MainActivity class before calling Forms.Init

I’ve personally tested Layout compression and Fast Renderers and I can confirm that there is a performance improvement especially on older Android devices so I really suggest you to use these features in your projects.

Forms Embedding

I have to tell you, I’m not particularly inclined to mix things so I prefer to keep separated Xamarin.Forms and native Xamarin projects.BUT…I can honestly see cases where you already have existing Xamarin.Forms pages and you want to use in other Xamarin iOS, Android or UWP projects.Thanks to the Forms Embedding now you can do it.

Improved macOS Desktop Support

In case you want to add macOS desktop support in your Xamarin.Forms apps 🙂

Android SDK Setup with Xamarin

May 4, 2019 | Guide | No Comments

As you know is very important to keep your system updated and this of course is valid for the Android SDK.You should alway use the lasted available Android components.The Official Xamarin Documentation is not very clear on how to configure properly the Android SDK, so here is what you should do to obtain the best from your Xamarin.Android projects.First of all you should really install the Xamarin Android SDK Manager instead of the classic SDK Manager.Probably the most important reason to do so is that since version 25.2.3 of the Android SDK Tools package, Google replaced the UI Manager with a command line utility. I really don’t know why, but I know that the Xamarin Android SDK Manager is a very good tool. So I really suggest you to download it.As stated in the official Xamarin website, the requirements are:

  • Visual Studio 2017 community edition or higher. Visual Studio 2017 version 15.5 or later is required. (I’ll suggest you to use the latest version 15.6)
  • Xamarin for Visual Studio version 4.5.0 or later.
  • Java Development Kit 8 (the JDK 9 is not supported yet inXamarin.Android)

The Xamarin Android SDK Manager is not compatible with Visual Studio 2015. You can add the Xamarin SDK Manager using the Visual Studio Installer: 

Visual Studio Installer
Install the Xamarin SDK Manager

Be sure to select the Xamarin SDK Manager and install it.If you launch again Visual Studio 2017 and click on Tools > Android > Android SDK Manager, the Xamarin Android SDK Manager will be launched instead of the Google Android SDK Manager.

Android sdk manager
Xamarin SDK Manager

Here there are two tabs: Platforms and Tools.

Platforms

Inside the first Tab you can download and install the platforms you want to support. You don’t need to install all the platforms, you just need to install the most recent one and the lowest that you still want to support.So if you want to support the platforms from Android 4.1, just install the Android SDK Platform 16 (Android 4.1) and the Android SDK Platform 16 (Android Oreo 8.1).

Tools

From the Tools Tab, you should always try to update the tools to the latest version:

Android Tools
Use always the latest available tools

So you should install:

  • Android SDK Tools 26.1.1
  • Android SDK Platform-Tools 27.0.1
  • Android SDK Build-Tools 27.0.3

I also suggest you to install the Android emulator is case you want to try your app on multiple devices. The latest available version is:

  • Android Emulator 27.1.12

I’ll update this guide every time there will be an updated component so I suggest to bookmark/follow this page.

Many modern apps require a secure authentication for users and Azure Active Directory Authentication Library (ADAL) enables application developers to authenticate users to cloud or on-premises Active Directory (AD). Here I show two different ways to add ADAL to a Xamarin.Forms project.

The short way: MTADAL Plugin

This is a plugin I have created to add ADAL to all my projects and I’ve decided to make it freely available to everyone.The plugin page here: http://www.xamarinexpert.it/plugins/mt-adal/A tutorial to use the plugin is here: http://www.xamarinexpert.it/2018/03/01/adal-made-easy/

Authentication with MTADAL Nuget package
MTADAL Nuget package

This plugin is really easy to use. You just need to install it in your projects (PCL/.NetStandard and platform projects) and write:

AuthenticationResult data = await MTADAL.Current.Authenticate(Authority, GraphResourceUri, ClientId, ReturnUri);

That’s it. Basically in less than a minute you are ready to authenticate your users.

The long way: Write the authentication code

In case you don’t want to use the MTADAL plugin, you can write the code by yourself in your projects.The first thing you need to do is install the ADAL nuget package in your projects (https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/)

Authentication with ADAL package
ADAL package

In our PCL/.NetStanrdard project we need to add this interface:

public interface IAuthenticator
{
    Task<AuthenticationResult> Authenticate(string authority, string resource, string clientId, string returnUri);
    void Logout(string authority);
    bool hasLoginData(string authority);
}

and when we want to authenticate a user we need to use this code:

var auth = DependencyService.Get<IAuthenticator>();
            AuthenticationResult data = await auth.Authenticate(App.Authority, App.GraphResourceUri, App.ClientId, App.ReturnUri);

Before we can authenticate the users, we need to add the code in each of the platform project we need the authentication (eg. Android, iOS, UWP):

Android

Here we need to implement the interface created in our PCL/.NetStandard project.

[assembly: Dependency(typeof(Authenticator))]

namespace YOURNAMESPACE
{
    public class Authenticator : IAuthenticator
    {
        public async Task<AuthenticationResult> Authenticate(string authority, string resource, string clientId, string returnUri)
        {
            try
            {
                var authContext = new AuthenticationContext(authority);
                if (authContext.TokenCache.ReadItems().Any()) 
                    authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
                var uri = new Uri(returnUri);
                var platformParams = new PlatformParameters((Activity) Forms.Context);
                var authResult = await authContext.AcquireTokenAsync(resource, clientId, uri, platformParams);
                return authResult;
            }
            catch (Exception ecc)
            {
                return null;
            }
        }

        public bool hasLoginData(string authority)
        {
            var authContext = new AuthenticationContext(authority);
            return authContext.TokenCache.ReadItems().Any();
        }

        public void Logout(string authority)
        {
            var authContext = new AuthenticationContext(authority);
            if (authContext.TokenCache.ReadItems().Any()) authContext.TokenCache.Clear();
        }
    }
}

We need to register the class with DependencyService otherwise the code will not work. We can register the class adding this line before the namespace:[assembly: Dependency(typeof(Authenticator))]Don’t forget it otherwise the authentication will not work!Inside your MainActivity class you also need to add this code:

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            base.OnActivityResult(requestCode, resultCode, data);
            AuthenticationAgentContinuationHelper.SetAuthenticationAgentContinuationEventArgs(requestCode, resultCode, data);
        }

This will intercept the result from the ADAL activity and will allow you to conclude successfully the authentication.

iOS

We need to add the class to our iOS project:

[assembly: Dependency(typeof(Authenticator))]

namespace YOURNAMESPACE
{
    class Authenticator : IAuthenticator
    {
        public async Task<AuthenticationResult> Authenticate(string authority, string resource, string clientId, string returnUri)
        {
            try
            {
                var authContext = new AuthenticationContext(authority);
                if (authContext.TokenCache.ReadItems().Any())
                    authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
                var controller = UIApplication.SharedApplication.KeyWindow.RootViewController;
                var uri = new Uri(returnUri);
                var platformParams = new PlatformParameters(controller);
                var authResult = await authContext.AcquireTokenAsync(resource, clientId, uri, platformParams);
                return authResult;
            }
            catch (Exception ecc)
            {
                return null;
            }
        }

        public bool hasLoginData(string authority)
        {
            var authContext = new AuthenticationContext(authority);
            return authContext.TokenCache.ReadItems().Any();
        }

        public void Logout(string authority)
        {
            var authContext = new AuthenticationContext(authority);
            if (authContext.TokenCache.ReadItems().Any()) authContext.TokenCache.Clear();
        }
    }
}

This class is the only thing you need to authenticate your users on iOS.Again, remember to add the line[assembly: Dependency(typeof(Authenticator))]

UWP

We need to add the class to our UWP project:

[assembly: Dependency(typeof(Authenticator))]

namespace YOURNAMESPACE
{
    public class Authenticator : IAuthenticator
    {
        public async Task<AuthenticationResult> Authenticate(string authority, string resource, string clientId, string returnUri)
        {
            try
            {
                var authContext = new AuthenticationContext(authority);
                if (authContext.TokenCache.ReadItems().Any())
                    authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
                var uri = new Uri(returnUri);
                var platformParams = new PlatformParameters(PromptBehavior.Auto, false);
                var authResult = await authContext.AcquireTokenAsync(resource, clientId, uri, platformParams);
                return authResult;
            }
            catch (Exception ecc)
            {
                return null;
            }
        }

        public void Logout(string authority)
        {
            var authContext = new AuthenticationContext(authority);
            if (authContext.TokenCache.ReadItems().Any()) authContext.TokenCache.Clear();
        }

        public bool hasLoginData(string authority)
        {
            var authContext = new AuthenticationContext(authority);
            return authContext.TokenCache.ReadItems().Any();
        }
    }
}

This class is the only thing you need to authenticate your users on UWP.Again, remember to add the line[assembly: Dependency(typeof(Authenticator))]

Summary

It’s incredibly easy to authenticate users in a Xamarin.Forms projects. You can do it in 2 ways:

  1.  Use the MTADAL Plugin
  2.  Install the ADAL Plugin, add then interface and add the classes above for each of your platform projects!

You want to create a mobile multi platform app and you really like C#.Xamarin is the perfect solution for you and if you don’t have any major experience with native mobile development, Xamarin.Forms is just a day-dream.So let’s see how we can create our first Xamarin.Forms projects and how it works.

Create the Project

From Visual Studio 2017 create a New project…Under “Visual C#” select “Cross-Platform” (1) then select “Cross-Platform App (Xamarin.Forms)” (2), choose name and location for your project (3) and press Ok (4).Now we need to configure our project. In this case we start with a Blank app that is perfect to explain how a Xamarin.Forms solution works. Under Platform choose the platforms you need. In this case I’ve chosen Android, iOS, Windows (UWP). Under UI Technology select Xamarin.Forms and under “Code Sharing Strategy” choose .NET Standard.After we press ok, Visual Studio will take several seconds (or minutes according to your machine) to create your solution.Inside the Solution Explorer we see now that we have a .NET Standard project (our common library, where we are going to write almost all our code), and Android project, an iOS project and a UWP project. The projects are already working so if we try to run one of the projects (Android, iOS, UWP) this is what we get:That’s brilliant, few second and we already have a working project for Android, iOS and UWP.Now it’s time to understand how a Xamarin.Forms project works so we are going now to analyze the projects we have in our solution.

.NET Standard

This is common project shared by all the other projects. It’s here that we are going to write our app. Here we write the UI and the logic and if our project it’s easy enough, we don’t need to write code in the other projects of our solution.Inside our project there are 2 file, App.xaml and MainPage.xaml. App.xaml is the entry point of our .NetStandard project. From this file Xamarin loads the first Page of the app and usually we initialize other parts of the project like Resources, Databases and so on.Now let’s see the structure of the code-behind file App.xaml.cs

using Xamarin.Forms;

namespace Tutorial01
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            MainPage = new Tutorial01.MainPage();
        }

        protected override void OnStart()
        {
            // Handle when your app starts

        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}

Inside the constructor we initialize the XAML file with “InitializeComponent()” and load the first page with “MainPage = new Tutorial01.MainPage();”.As you have seen, MainPage is the actual page displayed on-screen, so every time we want to change a page, we need to assign a new value to MainPage (We’ll see that there are also other ways to do it).OnStart is called when the app is started. OnSleep and OnResume are called every time the app appears and goes in background.Now it’s time for the MainPage file. This is the page that will be displayed when we will launch the app. This is the XAML file:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"             
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"             
             xmlns:local="clr-namespace:Tutorial01"             
             x:Class="Tutorial01.MainPage">
    <Label Text="Welcome to Xamarin.Forms!"            
           VerticalOptions="Center"            
           HorizontalOptions="Center" />
</ContentPage>

What we have here is a ContentPage and inside a single element, a Label with text (“Welcome to Xamarin.Forms!”) and alignment options, so where are saying that we want to show that text at the centre of the screen (we have seen it before).And this is the code-behind file:

using Xamarin.Forms;

namespace Tutorial01
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
    }
}

We see that MainPage inherits from a ContentPage (as the XAML file) and inside the constructor we need to call InitializeComponent to load the XAML file.Because the app does nothing, this file is basically empty otherwise here you can add the logic of your page (unless you want to follow an MVVM approach…I’ll add a link here as soon as the MVVM guide is ready).

Android Project

Let’s see the structure of the project:Inside the Resources folder you will add all your resources like images, styles and native layouts.MainActivity is the entry point of your Android app:

namespace Tutorial01.Droid
{
    [Activity(Label = "Tutorial01", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true,
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;
            base.OnCreate(bundle);
            global::Xamarin.Forms.Forms.Init(this, bundle);
            LoadApplication(new App());
        }
    }
}

Inside the method OnCreate we need to initialize Xamarin.Forms and load the .NetStandard project.Usually you don’t have to edit this file unless you have to load external plugins or intercept events like OnActivityResult (when you launch another activity, after it terminates you’ll get the result here) or OnResume (when the app goes in foreground).

iOS Project

Let’s see the structure of the project:Inside the Resources folder you will add all your resources like images or storyboards (you are not going to use them in Xamarin.Forms).The AppDelegate file is the entry point of your iOS app:

namespace Tutorial01.iOS
{ // The UIApplicationDelegate for the application. This class is responsible for launching the
    // User Interface of the application, as well as listening (and optionally responding) to
    // application events from iOS.
    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        // This method is invoked when the application has loaded and is ready to run. In this
        // method you should instantiate the window, load the UI into it and then make the window
        // visible.
        //
        // You have 17 seconds to return from this method, or iOS will terminate your application.
        //        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App());
            return base.FinishedLaunching(app, options);
        }
    }
}

Inside the method FinishedLaunching we need to initialize Xamarin.Forms and load the .NetStandard project.Usually you don’t have to edit this file unless you have to load external plugins.

UWP Project

Let’s see the structure of the project:This project seems a bit more complicated as it has two file: App.xaml and MainPage.xaml. In UWP, Xamarin.Forms is initialized inside the App.xaml file.

protected override void OnLaunched(LaunchActivatedEventArgs e) {
    Frame rootFrame = Window.Current.Content as Frame; // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (rootFrame == null) { 
        ... 
        Xamarin.Forms.Forms.Init(e); 
        ...
    } 
    ...
}

There is a lot of code but don’t worry, probably you will never have to edit it. The only thing to remember is that here the Xamarin Forms library is initialized.The MainPage.xaml is extremely simple:

namespace Tutorial01.UWP
{
    public sealed partial class MainPage
    {
        public MainPage()
        {
            this.InitializeComponent();
            LoadApplication(new Tutorial01.App());
        }
    }
}

The only thing we do here is to load our .Net Standard project.

Recap

During this tutorial we have seen the structure of a Xamarin.Forms project: When we create a new Xamarin.Forms project, Visual Studio creates for us:

  • .NetStandard project where we write the logic and the UI of our app
  • a project per each platform we want our app on.

We need to write code in these platform projects only if we need to initialize a plugin, write a custom renderer (I’ll write a tutorial for Custom Renderers) or in general write code for a particular platform.