After nine months of after-hours work, I released Plethora for iPhone in June 2010. Plethora is a design gallery that is powered by over 90 of the world’s top design blogs. All of the posts are manually curated by our team so that only the best designs make it through to the actual app.
I have been running design and other companies for nine years but Plethora was my first iPhone app so I probably approached the project quite differently to how most iPhone development houses would have. Here’s how we did it.
The Concept
In 2009 my day job was designing websites and I had a large project coming up. I usually get inspiration for new jobs by Googling and visiting various design blogs. On this occasion it was the weekend and that sounded like too much hard work, wouldn’t it be better if I could see the best of the best in one app on my phone?
I knew that I didn’t have the time to hunt for the best designs myself so we decided to approach existing design blogs to feed us their content via RSS. There were various reasons for building an iPhone app rather than just making a mobile website:
The UI that I wanted to build would be very hard to deliver via Safari.
The app is all about images, local caching sped things up a lot.
We did not want to compete with our contributing blogs.
95% of design blogs don’t have their own iPhone app and this would give them a way to be found in the App Store.
The Design
The very first thing I did was mockup the visuals in Fireworks. We decided fairly early on that we wanted the images to be the main focus so didn’t want any buttons on the interface at all, just the designs themselves. The problem was that we still wanted to make it easy for people to save, remove or share designs that they liked, so we came up with the hub menu. You swipe sideways to open a ring of buttons, slide over to the one you want to activate it. This feature has become quite a hallmark of the app.
This was hard to explain (as you probably just found out!) so I used Flash to make an video of the app in action. We were then ready to test the market by sending the video and UI screenshots to some of my favorite design blogs to see what they thought. Everyone said it was a great idea so we moved onto development.
The Development
This app has a complex web-based back-end which I developed myself in PHP and MySQL. It’s all hosted at MediaTemple who, apart from a few initial slow support responses, have been great to work with. There were four main components to the web development:
An automated API to fetch new posts from the contributing blogs.
An online administration area for curators to shortlist the designs.
A secondary admin for content editors to check wording and credits.
The live API that fetches new images for the app.
The above work kept me so busy that I ended up outsourcing most of the actual iOS development to a dedicated iPhone dev house here in New Zealand. This freed me up to do what I know best: the UI design, the PHP coding and the marketing.
The Business
Our original model was to sell the app but eventually decided to release it for free. We did this for a number of reasons:
We wanted to deliver inspiration to everyone equally.
Our contributor blogs were all free to access.
Even if we took per download the app needs to be maintained every day by our editors, so a subscription model is all that would really work and Apple wasn’t doing those at the time.
So how do we make money? Well we are six months in with thousands of users but haven’t made any money yet! We do have some ads but they bring in far less than our costs. We really don’t see the app ever making a lot of money but we are working on a couple of side-projects which will tie in nicely.
We are currently working on the Plethora Store which will sell boutique designer-centered products you can’t find anywhere else. We are also writing a couple of creative books that our audience will love.
What do you think?
Feel free to download the app for yourself and let us know what you think in the comments section below. You can also follow us on Twitter or Facebook and we post the most popular design of the day at our blog which you can subscribe to.
When deploying an application to a client, it may be necessary to upgrade the installed version of Windows Installer. For example, SQL Server 2008 requires that Windows Installer 4.5 be installed on the system, something that most Windows XP machines won’t have. It is simplest to just package the needed version of Windows Installer with your application, but if you need to check which version is installed manually, you can do one of the following.
Msi.dll Version
Navigate to the Windows\System32 directory of the computer (Generally C:\Windows\System32)
Find and check the version number of the file msi.dll
Running msiexec
Click Start
Click Run
Type msiexec
Press enter
In the window that appears, the version of Windows Installer will be on the first line
Martin Walker, CTO at Behaviour (formerly A2M) spoke to David Smith of Game Careers at the MIGS in Montreal in November 2010. Martin has been involved in commercial software development in Montreal since the mid 80′s. He has spent most of his career in the multimedia arena, working for companies like Matrox Electronics, Softimage and others. He has been a key player in building tools and environments for video productions including special effects and 3D computer graphics. His venture in the gaming industry has evolved into the creation of A2M’s multiplatform game engine and the elaboration of an optimized production pipeline to produce good quality games fast. This is his advice to those seeking to work in the games industry: “Be prepared to show the stuff that you’ve done and the experience you’ve acquired. Be prepared with the portfolio if you’re an artist or designer or programming examples or projects. Be prepared to answer intricate questions during the interview process. Investigate if you are from abroad, the immigration process, what do you need to do to spearhead the process. It is a bit tedious depending on what type of training you have and the experience you have in trying to immigrate to Quebec.” See the clip that follows:
A few days ago, we posted two C++ quizzes based on a question posted in a forum. Let’s review the first question
Quiz 1
#include<iostream>
class Foo {
public:
virtualvoid DoStuff()=0;
};
class Bar : public Foo {
public:
virtualvoid DoStuff(int a)=0;
};
class Baz : public Bar {
public:
void DoStuff(int a) override
{
std::cout << "Baz::DoStuff(int)";
}
void DoStuff() override
{
std::cout << "Baz::DoStuff()";
}
};
int main() {
Baz baz;
Bar *pBar = &baz;
pBar->DoStuff();
}
The guy was frustrated because he expected two things:
The code would compile without errors.
Line 30 would end up by calling Baz::DoStuff() which in turn would have printed that same in the output console.
Instead, he got the following compile-time error at that same line
e:\foo.cpp(30): error C2660: ‘Bar::DoStuff’ : function does not take 0 arguments
The root of this compilation error is at line 11: as we are closing the definition of class Bar without saying anything about method DoStuff without arguments but, instead, having overloaded DoStuff in line 10 with a version that takes an argument of type int, what we just did was hide the original Foo::Stuff() declaration. With that said, the compilation error makes sense.
The fact that Foo::Stuff() is a pure virtual method is not a necessary condition for this to happen at all. It would have happened with virtual and non-virtual methods as well.
I have the feeling that Java and C# developers may have experienced this when coding artifacts in C++ as, in those languages, this notion of hiding declarations is not available (there’s an alternative consisting in declaring members as private, so subclasses won’t get them visible, but in that case the decision of what is hidden belongs to the coder of the superclass. In C++, the decision is to be taken by the coder of the derived class.
How could my friend overcome this error in order to get the application working as he expected? By including a using declaration in the definition of Bar like the one at line 5 here:
class Bar : public Foo {
public:
// using introduces a name from a base
// class into a derived class scope.
using Foo::DoStuff;
virtualvoid DoStuff(int a)=0;
};
Now the application runs as initially intended.
In quiz 2, the C++ principle we just reviewed applies as well, but if hiding was not what we wanted to do, this issue could turn into something more dangerous because the application will compile anyway and the undesired behavior will have to be discovered at runtime.
Quiz 2
#include<iostream>
class Foo {
public:
virtualvoid DoStuff(char a)=0;
};
class Bar : public Foo {
public:
virtualvoid DoStuff(int a)=0;
};
class Baz : public Bar {
public:
void DoStuff(int a) override
{
std::cout << "Baz::DoStuff(int)";
}
void DoStuff(char a) override
{
std::cout << "Baz::DoStuff(char)";
}
};
int main() {
Baz baz;
Bar *pBar = &baz;
pBar->DoStuff('a');
}
Despite the fact that Foo::DoStuff(char) isn’t visible in line 30, the ‘a’ received as argument is implicitly converted to the int type, producing:
Again, the solution here is based on a using declaration as before:
class Bar : public Foo {
public:
using Foo::DoStuff;
virtualvoid DoStuff(int a)=0;
};
Once declared, we just compile, run and… voilà
As a conclusion, hiding a base class method is neither a bad thing nor something to avoid as long as it’s exactly what you wanted to get.
A little more than a month ago, I logged into my Google Webmaster Tools account and to check if Google had detected any crawl errors or any other problems with my site. Finding everything in good order, I was just about to close the browser tab when I noticed a sidebar link that had somehow escaped my attention in the past – Site performance (it’s under Labs). I clicked it and was appalled to discover that my site was “slower than 68% of sites”.
Naturally, I couldn’t leave it that way. Optimization problems are among my favourites. So I set out to speed up my site as much as possible, and after a month of off-and-on optimization efforts I managed to get the average load time down from 4.6 seconds to 1.5 seconds. In this post I’ll summarize all the performance tricks and techniques I used to achieve that. They are loosely ordered from most widely applicable to most narrow/esoteric.
Here’s how my site performance graph looks now (click to enlarge):
href="http://d2n8lc6c6oknhf.cloudfront.net/wp-content/uploads/2011/01/webmaster-tools-site-performance-graph.png">
href="http://d2n8lc6c6oknhf.cloudfront.net/wp-content/uploads/2011/01/webmaster-tools-site-performance-graph.png">
style=' display: block; margin-right: auto; margin-left: auto;' class="aligncenter size-full wp-image-2262" title="Site performance graph from Google Webmaster Tools" src="http://d2n8lc6c6oknhf.cloudfront.net/wp-content/uploads/2011/01/webmaster-tools-site-performance-graph-small.png" alt="Site performance graph from Google Webmaster Tools" width="480" height="229" />
You will undoubtedly notice that after reaching 1.5 seconds it gradually returns to 2.3. This was a calculated decision on my part, and I’ll discuss it after at the end of this post.
Combine and compress CSS files
Technically there is a number of ways to do this automatically. However, I was too lazy to do it “right”. Instead, I combined the files by hand and edited my theme’s header.php to include the combined CSS file instead of the default style sheet.
Resources
href="http://aciddrop.com/2009/02/02/php-speedy-wp-052-bug-fix/">PHP Speedy WP – automatically combine and compress CSS and JS. Warning: doesn’t play nice with CDNs.
href="http://wordpress.org/extend/plugins/wp-minify/">WP Minify plugin – like PHP Speedy WP, but more actively maintained and up-to-date.
href="http://w-shadow.com/blog/2010/12/14/where-did-that-js-css-come-from/">Where did that CSS/JS come from?
Remove unused JavaScript
There was this one JS file that didn’t seem to actually do anything. After some investigation, I discovered that WP was including it because I had comment threading turned on. Since my theme doesn’t actually support comment threading, I simply disabled it in Settings -> Discussion. This got rid of the .js file.
Resources
href="http://w-shadow.com/blog/2010/12/14/where-did-that-js-css-come-from/">Where did that CSS/JS come from?
href="http://stackoverflow.com/questions/4136738/find-dead-javascript-code">How to find dead JavaScript code
Far-future “Expires” headers allow browsers keep static content – e.g. CSS, JS and images – in their cache and avoid re-downloading the same files unnecessarily. It’s as simple as adding a couple of lines to your .htaccess:
class="wp_syntax">
class="code">
# Far-future "Expires" header for static files
<FilesMatch"\.(ico|jpg|jpeg|png|gif|js|css|swf)$">
ExpiresActiveOnExpiresDefault"access plus 8 weeks"
</FilesMatch>
Disable ETags
Again, just add this to your .htaccess:
class="wp_syntax">
class="code">
# Disable ETagsFileETagnone
Minify the HTML
Smaller page = faster page. I used the WPSCMin plugin for WP Super Cache to strip redundant whitespace from my pages and re-organize tags for better compressibility.
Resources
href="http://lyncd.com/wpscmin/">WPSCMin
href="http://ocaoimh.ie/wp-super-cache/">WP Super Cache
On the one hand, using a Content Delivery Network is a huge overkill for a small(ish) site like mine. On the other, it does improve performance for many visitors, and it helps with Reddit-proofing one’s site. It’s also ridiculously cheap – my CloudFront bill for December was around .30.
There are two ways to get your files into the CloudFront CDN. You can either upload them to Amazon S3 and give CloudFront the bucket name, or you can set up a “custom origin” distribution that makes the CDN automatically pull the required files from your server on an as-needed basis. I went with I went with the second option as the obviously easiest one.
Note, however, that the AWS CloudFront console lacks the ability to create custom origin distributions. You need to use a third-party tool like CloudBerry instead.
href="http://cloudberrylab.com/">CloudBerry Explorer
Enable preload mode in WP-SuperCache
By default, WP-SuperCache caches a post when someone first visits it. So if a post is visited only rarely, it’s cache entry is likely to expire before someone visits it again, and the next visitor will need to wait for the post to be re-generated. With preload on, WP-SuperCache automatically pre-caches all posts. This ensures that even less popular pages are will have a cached version available and load quickly.
Resources
href="http://ocaoimh.ie/preload-cache-wp-super-cache/">Further explanation and discussion of the Preload mode
Convert theme images to CSS sprites
This reduces the number of HTTP requests the browser has to make to render the page. Ideally, there should be only one image that the browser has to load to render all the decorative elements on the page.
Resources
href="http://www.alistapart.com/articles/sprites">A tutorial on CSS sprites
href="http://css-sprit.es/">CSS sprite generator
href="http://spriteme.org/">SpriteMe – a popular choice.
Convert CSS sprites to data: URIs and embed them in the combined CSS file
And this reduces the number of HTTP requests even further. There are ways of automating data URI generation (see the “Resources” section), but I just put my sprites through an online converter and edited the style sheets by hand.
Note that data: URIs don’t work in IE 7 and IE 6, so be sure to provide a fall-back style sheet specifically for those despicable two.
Resources
href="http://en.wikipedia.org/wiki/Data_URI_scheme">data URI scheme on Wikipedia
href="http://websemantics.co.uk/online_tools/image_to_data_uri_convertor/">Image to data URI converter
href="https://github.com/nzakas/cssembed">CSSEmbed – a small utility that automates data URI conversion and embedding in CSS files.
Optimize popular content images
On this site, there are a couple of pages that get a lot more traffic than the rest. By fine-tuning the images used on those pages to load as quickly as possible, I (hopefully) improved the first-visit experience for a significant fraction of this site’s visitors.
In practice, I uploaded the images to Smush-it, then ran the results through PNGCRUSH. For the trickier ones, I spent an hour or so playing with lossy compression options in Photoshop.
AdSense ads are loaded synchronously. This means that when the browser encounters an AdSense ad, it will wait until the ad has completely finished downloading before continuing to load the rest of the page. This can slow down your site considerably.
There is, however,
href="http://iamnoah.github.com/writeCapture/">a hack that lets one load AdSense asynchronously – in parallel with other content. The details are extremely involved, so I’ll just give you an implementation example:
Dire warning: While I believe that the AdSense ToS doesn’t explicitly forbid this technique, I also cannot claim that they allow it. Use at your own risk!
Lets face it, WordPress isn’t exactly thrifty with its markup. For example, it adds a whole slew of META and LINK tags to each page – a Windows Live Writer manifest, a shortlink, a “generator” tag displaying the WordPress version, three different types of feeds, and so on. Each of those tags has a purpose, but in practice only a few will be relevant for your site. You can save a Kb or two by removing the useless ones.
I removed 7(!) useless tags by adding this code to my theme’s functions.php file:
class="wp_syntax">
class="code">
function removeUselessMeta(){
remove_action('wp_head','rsd_link');//EditURI
remove_action('wp_head','wlwmanifest_link');//WLW Manifest
remove_action('wp_head','wp_shortlink_wp_head');//Shortlink//My theme already outputs a general feed autodiscovery tag, so no need for more.//Also disables comments feed autodiscovery (I doubt anyone really uses it).
remove_action('wp_head','feed_links',2);
remove_action('wp_head','feed_links_extra',3);//No, don't tell the whole world what version of WP I'm running.
remove_action('wp_head','wp_generator');//Disable rel='start' and rel='index' link tags. They make no sense on a site that//doesn't contain multi-page/series posts.
remove_action('wp_head','start_post_rel_link');
remove_action('wp_head','index_rel_link');}
add_action('init','removeUselessMeta');
You can trim away some more bytes by removing optional tags and optimizing your layout and CSS so that, for example, common class names are not repeated more often than necessary.
Resources
href="http://perfectionkills.com/optimizing-html/">Optimizing HTML
href="http://stackoverflow.com/questions/3008593/html-include-or-exclude-optional-closing-tags">List of optional closing tags
Cache the FeedBurner counter and convert it to PNG
A minor optimization to be sure, but it saves one DNS query and the PNG version of the feed counter is about half the size of the original GIF. Here’s the PHP script I use to create and display the cached image:
class="wp_syntax">
class="code">
<?php//Configuration$feed_id='wshadowcom';$bg_color='B9CFFF';$fg_color='330000';$cache_duration=3600*12;$cache_filename=$feed_id.'-cached.png';if(!file_exists($cache_filename)||(time()-filemtime($cache_filename)>$cache_duration)){//Retrieve the original badge$image_url=sprintf('http://feeds.feedburner.com/~fc/%s?bg=%s&fg=%s&anim=0',$feed_id,$bg_color,$fg_color);$image=imagecreatefromgif($image_url);//Save as PNGimagepng($image,$cache_filename,9, PNG_NO_FILTER);//Cleanupimagedestroy($image);}//Output the resulting imageheader('Content-type: image/png');header('Content-Length: '.filesize($cache_filename));header('Cache-Control: max-age='.$cache_duration);readfile($cache_filename);?>
Lazy-load avatars
The overwhelming majority of visitors never leave a comment. Chances are, most don’t even scroll down to the comments section. So why waste their time and bandwidth by loading avatars that they’ll never see? A better option is to delay the loading of avatars until the user has scrolled far enough to actually see them.
My implementation of this trick is too large to fit on this page, so I will leave it for a future post.
Resources
href="http://www.quirksmode.org/dom/events/scroll.html">scroll and mouse wheel events
href="http://stackoverflow.com/questions/769701/is-there-a-way-to-detect-when-an-html-element-is-hidden-from-view/769728#769728">How to detect when an element scrolls into view – a starting point.
href="http://www.javascriptkit.com/javatutors/dom2.shtml">Adding elements to the DOM
Disable AdSense (if you can afford it)
Finally, I disabled my AdSense ads and left them off for several days to test the impact they have on the average page load time. Surprise, surprise: the load time went down almost by a whole second. This is the steep 800 ms dip you saw on the performance graph – from ~2.3 seconds to ~1.5. The gradual increase back to 2.3 is me deciding that $XX/day from AdSense is worth the performance hit and re-enabling ads.
style=' display: block; margin-right: auto; margin-left: auto;' class="aligncenter size-full wp-image-2256" title="AdSense OFF vs AdSense ON performance" src="http://d2n8lc6c6oknhf.cloudfront.net/wp-content/uploads/2011/01/adsense-off-on-performance.png" alt="" width="250" height="258" />
I must admit I’m a bit miffed about these results. Consider: a single block of AdSense adds around 800 milliseconds to the page load time. By looking at the graph from Google Webmasters Tools, we can infer that Google sees a site as “fast” if it loads in around 1.5 seconds. So if you use AdSense and want your site to meet that speed criteria, everything else on your page must load in 700 milliseconds or less.
You’d have to do better a job at performance optimization than frickin’ Google did with AdSense.
Further Considerations
Here are a few things I considered but didn’t attempt either because of their tediousness or high costs:
Clean up the theme even further. There’s still a fair bit of redundancy in the markup and CSS.
Get a DNS
href="http://en.wikipedia.org/wiki/Anycast">anycast provider for my domain name.
Switch from Google Analytics to a something that doesn’t use JavaScript (e.g. AWStats).
Experiment with different CDNs.
Set up a
href="http://www.varnish-cache.org/">Varnish cache for WordPress.
Get more points-of-presence around the world. I’ve noticed that with the current setup – one server in USA – the time it takes to download the page HTML alone varies greatly depending on where the client is located.
Posted in Visual Basic on January 29th, 2011 by Admin
The long awaited version of Aspose.Cells for .NET 5.2.2 has been released. It includes support for exporting MS Excel 2007 Table’s styles while generating PDF files from Excel spreadsheets. Also internal modules for reading and writing ODS files are enhanced. The control’s base .htc files to JavaScript files are also upgraded for better productivity. This release includes plenty of new and improved features as listed below Extreme VB
Posted in Visual Basic on January 28th, 2011 by Admin
The long awaited version of Aspose.Words for .NET (9.6.0) has been released. There are impressive 156 issues/features addressed in this release. Text wrapping around shapes is supported quite well now when exporting to PDF, XPS and printing. Also most notably ADDRESSBLOCK and GREETINGLINE fields are now fully functional during Aspose.Words mail merge. Using the new ShapeRenderer class users can convert any shape from a Microsoft Word document into a raster or metafile image or render to a .NET Graphics object to their liking. Aspose.Words can render any document into SWF format. The resulting SWF contains the document pages and an embedded document viewer. Footnotes with custom reference marks are now fully supported in DOC, DOCX, WML, ODT. Partially supported in RTF (only first character of the custom reference mark). The list of new and improved features in this release are listed below. Extreme VB & .Net
The activity is the core of an android application. Each application can have one or more activities.
In this post we are going to explore the activity’s life cycle and understand the event handler of each stage through the activity’s life cycle.
Activities in the system are managed in an activity stack (Last in Last out). When a new activity is launched it becomes on the top of the stack. Any previous activity will be below it and won’t come to the top until the new one exists.
The application on the top of the stack has the highest priority from the operating system. While the activity that is not visible has lower priority even if the a running activity requires more memory, the system can shut down that activity to free memory.
Android runs each activity in a separate process each of which hosts a separate virtual machine. Android saves metadata (state) of each activity so that when a new activity launches so that it can come back to the activity when the user backtracks.
The activity can be in one of four states:
Active: the activity started, is running and is in the foreground.
Paused: the activity is running and visible but another activity (non full sized) is running on the top or a notification is displayed. The user can see the activity but can not interact with it. A paused activity is fully alive (maintains state and member information) but can be killed by the system in low memory situations.
Stopped: the activity is running but invisible because the user has launched another activity that comes to the foreground the activity is alive (maintains state and member information) but can be killed by the system in low memory situations.
Dead: either the activity is not started or it was in pause or stop state and was terminated by the system to free some memory or by asking the user to do so.
The following figure shows the states of the activity and the methods that handle each state
The sequence is as follows:
The activity starts, passes through onCreate(), onStart() the activity is still not visible to the user, onResume() then it comes to the foreground and becomes fully running.
If another activity launches or a notification appears the activity passes through the onPause() method. Then there would be two scenarios:
1.if the system decides to kill your activity due to low memory the activity starts the cycle again from onCreate() method with Bundle savedInstanceState parameter that holds data about the previous state of the activity.
2.If the user resumes the activity by closing the new activity or the notification the activity cycle continues from the onResume() method
When the user is about to close the activity the activity calls onStop() method then onDestroy() method when the system destroys the activity.
But if another activity runs while the current one is was not shut, the activity calles onStop() method and if it is not killed by the system it will call onRestart() method then onStart() mehod and continues the cycle.
onCreate(): will be invoked in three cases:
- the activity runs for the first time and it will be invoked with null Bundle savedInstanceState parameter.
- the activity has been running then stopped by the user or destroyed by the system then it would be invoked with Bundle savedInstanceState that holds the previous state of the activity.
- the activity is running and you set the device to different resources like Portrait vs landscape, then the activity will be recreated.in this method you will create the user interface, bind data to controls and register the event handlers for the controls. Then it is followed by onStart() method.
onStart(): will be invoked when the activity is first launched or brought back to the foreground
it would be followed by onResume() if the activity continues and comes to foreground, or by onStop() if the activity is killed.
onRestart(): is invoked in case the activity has been stopped and is about to be run again. Always followed by onStart() mehod.
onResume(); invoked when the activity is about to come to the foreground and is on the top of the activity stack. It is the place where you can refresh the controls if the activity is using a service that displays some feeds or news. Always followed by onPause() method.
onPause(): is invoked when another activity launches while the current activity is launched or when the system decides to kill the activity. In this method you have to cancel everything you did in onResume() method like Stopping threads, stopping animations or clearing usage of resources(eg the camera).This method is followed by onResume() if the activity returns back to front or by onStop() if the activity is to be invisible.
onStop(): is invoked when a new activity is about to come over the current one or the current one is to be destroyed. Always followed by onResume() if the activity comes back or onDestroy() if the activity is to be killed.
onDestroy():is invoked when the activity is shutting down because the activity called finish() [terminated the activity] or because the system needs memory so it decided to kill the activity.
Killable methods:
There are methods that are “killable” meaning that after theses methods return, the process hosting them can kill the activity without executing any further code (due to lack of memory)
These methods are onPause(), onStop() and onDestroy()
The entire activity life cycle is between the onCreate() where you construct the UI and aquire resources and onDestroy() method where you release all resources.
The visible life time of the activity is between onStart() and onStop(). Between the activity is visible to the user although he may be unable to interact with it. Between the two methods you persist the state of the activity so that if another one comes to the foreground then comes back to the original activity you find the state persisted.
The foreground lifetime is between the onResume() and onPause(). During this time the activity is fully interactive with the user. The activity can go through the resume and pause states many times (if the device sleeps or a new activity launches) .
ModelBaker delivers point and click web development for iPhone and Android with practically no knowledge of coding required. Download the free demo here.