Archive

Archive for the ‘tools’ Category

Scale Android drawables with a script

Here is a simple script to create lower-resolution Android drawables from higher-resolution ones.

For example, given a batch of -xhdpi images, it can generate -hdpi and -mdpi images.

With this script, it’s possible to export only highest-resolution artwork from authoring tools and then create the lower-resolution versions with a few batch commands.

Before, I would have to export all artwork versions one by one, adjusting the size, navigating to the right directory, double-checking to make sure I haven’t accidentally exported an -mdpi sized image into -hdpi, etc.

Script usage:

drawable_convert.py -d res/drawable-mdpi -d res/drawable-hdpi res/drawable-xhdpi-v14/select*.png

This will take select*.png from xhdpi and place lower-resolution versions into mdpi and hdpi folders.

Resize ratios are computed based on resource directory names.

The actual scaling is done by ImageMagick’s convert command.

https://gist.github.com/2771791

Categories: android, tools

Finding missing translations in an Android application

An app that is developed primarily in one or two languages, and supports more, needs to be updated from time to time.

To do this, missing string translations need to be identified.

The Lint tool from the Android SDK can do this, but I’ve found its output format to be difficult to work with.

Lint groups missing translations by string identifier, like this:

res/values/strings_widget.xml:7: Error: "widget_loading" is not translated in cs, es, fr, it, ja, ko, nb, nl, pt-rBR, sv, vi [MissingTranslation]
    <string name="widget_loading">Loading…</string>
    ^
res/values/strings_widget.xml:8: Error: "label_account_and_folder" is not translated in cs, es, fr, it, ja, ko, nb, nl, pt-rBR, sv, vi [MissingTranslation]
    <string name="label_account_and_folder">Account and folder:</string>
    ^

I believe it’s more useful to group missing translations by language code, so that they can be collected and sent to the translator for a particular language all at once.

With this in mind, I’ve written a simple script that does this. Its output look like this:

	Checking language 2, de
	***** Found 44 missing translations for language de

	<!-- res/values/strings_account_list.xml -->

	<string name=account_list_menu_uilock_now>Lock now</string>

	<!-- res/values/strings_account_options.xml -->

	<string name=account_options_folder_sync_type_spam>Sync as spam</string>
	<string name=account_options_prefs_preload_inlines_mobile>Embedded images, mobile</string>
	<string name=account_options_prefs_preload_inlines_wifi>Embedded images, WiFi</string>
	<string name=account_options_prefs_signature_auto>Add signature automatically</string>
	... more strings here

	Checking language 1, uk

	***** Found 47 missing translations for language uk
	... all missing translations for Ukrainian are printed here

The script is written in Python, and is available here: https://gist.github.com/2512076

Categories: android, tools

Moving Android projects from Windows to Linux

November 18, 2011 4 comments

This one had me really puzzled today.

I recently installed Ubuntu, just to see what developing for Android under Linux is like. Besides, it’s been about 10 years since I last used Linux, so I also wanted to see what it looks like these days.

I keep my source code in a remote Mercurual reporsitory, so copying my workspace from Windows to Linux was a snap (even if those are just different parttions on the same computer’s disk drives).

After doing “hg clone”, I opened up Eclipse, pointed it at my new workspace… and froze in a mixture of horror and confusion.

All my projects were marked with a red exclamation point, and the error window had a multitude of messages about Android requiring Java compiler compatibility level of 1.5 or better (… please use Fix project properties, etc.).

The confusing part was, all my projects are set up to use the workspace default for Java compiler platform level, and my just-created workspace’s setting was 1.6. Weird isn’t it?

The cause turned out to be my Java file encoding settings. Eclipse on Windows by default uses a single byte encoding for newly created Java files, which is my case is windows-1251 (Russian). Eclipse on Linux expects UTF-8. As soon as I changed my Linux workspace to use to windows-1251, and without touching those compiler compliance level settings, everything turned normal and my projects started building.

There is a bug filed in the Eclipse tracker going back to 2005 about this – whether or not Eclipse should default to UTF-8 for new files on Windows (and possibly MacOS). I’d like the default on Windows to be UTF-8, at least for Java files.

So… if you moved your Android code from Windows (and I presume, from MacOS) to Linux, and are getting the compiler compliance level error, check the encoding setting. Better yet, set up any new workspaces you create on Windows and intend to move to Linux later as UTF-8 right from the start.

Categories: android, tools

Signing Andorid packages for production builds

September 28, 2011 Leave a comment

I keep thinking about switching my production build system to be Ant-based, but keep exporting from Eclipse instead. Maybe one day… Meanwhile, here is how I get an exported (unsigned, unaligned) .apk ready for Market.

In my source tree, I have a special directory, release, which is the release (duh!) staging area. The production key files are located here, which, besides being convenient, makes sure they get backed up.

Making a production build for me takes three steps:

  1. Cleaning the project in Eclipse (I won’t want my production build to get a weird crash because of an outdated R.java).
  2. Generating an obfuscated, unsigned, unaligned .apk by selecting Android Tools – Export Unsigned Application Package in Eclipse.
  3. Running a script to sign and align the .apk, which gets it ready for a Market or a web site upload, or for installation to a test device.

The filename I use for the second step always follows a special pattern: it’s some base name, with the version number and the suffix “-raw” appended. So for Bluetooth Widget version 1.8.1, I export to “kmanBluetoothWidget-1.8.1-raw.apk“, and for WiFi Manager version 2.1.1pre3 I export to “kmanWifiManager-2.1.1pre3-raw.apk“.

( a side note: the “kman” thing goes back quite a few years… my co-workers used to call me that, because “Kostya” was too complicated for some people )

Similarly, there is a pattern to my production keystores: they are named the same as the application’s base file name (without the version, obviously), and the key alias inside the store also has a certain name.

Now, the script.

I’ve been using PowerShell as my command line window for about a month now, and just today rewrote my script from being a .cmd batch file into a PowerShell script.

The script takes two arguments, the first is the abbreviated application name, and the second is the version number.

So, after exporting, let’s say, kmanWifiManager-2.1.1-raw.apk, I run the script as “.\sign_and_pack.ps1 wfm 2.1.1” – where “wfm” is the application, “WiFi Manager” and “2.1.1” is the verison number. Or I could sign Bluetooth Widget version 1.8.1 by running “.\sign_and_pack.ps1 btw 1.8.1“.

The script determines the application’s exported .apk name based on the arguments, signs it with that particular application’s key, and aligns it for faster runtime resource access as recommended by Google.

Here is the source:

if ($Args.length -lt 2) {
	Write-Output "Usage: sign_and_pack.ps1 program version"
	exit
}

$argProgram = $Args[0]
$argVersion = $Args[1]

switch ($argProgram) {
	"wfm" {
		$procName = "WiFi Manager"
		$procBaseName = "kmanWifiManager"
		$procKeyName = "WifiManagerKey"
	}
	
	"btw" {
		$procName = "Bluetooth Widget"
		$procBaseName = "kmanBluetoothWidget"
		$procKeyName = "BluetoothWidgetKey"
	}

	default {
		Write-Output "Unknown application: $argProgram"
		exit
	}
}

Write-Output "***" "***" "*** Program: $procName, version: $argVersion" "***" "***" ""

$keypass = "*** my keystore password goes here ***"
$fileKeystore = "$procBaseName.keystore"

$fileRaw = "$procBaseName-$argVersion-raw.apk"
$fileTemp = "$procBaseName-$argVersion-temp.apk"
$fileDest = "$procBaseName-$argVersion.apk"

$fileRawExists = Test-Path "$fileRaw"

if (-not $fileRawExists) {
	Write-Output "Error: $fileRaw does not exist"
	exit
}

Write-Output "Copying $fileRaw to $fileTemp"
Copy-Item $fileRaw $fileTemp

Write-Output "Signing $fileTemp with $fileKeystore"
jarsigner -storepass $keypass -keystore $fileKeystore $fileTemp $procKeyName

Write-Output "Aligning $fileTemp to $fileDest"
zipalign -f 4 $fileTemp $fileDest

Remove-Item $fileTemp

Write-Output "" "***" "***" "*** Ready: $fileDest" "***" "***"

#$key = Read-Host "Install? (Y/N)"

#if ($key -eq "Y" -or $key -eq "y") {
#	Write-Output "Installing $fileDest"
#	adb install -r $fileDest
#}

Here is example output, assuming I just exported WiFi Manager 2.1.1 as “kmanWifiManager-2.1.1-raw.apk”:

PS D:\Android\proj-indigo\release> .\sign_and_pack.ps1 wfm 2.1.1
***
***
*** Program: WiFi Manager, version: 2.1.1
***
***

Copying kmanWifiManager-2.1.1-raw.apk to kmanWifiManager-2.1.1-temp.apk
Signing kmanWifiManager-2.1.1-temp.apk with kmanWifiManager.keystore
Aligning kmanWifiManager-2.1.1-temp.apk to kmanWifiManager-2.1.1.apk

***
***
*** Ready: kmanWifiManager-2.1.1.apk
***
***
PS D:\Android\proj-indigo\release> _

The commented-out stuff at the end of the script can install the just generated release .apk to a device (I’m not sure yet which is more convenient: doing it from the script, or typing “adb install -r” myself…)

So here it is….

Categories: android, tools

Workspace never loading in Eclipse

If you’ve been doing Android development for any length of time, you’ve no doubt experienced Eclipse getting stuck loading the workspace.

The symptoms are: you launch Eclipse, it starts to load, the progress bar in the launch window gets to about one third, and then it just sits there. Killing Eclipse.exe and starting over doesn’t help, it just happens again.

Here is a simple fix, found on stack overflow:

Open your workspace’s .metadata directory, then browse to .plugins\org.eclipse.core.resources and delete the file named .snap.

After this, the next time the workspace will load.

Categories: android, tools

Accessing resources in an AndroidTestCase

April 18, 2011 2 comments

I am currently writing some tests for low-level (not UI) classes, using AndroidTestCase. These tests need a variety of pre-configured input files, and I though it would be very convenient to provide these as assets packaged with the test application.

Adding the files as assets to the test application was the easy part, while getting access to them from a subclass of AndroidTestCase required a bit of work.

The base class, AndroidTestCase, has a method, getContext(), but it can’t be used to load assets from the test package, because that context refers to the package under test.

Checking the source for AndoridTestCase, I found these two very promising methods:

// AndroidTestCase
    /**
     * Test context can be used to access resources from the test's own package
     * as opposed to the resources from the test target package. Access to the
     * latter is provided by the context set with the {@link #setContext}
     * method.
     *
     * @hide
     */
    public void setTestContext(Context context) {
        mTestContext = context;
    }

    /**
     * @hide
     */
    public Context getTestContext() {
        return mTestContext;
    }

I only needed the getter method, actually, still – it’s marked with “@hide”, which means it can’t be called by applications.

The @hide marker is enforced by not including the method in Android.jar that applications are compiled with. So this method is present on the device, and does what is needed, but is intentionally made inaccessible to applications. I don’t know the reason why, especially considering the comment above the “set” method.

Ok, whatever the reason is… Time to use Java Reflection to access that context.

public class MessageProcessorTest extends AndroidTestCase {

	private final static String TAG = "MessageProcessorTest";

	private Context mContext;
	private AssetManager mAssets;

	@Override
	protected void setUp() throws Exception {
		super.setUp();

		try {
			Method m = AndroidTestCase.class.getMethod("getTestContext", new Class[] {});
			mContext = (Context) m.invoke(this, (Object[]) null);
		} catch (Exception x) {
			Log.e(TAG, "Error getting test context: ", x);
			throw x;
		}

		Log.i(TAG, "Own context: " + String.valueOf(mContext));

		mAssets = mContext.getAssets();
	}

	public final void test_MessageProcessor_1() {

		try {
			String[] list = mAssets.list("dirname");
			for (String s : list) {
				Log.i(TAG, "Source: " + s);
				InputStream stream = mAssets.open("dirname/" + s, AssetManager.ACCESS_STREAMING);
				runOneTest(stream);
				stream.close();
			}

			Log.i(TAG, "End of test");
		} catch (IOException x) {
			Log.e(TAG, "Exception during testing", x);
			fail();
		}
	}

	private static void runOneTest(InputStream stream) {
		// Run a test driven by the data in the stream
	}
}

And here it is. I can now put my data files under assets to supply a variety of data to the test function.

Categories: android, tools

Eclipse 3.6 SR2 is out

February 27, 2011 Leave a comment

Eclipse Helios 3.6 SR2 has been released. Get yours at the usual place.

The bug that was causing code assist freezes with large JavaDoc files is supposed to be fixed, but I would not know, because I got so used to having Android source installed! Great for exploring how things work, especially with Eclipse’s fast and easy way to open any Java class.

Try this (if you have the sources installed, pre my earlier posts): press Ctrl+Shift+T, enter “Activity”, and press Ok.

I’m already running this new Eclipse version, with the memory limit increased to 512 MB through eclipse.ini:

-startup
plugins/org.eclipse.equinox.launcher_1.1.1.R36x_v20101122_1400.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.1.2.R36x_v20101222
-product
org.eclipse.epp.package.java.product
--launcher.defaultAction
openFile
--launcher.XXMaxPermSize
512M
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
512m
--launcher.defaultAction
openFile
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx512m

Still on my mental to-do list: to try 64-bit Java and Eclipse (I’m running Windows 7 64-bit). The rest of my specs: Intel i860 CPU, 4 Gb of RAM, and a Corsair V128 SSD.

Categories: android, tools

“Jump to declaration” in Eclipse with Android ADT 9.0

January 29, 2011 Leave a comment

ADT 9.0 has a new feature: it lets you jump to the Android declarations of various resources.

I really wanted to use it, and tried pressing “F3″, which is the standard Eclipse way of jumping to a Java declaration. Right? Wrong!

Next I checked a few other places where this feature could be, like the “Navigation” menu. Not there, either!

Ok, here is the trick. At the risk of sounding like Capt. Obvious:

Capt. says "Hold down Ctrl"

You’ve got to hold down Ctrl while hovering the mouse. This pops up a a nice little menu, which lets you choose between jumping to the Java declaration (which is not too useful for R.id values) or to the actual declaration in an Android-specific XML file.

Categories: android, tools

Installing Android sources into Eclipse for debugging

January 27, 2011 2 comments

A couple of weeks ago I installed Android sources into my Eclipse environment. My primary motivation was to get JavaDoc comments in code assist, but those sources were also picked up by the debugger.

The problem with mismatched Android version sources

It’s pretty common when developing for Android to build the application with one version of Android SDK and debug with another (typically earlier) version. My environment is no exception: I build with Android 2.2 SDK, and debug on a Motorola Milestone that runs 2.1update1 (which will never be updated to 2.2, but that’s another story). This means that the sources installed for JavaDoc and code assistance are, strictly speaking, not the right ones for debugging, as you can see in the screenshot below:

performLaunchActivity vs. startActivityNow

The debugger says the application is stopped inside performLaunchActivity, but the source window shows startActivityNow. Let’s fix that.

Getting the right sources (again)

My development phone is a Motorola Milestone running 2.1update1, so I needed to find the right (or close enough) version of the base Android framework in the repository here:

http://android.git.kernel.org/?p=platform/frameworks/base.git;a=summary

I found what looked like 2.1update1 for my Milestone at the bottom of that page; it was a branch called “eclair-sholes-release2″ (“sholes” being the codename for Motorola Droid / Milestone architecture, and assuming that “eclair-sholes-release” was the first 2.1 release).

sholes-release-2 branch

In addition to the list of branches, the page also has a list of tags, which is another place to look for a particular version of Android.

Clicking on “eclair-sholes-release2″ took me to this page:

http://android.git.kernel.org/?p=platform/frameworks/base.git;a=shortlog;h=refs/heads/eclair-sholes-release2

which doesn’t have a download link, so I replaced “a=shortlong” with “a=snapshot” in the URL:

http://android.git.kernel.org/?p=platform/frameworks/base.git;a=snapshot;h=refs/heads/eclair-sholes-release2

Source code from major release-specific branches can be downloaded like this:

http://android.git.kernel.org/?p=platform/frameworks/base.git;a=snapshot;h=refs/heads/froyo;sf=tgz

You can get other versions by changing the branch name (froyo) in the link above (to donut, gingerbread, etc.)

Extracting the sources

This is how I extracted the sources on my computer, nothing special:

Extracting the sources

Pointing the debugger at the sources

The debugger has its own setting for source code lookup, which is separate from the “source attachment” to android.jar used before. To set this, switch to the debug perspective, then right-click on your running application, and select “Edit Source Lookup”, then proceed as shown below.

The left screenshot below also shows a deliberate error I made in one of my layouts, by having a ScrollView with more than one child, thus making my application crash.

The right screenshot shows how to select the right folder where Android 2.1u1 sources were extracted.

Bringing up debugger source lookup

Selecting the sources directory

This completes the setup.

The right source code version shown after a crash

This is what I get now instead of the misaligned source code shown near the top of this page. Looks like a pretty significant improvement to me:

Matching sources and variables

Categories: android, tools

Fixing slow code assist for Android in Eclipse Helios – update 2 (and getting Android sources into Eclipse, too!)

January 15, 2011 5 comments

As you can see from my previous posts, getting code assist to work well for Android projects in Eclipse Helios can be done in one of two ways. You can either uninstall Android JavaDoc package and lose method and parameter descriptions in code assist, or install a patched eclipse JDT plugin.

There is a third way, and you get Android sources for easy referencing and debugging too. Best thing, it’s really simple and only takes three steps.

Update January 29, 2011: make sure to also check out this post, which shows how to build with one version of Android and debug with sources for another.

1 – Get Android framework sources

If you don’t build Andorid system images, and don’t have Git and repo tool, get the sources from http://android.git.kernel.org as a tarball.

This is the framework tarball for Froyo (108 Megabytes):

http://android.git.kernel.org/?p=platform/frameworks/base.git;a=snapshot;h=froyo;sf=tgz

You can get other versions by changing the tag (froyo) in the link above (to donut, gingerbread, etc.)

2 – Extract a portion of the tarball into the right place

Eclipse wants sources in the right place, organized by package name, the same way the source code for your project is organized.

That right place is a “sources” directory that you should create under your android-sdk-windows\platforms\android-VERSION.

Open the tarball with your favorite program (I use WinRar) and navigate to core\java inside it. You will see a directory called “android”, which looks like this:

Now you need to extract the “android” folder inside the tarball into android-sdk-windows\platforms\android-VERSION\sources, so you get this:

3 – Verify the settings for Android.jar and hit refresh

Right click on android.jar in your project, and verify the location path:

After closing this dialog, refresh your project (press F5 in the project explorer or right-click on your project and choose Refresh).

And this is what we get from doing the above

JavaDoc in code assist

The ability to view Android framework sources right from Eclipse

… which also works in the debugger

And that’s it. With many thanks to http://android.opensourceror.org/2010/01/18/android-source/

Categories: android, tools
Follow

Get every new post delivered to your Inbox.