Archive for Tech

Ubuntu and Windows 7 dual-boot on the Lenovo x120e

So, I decided to get a Lenovo ThinkPad x120e for development purposes. The Chromebook I got from Google I/O made me appreciate the value of a light laptop with massive battery life, and the experience of installing Ubuntu on it made me think that I could actually start using something like that for development purposes. Of course, the disadvantages of the Chromebook are that it’s not necessarily easy to install different OSes on it, and the stupid, stupid touchpad. The SSD can be upgraded, so that’s not a big deal.

–RANT–
One of the reasons I got into Android way back in the G1 days was that I wanted a decent smartphone, but having played around with iPhones, I really liked physical keyboards as well, so along comes the G1, and I was instantly sold. The trend towards buttonless trackpads is terrible for the same reasons soft keyboards aren’t the end all, be all. A soft keyboard will NEVER be as comfortable as a real one for extended typing sessions, and buttonless trackpads will ALWAYS misinterpret your touches a certain percent of the time.
–END RANT–

Anyway, the x120e comes with a few disadvantages too:
1) It’s default Windows 7 installation comes with a ton of bloatware, and
2) For something that’s supposed to have a ton of battery life, an HDD seems silly.

So of course I ripped the HDD out, and replaced it with a Samsung 470 series 128gb SSD. Works great.

Of course, the next step was Ubuntu. There’s a number of pages detailing what you need to do to get Ubuntu running on the x120e, and I’ve already posted about one of the pitfalls I encountered, so ’nuff said for the mo.

Eventually, I decided I wanted to dual-boot Windows 7 though, since Ubuntu is great, but it’s not as well supported as it could be, software-wise (GIMP is just bad) and WINE isn’t perfect. Here’s where I ran into problems.

I’d reserved some space, knowing I was going to install Windows 7 eventually, but when the time came to do it, Windows refused to install, saying that it couldn’t be installed to a GPT type disk or something. Googling it didn’t help much, so I decided to backup the Ubuntu installation using dd, nuke everything, and try again. I repartitioned the disk using the Windows 7 installer, and installed.

Windows installed fine at that point, but then the Ubuntu installer couldn’t see the Windows install, and tole me the disk was blank. Googling around led me to some people saying that if you use GParted to create an NTFS partition, everything works, so I did that, and it did. I then re-installed Windows, and when it came time to install Ubuntu, it saw the Windows install, and everything was hunky-dory.

Until I rebooted, and I never got the GRUB menu. Well huh. I tried installing EasyBCD, but then when I tried going to Ubuntu, all I got was a GRUB prompt, and nothing else.

The solution to that eventually wound up being to take the hard drive out, put it in a USB enclosure, hook it up to another Ubuntu machine, and use sudo grub-install to reinstall GRUB.

The full process:
1) Hook the drive up to Ubuntu machine #2
2) Use GParted to figure out which device the drive was. (In this case, /dev/sdc. The Ubuntu partition was /dev/sdc5)
3) sudo mount /dev/sdc5 /mnt
4) sudo grub-install –root-directory=/mnt /dev/sdc

On reboot, I got a bunch of scary “Error, file not found:” messages that went away after awhile. Eventually, I got to an actual command prompt, typed sudo grub-update, and after that, everything was cool.

Side note:

Because I was restoring from a disk image, and because the drive configuration had changed in the meantime, I had to go into /etc/fstab, and change the UUIDs there to the appropriate ones for the new configuration. You can find the UUIDs for your partitions using GParted.

There were a ton more dead ends and missteps that I’ve left out, but those were the major pain points. At the moment,the only problem is that if you go from Windows 7 to Ubuntu with a warm boot, Ubuntu freezes, but cold booting works fine.

Comments off

Ubuntu on the Thinkpad x120e

To paraphrase JFK, we do not choose to install Ubuntu, or any other form of Linux because it is easy, we install it because it is hard.

That said, it’s not as hard as it could be, unless you install the wrong version. First, I installed the 32-bit version, which was what was recommended on the Ubuntu site. Everything went pretty well until I tried running Minecraft. I got as far as the create a new world screen, then it crashed. The solution: Install the 64-bit version. (The issue in this case is that fglrx, the proprietary video drivers for my video card, don’t play well with Java when you use 32 bit Ubuntu. 64 bit works.)

Of course, this lead down a Google rabbit-hole. I messed up the re-install because I didn’t specify an EFI bootloader partition, and the Ubuntu installer didn’t warn me that it wouldn’t work. (You get the No operating system found message.) Then some sort of graphics misconfiguration meant that when it tried to boot into Unity, (which I already hate) all I got was a blank screen. Three or four reboots later, this problem somehow sorted itself out, whereupon I disabled Unity, then apt-got fglrx, and after that, everything seemed to work fine. That still left replacing OpenJDK with Sun’s JRE. (apt-get remove openjdk-6-jre openjdk-6-jre-headless. That seemed to remove everything that needed to be removed.) Minecraft now runs, (I think. I did get a crash which corrupted my save file, but that was after messing with graphics options pretty intensely for five minutes or so.) It’s not perfect. Being Java, it seems like GCs cause stuttering, but being able to play it at all on what’s basically a slightly beefier netbook it kinda cool.

Now, I just need to install Eclipse and the Android SDK, and I can strop using my lapburney Macbook!

Here’s some useful links if you want to try this:
The Ubuntu community page for the x120e
The ArchLinux wiki page
A good blog post about this

Comments off

Android and https

I recently had to deal with using https with Apache’s http libraries. Not a simple task. If you just create a Uri with https in front of it, and your SSL certificate isn’t from a trusted authority, or if you’re using a self-signed certificate, you’re in for a world of hurt.

There’s a lot of solutions out there, and most of them involve trusting everyone, which isn’t so secure. The best solution I found is here:

Crazy Bob: Trusting SSL Certificates

It’s reasonably secure, but in order to use it, you’ll need the 1.6 JDK. You don’t need the Android SDK to create the needed keystore.

[UPDATE]

That method works if you’re only going to one domain. All other domains stop working with that method. A better method can be found at this Stack Overflow question:

http://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https/6378872#6378872

The code here appends your KeyStores to Android’s list, which is a much better solution. You’ll still need the method for generating a keystore in the first link.

Comments off

Slow Android autocomplete in Eclipse Helios

Eclipse Helios has been slow for me for awhile, and it finally annoyed me enough to try to google a solution.

This guy found a good, relatively easy fix.

Basically, you’re just downloading the Android source, and adding it to your Android SDK directory. Hit the link for full details.

Comments off

Referencing drawables in HTML in Android’s WebView

Here’s another interesting Android quirk:

So let’s say you have a webview that you want to populate with HTML from an arbitrary source, and you want to use an image in the res/drawable directory. You could try webview.loadData(html, “text/html”, “UTF-8″), and within the HTML, use

<img src="file:///android_res/drawable/icon.png" />

or something, but that won’t work. Instead, this is what I had to do:

WebView webview = (WebView)this.findViewById(R.id.webview);
String html = "<html><head><title>TITLE!!!</title></head>";
html += "<body><h1>Image?</h1><img src="icon.png" /></body></html>";
webview.loadDataWithBaseURL("file:///android_res/drawable/", html, "text/html", "UTF-8", null);

So basically, for some reason, you absolutely have to use loadDataWithBaseURL.

UPDATE

This only seems to work with 2.2 (API level 8)and up.

Comments off

Basic authentication with HttpClient on Android using https and PUT

‘ve been beating my head against a wall for hours with this one. The examples I’d been using all returned HTTP 400 Bad Request, and Apache’s HttpClient is cryptic enough so that the reason for this wasn’t obvious. The reason for this response still isn’t obvious, but thanks to Kyle Lampe, I now have some code that actually works:

try {
    String data = "YOUR REQUEST BODY HERE";
    //
    CredentialsProvider credProvider = new BasicCredentialsProvider();
    credProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
        new UsernamePasswordCredentials("YOUR USER NAME HERE", "YOUR PASSWORD HERE"));
    //
    DefaultHttpClient http = new DefaultHttpClient();
    http.setCredentialsProvider(credProvider);
    //
    HttpPut put = new HttpPut("YOUR HTTPS URL HERE");
    try {
        put.setEntity(new StringEntity(data, "UTF8"));
    } catch (UnsupportedEncodingException e) {
        Log.e(TAG, "UnsupportedEncoding: ", e);
    }
    put.addHeader("Content-type","SET CONTENT TYPE HERE IF YOU NEED TO");
    HttpResponse response = http.execute(put);
    Log.d(TAG, "This is what we get back:"+response.getStatusLine().toString()+", "+response.getEntity().toString());
} catch (ClientProtocolException e) {
    //
    Log.d(TAG, "Client protocol exception", e);
} catch (IOException e) {
    //
    Log.d(TAG, "IOException", e);
}

Comments off

Push notifications with Urban Airship on Android

So I’m testing out push notifications using Urban Airship’s system, and I’ve been ripping my hair out for the last day or so trying to get my app to respond to them. It turns out that the example code they have on their site doesn’t actually work. If you do everything exactly as they say, you’ll either get a ActivityNotFoundException when the BroadcastReceiver tries to start your activity, or you’ll get an ANR, and a log trace that looks like this:

E/Bundle  ( 1101): readBundle: bad magic number
E/Bundle  ( 1101): readBundle: trace = java.lang.RuntimeException
E/Bundle  ( 1101):      at android.os.Bundle.readFromParcelInner(Bundle.java:1580)
E/Bundle  ( 1101):      at android.os.Bundle.(Bundle.java:82)
E/Bundle  ( 1101):      at android.os.Parcel.readBundle(Parcel.java:1381)
E/Bundle  ( 1101):      at android.os.Parcel.readBundle(Parcel.java:1366)
E/Bundle  ( 1101):      at android.content.Intent.readFromParcel(Intent.java:5479)
E/Bundle  ( 1101):      at android.content.Intent.(Intent.java:5453)
E/Bundle  ( 1101):      at android.content.Intent$1.createFromParcel(Intent.java:5444)
E/Bundle  ( 1101):      at android.content.Intent$1.createFromParcel(Intent.java:5446)
E/Bundle  ( 1101):      at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:132)
E/Bundle  ( 1101):      at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:1480)
E/Bundle  ( 1101):      at android.os.Binder.execTransact(Binder.java:288)
E/Bundle  ( 1101):      at dalvik.system.NativeStart.run(Native Method)

What’s happening is that you register a PushReceiver with the AirMail control panel app, which then creates and sends an intent to start your activity. The problem being, (I think) that the intent gets sent from the scope of the AirMail app, meaning it wont necessarily have access to your classes.

The way I finally got this to work is by using the setClassName(String, String) method of the intent to explicitly set the packagename and class name of the activity I wanted. Stick this in the onClick method of your PushReceiver:

Intent i = new Intent();
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setClassName("com.example", "com.example.YourActivity");
YourApplication.this.startActivity(i);

Comments off

Google analytics drops metrics in Android if you send them too quickly

I just ran into this problem with the Google Analytics SDK for Android (v0.8). Basically, if you try to send too many pageviews too quickly, the tracker gets overwhelmed and forgets to track some of them.

My solution was just to space things out a bit with Timers and TimerTasks. I have a small wrapper around the analytics tracker, which has a timer, a static inner TimerTask class, and a long which is the soonest that a pageview should be sent. Whenever you want to send a pageview, you just call recordView, which looks like this:

public void recordView(String metric) {
        // The current time.
        long time = new Date().getTime();
        // We keep track of the next appropriate time to send a metric with sendTime. sendTime only gets updated
        // when we try to send something,
        if (this.sendTime > time) {
                time = this.sendTime;
        }
        this.sendTimer.schedule(new TrackTask(this, metric), new Date(time));
        // I have sendInterval set to 2000, meaning pageviews are sent at a minimum, two seconds apart.
        this.sendTime = time + this.sendInterval;
}

Then, TrackTask looks like this:

protected static class TrackTask extends TimerTask {
        //
        private WeakReference ref;
        private String metric;

        public TrackTask(Metrics met, String metric) {
                // WeakReference to avoid memory leaks.
                this.ref = new WeakReference(met);
                this.metric = metric;
        }

        public void run() {
                // try catch block because our WeakReference has the possibility of being GCed out from under us.
                try {
                        this.ref.get().tracker.trackPageView(this.metric);
                        this.ref.get().tracker.dispatch();
                } catch (NullPointerException e) {
                }
        }
}

Comments off

Getting items in a ListView to show Alpha values

So I was trying to implement a ListView in Android the other day where the items would have varying levels of alpha transparency in the background. For some reason, every item’s background would go black whenever the ListView scrolled. (presumably for performance reasons.) Googling around yielded not much, but a co-worker had solved this problem in a previous app. Looking through the layout file, I saw that the android:cacheColorHint was set in his layout, but not mine. Adding it solved the problem.

Basically, just adding android:cacheColorHint=”#00000000″ to the ListView enabled transparency while scrolling.

Comments off

Android memory leaks

Since I’ve been banging my head against this for the last 12 hours, I thought I’d post a solution here, so other people might stumble across it and benefit.

I ran into two memory leaks in Android itself in WebView, and Typeface. Both are because of bugs in the OS, so if you’re encountering memory leaks, and all your code looks pretty watertight, (Meaning you never pass Activities as a Context to a View, and you use WeakReferences for static inner classes) you might be hitting one of these.

The first bug for WebView is described here.

The solution is just to call destroy() on your webview in the onDestroy() method of the containing activity, then set any references to that WebView to null, just in case. The app I’m working on is webview heavy, so this was causing some grief.

The second bug for Typeface is described here.

The issue was that I was creating a new Typeface from assets in the onCreate method of my activity. Every time I did this, it was allocating around 700k of memory, which then never got released. Big, big problems. The solution in this case is to initialize the typeface object in a static class (You can subclass Application and stick it there if you want, but be aware that you can’t call getAssets() before the first activity gets it’s onCreate method called.) and then use that one instance for any TextViews you may have.

The only way I managed to figure out what was causing the leaks was to go into adb shell, and then use dumpsys meminfo. That showed me a whole lot of bad.

Comments off

Related Links

Resource Links