Scope

Because I was trying Ubuntu 10.10 on my laptop, I had to install a new development environment. Not too much work: I’ve used the installing instructions from Google [1].

This basically boils down to:

  1. Install Eclipse (I just used the ubuntu software center for this).
  2. Download Android SDK and unpack it.
  3. Install Android ADT plugin for Eclipse using the Eclipse install-software feature [2]
  4. Set the path to the android SDK / tools (step 2)  in the Eclipse preferences.

I didn’t install the JDK, because it was on my machine by default. I assume the package manager has that, but I’m not sure. Now I’m all happy with my new toys, installing Subclipse for SVN, getting my source, and coding away. Then the trouble started :)

Symptoms

It seems that I couldn’t  start any Android Virtual Device (AVD). I made a new run configuration, but it didn’t start. Instead I got an error, stating:

‘Launching android’ has encountered a problem.

An internal error occurred during : “Launching android”.

Clicking “details >>” produces an extra line:

Path for project must have only one segment

And, for full disclosure, the complete log-entry included trailing this post.

Cause & Solution

It seems that this rather cryptic message means nothing more in my case than “please enter a name and project for your run configuration”. I did have a “name”, but left the “Project” field empty. Entering a value in the ‘project’ (the “AndroBlip” you see next to ‘browse’) fixed it. Sources seem to indicate that the same error is produced if you don’t enter a value in the ‘name’-field.

run configurations screenshot

Screenshot

References

  1. http://developer.android.com/sdk/installing.html
  2. https://dl-ssl.google.com/android/eclipse/
  3. http://stackoverflow.com/questions/4961151/android-path-for-project-must-have-only-one-segment

Complete error log

!ENTRY org.eclipse.core.jobs 4 2 2011-02-20 12:12:00.397
!MESSAGE An internal error occurred during: “Launching android”.
!STACK 0
java.lang.IllegalArgumentException: Path for project must have only one segment.
at org.eclipse.core.runtime.Assert.isLegal(Assert.java:63)
at org.eclipse.core.internal.resources.WorkspaceRoot
.getProject(WorkspaceRoot.java:181)
at com.android.ide.eclipse.adt.internal.launch.LaunchConfigDelegate
.getProject(Unknown Source)
at com.android.ide.eclipse.adt.internal.launch.LaunchConfigDelegate
.launch(Unknown Source)
at org.eclipse.debug.internal.core.LaunchConfiguration
.launch(LaunchConfiguration.java:853)
at org.eclipse.debug.internal.core.LaunchConfiguration
.launch(LaunchConfiguration.java:703)
at org.eclipse.debug.internal.ui.DebugUIPlugin
.buildAndLaunch(DebugUIPlugin.java:866)
at org.eclipse.debug.internal.ui.DebugUIPlugin$8
.run(DebugUIPlugin.java:1069)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)

Android Market on the web

On 2011/02/04, in AndroBlip, Market, by uzar

Google launched their Android Market on the web two days ago. What I personally like is being able to browse through my installed Android apps on my computer and find new ones to install. You can buy apps on the web and they wil automatically be installed on your phone. There is also the option of leaving a user review for an app.

Of course we immediately looked to see how AndroBlip was featured there! :-)

AndroBlip on the Android Market on the web

Hopefully, this new way of finding apps for Android will make it easier to leave comments or suggestions for our app. We hope to see some user reviews soon!

There is also an option for us to add video’s to the app description, like for example Winamp did on their Market page. Suggestions for making a (fun?) video are welcome!

Simple EditText limitations

On 2011/01/12, in Android, Code, by ennaN

Indeed, quite simple, but still.

Limiting character amount

The first goal was to limit the amount of characters someone can type in an EditText. Well, this sounds easy and it is. You can set a filter, like so:

editText.setFilters(new InputFilter[]{
         new InputFilter.LengthFilter(MAX_SIZE)
});

Limiting to a certain value

Now to implement this for the setting that stops you from asking for a million pictures to be downloaded.

To be clearer: I have a preference that lets you set the amount of pictures you can download. You should be able to write only numbers* here.. I’ve done this, more or less inelegantly, with the “android:digit” attribute in the xml:

<EditTextPreference
       android:title="Max Amount"
       android:summary="The more, the heavier. Default = 12"
       android:key="viewMax"
       android:defaultValue="12"
       android:digits="0123456789"/>

* no, we’re not entering the amount in HEX.

This works OK, but you can type in a lot of 9′s if you want. That’s no good.

Now to add another LengthFilter is only applicable for numbers  up to (10^y)-1, e.g. up to 999: a LengthFilter(3) will of course limit you to 3 characters, not to an int of max 3.

I have not found a filter for the maximum value, as the standard InputFilter gives us “ALLCAPS” and the previously used LengthFilter. I think the cleanest method might be to write an InputFilter, but it’s rather easy to fix without one, using an OnSharedPreferenceChangeListener.

Simple summary of how to limit an edittext to a certain value

We can add a lot of Listeners, that trigger on a lot of different moments, this is just an example. The moment of warning might be a bit late (after having set the value), but as a proof-of-concept:

Implement OnSharedPreferenceChangeListener

Whenever you’ve changed the preference, trigger a function to check if everything is sane. The activity implements OnSharedPreferenceChangeListener, so you can do this:

getPreferenceScreen().getSharedPreferences()
              .registerOnSharedPreferenceChangeListener(this);

The Listener

Add the listener. It will check for the set value, and correct it if it’s not sane.

public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
		String key) {
  if ("yourPrefName".equals(key)) {
    String valueString = sharedPreferences.getString(key, "");
    int value = Integer.parseInt(valueString);
    if(value > MAX_VALUE){
	EditTextPreference p = (EditTextPreference) findPreference(key);
	p.setText(""+MAX_VALUE);
	Toast t = Toast.makeText(this,"Maximum amount limited to "+MAX_VALUE, Toast.LENGTH_SHORT);
	t.show();
    }else if(value < MIN_VALUE){
	EditTextPreference p = (EditTextPreference) findPreference(key);
	p.setText(""+MIN_VALUE);
	Toast t = Toast.makeText(this,"Minimum amount limited to "+MIN_VALUE, Toast.LENGTH_SHORT);
	t.show();
    }
}

This means that you CAN enter numbers that are too high or too low, but at least you’ll get a message saying you’ve failed, and the preference will remain something sane.

Bonus: a filter on an EditTextPreference

Now for a quick bonus. I was annoyed at first why you cannot simple add a filter to your EditTextPreference like you would with an EditText

yourEditTextPreference.setFilters(yourFilters);

This is because the input you’re getting for a preference actually is an EditText, and you’ve got to find it. Short story even shorter: get the EditText from the EditTextPreference. Duh :)

yourEditTextPreference.getEditText().setFilters(yourFilters);

Now I’ll see how fun it is to write a real filter. Why not?

Hierarchy viewer problems

On 2011/01/10, in Android, Code, by ennaN

Time to catch up on some of the android blogposts! Lets start with a simple one: this annoying bug stops you from opening the very usefull Hierarchy-viewer.

“Failed to get the adb version: Cannot run program “adb.exe”: CreateProcess error=2, The system cannot find the file specified”

There seem to be several issues here, ranging from installing all sorts of new stuff to reinstalling the SDK, but there’s one sollution that has helpt me on 2 different (windows) machines: adding the new location of the “adb.exe” to your environment path.

Step 1: locate adb.exe. It wil probably be in the platform-tools dir (that’s new I guess)

Step 2: add the location to your PATH. In windows 7:

  • Rightclick on “my computer”
  • Advanced system settings (on the left)
  • Button “Environment Variables”
  • Select “PATH” and press “Edit…”
  • Add your path, e.g. add in the end: “;c:\android\sdk\platform-tools
  • press all OK buttons.

Win!

AndroBlip 2.0

On 2011/01/09, in Releases, by ennaN

AndroBlip in the Android MarketA long time since there was an update! We’ve been changing things like crazy, sometimes two or three times over, so it took a little more time than planned.

First of all: how to get it, second: what’s new?

Getting AndroBlip 2.0

1. Download AndroBlip on the Android market (small fee of 0,99 euro)
2. Download from the Website (apk): Androblip 2.0 (free).

Be adviced: you’ll probably have to re-authenticate to your account after updating. Really sorry about that.

ChangeLog

Apart from the extra features, the layout changes and bugfixes, there are a lot of changes going on “under the hood”. That’s why this major release is baptized “2.0″! We haven’t thought of a spiffy name for this release, sorry bout that :). Check out the new layout (List style) and tell us what you think!

Features

  • Added Search. Press the search key on your phone, or select it as a view
  • Notifications added. Press menu->notifications
  • Page up/down buttons on the comments screen: easy scrolling! Long-click on these buttons for top/bottom

Layout

  • The Grid should render a lot better now (no more 1-pixel-too-large). Major thanks to Thomas from Frozen Fractal for that!
  • New layout: List view (go to menu->prefs to set this style)
  • Preferences are now according to Android standards
  • Easier usable buttons (e.g. view-choosing dialog, links at the bottom of entries)
  • Fixed ‘add date’ difficulties in upload screen
  • Trying to find the last texts without the proper font
  • Numerous smaller changes

Bugfixes & other changes

  • Bugfix for relative paths in links
  • Loading screens are dismissable
  • Cache uses standard (browser shared) cache
  • Grid layout now works for all(?) aspect ratios
  • Work on the back-button behaviour (we’ve seen that one before :)  )
  • Entry date visible
  • After posting comment view that comment

Handling HTML in a TextView

On 2010/11/28, in Android, Code, by ennaN

When you have HTML and you want to show it to your users, one of the possibilities is using a WebView. Check the WebView tutorial for more info. You can also use a TextView, but the HTML has to be changed for that. You could use linkify for this. This should be enough, but when you also want (for instance) bold and italic to work, we have to do some more trickery. The first iteration we used was this:

//description is a TextView
description.setText(Html.fromHtml(desc));
description.setMovementMethod(LinkMovementMethod.getInstance());

This works amazingly well, except for this ‘minor’ detail: full links are working perfectly, but a link like this does a force close:

<a href="/dr">Link with relative path</a>

The TextView is not a browser, so it doesn’t even know what protocol we are using, let alone what domain or path we’re supposed to be in. This will result in a force close, with a log that looks like this:

ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.View data=/dr}

The intent expects something like “http://” or “mailto:” I presume, but if it gets “/dr”, there is no activity to handle the link.

Elegance aside, a simple solution is to make an absolute link if you know the correct data. This is a quick and dirty solution, but let’s share it anyway because a lot of solutions we found were specifically for linkify, not for complete “fromhtml” purposes.

/**
 * Removes relative a hrefs
 * @param spantext (from Html.fromhtml())
 * @return spanned with fixed links
 */
public Spanned correctLinkPaths (Spanned spantext) {
  Object[] spans = spantext.getSpans(0, spantext.length(), Object.class);
  for (Object span : spans) {
    int start = spantext.getSpanStart(span);
    int end = spantext.getSpanEnd(span);
    int flags = spantext.getSpanFlags(span);
    if (span instanceof URLSpan) {
      URLSpan urlSpan = (URLSpan) span;
      if (!urlSpan.getURL().startsWith("http")) {
        if (urlSpan.getURL().startsWith("/")) {
          urlSpan = new URLSpan("http://domain+path" + urlSpan.getURL());
        } else {
          urlSpan = new URLSpan("http://domain+path/" + urlSpan.getURL());
        }
      }
      ((Spannable) spantext).removeSpan(span);
      ((Spannable) spantext).setSpan(urlSpan, start, end, flags);
    }
  }
  return spantext;
}

We traverse the objects in the Spanned. If we find a URLSpan we copy the span and fix that one. Then we remove the old span, and insert the new one. The copy move might not be necessary, but as it doesn’t bother us at the moment I’ll leave it like this. This has taken up quite enough time, thankyouverymuch. If you want to do something extra, and instead of opening a browser do your own onClick magic, you can take a look at this anddev forumthread.

Finally, our assign has to look like this obviously:

//description is still a TextView
description.setText(correctLinkPaths(Html.fromHtml(desc)));
description.setMovementMethod(LinkMovementMethod.getInstance());

Another interesting link is this bugreport on code.google.com. I’d say that your browser shouldn’t know where to point itself, but apparently the project members don’t agree.

No drives in export dialog

A bit offtopic from the usual ‘I had trouble with android’ posts, but this morning as I was trying to export some pictures, and only my ‘user dir’ and ‘desktop’ where available for choice. No disks at all. Annoying.

The reason it happened was, I think, the last export location (a removable device) wasn’t there anymore. Don’t know this for sure though.Anyway, teh google helps! It’s about the same symptoms, maybe not the same cause but still. Some sidenotes to that post are neccessairy, so this is what I did:

First, find the preferences file.

This is the location on my windows 7 , but the forum post also states this article for more location possibilities on other systems like Vista and all.

C:\Users\–YOUR USERNAME–\AppData\Roaming\Adobe\Lightroom\Preferences

It could be you try to open the “Application Data” dir, but for some reason this doesn’t work in Windows 7 installs. Just go to that AppData dir. Just try to find the file called “”Lightroom 2 Preferences.agprefs”.

Find the line for the export dialog.

Find this line:

AgMRUPopupList_AgExport_destinationFolderPathPrefix

Fix that line.

With me there was a line in there that was not a real option anymore. But just removing that line didn’t work. I don’t know why, but I had to fiddle around with it a bit. It seems to me that there should be more than 1 line, and they all should exist. My file part looks like this now:

AgMRUPopupList_AgExport_destinationFolderPathPrefix = “s = {\
\”C:\”,\
\”E:\\\\fotos\”,\
}\

Finished!

Again, props to this adobe forums link , which by the way also describes the lines to edit for a similar problem with the import dialog.

http://forums.adobe.com/message/2746280

It seems that a WebView element in Android reserves some space for a vertical scrollbar by default. This shows up as a small, vertical strip of white space on the right, which is not padding or margin but some space reserved for a scrollbar.

To get rid of this you have to set the scrollbar style to display the scrollbars inside the content area. This can be done with the following code:

webview.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

AndroBlip 1.4

On 2010/08/29, in AndroBlip, Releases, by ennaN

AndroBlip in the Android MarketAs the end of life.turns. is come and gone we can safely say that the quick development and release circle for that feature didn’t do too much harm. Now these features have to be removed as the project is at it’s end. Together with some small layout changes and some requests this makes for version 1.4!

Getting AndroBlip 1.4

1. Download AndroBlip on the Android market (small fee of 0,99 euro)
2. Download from the Website (apk): Androblip 1.4 (free).

ChangeLog

Removed life.turns. options

As the options and upload were specifically for the life.turns. project that has ended, the clutter has been reduced by removing the files and menu option for it.

Long-press on entry shows EXIF

A reasonable request, and easy enough to do: long-press on an entry shows you the EXIF information, just as you would see when you click the link a bit lower on the same page.

Autorefresh

The first second comment in the market (by ‘Andrew’) requested this quite quickly and it has been requested by mail too. We’ve made this a setting, because it can be a real pain when you have a bad data connection. It starts ‘off’ by default, and you can find it in the preferences. We also changed the ‘loading’ behaviour a bit, so to have a better reponse on slow loading systems. If you’re checking out the preferences, also check out the new layout of the about page, where we now list some new application statistics.

Stats

We’ve added the new resource ‘statistics’ on the about page as you can see below.

File location Bugfix

The previous update tried to fix the fact that all files were saved in the root of your sdcard. But that didn’t work. This update should fix that persistent bug and place everything in the .AndroBlip folder. You can remove all the files starting with “.ABlipCache” if you want because they should and will be stored in the .ABlipCache folder. (Yes, you can figure out why I didn’t fix the bug in the first place from those filenames and that foldername :)  )

This morning I woke up to this little message:

Error generating final archive: Debug certificate expired on 8/23/10 8:45 AM!    AndroBlip.coffee        Unknown    Android Packaging Problem

Well, that was annoying. According to google this is expected after your debug key is a year old. I have no clue why this is; it doesn’t seem to have any purpose, but luckily they do find us a solution:

To fix this problem, simply delete the debug.keystore file. The default storage location for AVDs is in ~/.android/avd on OS X and Linux, in C:\Documents and Settings\\.android\ on Windows XP, and in C:\Users\\.android\ on Windows Vista.

The next time you build, the build tools will regenerate a new keystore and debug key

This also seems to happen if you’re on a non-gregorian locale, but that’s not the case for me. Check out that google link for that one.

Minor note: running the program on the same virtual machine, gives you trouble with a new signing/debug key:

installation failed due to different application signatures.
You must perform a full uninstall of the application. WARNING: This will remove the application data!
Please execute ‘adb uninstall com.huiges.AndroBlip’ in a shell.
Launch canceled!

Just uninstalling the application in the virtual machine works fine.
It does however mean that if you work with a lot of test-data in your app, you’ll have to find a way to keep that around when uninstalling your app. As far as I know this is unavoidable when your key expires. This site comes up with a solution: create your own key with a much larger expiration date:

keytool -genkey -keypass android -keystore debug.keystore -alias androiddebugkey -storepass android -validity 10000 -dname "CN=Android Debug,O=Android,C=US"