android


Using styles on Android layouts 1

A very cool feature of Android that many developers do not know (at least me 6 months ago) is the possibility of using “styles” on Android XML layouts. This thing is similar to CCS on HTML and provides a method to simplify the XML design.

First, let’s see an example of a XML layout without styles, you can notice the need to repeat attributes and the difficulty of reading the XML:

<LinearLayout
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:orientation="vertical">
 <TextView
  android:text="@string/text1"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:textStyle="bold"
  android:textColor="@color/white"
 />
 <TextView
  android:text="@string/text2"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:textStyle="bold"
  android:textColor="@color/red"
 />
</LinearLayout>

But we can define styles grouping this attributes on the file res/values/styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <style name="VerticalLinearLayout">
  <item name="android:layout_width">wrap_content</item>
  <item name="android:layout_height">wrap_content</item>
  <item name="android:orientation">vertical</item>
 </style>
 <style name="WhiteText">
  <item name="android:layout_width">wrap_content</item>
  <item name="android:layout_height">wrap_content</item>
  <item name="android:orientation">vertical</item>
  <item name="android:textStyle">bold</item>
  <item name="android:textColor">@color/white</item>
 </style>
 <style name="RedText" parent="@style/WhiteText">
  <item name="android:textColor">@color/red</item>
 </style>
</resources>

Note te possibility of  inheriting styles, in this example “RedText” is inherited from the “WhiteText” style changing only the text color.

Our XML layout, with styles, gets reduced to:

<LinearLayout style="@style/VerticalLinearLayout"/>
 <TextView style="@style/WhiteText"
  android:text="@string/text1"
 />
 <TextView style="@style/RedText"
  android:text="@string/text2"
 />
</LinearLayout>

Finally,  you can see that I’m using colors (@color/white and @color/red) which must be defined on the file res/values/colors.xml (in a similar way to strings):

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <color name="white">#ffffffff</color>
 <color name="red">#ffff0000</color>
</resources>

A small problem with the facebook Android SDK

At Mobialia the lasts weeks I was involved on the development of a social app using, among other social networks APIs, the facebook API.

For me it was easier to implement Twitter API access using only the signpost library, for facebook they recommend to download their Android SDK, and I did so. First we need a class attribute with the Facebook object:

Facebook fb = new Facebook(appId);

The problem is during the autentication process: we must call the fb.authorize method…

fb.authorize(this, PERMISSIONS, ACTIVITY_CODE, this);

And wait for the result of this called activity on our onActivityResult method

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    fb.authorizeCallback(requestCode, resultCode, data);
}

But, here is the problem, under heavy memory requierements (like testing on a old HTC Magic) the caller activity may be killed, and the status of the Facebook object is not maintained so the call to authorizeCallback is going to fail.

Then I need a method to mantain the Facebook object status, and here comes the hack. I added this method to the Facebook object:

public void setStatus(int mAuthActivityCode, DialogListener mAuthDialogListener){
    this.mAuthActivityCode = mAuthActivityCode;
    this.mAuthDialogListener = mAuthDialogListener;
}

And I call this method on my onActivityResult:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    fb.setStatus(ACTIVITY_CODE, this);
    fb.authorizeCallback(requestCode, resultCode, data);
}

Note that the DialogListener is the same Activity. Other solution may be to avoid killing of the caller activity, but I don’t figure how…


Using two location providers on Android 2


Android has two kinds of accuracy on location:

  • Fine: provided by the GPS, needs some time to be obtained
  • Coarse: location determined with the cell of the mobile network

This location methods can be enabled or disabled by the user on the preferences or with some widgets.

Initially on our apps we used only one LocationProvider with “Fine” accuracy:

  • If the GPS was disabled it used automatically network-based location
  • But if GPS was enabled, the location used it needing some time to be determined

As the data couldn’t be obtained until the location is determined, the app didn’t showed data, receiving this kind of error reports from some users.

The best solution that I found is to mantain two separated providers, with different precisions and receive location updates using both.

LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(false);
criteria.setPowerRequirement(Criteria.POWER_LOW);       

criteria.setAccuracy(Criteria.ACCURACY_FINE);
String providerFine = manager.getBestProvider(criteria, true);

criteria.setAccuracy(Criteria.ACCURACY_COARSE);
String providerCoarse = manager.getBestProvider(criteria, true);

if (providerCoarse != null) {
    manager.requestLocationUpdates(providerCoarse, 5*60000, 100, this);
}
if (providerFine != null) {
    manager.requestLocationUpdates(providerFine, 5*60000, 100, this);
}

You can also check if providerFine and providerCoarse are the same provider. When receiving location, the one received from providerFine must take precedence over the one from providerCoarse. Location’s provider can be obtained with location.getProvider():

public void onLocationChanged(Location location) {
     if (location.getProvider().equals(providerFine)) {
     ...

This is a trick that we are using on our Gas Stations Spain app and also on Wikiplaces (open sourced).


Mobialia at LabAndroid 1

This week I was speaking at LabAndroid, a spanish initiative about Android devices, apps and development.

I developed a special app for this event called “Wikiplaces” and I made the code avaiable as open source on Google Code.

This app shows on a map or on a list places from Wikipedia near your location. I tried to include on it small code snippets for common things like styles on layouts, obtaining location, launching Google Maps Navigation, etc.


Dealing with the “Bitmap Size Exceeds VM Budget” error

One of the most common errors that I found developing Android Apps is the “java.lang.OutOfMemoryError: Bitmap Size Exceeds VM Budget” error. I found this error frecuently on activities using lots of bitmaps after changing orientation: the Activity is destroyed, created again and the layouts are “inflated” from the XML consuming the VM memory avaiable for bitmaps.

Bitmaps on the previous activity layout are not properly deallocated by the garbage collector because they have crossed references to their activity. After many experiments and consulting with the cost of an ecommerce website, I found a quite good solution for this problem.

First, set the “id” attribute on the parent view of your XML layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:id="@+id/RootView"
>
...

Then, on the onDestroy()  method of your Activity, call the unbindDrawables() method passing a refence to the parent View and then do a System.gc()

@Override
protected void onDestroy() {
	super.onDestroy();

	unbindDrawables(findViewById(R.id.RootView));
	System.gc();
}

private void unbindDrawables(View view) {
	if (view.getBackground() != null) {
		view.getBackground().setCallback(null);
	}
	if (view instanceof ViewGroup) {
		for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
			unbindDrawables(((ViewGroup) view).getChildAt(i));
		}
		((ViewGroup) view).removeAllViews();
	}
}

This unbindDrawables() method explores the view tree recursively and:

  • Removes callbacks on all the background drawables
  • Removes childs on every viewgroup

This solved the problem on many of our Mobialia apps.

UPDATE 2011-03-30:

Today @luiskap from SpartanBits told me another good solution: if you don’t need different layouts for portrait and landscape modes, you can make your activity react to orientation changes (avoiding activity destroy) adding to your activity’s manifest: android:configChanges="keyboardHidden|orientation" and overriding the onConfigurationChanged method, calling setContentView reusing the already created views. There is a good explanation on StackOverflow.


Find Android apps with AppBrain

One of the first things that you can notice after buying an Android phone is the great amount of mobile applications (apps) that you can download from the Android Market, but searching for a specific app can be very frustrating, and a time-consuming task.

This is due to one of the biggest problems of the Android Market: the lack of a complete web interface to query the applications avaiable, and AppBrain is an independent web (not affiliated with Google) where you can list, search, etc. those apps.

There are many similar webs: Cyrket, Bubiloop, but Appbrain has some features which make the difference:

  • You can sign-in on the web with your Google account
  • Apps can be queried by country, genre (of the user), age range, etc.
  • You can create list of apps and share it with your friends
  • There is an android app (search for AppBrain on the Android Market) to synchronize your mobile with appbrain, and once installed:
  • You can query the installed apps on your mobile
  • You can install apps from the web

And everything with a very simple and pretty interface, so don’t wait to try it:

http://www.appbrain.com


Google DevFest 2010

As many of you know, this year I’m involved on Android with my project Mobialia. On February I was on the Android Developer Lab at Madrid and today I returned for the Google DevFest.

The event started with Dave Burke presenting Google Technologies in general. Many jokes about the iPhone (to show the Chrome2Phone extension he send a page about iPhone unlocking from Chrome to a Nexus One). He made the typical Sunspider Javascript Test comparation between a Nexus One with Froyo and an iPad. It also was quite impressive so see GWT Quake2 Port running on Chrome at 50 FPS and the new voice/camera input fields on HTML5.

Then the sessions where split on two lines, I assisted to the Android, Chrome&HTML5 and Maps related.

Our beloved Reto Meier was speaking at the Android Sessions, much more technical than on February’s Android Developer Lab (good!). On his first session he made a great presentation about good and bad practices developing Android Apps (I suggest every android developer to see it!), on the second he speaked in detail about Cloud to Device Messaging and vice-versa. He gave me lots of app ideas using this feature. Finally he swowed us proudly his new Samsung Galaxy Tab and encouraged us to adapt our applications to the new tablet devices.

There were also very short presentations of spanish app developers (eAdventure, LibreGeoSocial, Inmobilia, Sicad and great the one of AnderWeb!).

Next, Paul Kinlan speaked about Chrome Apps and Extensions, the App Store and HTML5 on detail. I’m also very happy to see the progression of HTML5 and how Chrome is leaveraging the innovation towards a better web. Quite funny to see a modified Pacman Doodle controlled with the acceleromers of the iBook. There was also a presentation of Fiabee showing their HTML5 app and Chrome extension.

On the last sessions with Josh Livni talking about maps and presenting the Google Maps API v3, I was very impressed with maps customization, Fusion Tables and the new Google Street view API possibiliting the creation of 360º photos and adding them on specific locations (as inside a bar!).

All the sessions where recorded on video and will be avaiable at the Google DevFest Madrid web site.


Mobialia Chess Engine for Android

The new version 2.0 adds the support to play online on freechess.org (FICS). You can play against people all around the world and compare your chess knowledge with this engine we’re creating. Thousands of hours of entertainment with this new version.

This needs to be a comprehensive chess engine, with full understanding of all rules and moves along with the ability to vary the level of AI difficulty.

Other features will include 1 and 2 player functionality, choice of board/pieces, undo last move, move animations etc

Please provide details of any previous projects that may be relevant, If we like the look of your work we will reply with a detailed game brief.

Bidders should have previous experience in developing apps and games and be familiar with Android OS. There is the potential for an IOS version at a later date so experience in Xcode would be a bonus.

Require a turnaround within 14 days of accepting project so would be suited to someone who has already developed a similar title.

Also has many improvements on the interface and gameplay, which makes Mobialia Chess 2.0 the best chess app for Androidso you can play it with the best accessories from sites like HotRate online, like headsets or android controllers.

Try it! The LITE version is free, and the complete version is available for only 1.99 EUR at the Android Market and if you like playing more from a desktop computer or laptop you can find out more here about this awesome website for every type of online gaming, so you can start your chess tournament from your android or laptop from home !

Check all the Mobialia Chess for Android features at http://www.mobialia.com/chess