David Janes' Code Weblog

April 8, 2012

NSURLConnection, ETag and caching

code fragments,iphone,tips · admin · 7:40 am ·

If you’re using NSURLConnection and using If-None-Match/ETag and you’re depending on getting a 304 status to determine that “nothing changed”, make sure you do this:

[request setCachePolicy:NSURLRequestReloadIgnoringCacheData];

If you don’t, after your first request/response cycle, NSURLConnection will start returning status 200 instead as it’s pulling the result from its local cache.

February 26, 2012

iTunes & Missing Files

macintosh,tips · admin · 2:45 pm ·

If you’re like me and keep your iTunes files on external disks, you’ll occasionally end up in a situation where the external disk is not available and iTunes ends up marking all your files with an “exclamation mark”, indicating they’re not available.

To have to do to fix this is hold CTRL+ALT when starting iTunes and it’ll re-figure everything out.

Hat tip.

February 2, 2012

times

python · admin · 7:49 pm ·

Interesting

Times is a small, minimalistic, Python library for dealing with time conversions to and from timezones, for once and for all.

times tries to make working with times and timezones a little less of a clusterfuck and hopefully set a standard of some sort.

See my previous posts on working with pytz and dateutil (and also). I’m looking forward to trying out times.

December 7, 2011

Thoughts on Python 3

python · admin · 7:36 am ·

I’m learning a new language next year (suggestions welcome). I’ve totally ignored Python 3 and plan to continue doing so.

Read Armin Ronacher on “Thoughts on Python 3“.

Because as it stands, Python 3 is the XHTML of the programming language world. It’s incompatible to what it tries to replace but does not offer much besides being more “correct”.

Python 3 kills what makes Python great.

November 15, 2011

Python, Sqlite3, FTS3 & MacOSX

db,python,tips · admin · 8:49 am ·

If you can’t load FTS3 on a Mac, this post on StackOverflow tells you how to solve the problem.

The final bit of magic is in:

from pysqlite2 import dbapi2 as sqlite3

November 11, 2011

Beautiful Code

android,code fragments,java · admin · 8:40 am ·

This is what I’m aiming for — powerful declarations, minimal logic. UIButtonGroup, UIWebView and UIBundleHelper carry a lot of the weight here and I hope to explain (and share) all of these soon.

public class TTActivityInfo
  extends TTAbstractActivity
{
  public Button uiLeftButton;
  public Button uiRightButton;
  public UIButtonGroup buttonGroup;

  public WebView uiWebView;

  static String lActivityTitle = "Welcome!";
  static String lLeftButtonTitle = "Welcome";
  static String lRightButtonTitle = "About the app";

  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);

    this.setContentView(R.layout.tt_activity_info);

    UIHelper.bindViews(this);
    UIHelper.hookupButtons(this);

    _configureWebView();
    _configureNavigationBar();
    _configureButtons();

    UIBundleHelper.restoreActivityStateFromBundle(this, savedInstanceState);

    if (savedInstanceState == null) {
      _forceWebViewToCurrentState();
    }
  }

  @Override
  protected void onSaveInstanceState(Bundle _bundle)
  {
    UIBundleHelper.saveActivityStateToBundle(this, _bundle);
  }

  protected void _configureNavigationBar()
  {
    TTUI.configureNavigationBarTitle(this, lActivityTitle);
  }

  protected void _configureButtons()
  {
    TTUI.configureBlueButton(this, uiLeftButton, lLeftButtonTitle);
    TTUI.configureBlueButton(this, uiRightButton, lRightButtonTitle);

    buttonGroup = new UIButtonGroup(uiLeftButton, uiRightButton);
    buttonGroup.select(uiLeftButton);
  }

  protected void _configureWebView()
  {
    if (uiWebView == null) {
      return;
    }

    uiWebView.getSettings().setJavaScriptEnabled(true);
    uiWebView.setWebViewClient(new UIWebViewClient(this, "uiWebView"));
  }

  protected void _forceWebViewToCurrentState()
  {
    if (uiWebView == null) {
      return;
    }

    if (buttonGroup.getSelectedButton() == uiRightButton) {
      uiWebView.loadUrl("http://www.google.com");
    } else {
      uiWebView.loadUrl("http://www.davidjanes.com");
    }
  }

  public void _handleButtonSelected(Button _button)
  {
    buttonGroup.select(_button);

    _forceWebViewToCurrentState();
  }

  public void uiLeftButton_onClick(Button _button)
  {
    _handleButtonSelected(_button);
  }

  public void uiRightButton_onClick(Button _button)
  {
    _handleButtonSelected(_button);
  }
}

November 10, 2011

Activity (I): The First Rule of Android Activities

android,java · admin · 5:43 pm ·

Android Applications are structured around Activities. Understanding how Activities work and structuring your code within that framework is key to creating successful Android applications. Do not try to fight this: I know from hard personal experience that this does not work.

Here is the first thing you need to know about Android Activities, and understanding this will shape everything you do while coding them in the future:

Activities can be fucking destroyed and recreated at any time – even while the user is interacting with them.

Do you understand this and the implications of this? Probably not, but I’ll outline the implications of this over a few blog posts and how to work with it.

When your activity is destroyed, you lose everything – all your variables, everything you’ve setup, popup alerts, the Activity object itself. All gone.

Here are some times that an Activity will be destroyed and recreated:

  • You rotate your Android
  •  You open or close a Keyboard
  •  Another Activity is showing and Android needs the memory

In Android parlance, these are called “Configuration Changes“. There are ways to block this from happening, but I suggest it’s better to roll with the punches and “do the right thing”.

Fortunately Android destroys and recreates Activities in a well-defined structured manner and provides the proper places (albeit Java-clumsy) to save and restore the state so that the user won’t see that the whole interface they were looking at was destroyed and remade. More about this soon.

Naming Standard: _configure and _update

android,ideas · admin · 12:13 pm ·

In preparation for a series of posts I’m about to do on Android Activities, I want to do a brief post on a recent standardization I’ve decided on. When doing user interfaces, there’s two things that I’m always doing: some initial configuration of elements (such as setting the color or font of a label) and then maybe multiple times changing the state of an element (such as setting the actual label text).

So from now on, I’m naming these:

  • _configureXYZ – a function / method for the one-time setup of an XYZ.
  • _updateXYZ – a function / method for changing the state of an XYZ, with the expectation this is going to be called multiple times.

Note that I don’t write one-function per UI element. It’s more like _updateButtons, _updateMaps, etc.

Note the underscore. Whenever I write a function that’s intended only for the use of the current object, I prefix with “_“.

October 29, 2011

Good-bye Delicious

startups,tips · admin · 5:46 am ·

Yahoo sold Delicious to another company and for the most part it hasn’t worked for me since the transition. I don’t use the “social” part of the bookmarking: I just try to bookmark every interesting page I read in case I need to find it again in the future. If Yahoo had been clever, they could have built cleverer search infrastructure around bookmarking information but of course “Yahoo” and “clever” rarely appear in the same sentence with being chaperoned by “not”.

I know startups are hard and I feel a little bit bad about kicking them when they’re down but features likely multi-word tagging are not so nearly interesting to me as “working” so it’s off to Evernote which has a lot more powerful clipping capabilities, is well funded, charges money – free doesn’t stay in business.

Here’s how I did the migration:

  • If you have 8747 bookmarks like me, you’ll need to do this and do two export / imports. Delicious’ new API only exports 1000 entries (f*ck you very much), so you’ll have to hack your DNS a little to pull the API data from the old Yahoo servers that are still up and running. I hand edited the exports to avoid duplicates though maybe Evernote is clever enough to figure this out on it’s own.
  • Follow the instructions on this page. Basically:
    • curl https://USERNAME:PASSWORD@api.del.icio.us/v1/posts/all > backup.xml
    • paste into here http://jsdo.it/palaniraja/uphW/fullscreen (on a Mac anyway)
    • save the results as toimport.enex
    • run Evernote and run File > Import

October 24, 2011

Automatically Binding Resources to Methods in Android Applications

android,code fragments,java · admin · 4:33 pm ·

AKA I’m as mad as hell at Java and not taking it any more Part II.

When developing Android applications, binding resources to end method calls is even more annoying than binding resources to variables.

One approach is to create an anonymous inner classes implementing various listener interface.

UIButton postButton = (Button) findViewById(R.id.share_post);
postButton.setOnClickListener(new View.OnClickListener() {
  public void onClick(View v) {
    // do stuff ...
  }
}

The other is to just implement the listener interface with whatever activity you’re using and figure out what button is being pressed.

I’d just as soon have the data wired up automatically to functions if it’s there. Here’s how I’m doing it now.

In MyActivity:

// class fields
public ImageButton uiButtonDining;

// in onCreate
UIHelper.bindImageButtons(this);

This will automatically wire to the following function

public void uiButtonDining_onClick(ImageButton _imageButton)
{
  // ... do stuff ...
}

I’ve only done this for ImageButton so far but I’m hoping this approach will scale for various other widgets.

The Code

Here’s The Magic for UIHelper.java:

static public void bindImageButtons(final Activity _activity) {
  Field[] instance_fields = _activity.getClass().getDeclaredFields();
  for (final Field instance_field : instance_fields) {
    if (!ImageButton.class.isAssignableFrom(instance_field.getType())) {
      continue;
    }

    LogHelper.debug(true, _activity, "field=" + instance_field.getName());

    try {
      final ImageButton button = (ImageButton) instance_field.get(_activity);
      if (button == null) {
        LogHelper.debug(true, _activity,
        "Button is stil NULL", "field=" + instance_field.getName());
        continue;
      }

      String callback_onClick_name = instance_field.getName() + "_onClick";
      try {
        final Method callback_onClick = _activity.getClass().getMethod(
         callback_onClick_name, ImageButton.class);

        button.setOnClickListener(new View.OnClickListener() {
          public void onClick(View v) {
            LogHelper.debug(false, _activity, "clicked", "field=" + instance_field.getName());

            try {
              callback_onClick.invoke(_activity, button);
            } catch (IllegalAccessException x) {
              LogHelper.debug(true, _activity,
              "Couldn't invoke callback", "callback=", callback_onClick, x);
            } catch (InvocationTargetException x) {
              LogHelper.debug(true, _activity,
              "Couldn't invoke callback", "callback=", callback_onClick, x);
            }
          }
        });
      } catch (NoSuchMethodException x) {
        LogHelper.debug(true, _activity,
        "no callback", "method=", callback_onClick_name);
      }
    } catch (IllegalAccessException x) {
      LogHelper.debug(true, _activity,
      "Can't set R.id", "name=", instance_field.getName(), x);
    }
  }
}
Older Posts »

Powered by WordPress

Switch to our mobile site