Exporting Photoshop Layers for Android
Aug 10, 2013I’m working with a team on a rather large Android project that has a highly customized UI and therefore has a lot of artwork.
As is fairly typical for this type of project, the design is done by a third-party design house, and delivered as Photoshop PSD files.
For the developers on the project, it can be a bit time-consuming to manually copy layers from the PSD to new documents, resize them appropriately for all of the supported Android resolutions (ldpi, mdpi, hdpi, and xhdpi), and then export them to PNG files.
Not being a Photoshop expert, I was pleased to find that Photoshop is scriptable with several scripting languages, including JavaScript. Since JavaScript is the only one that’s supported on all platforms on which Photoshop runs, I figured I go with that.
Looking around the web, I found a number of scripts that claimed to at least export layers, if not resize them the way I want. Unfortunately, they just plain didn’t work. I’m guessing that they worked with previous versions of PS, and just weren’t compatible with CS6.
Finally, I found a very polished, working ‘Export for iOS’ script by Daniel Wood of runloop.com at http://pastebin.com/12dHWYm8
This script does exactly the steps that I was looking for, except that it does it for the various iOS asset sizes. If you are an iOS developer, and you don’t have something like this, go get it - it will save you tons of time.
So, I simply modified the iOS script to export image sizes appropriate for Android ‘drawable’ assets.
The script, along with a README containing instructions for installation and use are on my Github account at https://github.com/rfreedman/Export-Photoshop-Layer-For-Android
Java Dates
Nov 24, 2012I often see questions about why a date fetched from a database via JDBC has the ‘wrong’ timezone, or the ‘wrong’ time.
The basic thing that all Java programmers must understand when working with dates is that Java Date objects do not have a TimeZone. A Date represents its point in time as the number of milliseconds elapsed since the “Java Epoch”, January 1, 1970, 00:00:00 GMT.
So, a Java Date is essentially a Long. It embodies no concept of a TimeZone.
Every SQL database that I’m aware of does essentially the same thing. The epoch used may be different, but virtually all databases store dates in a similar timezone-free format. Your JDBC driver is responsible for doing the conversion when you insert or select a date. When you select a date from a database, you get a timezone-free representation of that date, just as if you had created that date in Java.
The part that confuses people is that they typically print the date, to the console, to a log file, or a web page, to see its value. And whether you are doing this in your sql console, or in a Java application, printing a date means formatting the date. Formatting the date necessarily introduces a TimeZone.
The really confusing part is that the most naive way of printing / formatting a date uses the ‘default’ TimeZone, and does not make this fact obvious. So the novice prints the date, sees an unexpected time zone, and assumes that the Date has the ‘wrong’ time zone. What has really happened is that the default timezone isn’t what they expected it to be.
We also see folks formatting the date, with an explicit TimeZone, and then re-parsing that string back into a Date object, thinking that they have somehow changed the Date’s TimeZone. But, as I mentioned, the Date doesn’t have a TimeZone. So then they wonder why the TimeZone hasn’t changed.
The bottom line: Remember that Dates don’t have TimeZones. Producing a String from a Date (including implicit or explicit use of toString()) without specifying a TimeZone always formats that date string using the local default TimeZone. The TimeZone does not come from the Date. It comes from the local system. What is your default TimeZone? See TimeZone.getDefault()
Here is a small example that illustrates formatting of a Date with TimeZone:
import java.util.Date;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
public class DateFormatExample {
public static void main(String[] args) {
SimpleDateFormat formatNY = new SimpleDateFormat();
formatNY.setTimeZone(TimeZone.getTimeZone("America/New_York"));
SimpleDateFormat formatLA = new SimpleDateFormat();
formatLA.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
Date now = new Date();
System.out.println("The current date and time in NY is " + formatNY.format(now));
System.out.println("The current date and time in LA is " + formatLA.format(now));
}
}
For extra points, replace ‘new Date();’ with ‘new Date(0)’, and see what the moment of the Java Epoch looks like in these time zones. For even more extra points, store a date in your favorite database, select it back, and format it as above. Convince yourself that Dates are TimeZone-free.
An Improvement - the Calendar class
If you look at the JavaDocs for the Date class, you’ll see that most of its methods have been deprecated, with the notable exceptions being the constructor and the toString() method. This is because those now-deprecated methods lacked support for localization.
The java.util.Calendar class was an attempt to replace the Date class with a better implementation. The methods in the Date class that were deprecated have been re-implemented in the Calendar class.
To make up for Date’s lack of a Locale, Calender has a locale property, and setLocale and getLocal methods. This allows Calendars to localized.
Calendar also has a timeZone property and associated mutator methods setTimeZone and getTimezone. It has two constructors - one that takes a TimeZone and a Locale, and one that takes no arguments.
The no-arg constructor initializes the calendar with the default time zone and the default locale. As with the use of the Date class, Calendar’s no-arg constructor using default values is the one that is most likely to be used, and the one most likely to cause confusion.
Calendar has some other improvements over Date, including a number of additional date manipulation and comparison methods. Finally, you can set the date of a Calendar with the setTime() method, and retrieve the date of a Calendar with the getTime() method.
Calendar is now the preferred class to use, and Date should only be used when interfacing with “legacy” code, such as JDBC.
An Alternative - Joda Time
Early on, it became apparent that Java’s Date class just doesn’t have a lot of the functionality that programmers commonly need when dealing with dates. One of the most wished-for features was (and still is) a Time class that is independent from Date. One might, for instance, wish to represent “4:00 PM”, and perhaps compare it to “2:00 AM” to see which is earlier.
Joda Time appeared around 2003 to solve this and many of the other problems with java.util.Date. (Joda provides times irrespective of dates with the Instant class.) When Calendar arrived on the scene, it improved things a bit, but Joda was still needed. Joda is still actively maintained, and as of the end of 2012, is still arguably the best way to handle dates in Java. Notably, Joda even includes support for Hibernate.
Coming Improvements - JSR-310
In 2007, folks from Google, Sun, Red Hat, and others got together with Stephen Colebourne, founder and leader of the Joda project, and produced JSR-310, a Java Specification for a new Date and Time API. JSR-310 is heavily influenced by the Joda Time library, but is not exactly the same.
JSR-310 was initially slated for implementation in Java 7, and now is a candidate for inclusion in Java 8. This is sorely needed in Java - let’s hope that JSR-310 makes it in the Java 8 release!
Dell Vostro 200 Ethernet Card Replacement
Sep 29, 2012I’ve been experiencing intermittently high rates of packet loss on my home network for a while now.
After much troubleshooting and swapping of spare routers, I eventually figured out that the problem was with my ‘house server’, a Dell Vostro 200 running Ubuntu Linux. Apparently, the on-board ethernet interface was defective. While it still worked, it was the source of the packet loss. I unplugged the the cable between it and the router, and the packet-loss problem instantly went away.
After determining that the cable itself was not the problem, I ordered a new ethernet card, an Intel PWLA8391GT PRO/1000 GT PCI Network Adapter from Amazon for a little under $40 USD. I’m happy to report that I installed it, turned the server back on, and it just worked. Ubuntu 12.04.1 LTS (Precise Pangolin) required no configuration, and no additional driver installation.
So, if you need a new or additional network card for Dell Vostro 200, I highly recommend the Intel Pro/100 GT.
Command-Line Android Screen Capture with Groovy
May 30, 2012I’m writing a chapter about jQuery Mobile for a Manning book, tentatively titled “Mobile Web Apps In Practice”.
I need to get some good, high-quality screen captures for illustrations for the chapter. I read a few articles about how to do a screen capture on an Android device using the ddms tool from the Android sdk, and that worked fine (see, for example, http://forum.gtvhacker.com/gtv-guides/topic59.html if you’re interested). But I figured that there had to be an easier way.
I found Java code for use of the ddmlib library for working with the Android SDK to do a screen capture at https://github.com/roman10/roman10-android-tutorial/blob/master/screenshot/src/com/android/screenshot/Screenshot.java.
This was good, but I both wanted an easy one-liner shell script, and to be able to customize the operation easily. So, being a fan of Groovy, I turned the Java code into a Groovy script, and dumped the source code for ddmlib in favor of a Grapes reference to the library in the central Maven repo.
I set up the groovy script to run as a shell script, and got rid of the .groovy extension.
Now I have a nice command-line way to do Android hardware screen captures.
The script is at https://github.com/rfreedman/android-screencapture. Feel free to fork and hack!
Inflection (Pluralization) in Java
Apr 26, 2012Most non-trivial, user-facing software eventually needs to do declension to offer reasonable feedback. Often, simple inflection of nouns is sufficient.
There are some good inflection libraries in other languages, perhaps most notably Damian Conway’s Lingua::EN::Inflect for Perl, and Rails’ ActiveSupport::Inflector, but there are surprisingly few good stand-alone implementations for Java.
A search on the web for ‘Java Inflector Library’ will find you references to ModeShape (formerly JBoss DNA), ActiveJDBC, Apache CXF, NetBeans, and other projects, all of which are larger projects that include an inflection class or sub-library.
The Evo Inflector library is a stand-alone library that looks to be very full-featured, and is in the maven repos, so would appear to be open-source, but I wasn’t able to find a license or a source code repository for it. It is also more of a ‘kitchen-sink’ library, and not dedicated to inflection.
The one stand-alone library that I was able to find that has an open-source (Apache 2.0) license is the simply-named “Inflector” library. It’s simple - English nouns only - and I’m using it in my current project. However, after an extensive search, I’ve been unable to find a source repo for it. It appears that it used to live at https://inflector.dev.java.net, but that does not seem to exist any more.
I think that it would be really useful to a stand-alone, open-source library dedicated to inflection, and able to handle adjectives and pronouns in addition to nouns. It would also be really nice if it handled more languages than just English.
Anyone up for the challenge?
Java Desktop Integration with Java 6
Mar 19, 2012Integrate Your Java Application With The Desktop
It’s been a number of years since I attempted to do Java desktop integration, and back then I depended on the JDesktop Integration Components (JDIC) project to provide a platform-independent interface to native web browser.
I needed this functionality again recently, and checked back in on JDIC, only to find that the project never made it to 1.0 release status, and hasn’t been updated in over two years.
Fortunately, with a bit more research, I found that as of Java SE 6, most of the JDIC functionality has been built into the new java.awt.Desktop class.
The documentation is pretty good, so here just a couple small examples to whet your appetite.
Desktop desktop = null;
if(Desktop.isDesktopSupported()) {
desktop = Desktop.getDesktop();
desktop.browse(new URI("http://greybeardedgeek.net"));
}
:::java
Desktop desktop = null;
if(Desktop.isDesktopSupported()) {
desktop = Desktop.getDesktop();
desktop.edit(new File("someFile.txt"));
}
The Desktop class supports browsing and editing as shown above, as well as printing, opening a file with its associated application, ane creating a new email in the native email client. If you’re looking for JDIC’s old System Tray functionality, that’s in the java.awt.SystemTray class.
Apache mod_jk and OS X Lion
Oct 25, 2011I just upgraded my MacBook Pro to OS X Lion, and then had to spend a little while getting my development environment working again. There wasn’t too much to fix, but I didn’t find resolutions to all of my issues in one place.
So, here’s what I had to do:
The Java environment is not installed by default - run 'java' from the command-line, and Lion will automagically install it.
The (legacy) project on which I'm currently working fronts Tomcat with Apache2 using the mod_jk module. After the upgrade, this module is missing. There's nowhere that I could find to download a binary - you have to build it yourself from source.
The download of the source can be found at http://tomcat.apache.org/download-connectors.cgi. Instructions for building it on Lion are at http://www.malisphoto.com/tips/tomcatonosx.html.
To be able to build the source, you have to install XCode from the App Store. Note that the App Store only installs the XCode installer, not XCode itself. You still have to run the XCode installer. Then (and this is the part that took me a while to figure out), you have to reboot. Otherwise you get errors when running the configure script.
Finally, Apache was up and running, (I could see it by running netstat), but I couldn't connect to it. Further investigation revealed that I could connect to it using my '.local' machine name, but not 'localhost' or any of the other aliases that I had in /etc/hosts. The answer, which I found at http://www.justincarmony.com/blog/2011/07/27/mac-os-x-lion-etc-hosts-bugs-and-dns-resolution/, is that Lion does not allow (or rather, does not work properly with) multiple host names per line in /etc/hosts. Putting one per line fixed the problem.
Now, all seems to be well with my development environment (we'll see....)
Hopefully, this has helped you to get yours running smoothly as well.
Notational Velocity on Android
Aug 10, 2011I’ve been using Notational Velocity for note-taking on my Mac for a while now, and can highly recommend it. It’s a wonderfully minimalistic interface, and “just works” for text. I used to use Evernote, but found that I don’t really need all of the features and multiple media types - NV feels like the right fit.
Notational Velocity syncs with SimpleNote, but until recently, I hadn’t seen a decent way to access my NV notes from my Android phone. A couple of months ago however, Notational Acceleration appeared on the scene. It syncs NV notes through SimpleNote. It’s not quite feature-complete yet, but for basic syncing, reading, and writing of notes, it has the same minimalistic feel as Notational Velocity, and “just works”. I highly recommend it.
A Beginner's Take On Git
Jul 29, 2011Git, for those of you who have been living under a rock, is a a very popular distributed software revision control system.
It has been around since 2005, and has been gaining quite a bit of traction over the last several years. Git is one of those things that I’ve been meaning to try on my own time for a while, but a few months ago, I started a new project, and decided to dive in.
Even after reading all of the Git tutorials and watching the videos, it took the team a while to find a Git workflow that made day-to-day development go smoothly. The workflow that we eventually adopted works very well for us, and I haven’t seen this exact workflow explained anywhere else, so I thought I’d document it here in the hope that it well help someone else.
If you are an experienced Git user, and you see danger lurking in this workflow, or just know of a better way, please let me know in the comments.
If you have not tried Git or any other distributed revision control system, I urge you to try one. For a long time, I questioned the need for a distributed revision control system, and was relatively happy with Subversion. Now that I’ve used Git, I understand what all of the noise was about. There are many advantages to this type of system that do not have anything directly to do with whether your team is distributed or not. Now, I’d never go back to Subversion if I didn’t have to. And if I did, I’d use git-svn.
My basic goal when working out this workflow was to minimize Merge Hell. We’ve all experienced Merge Hell, especially when using either CVS or Subversion. All of the Git documentation that I read made it seem like Git could help considerably with staying out of this situation. However, as soon as a second developer joined the team, I found myself in Git merge hell. That event was the genesis for this workflow.
Before I explain the details of the workflow, let me set out a few basic suggestions that I think are a good idea no matter what kind of revision control system you are using:
- Do all development on a branch, not on the trunk (or in Git terms, on a 'feature' branch, not on the 'master' branch)
- Commit (and in the case of a distributed RCS, 'push') small changes frequently
- Endeavor to make difficult merges a local problem - try not to let them affect the rest of the team
The following workflow assumes that you are following the three suggestions above. So, from start to finish on a feature, here’s the basic ten-step workflow:
- make sure that your master branch is up to date with the remote repository (git pull master)
- either create a feature branch (git checkout -b feature_branch) or switch to an existing feature branch that has been fully merged with the master branch (git checkout feature_branch)
- do your work on the feature branch, add the changes to git (git add .), and commit them to the feature branch (git commit)
- switch back to the master branch (git checkout master)
- make sure that your master branch is up to date by pulling any new changes from the remote repo (git pull)
- switch back to the feature branch (git checkout feature_branch)
- merge any new changes from the remote master into your feature branch with 'rebase' - this is the 'magic' part (git rebase master)
- switch back to the master branch (git checkout master)
- merge the feature branch into the master branch (git merge feature_branch)
- push your changes to the remote repo (git push origin master)
Ok, so that sounds a bit complicated. Fortunately, some of the steps can be skipped some of the time, and even when you have to do them all, I’ve found that it becomes second nature once you understand the reason for each of the steps, and what each does.
So, here’s a step-by-step explanation:
Step 1 is to simply make sure that you have a current copy of the remote codebase before you start work on a new feature. A no-brainer.
Step 2 is set up the branch on which you are going to do your work. If it already exists, make sure that it’s fully merged into master to make sure that you don’t have to merge it later while you are merging your new changes
Step 3 - do your work
Steps 4 and 5 ensure that your master branch is up to date with the remote repo - this pulls in any changes that have been pushed to the remote master branch while you were doing your work. If there are changes pulled, they will merge cleanly, as you haven’t made any changes directly on your local master (this is why we work on a feature branch). If there were no changes on the remote master (‘git pull’ reported no changes), you can skip steps 7 and 8.
Step 7 merges new changes from the remote master with your work on the feature branch. The magic here is the ‘git rebase’ command. Rebase effectively shelves (temporarily rolls back) the commits that you have made on your feature branch, applies the updates from the master branch to the feature branch, and then ‘replays’ your commits back on top of the feature branch.
The first part, shelving your feature commits and updating the feature branch with the updates on master, when used this way, will always happen cleanly. The second part, replaying your commits, is where you will potentially encounter one or more merge scenarios.
There are some very advantageous things about this step. First, because your local commits are put ‘on top of’ the merged commits from the remote master, it is a ‘cleaner’ merge. Generally, it effectively results in a two-way merge instead of a three-way merge - i.e. merges tend to be easier to do. Second, once you are done, the timeline is easier for everyone to understand. Even though two or more developers may have interleaved commits, it comes out looking one developer committed all of their changes, and then the other developer committed all of theirs. To me this is both magical and invaluable.
Step 8 simply puts you back on the master branch
Step 9 merges your local feature branch into your local master branch. Again, if you have followed the plan, this will be a clean, ‘fast-forward’ merge. Your feature branch and your local master branch are now identical.
Step 10 pushes your local master branch to the remote master branch. Also a fast-forward merge, unless someone else has pushed to the remote master after you did step 5. Unlikely, but possible. Solution left as an exercise for the reader.
Rinse and repeat.
There has been much discussion on websites everywhere about how ‘rebase’ is evil because it rewrites history. I think that it’s important to note that using rebase on commits that have already been pushed to the remote repo is evil. Here, however, we’re rewriting local history, because that’s what makes the ultimate timeline make sense, and we’re not altering any history in the remote repo.
Ok, that’s it. Let the discussion ensue!
Testing Grails Controllers with Spock Part 2
May 19, 2011My previous post showed how to get around some of the shortcomings of testing Grails Controllers with the ControllerSpec provided by the Spock testing framework.
I also found that ControllerSpec is a subclass of UnitSpec, so it does not provide transactional rollback. This makes ControllerSpec somewhat undesirable for an integration test.
So, I merged the code for ControllerSpec and IntegrationSpec to create ControllerIntegrationSpec. It works just like ControllerSpec, but executes each test method in a transaction, and rolls the transaction back at the end of the method.
Here is the Groovy source, which can also be found at https://github.com/rfreedman/spock-integration-controller-spec/