CategoryAndroid

Out Of Memory Exceptions when using Images in Android

I haven’t talked about my app for a while. The development was going quite well. When the learning phase of working with android was decreasing, the development effort decreased and I started to embrace the android development framework and its lifecycle.
The functionality of my app increased rapidly, with tons of new features and the look and feel got better and better and better (thanks to www.fierkant.nl!)

That’s when random crashes of my app start to occur at random moments in the app.
The debugger couldn’t help me at all and all I got was this exception message:

 Out of memory: Heap Size=49159KB, Allocated=40884KB, Limit=49152KB

I couldn’t really figure out why, I did use some memory by drawing some images, but it wasn’t huge.
So I googled it and it seems to be a common problem. A lot of people run in to these Memory issues.

The garbage collector collects all elements which are not used. Unfortunately, the views have a callback, this is why the garbage collector cannot detect that they aren’t used anymore.

I found some code which unbinds all views and their descendants. I tweaked it a bit and rewrote it for c#.

protected void UnbindDrawables(View view)
{
   if (view == null) { return; }

  if (view.Background != null)
  {
      view.Background.Callback = null;
  }
  if (view is ViewGroup)
  {
       for (int i = 0; i < ((ViewGroup)view).ChildCount; i++)
       {
           UnbindDrawables(((ViewGroup)view).GetChildAt(i));
       }
       if (!(view is AdapterView))
       {
           ((ViewGroup)view).RemoveAllViews();
      }
  }
}

Now that we’ve got this method, we can call it in the OnDestroy of an Activity.
In this example, I use my LayoutContainer view, which is my outer wrapper view which contains all views of the current layout. Feel free to use your own view id, but make sure the images you want to unbind are in this view.

protected override void OnDestroy()
{
   base.OnDestroy();

   UnbindDrawables(FindViewById<RelativeLayout>(Resource.Id.LayoutContainer));
   System.GC.Collect();
}

When I implemented this in all activities (perhaps consider a BaseActivity), the memory issues were gone and I have not seen them since.
A lot of people suggest to add android:largeHeap=”true” to your manifest file so your app can use more heap size. I don’t consider that as a good solution. You should try to keep your application clean and only use the memory you really need. Just clean everything up as you’re supposed to.

Creating a circular bitmap in Android in C#

A while ago, I was looking for a way to change a bitmap into a circular bitmap.
There are a lot of good examples on the internet, but none of them completely met my requirements.
So I used one of them as base to create my own helper for creating a circular bitmap.

public static Bitmap CreateRoundedBitmap(Bitmap bitmap, int padding)
{
    Bitmap output = Bitmap.CreateBitmap(bitmap.Width, bitmap.Height, Bitmap.Config.Argb8888);
    var canvas = new Canvas(output);

    var paint = new Paint();
    var rect = new Rect(0, 0, bitmap.Width, bitmap.Height);
    var rectF = new RectF(rect);

    paint.AntiAlias = true;
    canvas.DrawARGB(0, 0, 0, 0);
    canvas.DrawOval(rectF, paint);
    paint.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.SrcIn));

    canvas.DrawBitmap(bitmap, rect, rect, paint);
    return output;
}

I’m not a fan of static methods, but when no context is used, I’m not that bothered.

A border can be added by drawing a second oval with a stroke width and a color property set to the paint instance.

 var rect2 = new Rect(padding, padding, bitmap.Width - padding, bitmap.Height - padding);
 var p = new Paint();
 p.Color = Color.White;
 p.StrokeWidth = 10;
 p.AntiAlias = true;
 canvas.DrawOval(new RectF(rect2), p);
 

This example creates a white border around the circular bitmap.

In my app, I use a lot of white circular bitmaps. To keep the code as DRY as possible, I created another helper method for creating white bitmaps.

public static Bitmap CreateWhiteBitmap(int width = 160, int height = 160)
{
    var bitmap = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888);
    Canvas c = new Canvas(bitmap);
    c.DrawColor(Color.White);
    c.Save();
    return bitmap;
}

Another static. Still can’t be bothered, because no context is used.
I do like to point out that statics can be very dangerous. When statics are used as repositories to read static variables, files or whatever kind of data, remember to at least always use locks, but even better… just don’t use statics!!

Now let’s bring it all together.

In my activity, I use the following code to create a bitmap, change it to a circular bitmap and add it to an ImageView (with id “Image” in my Layout file):

var bitmap = BitmapHelper.CreateWhiteBitmap();
bitmap = BitmapHelper.CreateRoundedBitmap(bitmap, 10);
var imageView = view.FindViewById<ImageView>(Resource.Id.Image);
imageView.SetImageBitmap(bitmap);

That’s it! Hope this helps!

Changing the layout for different states of an android button

A button in android can have one or multiple states:

  • android:state_pressed
  • android:state_focused
  • android:state_hovered
  • android:state_selected
  • android:state_checkable
  • android:state_checked
  • android:state_enabled
  • android:state_activated

The layout of a button’s state cannot be changed from within the layout file itself.
A drawable resource file needs to be used to set a layout for the different states.

This resource file should contain a selector with a collection of item elements.
Every item element can target one (or multiple) state(s) of a button by adding the state and its value as attribute. See example below.
It is not necessary to implement all states. An item element with no state attribute is used as default state. See last item element in example below.
This resource file is stored in the Drawable folder of the Resources content (F.E. /Resources/Drawable/button.xml).
Other resources can be referenced and used. In the example below, two custom defined colors are used (@color/custom_theme_button_primary and @color/custom_theme_button_secondary).
When a combination of states are defined on an item element, all states need to be active!

The following example adds three layout states to a button; pressed, disabled and a default state.

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_pressed="true" android:color="@color/custom_theme_button_primary">
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
      <solid
          android:color="@color/custom_theme_button_secondary" />
      <padding
          android:left="10dp"
          android:top="10dp"
          android:right="10dp"
          android:bottom="10dp" />
    </shape>
  </item>
  <item android:state_enabled="false" android:color="@color/custom_theme_button_primary">
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
      <solid
          android:color="@color/custom_theme_button_secondary" />
      <padding
          android:left="10dp"
          android:top="10dp"
          android:right="10dp"
          android:bottom="10dp" />
    </shape>
  </item>
  <item android:color="@color/custom_theme_button_secondary">
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
      <solid
          android:color="@color/custom_theme_button_primary" />
      <padding
          android:left="10dp"
          android:top="10dp"
          android:right="10dp"
          android:bottom="10dp" />
    </shape>
  </item>
</selector>

Setting the color attribute on the item element sets the text color. Setting the color attribute in the solid element within the shape element will set the background color for this shape.
Note: The margin cannot be set in a drawable resource file.

In the layout file, the button needs to contain a reference to the drawable resource file:

<Button
    style="@style/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="10.0dp"
    android:layout_marginRight="10.0dp" 
/>

This example requires a drawable resource with the name “button”. Simply create a xml file with the name “button.xml” in Resources/Drawable and add your selector and items.

Android Activities, it’s all about overriding event methods

In my previous post, I talked about class Attributes on Activities.
This post is about overriding event methods to influence the behavior of the Activity.

Activity LifeCycle

When a new Activity is created, the template overrides one event method; OnCreate.

[Activity]
public class MyActivity : Activity
{
    protected override void OnCreate(Bundle bundle)
    {
       .....
    }
}

The OnCreate is part of the Activity LifeCycle.
It is important to understand the Activity LifeCycle, it is one of the fundamentals of an android application.
The OnCreate method works like the Page_Load method of a WebForms page.
This is ideal for setting up the Activity.

For instance:

  • loading layout files
  • updating controls
  • binding event handlers

All event methods of the Activity LifeCycle:

  • OnCreate
  • OnStart
  • OnResume
  • OnPause
  • OnStop
  • OnDestroy
  • OnRestart

When an activity changes state, the corresponding event method is called.
All these methods can be overridden and implemented.

The Activity exposes a lot more overridable event methods.
These are methods I use a lot:

Options menu

The following event methods are used for controlling the options menu:

public override bool OnPrepareOptionsMenu(IMenu menu)
{
       // add your options items to the menu here
      return base.OnPrepareOptionsMenu(menu);
}

public override bool OnOptionsItemSelected(IMenuItem item)
{
    // detect selected menu item and handle action
    return base.OnOptionsItemSelected(item);
}

The OnPrepareOptionsMenu is called when the options menu is created. Custom options can be added to the menu argument.
When an option item is clicked, the OnOptionsItemSelected is called with the selected option item as argument. I usually use a switch on item.Id to detect which item is selected.

The back button

The following event method is called when the back button is pressed:

public override void OnBackPressed()
{
    // handle back button
    base.OnBackPressed();
}

the base.OnBackPressed() provides the default back button behavior. Remove this line when you want to disable the default back button behavior, but I do not recommend it. People expect this behavior from the back button.

Creating Dialogs

This following event method is called when ShowDialog() is called in the current Activity.

public override Dialog OnCreateDialog(Bundle savedInstanceState)
{
    // Create and return dialog here.
}

This method is used to create a dialog.

This should help you get on your way with creating your Activities.

Android Activities, it’s all about the attributes

As promised in my previous post (way too long ago, I know! I’m Sorry!!!), I would talk more about the Activities for Android applications in .Net (By Xamarin).
I want to start with one of the most important parts of the application, the Activities.

[Activity]
public class MyActivity : Activity
{
    protected override void OnCreate(Bundle bundle)
    {
       .....
    }
}

This is the very basic of an Activity. It inherits from Activity and has an attribute Activity. The Activity base class provides many overridable methods, like onCreate, which is called when the Activity is created (think of the Page_Load in WebForm pages).

The Activity attribute has many interesting properties, some of them are listed below:

  • Label, this provides the label for the application, shown in the Android app screen
  • MainLauncher, this is an indication whether the Activity is the main activity and will be started on application startup.
  • Icon, Sets the icon for the application
  • Theme, sets the theme for the application, this can be a custom theme or a predefined theme.
  • ConfigurationChanges, sets which changes are handled by the application itself.
[Activity(Label = "My application",
          MainLauncher = true,
          Icon = "@drawable/icon",
          ConfigurationChanges = Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize,
          Theme = "@android:style/Theme.NoTitleBar")]
public class MyActivity : Activity
{
       .....
}

This is an example of the Activity with attributes. No custom code is needed to make this work.

The ConfigurationChanges is set to “Orientation” and “ScreenSize”, this means that orientation changes are handled by the Activity. I use this a lot with WebViews, this stops the application from reloading the page when the orientation changes.

The Theme “NoTitleBar” removes the titlebar from the application. This makes it possible to create your own title bar.
A list of all available predefined themes can be found here

Creating native iOS and Android apps in Visual Studio using C#

Lets go Mobile!

One of my interests in software development is in mobile devices, websites and applications. I have blogged about it in several topics. But this was all about mobile websites and optimizing your website for mobile devices.

In my search for new and interesting things, I ended up with an idea to develop a native app. Because I don’t own any apple device (proud of that!), I wanted to develop a native Android application.

A good starting point for creating Android apps is, of course, the Android docs. But there is one disadvantage, it is Java. I don’t really hate Java, but it is just not for me. I don’t have an IDE set up for Java, I don’t know the language as well as c#, so I didn’t really feel like working with c#.

Xamarin

That is when I found Xamarin. It was actually Scott Hanselman who blogged about it. If you don’t know who Scott Hanselman is, please read his blog! Even better, if you have the change, go and see him when he is speaking.

Xamarin lets you develop native apps in Visual Studio using c#. Everything is strongly typed and works how you expect it to work. The debugger starts the Android emulator and lets you easily test your application.

Just one bad thing about Xamarin, the pricing! It is very expensive, but you can download a 30 day trial.

Setting up your environment

Before you can use Xamarin, you need to set up your environment. I assume you already have Visual Studio installed.

To start using Xamarin, you need to install the following:

First install the Java JDK.  In my case I needed to updated the PATH environment variable (Control Panel -> System -> Advanced System Settings -> Environment Variables) and add the bin folder to this variable. In my case C:\Program Files\Java\jdk1.7.0_51\bin.

After that, unzip theAndroid SDK to a location of choice. Run the SDK Manager as administrator. And install all desired packages.
The installed APIs can be selected from within Visual Studio in the Project Properties.

Now this is done, we can install Xamarin. When this the installation is completed, start Visual Studio and configure it. Go to tools -> options and select Xamarin. In the Android Settings tab Select the Android SDK location. And that’s it. Ready to go!

Project Settings

When you open Visual Studio and select new project, you will find a new option in templates, Android. By selecting this option, you will find several Android applications. Most of it just change the API level.

This can simply be changed in the properties window of the Project.

android-properties
Updating the “Minimum Android to target” property will change the targetted API level. My suggestion: keep the API level as low as possible.  This enhances accesibility.

The Xamarin docs are a good place to start. They have a lot of good tutorials to get started. In my next posts, I will post about native apps and code!