After creating a new project in Android Studio 0.3.1 utilizing Gradle, opening the project on a new machine gave me a few problems.

First, I got: Gradle could not resolve all dependencies.

To fix this, I opened the SDK Manager and downloaded the Android Support Library, since com.android.support:appcompat-v7 isn’t in Maven Central.

Next, I got: Could not execute build using gradle installation.

To fix this, I opened a terminal and ran gradle build. Ubuntu informed me it wasn’t installed, so I:

  1. downloaded it
  2. moved it to /opt/gradle
  3. went to Settings > Gradle in Android Studio
  4. under Project-level settings, selected Use local gradle distribution
  5. changed both Gradle home and Service directory path to /opt/gradle
  6. restarted Android Studio

And everything worked!

$ logout

Advertisements

I’ve accumulated a few laptops over the past five years. My first laptop “lasted” for four years of college (i.e. killed its first hard drive and was running Vista for most of its career), but I’ve since moved on to more powerful, non-Windows machines. Though four computers may seem a little unnecessary to my girlfriend, each still serves its own purpose in the various virtual ventures I partake in today.

Dell Inspiron · Windows 7 · Previously, my primary computer. Currently hooked to my MIDI-enabled piano for any time I want to work on some music. Occasionally turned on and remote desktop’d into when I really need IE or Photoshop.

System76 Gazelle Professional · Ubuntu 13.04 · Primary computer for everything; mostly-permanent denizen of my desk hooked to an external mouse, keyboard, hard drives, and second monitor.

Apple MacBook Pro · OS X 10.9 · Day job computer; occasional development and double pixel-density web testing at home.

Lenovo ThinkPad X201 · Lubuntu 12.10 · Primary “laptop,” i.e. portable computer; pretty much a dedicated development machine and replacement for my Samsung N130 netbook, whose two-year use inspired my full switch to Linux, and whose left-clicker recently went kaput.

$ logout

In case you want to make a TextView clickable, simply setting an onClick handler won’t do it. Make sure you set your android:clickable attribute:

...
android:onClick="doMagicalThings"
android:clickable="true"
...

$ logout

In one app I’m working on, we’re using a ListView to display a near-realtime stream of posts by various users. However, with constant updates, it was easy for any post a user is reading to get bumped down out of view due to new items being added at the top. This is how I fixed it.

The flow to this solution is:

  1. Finding what index of the list we’re currently scrolled to (+/- the pixel offset, for more exactness),
  2. Adding our new posts at the top,
  3. Doing a notifyDataSetChanged(),
  4. Waiting for our new items to be drawn to calculate our new scroll position.

We’ll start before our for loop / add()ing block, inside the method that checks for new posts (in our case, onLoadFinished()):

// Set up vars to track current scroll position / number of
// posts already displayed
boolean newPosts = false;
int scrolledToIndex = 0;
int topOffset = 0;
int startCount = mAdapter.getCount();

// If we've received new posts, we'll set our current scroll
// values:
if (/* ...we've detected new posts... */) {
    scrolledToIndex = getListView().getFirstVisiblePosition();
    View v = getListView().getChildAt(0);
    topOffset = (v == null) ? 0 : v.getTop();

    newPosts = true;

    // Add new posts...
}

// Update the ListView
mAdapter.notifyDataSetChanged();

// Get number of new posts
int delta = mAdapter.getCount() - startCount;

// Set final variables
final int finalTopOffset = topOffset;
// The index of our first visible post has changed by delta
final int finalScrollToIndex = scrolledToIndex + delta;

// Wait until list has drawn our new posts before scrolling
// to our previous location
getListView().post(new Runnable() {
    @Override
    public void run() {
        try {
            getListView().setSelectionFromTop(finalScrollToIndex, finalTopOffset);
        } catch (IllegalStateException e) {}
    }
});

$ logout

I very recently had a conversation with a client about implementing email notifications for his online community built with my software. There was, of course, an urge in him to notify users every time the equivalent of a thread is created or responded to. There was also the need for an email to go out as soon as a personal message was received.

For the latter, I was on board; but for the former, I had to make a point– no matter how subjective. My point was that I will unsubscribe from any site’s mailing list the minute I get an email with things I don’t care about. Emails are on the level with text messages for me, arriving on my phone with an envelope notification, pining to pull me away from reality the minute it arrives. And it’s not that my time is money, but because I loathe spending time reading random minutia that I hate your everyday “engaging” emails (especially when they arrive every day).

Needless to say, I made the point that when designing a product and how it will send out notification emails, it’s important to remember:

  • You’re not the only site that any given user is a member of.
  • People have vastly varying degrees of tolerance for emails meant only for getting them to your site again.
  • Don’t automatically opt users in. Unless your software is going to take me out to dinner and learn my quirks first, don’t assume you know how I like my email notifications. Instead, give me the choice and demonstrate why your notifications will be useful to me.

On a related note, LunchTable just got email notifications today, unsent until you subscribe.

$ logout

I have a ton of movies. When I first got a Raspberry Pi late last year, my first thought was to use it as a media center. So I hooked it up to my high-def TV and a hard drive with some very old pirated Simpsons episodes (from the days of Napster), and installed Raspbmc on an SD card. It worked great, and despite the need to get up and plug it in, and the $10 wired keyboard I used to control it, it worked great. If I had more money at the time, I would’ve gone with a Wi-Fi dongle so I could use my phone as a remote, or at least gotten a wireless keyboard.

A few months went by before my parents came up with a spare Blu-ray player that also happened to support DLNA— finally, I could be lazy again. I hooked the Pi straight into my router upstairs, plugged in the harddrive, and installed MiniDLNA. Downstairs, the Blu-ray player picked it up and instantly I had access to all of my digital video.

But soon, I craved more. So I decided to convert my DVD collection.

Converting

HandBrake turned out to be the best software for the task, both for its abilities and propensity for any OS you’re using (like Ubuntu). Ripping is pretty straightforward:

  1. Insert the DVD, click Source
  2. I used the dropdown to select my DVD drive (/dev/sr0)
  3. Hit okay, it starts scanning
  4. Select the title with what should be the duration of the movie. If you’re having trouble, check out When HandBrake won’t rip your DVDs.
  5. I’m happy with my 90-minute movies taking up around 1 GB– my 1 TB harddrive can handle it. So I started with the High Profile preset, and made the following changes:
    1. Format: MKV
    2. Video
      1. Framerate: Constant
      2. Constant Quality: RF: 16
    3. Audio
      1. English Track – Mix: Dolby Surround
  6. Press Start and let it run in the background.

These settings were perfect for a high quality video of moderate size in a format supported by my Blu-ray player. Experiment to see what works best for you.

On my machine, it takes about 25 minutes to transcode a 90 minute movie, with my CPU load hovering around 9 or 10. I couldn’t get my 5 year old Dell with an Intel Core 2 Duo processor to complete a whole rip, though it does like to overheat a lot these days. Enjoy!

$ logout

DRM is a common theme in the Internet Age’s story. Like watermarks on currency or microprint on checks, there are many reasons to prevent people from copying things, especially when you remove tangibility.

But sometimes it goes too far. I never bought music off the iTunes store again after I downloaded an album and found it wouldn’t abscond with me to another player. After I bought my first ebook today, I can’t say I’ll readily do it again.

I found an interesting technology book that I wanted to read on Amazon, ready for purchase in Kindle’s format. I own a Nook because it supports open formats (and PDFs), so I started looking around for a compatible version. Barnes & Noble only sold hard copies and the publisher only offered it in iPad format. I thought maybe I can convert it and I found out about a site that does just this. So I bought the book, and was told conversion wasn’t possible due to DRM. Ah, it’s so nice of Amazon to protect me from myself.

  1. So the first step was getting the book out of the cloud. For this I downloaded Kindle for my OS; I was on my work computer so I downloaded the Mac version. If I was at home, I would’ve had to get the Windows version and use wine to get it on Ubuntu.
  2. I found the AZW file for my book in the file system and copied it into a more visible location. It was located in:
    1. Windows: C:\Users\<username>\Documents\My Kindle Content\
    2. Mac: /home/<username>/Library/Application Support/Kindle/My Kindle Content/
  3. After reading a superuser question, I found a DRM removal tool for this exact situation. The standalone app didn’t work for me, so I downloaded calibre (cross-platform, nice!) and installed the DeDRM plugin from the previously downloaded tool, following the README instructions.
  4. Restarted calibre, opened up my book for conversion to ePub, and had a free and open copy in less than a minute.

I don’t believe in an era of innovation and free-flowing information ushered in by overprotective rights owners. From my reality, I’ve already given you my money–and for a mere $5 less than a physical copy, which is outrageous in itself. The least you could do is give me a quality product that will work with my gadget of preference.

So I can’t say I’ll be anxiously looking for my next ebook purchase. But it’s comforting to know that there are always ways to shake off the fetters of myopic companies and their ill-founded mechanics.