Thursday, 29 November 2012

How to bypass SSL certificate checking in Apache Cordova 2.2 on Android



How to bypass SSL certificate checking in Apache Cordova 2.2 on Android

(or how to override CordovaWebViewClient in versions of Cordova 1.9+)

I came across a strange issue where I was unable to access a secure URL using HTTPS.  At first I thought it was due to the Cordova whitelist since there was an issue with it in Cordova 2.1.  In order to access an external URL you have to whitelist them eg
<access origin="https://www.wikipedia.org" subdomains="true"/>
This didn't help though and even if I allowed all URLS using
<access origin = "*"/>
it still didn't work.  Strangely though it was only one secure URL I couldn't access, not all of them

As it turns out, it was probably to do with the way Cordova assesses valid certificates.  When an Android app is signed and deployed it is deployed in 'production mode' which means that any secure URL accessed must have a valid certificate signed by a certificate authority (CA), so cannot be self-signed.  Something about this particular certificate, though signed by a CA, was being rejected by Cordova, which led me to raise this bug: https://issues.apache.org/jira/browse/CB-1947

Since I'm impatient, I decided to try and bypass the certificate checking.  Searching led me to various solutions, all based on extending CordovaWebViewClient and overriding the onReceivedSslError() method. For example:

public class SSLAcceptingWebViewClient extends CordovaWebViewClient {
    public SSLAcceptingWebViewClient(DroidGap ctx) {
        super(ctx);
    }
    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            handler.proceed();
    }
 
}

This was the easy part.  I then needed to tell Cordova to use my new class, rather than the default one.  This seemed simple as the advice I found on stackoverflow was to set it like this:
this.setWebViewClient(this.appView, new MyWebViewClient(this));
Unfortunately, this method signature no longer existed in Cordova 2.2.  Altering it to
this.appView.setWebViewClient( new SSLAcceptingWebViewClient(this));
compiled fine.  However, it resulted in a NullPointerException in the onPageLoad() method as seen by various others with no resolution.  I couldn't find any solution to this on the web, so I had to dig into the source code for Cordova.  Since it was a NullPointerException something had to be null, and the offending line was
if (!this.appView.useBrowserHistory) {
Since 'this' couldn't be null and useBrowserHistory is a boolean, it could only be appView that was null.  Some messing around finally led me to this solution in my main activity class

public class MyActivity extends DroidGap {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.init();
     
        CordovaWebViewClient webViewClient = new SSLAcceptingWebViewClient(this);
        webViewClient.setWebView(this.appView);
        this.appView.setWebViewClient(webViewClient);
     
        super.loadUrl("file:///android_asset/www/index.html");
    }
}

And it works! I've successfully bypassed the SSL certificate checking!  Obviously this is inherently insecure, so I can't recommend it as a permanent solution.  I'm hoping that the above bug will be resolved in the next version of Cordova and I can switch my bypass solutions off.

If you need to override CordovaWebViewClient, this seems to be the way to do it.  If you know a better way, please do let me know

Tuesday, 20 November 2012

Creating an Android Jelly Bean Daydream from a WebView


One of the new nifty features on Android Jelly Bean 4.2 is the concept of daydreams (basically a screensaver but also displays when docked etc).  I wanted to create one that displayed an HTML page, which makes for prety easy development and this is how

First of all, this assumes you have API 17 (Android 4.2) installed, otherwise you won't have access to the relevant Android class

Android Daydream option


You need to create a new class that extends android.service.dreams.DreamService and override the onAttachedToWindow() method which is what is called when the service starts up.  In here all you really need to do is create a new WebView as normal and attach it.  Example code below

import android.annotation.TargetApi;
import android.service.dreams.DreamService;
import android.webkit.WebView;
@TargetApi(17)
public class MyDreamService extends DreamService {
    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        // Allow user touch
        setInteractive(true);
        // Hide system UI
        setFullscreen(true);
        // Set the dream layout
        WebView webView = new WebView(this);
        setContentView(webView);
        webView.loadUrl("file:///android_asset/www/test.html");
    }
}

The last line is loading my local HTML file but you could load any page here (remember to set the INTERNET permission for external pages though)

The service needs to be declared in the manifest, for example

<service
    android:name=".MyDreamService"
    android:exported="true"
    android:label="@string/short_app_name" >
    <intent-filter>
        <action android:name="android.service.dreams.DreamService" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>

That is pretty much all you need to do! Install your app and try it! The dream setting are under Settings > Display > Daydream

There are various options you can set (eg I set the fullscreen option above) that are documented in the API here: http://developer.android.com/reference/android/service/dreams/DreamService.html

Not a very exciting screenshot but this is my html page displayed as a daydream in the 4.2 emulator
And there you have it, easy! Hope this helps someone

Wednesday, 10 October 2012

Eclipse Appcache Generator - auto-generate HTML5 appcache files



HTML5 Appache

I won't go into a full explanation here (if you want a tutorial the HTML5 Rocks website) but HTML5 appache is a method of caching web content so that, when offline, it can still be accessed

One method of doing this is to add a meta tag to each page specifying an appcache file, which will tell the browser to cache that page. But what if you want to tell the browser to cache everything when the site is first accessed? Well HTML5 has a way of doing that too - you still add the meta tag but also specify the files to be cached in the file. When it is accessed, those files will be cached. This though leaves you with a problem - how do you make sure you locate every file to be cached and add them to the file? This is where this plugin can help

Plugin

The Appcache Eclipse Plugin is a plugin for the Eclipse IDE that will check all your files for your site and add all html, image, css and javascript files to the appcache. Once the plugin is installed, all you need to do is add the click the menu button and add the meta tag to your page(s)

At the moment it will create an appcache file for the folder selected and all subfolders. This will be improved over time to add additional useful features

Download

As this is a plugin, you need to download the Eclipse IDE. Using Eclipse is beyond the scope of these instructions

Often there are 2 methods of installing an Eclipse plugin - direct download or update site. Our update site is coming soon, so direct download of the jar file is the only option for now

Installation

Once you have download the jar file, simple copy it into the plugins folder of Eclipse install folder. The path should be <ECLIPSE HOME> - plugins

Now restart Eclipse if it was already running. The plugin should now be installed

Generate an appcache file

Inside Eclipse, in either the Project Explorer or Navigator, right click on root folder of your website. By default this will be called WebContent. You should see a menu option called Generate Appcache

Clicking this menu option will generate an appcache folder in your web root folder called appcache.appcache. You can rename it to whatever you like, but the rest of the instructions will assume you leave it as appcache.appcache

Link to your pages

On each html page you will need to add an HTML5 appcache argument. This goes in the <html> tag like this:
<html manifest="appcache.appcache">
This is all you need to do except ensure your web server serves the appcache file correctly. There are some good instructions on the HTML5 Rocks site

Enjoy

This should make generating full-website appcache a whole lot easier.  The plugin is open source so if you have any feature requests, or want to contribute, head over to the appcache pages on the website

Sunday, 26 August 2012

Running Jenkins CI on a Raspberry Pi

I've had this idea for some time of running my own Jenkins CI (continuous integration) server for building my mobile apps.  That was exactly what I intended to run on my Raspberry Pi when it arrived.  Now it has arrived, I thought I would share an issue I had so that others with the same problem can also solve it

My Raspberry Pi

My Pi is running Raspbian, which is Debian based, so theoretically installing Jenkins is as simple as running apt-get:
sudo apt-get install jenkins
This certainly installed it ok, but for some reason, it wouldn't start up.  Searching google revealed on possible issue regarding Java versions - specifically that Sun Java currently doesn't run on the Raspberry Pi.  A summary of how to fix that issue is:
sudo update-alternatives --config java
 
then chose OpenJDK followed by a reboot of the Pi.
Jenkins starts up as expected after boot.
However, my installation had already installed OpenJDK, so that wasn't my issue

As it turns out, the issue is a bug in Jenkins which leads Jenkins to attempt to extract itself into a full directory, resulting in a
java.io.IOException: No space left on device
in the logs (/var/log/jenkins/jenkins.log)

This issue was supposedly fixed in Jenkins version 1.443.  However my installation was 1.447, so it is still an issue (I have re-raised the bug as JENKINS-14934).  In the meantime the original bug JENKINS-11366 has a workaround which solved it for me:

Edit /etc/default/jenkins and change the line starting JENKINS_ARGS so that it references JENKINS_HOME instead of /var/run
JENKINS_ARGS="--webroot=$JENKINS_HOME/war --httpPort=$HTTP_PORT --ajp13Port=$AJP_PORT"
Jenkins on my Raspberry Pi

Monday, 13 August 2012

No cursor in Ubuntu linux 11.10

I've had this weird problem lately on Ubuntu 11.10 (64 bit) - I only seem to have a cursor in some windows and never in any of the system windows (desktop, unity bar etc). Well today it was winding me up so I decided to try and fix it

A quick google got me this page: No Cursor in Ubuntu 11.04 with a Legacy Nvidia Card. Not the right version of Ubuntu I know, and I have no idea what video card I have either, as the system info shows it as 'unknown'. But I figured I'd try it anyway

Steps from that page:
1. Open a terminal window 2.
Stop the x server: sudo service gdm stop
3 Uninstall the nouveau driver: sudo apt-get --purge remove xserver-xorg-video-nouveau
4. Reboot the machine

When I got the step 2 though, it said the gdm service wasn't found, so I just did step 3. This unfortunately stopped the cursor moving at all! So I reinstalled the nouveau driver, and now it works! Now idea why!

So for anyone who needs this, my steps were:

1. Open a terminal window
2 Uninstall the nouveau driver: sudo apt-get --purge remove xserver-xorg-video-nouveau
3. Reinstall the nouveau driver: sudo apt-get install xserver-xorg-video-nouveau

And all was well with the world again :)

Monday, 16 July 2012

Apache Cordova (PhoneGap) + processing.js


The problem


I wanted to be able to create cross-platform mobile applications whilst not having to do it in Javascript.  I've never liked Javascript, I'm not really sure why, maybe I don't fully understand it.

The solution


I had a brainwave that I could create a functional Java application using Processing (that I have used a lot and, hopefully, will be contributing author to a book on the subject if it ever gets published), port it to processing.js and deploy that as an Apache Cordova (PhoneGap) based mobile application.  As a short explanation, Apache Cordova is a cross-platform framework for writing and deploying HTML5 apps to most mobile platforms.  Processing is a graphical Java-based library of which processing.js is the Javascript equivalent.  Using both processing.js and Cordova, I should be able to deploy a java-based application into a cross-platform framework and run it as javascript

The code


This is the easiest way to do it (there are other ways involving deploying the procesing code as Javascript, but I have found the initial translation from Java PDE to have minimal performance impact)

This should work with any HTML5-enabled platform as supported by Cordova, though different browsers may have issues.  Either way, I have tried this on Android, but I will keep the instructions generic and only talk about how to integrate PhoneGap with processing.js

1. Create a new Cordova application (see Apache Cordova instructions) as per your phone platform

2. Download the latest processing.js library file - http://processingjs.org/ either by right-clicking and saving, or just copy the .js source into a new file.  Put this file in the same folder as your Cordova HTML file

2. In the HTML file you will need to reference the processing.js library (as well as Cordova) eg
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" charset="utf-8" src="cordova-1.8.0.js"></script>
<script type="text/javascript" src="processing-1.3.6.js"></script>
<body>
</body>
</html>

This tells the page to use these libraries

3. Copy your Processing PDE files into the same folder.  Alternatively, if you aren't writing in Processing itself, you can use javascript.  Basically this follow the quick start guide on the processing.js website:
http://processingjs.org/articles/jsQuickStart.html
http://processingjs.org/articles/p5QuickStart.html

4. If using PDE files, link the HTML page to the files using the <canvas> tag eg
<body>
<div id="processing-canvas">
<canvas id="mygame"
data-processing-sources="mygame.pde"></canvas>
</div>
<body/>

5. That's it. It will work as if by magic

Calling Cordova from Processing


If you also want to be able to call Cordova functions, which are Javascript, from your Processing sketch you need to do a little more work

6. You need to link Processing and javascript

i. Create an interface to hold the Javascript object eg
public interface JavaScript {
}
The instance will be created in Javascript, so hang in there

ii. Add any methods you want to call to the interface.  For example, I want to make the phone vibrate, so I've added
interface JavaScript {
void vibrate();
}

iii. Add an instance variable declaration
private JavaScript javascript;

iv. Add a method to inject the Javascript instance
void bindJavascript(JavaScript javascript) {
this.javascript = javascript;
}

v. Call the instance where needed eg
// defensive programming just in case
if (this.javascript != null) {
this.javascript.vibrate();
}
    At this point none of this code actually DOES anything, we're just setting up the bridge between Processing and javascript

vi. Bind the javascript in a javascript <script> tag in the HTML file
var bound = false;
function bindJavascript() {
var pjs = Processing.getInstanceById('<name of your PDE file without the .pde>');
if (pjs != null) {
pjs.bindJavascript(this);
bound = true;
}
if (!bound) {
setTimeout(bindJavascript, 2000);
}
}
bindJavascript();
At this point you have created the bridge between processing and javascript. Your JavaScript instance variable will be injected by the above javascript code.

vii. Now we need to create an equivalent javascript call for vibrate().  When the javascript.vibrate() is called in your Processing sketch, the processing.js will call the same function on the javascript object.  So we need a javascript vibrate() function to correspond to the interface method we created in Processing ie
function vibrate() {
}

viii. Now all we need to do is call Cordova from that function ie
function vibrate() {
// cordova function
navigator.notification.vibrate(1000);
}

And there we have it, Cordova called from Processing

To add other functions all you to do is:
- add the method to the interface in Processing
- call that method from your sketch
- create a corresponding javascript function
- call Cordova (or any javascript) in that function

Magic

PhoneGap + processing.js = big problems

This is less a 'code solution' than it is a code issue, in that I don't know how to fix it and abandoned the solution.  I will likely go back and attempt to resolve at some point, but for now I just want to tell you about what I'd wanted to create, what the issues were and how it caused my PhoneGap app to be labelled as "sucks!!!!"

As I previously blogged this solution, I figured I should also share these issues

The problem

I wanted to be able to create cross-platform mobile applications whilst not having to do it in Javascript.  I've never liked Javascript, I'm not really sure why, maybe I don't fully understand it.

The solution

I had a brainwave that I could create a functional Java application using Processing (that I have used a lot and, hopefully, will be contributing author to a book on the subject if it ever gets published), port it to processing.js and deploy that as an Apache Cordova (PhoneGap) based mobile application.  As a short explanation, Apache Cordova is a cross-platform framework for writing and deploying HTML5 apps to most mobile platforms.  Processing is a graphical Java-based library of which processing.js is the Javascript equivalent.  Using both processing.js and Cordova, I should be able to deploy a java-based application into a cross-platform framework and run it as javascript Ideal. I thought

The issue(s)

Porting the Java-based Processing application to processing.js wasn't as easy as it appeared due to limitations/differences between Java and Javascript (such as variables and methods being public). I also needed to rewrite some code due to limitations with processing.js (such as there being no enum support). However, after some trial and error I was able to get it running in a desktop browser, and it all seemed good

I managed to integrate the Java source with Javascript, so that at runtime the UI could call Javascript, and therefore Cordova, and initiate phone-specific functions.  One example being the phone's vibrate facility.  It was looking good

A BIG issue

Or at least it looked good to me.  I'd tested it on 2 phones, an HTC Sensation XE running Android 2.3 (Gingerbread) and a Samsung Galaxy Nexus running Android 4.0 (Ice-Cream Sandwich).  Unfortunately it didn't look good to other people 'in the wild'.  I started receiving Google Play reviews that my app "Sucks!!!!" because it either displayed a blank screen, or the buttons weren't clickable etc.  I was confused, maybe the users didn't realise they needed to click 'Start' I thought.  But the bad reviews rolled in

As I had limited devices, and resources, I posted on facebook asking my friends to install the app and let me know if they found any issues.  Someone did (thanks Che!). The app functioned ok for a bit, then seemed to freeze so they couldn't press any of the buttons.  Eventually, I did manage to reproduce this on one my phones - at random places the app would appear to freeze, though I could tell by the vibrate I'd added that it was still functioning, just the UI wasn't updating

I has a sad :(

As I was receiving poor reviews, I wanted to fix this FAST.  So I quickly reverted to a native Android app and redistributed it to Google Play.  The poor reviews have now stopped, but I haven't fixed the underlying issue.  Searching Google hasn't revealed anything, so I'm left with debugging this myself

For anyone interested in progress, my app can be seen on Google Play, bad reviews and all :(

I have a request for anyone reading this:  have you experienced this same problem? If you have, comment below or bung me an email on antony@weblore.eu. I'd be interested in your perspective

Monday, 25 June 2012

The PhoneGap Viewport size is too small on Android?

I spent quite some time today trying to figure out why, when I load an external HTML file into my PhoneGap (Apache Cordova) app, the viewport only filled part of the screen



Notice the big space at the bottom and the side border. I couldn't figure it out, so I started searching on Google:

Googled solution 1 - Set the viewport meta tag


Lots of the solutions I found involved setting the meta tag for the viewport, eg
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0/>

However, this seemed to have absolutely no effect whatsoever.  I tried many variations of this

Googled solution 2 - Set the page to use all the space


Other solutions involved setting CSS so that the page filled the screen, eg

html, body {
    width: 100%;
    height: 100%;
    padding: 0;
    margin: 0;
}

This also had absolutely no effect.  I was getting confused by now

Googled solution 3 - Set Android properties


I found a couple of solutions that involved setting properties in the Android Activity, eg
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN |
                WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

This had the nice effect of making my app fullscreen, but still with a small viewport.  By this point it was starting to wind me up and I had to eat something to calm myself down

My solution


After hacking around a lot (loading internal pages, using iframes etc), I decided that maybe it was because I was using a low version of the android target.  I was hoping to target pretty much every device by setting the target to 3 (Android 1.5) eg
<uses-sdk android:minSdkVersion="3" />

Bizarrely, changing this to 7 (Android 2.1) fixed the problem.  I'm guessing this is due to the low screen resolutions of the early devices.  But anyway, problem solved, and it only took me a few hours :@

Hopefully this will help someone in the future and save them a few hours of pain


Tuesday, 22 May 2012

How I brute-forced my own keystore password


How I brute-forced my own keystore password


If, like me, you've been in the unfortunate siutation where you have forgotten your own keystore (or certificate key) password then help may be at hand. After some fruitless searching I decide to write my own piece of software to brute force my keystore certificate.  As I am/have been a Java programmer I decided to write it in the language I knew best, and this is how I did it.

I have made the source code available for anyone who wants it

Loading the keystore


The Java API already has code for loading a keystore, java.security.KeyStore.  The keystore needs to be placed on the classpath (I just stuck it in the root on my Eclipse project)

// Load the keystore in the user's home directory
File file = new File(keystoreName);
is = new FileInputStream(file);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(is, keystorePassword.toCharArray());
return keystore;

The above code simply attempts to load a keystore with the given keystoreName (filename) and keystorePassword.  If the password is incorrect an exception will be thrown.  As I was in a hacky mood, I went with catching the exception and returning null if the password was at fault.  The full method looks like:

public KeyStore loadKeystore(String keystoreName, String keystorePassword) {
FileInputStream is = null;
try {
// Load the keystore in the user's home directory
File file = new File(keystoreName);
is = new FileInputStream(file);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(is, keystorePassword.toCharArray());
return keystore;
} catch (java.security.cert.CertificateException e) {
throw new KeystoreException(e);
} catch (NoSuchAlgorithmException e) {
throw new KeystoreException(e);
} catch (FileNotFoundException e) {
// Keystore does not exist
throw new KeystoreException(e);
} catch (KeyStoreException e) {
throw new KeystoreException(e);
} catch (IOException e) {
if (e.getCause().getMessage().contains("Password verification failed")) {
return null;
}
throw new KeystoreException(e);
} finally {
try {
is.close();
} catch (IOException e) {
// at least we tried
e.printStackTrace();
}
}
}

To check a keystore password this just needs to be called a LOT of times with different configurations of password.  However we will come back to that shortly as, on this occasion, I knew my keystore password but not the password for the certificate it contained.

Loading a keystore key

So I now needed to load the certificate.  Java also has an API for this in the java.security.Key class.  In a similar vein to before, we can wrap this call so it returns null if unsuccessful

public Key loadKey(KeyStore keystore, String keyAlias, String password) {
try {
// get my private key
Key key = keystore.getKey(keyAlias, password.toCharArray());
return key;
} catch (NoSuchAlgorithmException e) {
// let it return null
} catch (KeyStoreException e) {
// let it return null
} catch (UnrecoverableKeyException e) {
// let it return null
}
return null;
}

Assuming we could load the keystore, we can use that to try and load the key.  Either way, we now have methods for attempting to load a keystore of key.  Null will be returned if we are unsuccessful

Brute forcing


Next we need to be able to call one of these methods but alter the password attempt each time.  Firstly I defined the possible characters it might comprise:

// possible characters used
char[] charset = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z' };

You can add, or take away, any that you want.  We will also need to store the current guess so we can increment it on the next iteration. I've stored them like this

private char[] cs; // Character Set
private char[] cg; // Current Guess
public BruteForce(char[] characterSet, int guessLength) {
cs = characterSet;
cg = new char[guessLength];
Arrays.fill(cg, cs[0]);
}

Next we need to increment the current guess each time so we are trying a different password, making sure we try every combination

protected void increment() {
int index = cg.length - 1;
while (index >= 0) {
if (cg[index] == cs[cs.length - 1]) {
if (index == 0) {
cg = new char[cg.length + 1];
Arrays.fill(cg, cs[0]);
break;
} else {
cg[index] = cs[0];
index--;
}
} else {
cg[index] = cs[Arrays.binarySearch(cs, cg[index]) + 1];
break;
}
}
}

The above method increments the currentGuess array each time it is called, making it 1 larger if necessary.  This means we try every combination of every character in the array eg
aa
ab
ac
ad

and so on

The current guess can then be used to attempt to load the keystore, or key.  If null is returned the password was wrong and the next guess can be attempted eg

public synchronized String getNextAttempt() {
increment();
return String.valueOf(cg);
}
String attempt = attack.getNextAttempt();
boolean found = source.attempt(attempt);

Notice the use of the synchronized key word - I added this as I ran it in a multithreaded environment.  Making the method synchronized means that the incrementing and getting the next guess are atomic, so no other thread can access the next guess at the same time.  This ensures that none are missed

Putting this all together I managed to brute force a 7 character password in about 5 hours (using 100 threads on an i7 PC)

I built a mini-framework around it that I've put on sourceforge.  I also added an heuristic brute force attack (using keywords I might use in a password) until I fouind that it wasn't any of those, leaving me to have to brute force it. Feel free to use it.  If anyone wants to take on developing it further let me know and I'll give you access to the repository


Thursday, 10 May 2012

Installing and using mobilize.js to transform a desktop site to a mobile site


Installing and using mobilize.js to transform a desktop site to a mobile site

mobilize.js offers a neat and simple method of creating a mobile optimised website with very little change to the main desktop site. With a few lines of javascript and some css you can create a mobile optimised site without having to maintain 2 different sets of content.

However the instructions on the official site aren't the best. So with some digging I managed to transform -

From this (Firefox on my laptop):



To this (Android browser on my Samsung Galaxy Nexus):



with no html changes other than adding some <script> tags to the <head> element.  Plus automatic browser detection to display either site depending on the browser used - mobile, or desktop

Here are some step-by-step instructions on getting it working.

Why would you want to?

So going back to the beginning, these were my requirements:  I wanted to create a mobile optimised site but, as I already had a main desktop site, I didn't really want to maintain 2 sites and duplicate the content.  I also needed mobile browser detection so that the correctly optimised site would be served.

The problem, however, is that my site was static (ie was all html based, not dynamic in terms of PHP or Java etc) so I couldn't just create a new set of basic pages and pull in my content.  A google search led me to mobilize.js (http://mobilizejs.com/). This looked ideal. Although my site wasn't built with WordPress or Sphinx (for which mobilize have plugins) it offered a method for using it with custom web sites. Ideal I thought

As it turns out however, it wasn't as ideal as I thought because the official documentation is quite confusing. A google search didn't help as everyone else was confused too.  So I did what any geek would do, I downloaded the source from github and set to work.

Firstly, I discovered a couple of things that are not very clear in the official documentation:

i. The official documentation pretty much expects that you will use the official cloud hosted solution.  Most of the instructions assume you know this and want to do this.  Therefore there is very little documentation on installing it, only on integrating it into your site
ii. If you don't want to use the official cloud hosted solution because you want to host it yourself, you are more-or-less on your own.  There are a few instructions (http://cdn.mobilizejs.com/docs/trunk/manual/hosting.html) but these are not comprehensive enough to get you started

So, if you're trying to use mobilize.js and are wondering where the 'download' button is, the following should help you

How-To

1. Cloud hosting

mobilize.js is installed on a server that mobilize provide.  If you are happy using their cloud hosted service (which is free) then you can skip step 2 and move onto step 3
However, if, like me, you don't want to use someone else's hosted solution and would rather host it yourself then step 2 will tell you how to do that

2. Self-hosting

As mobilize.js is a javascript-based solution you don't need a special server to host it. I am hosting it on a standard Apache server along with my web content. The work of transforming the site is done on the client using javascript, so there are no specific requirements for the server other than the ability to host javascript (which you likely have anyway if you are serving a website).  This was a plus for me as it meant I didn't have to pay any extra for serving it

As mobilize don't provide a distribution as such, it has to be compiled from source, which they provide on github.  As I already had to do these steps (after I'd worked it out!),  I have added the mobilize.js library for download from my google drive here

If you just want to download the library, do that, extract it then go to step d.  Otherwise steps a-c show you how I created the library from the mobilize.js source

a. Download the source

First thing you need to do is download the source from the official github repository (you can just download the .zip if you don't have a git client)

b. extract source if necessary

If you downloaded the zip file, extract the zip file if necessary.  You will also need Python installed on your machine. My Ubuntu machine already had it installed, but you may need to install it: http://www.python.org/getit/

c. Build the mobilize.js library

Create the library using the release.py python script in the folder you extracted from the zip file, setting the localdeploy option (if neither of these work, hopefully you can work out the exact command, just make sure you run the right script with the localdeploy option set to true):
on linux: ./release.py localdeploy=true
on windows: python release.py localdeploy.true
This will create a folder in the <extracted zip folder>/releases folder called (oddly) 'localdeploy=true'.  This is your mobilize.js library. I suggest renaming it to something sensible! I've called mine 'mobilize'

d. Copy the library to your source code

Copy the mobilise.js library to your website source.  Mine is under 'js'



e. Link to the library

You will need to tell the library where the source is located by setting a baseURL option using javascript
mobilize.cdnOptions.baseURL="http://localhost/js/mobilize";
 When you deploy this, the URL will need to be the path to your website, so you will have to change it.  However it needs to be placed on each page, so you would have to change it on every page. So I've put mine in a separate javascript file (called mobilize.post.call.js) so I only have to change it in one place

 Then I have placed a reference to that file on my html page in the <head> tag, ie:
<head>
<script type="text/javascript" src="/js/mobilize.post.call.js"></script>
</head>
 Now I only have 1 place where I need to change between localhost and my final URL

You are now ready to start integrating your hosted mobilize.js code into your website.  The following applies whether you are hosting it yourself or not, there is no difference from here onwards other than the URLs used

3. Minimum integration steps

a. Add the mobilize.js script tag

Add a script tag to each page to tell it to use mobilize.js
For self-hosting:
<script type="text/javascript" src="/js/mobilize/js/mobilize.core.min.js"></script> 
               (or wherever you placed it)

For mobilize hosting:
<script type="text/javascript" src="http://cdn.mobilizejs.com/releases/0.1/js/mobilize.core.min.js"></script>

b. Tell mobilize how to construct the mobile page

Create a javascript file to tell mobilize how to construct the mobile page.  I have called mine mobilize.weblore.js

Either way, the basic structure is something along the lines of:
mobilize.extend(mobilize, {
constructBody : function() {
// Map content elements to jQuery Mobile
// div[data-role=content] here
// Map different elements to jQuery Mobile theme
this.constructHeader();
this.constructContent();
this.constructFooter();
},
constructHeader : function() {
var mobileHeader = $("#mobile-body div[data-role=header]");
},
/**
* Move content area from web site to mobile site
*/
constructContent : function() {
var mobileContent = $("#mobile-body div[data-role=content]");
},
constructFooter : function() {
var mobileFooter = $("#mobile-body div[data-role=footer]");
}
});

This tells mobilize how to construct a mobile page using jquery mobile. The default template provided my mobilize looks like:
<div id="mobile-body">
<!-- http://jquerymobile.com/demos/1.0a3/#docs/pages/docs-pages.html -->
<div data-role="page">
<div data-role="header"></div>
<div data-role="content"></div>
<div data-role="footer"></div>
</div>
</div>
So the javascript above maps the divs from the template. You can override the template with a local one using the mobilize.cdnOptions.template option, but I have just gone with the default

We will come back to how to utilise the above template and javascript to display the site

c. Tell mobilize where the construction script is

Create a mobilizeCustomInit() javascript function to tell mobilize where your javascript file is that constructs the page (from step b).  You could place this in a <script> tag on each page, but using a separate .js file means you can reuse it on each page and just link it with a <script> call to that file. I have called mine mobilize.pre.call.js
function mobilizeCustomInit() {
mobilize.cdnOptions.javascriptBundles.push("http://<your website>/js/mobilize.weblore.js");
mobilize.cdnOptions.cssBundles.push("http://<your website>/mobile.css");
}
Simply replace the <your website> with the URL of your site (and change the path if necessary depending on where you put the .js file)

You will also see that I have added a custom .css file here. As mobilize removes any .css from the original page, you need to specify your .css here, even if it is the same as the desktop site css file. I have created a mobile-specific one I've called mobile.css

d. Link javascript and HTML

Link the above javascript to the html pages. If you have used separate files, it will look something like this:
<!-- the mobilizeCustomInit() from step c -->
<script type="text/javascript" src="/js/mobilize.pre.call.js"></script>
<!-- the call to mobilize from step a -->
<script type="text/javascript" src="/js/mobilize/js/mobilize.core.min.js"></script>
<!-- the call to set the baseURL if self-hosting -->
<script type="text/javascript" src="/js/mobilize.post.call.js"></script>

2 things to note here:
- they must be in this order
- mobilize.post.call.js only applies if you are self-hosting

e. Check it works

From this point you can try your new mobile page. To test locally you need a local mobile browser. One way is to use firefox and the User Agent Switcher plugin (http://chrispederick.com/work/user-agent-switcher/). You can then set firefox to act like an iPhone browser. mobilize will detect the user agent and display the mobile site instead of the desktop site

By default the page rendered displays nothing in the <body> tag, so you will currently have a blank page

f. Add html elements to the mobile page

Now all you need to do is use jquery mobile to set elements from your pages into the structure using the script in b. This will enable the content you want available on the mobile site

jquery selectors (http://www.w3schools.com/jquery/jquery_ref_selectors.asp) are used to select elements from the html page and display them on the mobile page

For example:
constructHeader : function() {
// heading
var heading = $('#Top');
// get a handle on the header
var mobileHeader = $("#mobile-body div[data-role=header]");
// Set heading
mobileHeader.append(heading);
},
takes the <div id="top"> element from my html page and adds it to the top section of the mobile page (as per the template in b)

You just need to keep doing this for any elements you want displayed, adding them to the section you require, in the order you require

This uses standard jquery, so any help you need in obtaining elements to display can be found on the jquery pages (you don't need to add jquery to your site, it is pulled in by mobilize.js).  You can just style the existing elements differently using a different css if required

It works!

Once you've followed these steps, you should now have an operational mobile site that automatically detects mobile browsers and displays the relevant site.  Once I had figured out how (which I've now shared with you) it was very easy

Now I have a dekstop site and a mobile site, both using the same content. So any updates I make are immediately available on both sites. Pretty neat

I have hopefully made this as easy to follow as possible. Both jquery and mobilize have additional features that I haven't mentioned, but this should at least get you going with a working mobile site transformation.  Any error or comments etc, just let me know

Tuesday, 17 April 2012

How to add AdWhirl to an Android app (part 2)

After my earlier post, I found another way of doing this which relies on setting the ad placement in a layout.  This also is pretty easy

As I was getting poor results from AdMob I decided to add AddWhirl to my android app so I could use multiple ad providers.  Little did I know that the documentation for AdWhirl was going to be so bad!  A google search didn't help much, just lots of other people wanting to do the same and getting stuck or confused.  The official instructions didn't help much (https://www.adwhirl.com/doc/android/AdWhirlAndroidSDKSetup.html) - as soon as I had started I got a compile error because of something ommitted from the instructions.

So I set out to solve the problem on my own.

1. Set your app up on your chosen Ad provider website (or multiple, but for this explanation I'll go with Admob).  You'll need the ID

2. Set your app up on the AdWhirl website.  Add the ad provider (in this case AdMob) and enter the ID.  Switch it on!  You'll need the AdWhirl ID later, but not the AdMob one as AdWhirl hadles that for you

3. Download the AdMob (or whoever) SDK and add it to the libs folder of your Android app

4. Do the same for AdWhirl

5. Add the jars to the build path of your app (I'm using Eclipse so right click > properties > Java build path > Add Jars

6. Create a layout that includes the following element (or add to an existing layout)

    <com.adwhirl.AdWhirlLayout
        android:id="@+id/adwhirl_layout"
        android:layout_width="fill_parent"
        android:layout_height="match_parent" />

7. Alter your activity to implement AdWhirlInterface.  This will cause a compile error as there is method to implement.  I have no idea what it is for, so I added this

@Override
public void adWhirlGeneric() {
// TODO Auto-generated method stub
}

8. If it doesn't already, you need to set the activity to use the layout.  You do this in the onCreate method

/*
* (non-Javadoc)
*
* @see android.app.Activity#onCreate(android.os.Bundle)
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.<name of layout>);
}

9. Then you need to load the app, which will be placed in the relevant place in the layout


AdWhirlManager.setConfigExpireTimeout(1000 * 60 * 5);
AdWhirlTargeting.setKeywords("some keywords delimited by strings");
// you can add other criteria here such as gender or age
AdWhirlTargeting.setTestMode(true); // change to false before deployment
// this is the layout element we added earlier
AdWhirlLayout adWhirlLayout = (AdWhirlLayout) findViewById(R.id.adwhirl_layout);
adWhirlLayout.setAdWhirlInterface(this);

You can just stick this after the setContentView() in the onCreate() method

7. In your AndroidManifest.xml add any permissions requored by the ad vendor (eg AdMob).  AdMob requires:

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

8. Also in AndroidManifest.xml add anything required by the ad provider you are using (so in my case AdMob).

        <activity
            android:name="com.google.ads.AdActivity"
            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" >
        </activity>

This is necessary because AdWhirl simply mediates the providers, you still need to set the provider-specific activity etc

9. Add your AdWhirl ID to the activity you are loading the ad in (or you cna add it at application level) in AndroidManifest.xml
For example
<activity android:name="your.app.Activity" android:label="@string/app_name"
android:theme="@style/themeBase"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:value="<your adwhirl key" android:name="ADWHIRL_KEY"/>
</activity>

9. Try it (Note that it seems to take AdWhirl some time to update settings so if you get no ads, check everything is set right, then wait a few minutes)

Yes that is it.  The above displays ads from AdMob using AdWhirl in my app.  It took me ages to work out, so hopefully this will help some others out there!

How to add AdWhirl to an Android app (with decent instructions!)

As I was getting poor results from AdMob I decided to add AddWhirl to my android app so I could use multiple ad providers.  Little did I know that the documentation for AdWhirl was going to be so bad!

A google search didn't help much, just lots of other people wanting to do the same and getting stuck or confused.  The official instructions didn't help much (https://www.adwhirl.com/doc/android/AdWhirlAndroidSDKSetup.html) - as soon as I had started I got a compile error because of something ommitted from the instructions.

So I set out to solve the problem on my own.  In the end the solution was pretty easy:

1. Set your app up on your chosen Ad provider website (or multiple, but for this explanation I'll go with Admob).  You'll need the ID

2. Set your app up on the AdWhirl website.  Add the ad provider (in this case AdMob) and enter the ID.  Switch it on!  You'll need the AdWhirl ID later, but not the AdMob one as AdWhirl handles that for you

3. Download the AdMob (or whoever) SDK and add it to the libs folder of your Android app

4. Do the same for AdWhirl

5. Add the jars to the build path of your app (I'm using Eclipse so right click > properties > Java build path > Add Jars

6. Add the following code to your activity

AdWhirlManager.setConfigExpireTimeout(1000 * 60 * 5);
AdWhirlTargeting
.setKeywords("some keywords delimited by spaces");
// you can add other stuff here to target your ads, age, gender etc
AdWhirlTargeting.setTestMode(true); // set to false before deploying
AdWhirlLayout adWhirlLayout = new AdWhirlLayout(this, <your AdWhirl ID string>);
//adWhirlLayout.setGravity(gravity); // I haven't set this, but you might want to
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
getWindow().addContentView(adWhirlLayout, layoutParams);

Note that you don't need your activity to implement AdWhirlInterface, it works without it

7. In your AndroidManifest.xml add any permissions requored by the ad vendor (eg AdMob).  AdMob requires:

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

8. Also in AndroidManifest.xml add anything required by the ad provider you are using (so in my case AdMob).

        <activity
            android:name="com.google.ads.AdActivity"
            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" >
        </activity>

This is necessary because AdWhirl simply mediates the providers, you still need to set the provider-specific activity etc

9. Try it (Note that it seems to take AdWhirl some time to update settings so if you get no ads, check everything is set right, then wait a few minutes)

Yes that is it.  The above displays ads from AdMob using AdWhirl in my app.  It took me ages to work out, so hopefully this will help some others out there!

Thursday, 29 March 2012

Removing default apps from a rooted android phone

I recently needed to remove some of those rubbish default apps you get on android phones. You know the ones, the ones that come with the phone but you can't uninstall.  It is especially annoying if you don't ever want to use them and they are taking up loads of space on your phone because you have an Android version prior to Froyo (2.2) so apps can't be installed to the SD card

One of my phones (a Sony Ericsson Xperia X8) is on Android 2.1 and I want it stay on that OS, but it was running out of memory.  I already rooted it some time back, and a quick google search came up with this great guide: http://androidadvices.com/remove-default-applications-rooted-android-phones/

I have one thing to add though, which is why I am writing this.  Once I'd uninstalled FourSquare, Facebook, Stopwatch, Planet3 and loads of other stuff I didn't want, I was surprised that they still showed as installed.  So I checked again with the article above, nope, definitely gone.  But they still show in my apps and the memory is still full.  Here is the solution:  Go into the app manager and 'uninstall updates'.  It will fail to uninstall (because the app is already gone) but now they don't display and the memory is freed.  Hurrah!

Monday, 19 March 2012

Using RoboGuice with BlackBerry Android Runtime

I have recently been porting Android application to run on the new BlackBerry Tablet OS 2.0 which includes an Android 2.3 runtime.  However, one of my apps kept failing the BlackBerry packager checks because:

3 uses-package com.google.android.maps
However my app wasn't using it, and a search of my code didn't reveal any uses of it either.
It turns out that, because I was using RoboGuice, which has a MapActivity, the BlackBerry packager was picking that up, even though I wasn't using it.

The only solution I could think of was to unpack the roboguice jar, delete the MapActivity class, then repackage it.  Then the BlackBerry packager was happy!

Hope this helps someone

Runtime Bean Wiring

Sproing provides an easy method of wiring an object into Spring at runtime when that object hasn't been created by Spring but needs access to Spring beans.

The SpringWirer class provides a static method that, given an object, will wire it into the existing application context and set the spring beans needed

public class Jedi {
  private Force force;
  public Jedi() {
    // wire this object up
    SpringWirer.wireBean(this);
    force.push();
  }
  // set the Force spring bean
  public void setForce(Force force) {
    this.force = force;
  }

In this example, the Force object can be accessed because it is a bean defined in Spring. At runtime, the SpringWirer.wireBean(this) call will wire the object into Spring, setting the Force object using the setter method

Sproing version 0.3.2 is available now from Sith Open Source

Sproing: Arbitrary Spring loading

Sometimes is is desirable to load spring when an arbitrary (ie, not containing a main() method) object is created. Sproing provides this for when another application is creating java objects in order to provide a route into your code (for example FitNesse, The Grinder etc) that you need to wire into spring. Sproing does this by loading any application context files you specify and then wiring the object into it, allowing you to inject beans at runtime.

Spring beans are weired using the AutowireCapableBeanFactory.AUTOWIRE_BY_NAME strategy, so your object needs to have setter methods with the same names as the beans you want to wire up. You need to create a subclass of ApplicationWirer and implement the getPaths() method to return the paths of the spring application context files you want to wire up

For example:
  public class YourAppWirer extends ApplicationWirer {
    public String[] getPaths() {
      return new String[] {
        "classpath:someApplicationContext.xml",
        "classpath:applicationContext.xml"};
    }
  } 


To wire up your object, all you need do is create a new instance of your overridden ApplicationWirer class in a constructor on your object, and call the wire() method

For example, using YourAppWirer in the above example:

  public class JediMindTrick {
    public JediMindTrick() {
      new YourAppWirer().wire(this);
    }
  } 

Provided you have defined public setter methods for any spring dependencies your object needs, and called them the same names as described above, spring will inject these at runtime. You can then write your object methods as normal

Sproing version 0.3.1alpha is available now from Sith Open Source

Creating a Spring Application

Creating a standalone (ie non-web) application can seem a little confusing to some. Sproing makes this easy by extending a Sproing class and implementing a method, and that's it!

All you need do is have your main (the class with the main() method that starts the application) extend ApplicationWirer and implement the getPaths() method that returns the path(s) to your application context xml files. Then a single call to the wire() method does the rest
import uk.org.sith.sproing.spring.ApplicationWirer;
public class Main extends ApplicationWirer {
  public static void main(String[] args) {
    Main main = new Main();
    main.wire(main);
  }
  public String[] getPaths() {
    return new String[] {"applicationContext.xml"};
  }

This code will start your application and load the applicationContext.xml file into spring with all the spring beans defined. Easy!

Sproing version 0.3.1alpha is available now from Sith Open Source

Sproing: Spring static ApplicationContext access

It is often useful to gain access to the ApplicationContext object in order to locate existing beans. Sproing provides a ApplicationContextProvider class that can be used anywhere in a spring application to access the application context like so:

 ApplicationContext ctx = ApplicationContextProvider.getApplicationContext(); 

If you have used Sproing to start the application and/or load Spring, you will automatically have access to this class. If you want to use this feature of Sproing in a web application, all you need to do is declare the ApplicationContextProvider as a spring bean in your spring xml file ie

 <bean id="applicationContextProvider" class="uk.org.sith.sproing.spring.ApplicationContextProvider"/>

Sproing version 0.3.1alpha is available now from Sith Open Source

Sproing: FitNesse-Spring integration

Sproing wires up FitNesse fixtures into Spring by loading any application context files you specify and then wiring the fixture into it, allowing you to inject beans into the fixture at runtime.

The fixture needs to implement SpringWirableFixture and extend your chosen FitNesse fixture. It is wired
using the AutowireCapableBeanFactory.AUTOWIRE_BY_NAME strategy - it needs to do this to work properly with
FitNesse, so your fixtures need to have setter methods with the same names as the beans you want to wire up

You need to create a subclass of AbstractFixtureWirer and implement the getPaths() method to return the paths of the spring application context files you want to wire up

For example:
   public class YourAppFixtureWirer extends AbstractFixtureWirer {

      public String[] getPaths() {

         return new String[] {
                  "classpath:fitnesseApplicationContext.xml",
                  "classpath:applicationContext.xml"};
      }

   }


To wire up your fixture, all you need do is create a default constructor (or setUp() method if using a fixture that
has one) and create a new instance of your overridden {@link AbstractFixtureWirer} class

For example, using YourAppFixtureWirer in the above example:


   public class TestFixture extends ColumnFixture implements SpringWirableFixture {

      public TestFixture() {
         new YourAppFixtureWirer().wire(this);
      }
   
   }


FitNesse will call the default constructor, wiring up your fixture with the bean factory. Provided you have defined
public setter methods for any spring dependencies your fixture needs, and called them the same names as described
above, spring will inject these at runtime. You can then write your fixture methods as normal

It can be downloaded from sourceforge