Frost 3.1.17 Released

The big GIF update is here! You can now save GIF files into your image vault. I’ve also added an ad blocker, some UI tweaks, and squashed several bugs. Full change log follows:

  • Added native GIF support to image vault. You can now save GIF images from the web into your image vault and play them. Only GIF images saved since this update will work properly
  • GIF files can now be imported into the image vault from your device storage
  • GIF files can now be exported from the image vault to your device storage
  • Added experimental ad block (disabled by default)
  • Do you know more than one language? Help us translate Frost – see the new button in the options menu
  • Changed the look of tab loading progress icon
  • Tab bar will disappear when you scroll down, and reappear when scrolling up (with option to enable or disable)
  • Tab bar will adjust height based on device form factor and screen orientation if necessary
  • Viewing images in the image vault will now use entire screen on devices with an onscreen navigation bar (Android 4.4+ only)
  • Image saving dialog will now show progress in kilobytes
  • Fixed text selection context menu causing screen shift
  • Fixed missing xx-hdpi icon asset
  • Minor code base optimizations
  • Performance tweaks – browser scrolling should be slightly smoother
  • [Lite Version] Repositioned ads to be slightly less intrusive

Note that your device must support one of the following ABI’s to receive this update:

  • ARM
  • ARMv7a
  • MIPS
  • x86

I will be submitting this update to the Amazon app store as well. It should be available once it gets through their review process.

Importing libraries into Android Studio

Not all Android libraries out there provide a Maven dependency to include it into your project. Sometimes you will just have to resort to the original method of just including the source code in your project.

For this example, I will be importing the SlidingMenu library for Android by Jeremy Feinstein.

First of all, allow me to illustrate the folder structure of your entire project:

importlibrary

To achieve this structure, you will have to create library folder in the root of your project, and import the code library you want to include into it as a module. Note that if the code library you are trying to import doesn’t already have a build.gradle file, you may need to import it into Eclipse first and generate the necessary build.gradle file (as of writing this post, Android Studio is unable to generate build.gradle files for eclipse projects).

Next, based on the naming conventions I established in the image above ensure you have the following:

In your APP’s build.gradle file make sure you have:

dependencies {
    // Your other dependencies go here
    compile project(':libraries:SlidingMenu')
}

This tells Gradle that your App has a dependency on SlidingMenu.

In SLIDING MENU’s build.gradle file make sure it has the following:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.7.+'
    }
}

apply plugin: 'android-library'

repositories {
    mavenCentral()
}

dependencies {
    compile 'com.android.support:support-v4:19.0.0'
}

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.1"

    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 16
    }

    sourceSets {
        main {
            java.srcDirs = ['src/main/java']
            res.srcDirs = ['src/main/res']

            manifest.srcFile 'src/main/AndroidManifest.xml'
        }
    }
}

This tells Gradle how to compile and build the Sliding Menu module. We’re telling it that Sliding Menu depends on the Android V4 Support library, the SDK version target to build against, and finally, the folders paths where the source code, resources, and manifest files are located.

Your PROJECT’s settings.gradle file should look like this:

include ":libraries:SlidingMenu", ':App'

This tells Gradle the modules it should build for your entire project, and the order to do it in. Obviously we want to build Sliding Menu before we build our app, because Sliding Menu is a dependency and it expects it  to be already compiled.

In android studio press the Tools -> Android -> Sync Project with Gradle Files button, then rebuild your project. If all went well you should be able to import the com.jeremyfeinstein.slidingmenu.lib.SlidingMenu library into your app’s source files.

Registering global filters in ASP.Net MVC 4 with Autofac

Suppose we have a custom filter defined as follows:

public class CustomFilterAttribute : ActionFilterAttribute
{
    public MyPropery Property { get; set; }
    ...
}

There’s a new way of registering MVC global filters using AutoFac. First, remove the filter registration from your RegisterGlobalFilters because we will have Autofac handle adding them to our controllers/actions instead of MVC.

Then, register your container as follows:

var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());

builder.RegisterType<MyProperty>().As<IProperty>();

builder.Register(c => new CustomFilterAttribute(c.Resolve<IProperty>()))
                .AsActionFilterFor<Controller>().InstancePerHttpRequest();

builder.RegisterFilterProvider();

IContainer container = builder.Build();

DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

Note that by passing in the Controller class into the extension AsActionFilterFor() we are telling AutoFac to apply this filter to all classes that derive from the Controller class (which, in MVC, is all controllers). Since we are calling AsActionFilterFor() without any arguments, we are also specifying we want to have the filter applied to all actions within the specified controllers. If you want to control the scope of your filter, such as applying it to a specific controller and action, you can use lambda expressions like so:

builder.Register(c => new CustomFilterAttribute(c.Resolve<IProperty>()))
    .AsActionFilterFor<HomeController>(c => c.Index())
    .InstancePerHttpRequest();

If your action takes a parameter, use the default keyword to specify:

builder.Register(c => new CustomFilterAttribute(c.Resolve<IProperty>()))
    .AsActionFilterFor<HomeController>(c => c.Detail(default(int)))
    .InstancePerHttpRequest();

Note that you have to use a different extension method based on what type of filter you are registering, here are the supported filter types:

  • AsActionFilterFor
  • AsAuthorizationFilterFor
  • AsExceptionFilterFor
  • AsResultFilterFor

Frost 3.0.13 Released

Frost 3.0.13 Old

This update has been due for a while. Android has advanced quite a bit since ICS (4.0+) and it was a challenge implementing new SDK features while maintaining cross compatibility with older versions of Android. I decided it was time to end the cycle of despair, toss out the old and obsolete, and embrace the new hotness.

So starting off, this is the first version that will not support Android Gingerbread (2.3.x). And on top of that I decided to stop using Eclipse.

So what exactly is this new hotness?

Frost 3.0.13 New

First is a full redesign of the interface, using holo interface elements, fragments, view pagers, things that were simply difficult or impossible to implement before. Next is the use of Android Studio which is far and away more capable as an IDE. Part of Android Studio includes Gradle integration, which is a powerful build system with Android support. Thanks to this, it will be a lot easier to release updates to Frost in the future. Lastly is support for the experimental ART runtime, which was introduced in Android 4.4.

Here is the complete change log:

    • Rewritten from scratch for Android 4.0 and up
    • Redesigned holofied interface
    • Added bookmark folders
    • Can now be used as default browser
    • Built in video player with improved support (Kitkat only)
    • Reworked exit functionality
    • Stashes are now called vaults
    • Improved image vault performance
    • Many stability improvements
    • Support for ART runtime
    • Support for file downloads
    • Improved image quality in image vault

Adding ActionBarSherlock as a Library into Android Studio

Using maven (similar to NuGet for those of you familiar with the .NET world) and gradle together makes it possible to include libraries in your project without having to manually download the source code and dump it into your project folder. Aside from making it easier to update to newer versions of those libraries as they are released, the imported files don’t clutter up your project folder structure and source repository as much as the complete library source. The downside is that this approach is not appropriate if you intend to modify the source code of the library.

    1. Open your Android SDK Manager and make sure you have the latest version of the Android SDK Platform and Build Tools installed (version 19.0.0 as of this post).
    2. Create or import your project into Android Studio. Now look for the build.gradle file. There is one located in the root of your project, ignore this one. There should be a build.gradle file located in the main module within your project (where your application’s source and resources are).
    3. Modify the build.gradle file you found to include the following, if it already doesn’t:
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.6.+'
    }
}

apply plugin: 'android'

repositories {
    mavenCentral()
}

dependencies {
    compile 'com.android.support:support-v4:13.0.0'
    compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
}

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.0"

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 19
    }
}

That should be it. On your first build you should see the folder: /libraries/ActionBarSherlock/actionbarsherlock/ appear in the root of your project. Any references to ActionBarSherlock should then resolve themselves in your code.

The following steps are also relevant to other libraries available through maven, simply modify the “dependencies” section of the build.gradle.

Dynamically Generating Lambda Expressions at Runtime From Properties Obtained Through Reflection on Generic Types

Lately I’ve been having to export some of my data entities into CSV files, and I’ve been using the CSVHelper nuget package to achieve this. As is common, property names don’t translate well into readable column headers, so you have to provide some kind of property to string mapping.

This is how CSVHelper handles it:

namespace MyApplication.CSVMapping
{
	public class MyModelCsvMap : CsvClassMap
	{
		public override void CreateMap()
		{
			Map(m => m.Id).Name("Model Id");
			Map(m => m.Description).Name("Model Description");
			Map(m => m.StartDate).Name("Start Date");
			Map(m => m.EndDate).Name("End Date");
			Map(m => m.RunDate).Name("Run Date");
		}
	}
}

Nothing too fancy, just passing my model type into the derived class, and going through each class member, setting the Name property.

However, as is also common, I may also have a form tied to this model and I want to use the built in DataAnnotations to set the form labels for each field, like so:

namespace MyApplication.Models
{
	public partial class MyModel
	{
		[DisplayName("Model ID")]
		public int Id { get; set; }
		[DisplayName("Model Description")]
		public string Description { get; set; }
		[DisplayName("Start Date")]
		public DateTime StartDate { get; set; }
		[DisplayName("End Date")]
		public DateTime EndDate { get; set; }
		[DisplayName("Run Date")]
		public DateTime RunDate { get; set; }
	}
}

Noticing some redundancy here? Could I perhaps have CSVHelper get the property column header names from the DisplayName Attribute in the model rather than having to create a seperate CsvClassMap? That way I wouldn’t have to repeat my property to string mappings.

For this I will have to create a generic version of the CsvClassMap class, which takes in my entity type. From there I can get all the properties in that type, and start iterating through them. For each property, I check if it has a DisplayName attribute, and if it does, get what the value is. The tricky part is passing in the property into CSVHelper’s map method which expects a Expression<Func<TEntity, object>>. Here’s the complete code:

using System;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using CsvHelper.Configuration;

namespace MyApplication.Common
{
	public class BaseCsvMap : CsvClassMap where TEntity : class
	{
		public override void CreateMap()
		{
			PropertyInfo[] props = typeof(TEntity).GetProperties();
			foreach (PropertyInfo prop in props)
			{
				var displayAttribute = prop.GetCustomAttributes(false).FirstOrDefault(a => a.GetType() == typeof(DisplayNameAttribute)) as DisplayNameAttribute;
				if (displayAttribute != null)
				{
					var parameterExpression = Expression.Parameter(typeof(TEntity), "x");
					var memberExpression = Expression.PropertyOrField(parameterExpression, prop.Name);
					var memberExpressionConversion = Expression.Convert(memberExpression, typeof(object));
					var lambda = Expression.Lambda<Func<TEntity, object>>(memberExpressionConversion, parameterExpression);
					Map(lambda).Name(displayAttribute.DisplayName);
				}
			}
		}
	}
}

That should be fairly self explanatory. The only strange “gotcha” is having to call Expression.Convert() before constructing the lambda expression. This is because the expression explicitly expects “object” as it’s type, and your entity likely contains typed members ie. strings, ints, decimals, etc.

You can also modify the above class to working with any custom attributes that you may have defined, just remember to pass true into the GetCustomAttributes() method.

Frost 2.7.0 Released

DuckDuckGoLogoVersion 2.7.0 of Frost has been released and with it comes big changes to the user interface. Frost first came out when Gingerbread was the latest version of the Android OS, and since then Android has made big leaps in how apps present themselves on the platform. The focus was on making it clear to the user what actions and options they had available to them at any moment, and because of that, the options menu button was removed, and action bars became commonplace.

With that in mind, we’ve removed all dependencies for the option menu button in our app, and placed all functions that used to be there in menus or action bars that are easily accessible on your screen. You’ll notice the browser menu is now sporting a new look with many more buttons, and the image stash has undergone a makeover to make things easier to find. We’ve also recognized newer devices by including high resolution icons for their higher resolution displays.

Frost has always focused on protecting our user’s privacy and with that we are happy to announce the addition of DuckDuckGo as a supported search provider in the browser. It’s only logical that we included DuckDuckGo as they share the same commitment to our user’s privacy as we do and we feel that it is the best option in protecting our user’s browsing habits. DuckDuckGo accomplishes what the larger search engines fail at, and that is treat its users anonymously. Your search queries are never saved or shared, and you can be confident your search results are never filtered based on profiling.

As always, your suggestions and comments are welcome.

Here is the full change log for version 2.7.0 of Frost:

  • Frost will exit if the power button is pressed or if the device goes to sleep
  • Updated browser menu interface
  • Fixed image downloading on 4chan and other sites
  • Removed options menu in browser – options available in browser menu
  • Removed options menu in image gallery – long press an image to view action bar
  • Removed options menu in image viewer – options available when image is tapped
  • Removed options menu in folder view – options available in action bar
  • DuckDuckGo available as search provider
  • Added option to change default search provider
  • Added hi-res icons for large high density displays
  • Optimized data access in bookmark stash
  • Updated useragent strings
  • Added ‘About’ section in settings
  • Further stability and usability improvements to importing images from the SD card

Frost 2.6.1 Released

Frost 2.61 has been released following the issues that Android 4.2 Jelly Bean caused due to Google changing the default provider for the built in AES encryption. Thanks again to all the users that reported the issue.

We’re currently working on version 3.0 of Frost. Planned changes include a complete overhaul of the bookmark stash, most notably allowing for bookmarks to be organized into folders.

Frost 2.6 Available

Frost 2.6 has been released for Android. Good news for those of you with large image stashes: this release focused on improving performance in the image stash folder view. We’ve managed to make huge improvements in speed. Using older versions of Frost it could take upwards of 20 seconds to load stashes with 1000+ images and 50+ folders. With version 2.6 we’ve managed to speed it up to the point where it takes a fraction of a second.

We’ve also made several changes based on user feedback. Cancelling a slideshow will allow the user to manually flip through the images in consecutive order. We’ve also finally fixed a bug that causes decode errors when trying to save images from certain websites.

We plan on doing these speed improvements iteratively. In the next update we will focus on adding bookmark folders as well as tools to help you organize your bookmarks. Not to mention applying many of our performance improvements to the bookmarks view as well.

Here is the full change log for this release:

  • Improved image stash folder loading performance
  • Added support for tel: links
  • Added image stash folder sorting option
  • Added quick scrolling to all lists
  • Added Google support libraries to improve compatibility
  • Moved change password dialog to settings menu
  • Imported files are now sorted in natural order of their filenames
  • Fixed image ordering when slideshow cancelled
  • Fixed bug causing decode errors when saving images
  • Fixed video player history not being cleaned up properly
  • Code optimization & bug fixes

Frost 2.5 Released

A note to Android 2.2 (Froyo) users: please backup your stash prior to updating. There is a bug in your version of Android that will wipe your stash when updating the app. Please see the FAQ for instructions on how to backup Frost and this post for more details.

 

We just released update 2.5 for Frost. As I mentioned in our previous post, we focused on the browser interface for this release. Our goal was to eliminate clutter in the options menu, and we’ve achieved this by moving a lot of common browser actions to a quick action menu in the tab bar. In future updates we will be working towards eliminating the options menu entirely as more devices are released without any hardware menu buttons.

The next biggest change is the addition of tab sessions. From now on, whenever you log into your stash you will be prompted to restore the tabs from your previous private session. Note that in order for your tab session to be saved, you need to be logged into your stashes.

Finally, there are countless optimizations and bug fixes. We’ve fixed some compatibility issues with some websites like Gmail and Twitter, as well as changed the way batch operations are handled to improve reliability and performance.

Please don’t hesitate to contact us with feedback using the contact form at the top of the page.

Frost Version 2.5

  • New browser interface
  • Added tab sessions. When logging into your stash you will be prompted to restore tabs from your previous private session
  • Added DOM storage support
  • Added password mask
  • Added support for new devices without menu buttons
  • Updated Import to SD interface
  • Improved batch data operations
  • View Image option will now open a new tab (Thanks John!)
  • Fixed tab cutoff bug
  • Fixed several site loading issues: Gmail, Twitter, etc. (Thanks V!)
  • Fixed crash on rotation
  • Fixed several rare crashes
  • A lot of code cleanup & optimization
2 of 5
12345