Thursday, February 16, 2012

Google's Android Market and Apple's App Store (part2)

Some days ago I wrote about a comparison between Google's Android Market and Apple's App Store.
In this blogpost I will describe what happened after the first blogpost.


Valve response

We got the following email from Valve.

Valve recently filed a takedown notice with Google’s Android Market based on infringement of the trademark Steam by Nasa Trained Monkey’s “Steam Mobile” app. Valve is the owner of trademarks in Steam and the Steam logo. The Steam mark is registered in many countries.

We are happy for developers to use the Steam APIs, but we are concerned about confusion with your use of Valve’s trademarks. Unfortunately, Google’s infringement notice is very generic and does not allow us to explain what we want from the app author. Both of the following changes are required to remedy the trademark issues:

1. Change the name of your app in the title and/or icon to not contain “Steam” first, such as “Nasa Trained Monkey’s Chat for Steam” or some other name that does not confuse the public into thinking Valve created the app.
2. Use an application icon (and any other associated imagery) which does not include Valve’s Steam logo.

If you can make these changes, we’d be happy to see your app going back up. We do appreciate your support of the Steam community. Please respond with any questions. Thank you.

Google response

My blogpost was read by Matias Sulzberger @sulzberger. I studied with him in the university and he now works in Google Argentina. He contacted me and told me he was going to show it to someone inside Google.

Thanks to Matias, I met Nicolas Bortolotti @nickbortolotti.
Nicolas is a Developer Relations Program Manager in Google. He took the time to come to our offices to talk about the Android Ecosystem in Argentina.

We explained him our issues with the Android market and how different it is in relation with the AppStore. He told us that he will use our case to find a way to improve the experience.

Conclusion
For now, the situation stays the same but I am happy that someone is doing something about this.

Friday, February 10, 2012

Global Android Dev Camp desde Argentina!


Ayer el GTUG La Plata envió un comunicado sobre su participación en el Global Android dev Camp. Les dejo la información.

El fin de semana del 18 y 19 de Febrero hay un evento mundial de programación en Android, el Android Dev Camp. El evento es una competencia de programación en la que se desarrolla un aplicación durante las horas que dura, y se realiza en muchas ciudades al mismo tiempo.

Luego del evento se va a votar la mejor aplicación y van a haber varios premios, entre los sponsors globales están o'reilly, paypal y sony. Y se pueden sumar algunos más esta semana.

El evento en La Plata se hace en las oficinas de devsAr y durante el evento se dará ayuda con el desarrollo, y va a haber video-conferencias (hangouts) de 15 minutos cada 2 horas sobre distintas APIs de Android.

Los que estén interesados llenen este formulario para participar:
https://docs.google.com/spreadsheet/viewform?hl=es_ES&formkey=dGcwdjV...

Para información del evento global visiten:
http://android-dev-camp-2012.blogspot.com/

Suerte!

Wednesday, February 8, 2012

Porting android apps to the Playbook

Last night I tried to port two android applications I have in the Android market to the Playbook. This is my experience so far.

With the Playbook and BB10 supporting the Java Android Runtime, RIM opened the door to android developers. You can basically repack your android app to work inside the Playbook and BB10 powered devices.

After installing the Eclipse plugin and started working to get this done.

Super simple app
My first app to repack was a simple sound bank app called TanoPasman.
I opened the project in Eclipse,

Right click on the project => Blackberry tools => Add Blackberry Nature to the project.
Right click on the project => Run as... => Blackberry Android Launch.
That's it. First application repacked!

More complex app
The second app I repacked was a bit more complex.
It's called EstadoDelTransito and it's a traffic status application for Buenos Aires, Argentina.
Source code is available here.

I did the same process but this time it failed. Google maps are not allowed.
What!? Which are the limitations again?

Here's the full list.
Inside that we can read:

The following Java software packages:
Vending (In App Payments): com.android.vending
Cloud To Device Messaging (Push): com.google.android.c2dm
Google Maps: com.google.android.maps
Text to Speech: com.google.tts

I ended up removing the google maps dependency and every call to the map library.
After up the launched without any issue but another problem appeared. ACTION_SEND is not supported :(

Looking for alternatives
Honestly I was quite pissed that I couldn't use maps inside the Playbook.
A traffic status application without a map sounds kind of lame. That's when I remember an open source project for maps existed, osmdroid.
I didn't port EstadoDelTransito code to that yet but I did test it out with an app called bikeroute and it did work!

Here you can see a screenshot:



Big thanks to Bryan Tafel and Mariano KIWO Carrizo who help me testing this apps in their Playbook.

Interesting facts
Becoming a Vendor
I tried to become a vendor on October. The confirmation mail never arrived.
I ended up registering with some other email three days ago. I will see what happens.

You just need the apk
The funny thing about repacking is that you don't need the source code!
If you get an apk, you just need to get the command line tools and you are ready to upload someone else work as your own! I don't know how RIM is dealing with that but it's kind of scary.

Admob?
Both of my apps use Admob. No ads were shown while running in the Playbook.
I am not sure how I am supposed to port that.

Free Playbook!
RIM provide one free 16GB BlackBerry PlayBook tablet to every registered BlackBerry App World™ vendor who converts their Android app for use on the BlackBerry PlayBook tablet and submits it to BlackBerry App World between February 2, 2012 and February 13, 2012. Link.

Conclusion
I am quite sourprised how easy it was to port an android application to Playbook.
I hope I can get a Playbook so I can start testing some stuff.
I can think of:
  • Testing cocos2d-x with the native SDK. (It was ported by RIM themselves!)
  • Finding out if it's possible to mix an HTML5 with Android
  • Looking for a way to support admob.
If you have an android application in the market, port it. There is no excuse.

Saturday, January 28, 2012

Porting Unity3d's coroutines to Android/iOS

I have been quite away from Android development.
I have been coding a game for iOS: Shaman Doctor and now I am testing Unity3d.
This blog describes my wish to port that coroutines to other platforms.

Introduction

In Unity3d I am coding in C# and I learned about coroutines.
To give you an idea of how they work, check this blog posts:

Unity3d implementation for coroutines is somehow different.
To understand what I am saying, read the first link.
It gives an explanation of how it should be working inside Unity3d.

Usage
In the code where I use Unity3d coroutines is where I need to do a state machine code.
A super simple example would be:

Imagine you need to add a button but you can only click it once every two seconds.
I can imagine two possible implementations. Bare in mind that I didn't test this code.

Using time. objective-c code:

#define SECONDS_TO_ENABLE 2
@synthesize lastTimeUsed;

@implementation PotionController

- (id)init {
self = [super init];
if (self) {
self.lastTimeUsed = 0;
}

return self;
}

- (void)click {

NSTimeInterval now = [[NSDate date] timeIntervalSince1970];
NSTimeInterval difference = fabs(self.lastTimeUsed - now);

// if two seconds haven't pass, return.
if ( difference < SECONDS_TO_ENABLE ) {
return;
}

self.lastTimeUsed = now;

// Click logic here.
}

Disabling and sending an enable msg to be run after 2 seconds. Android code.

In this case it's a done with the View's postDelayed() method. It could be done
with a Handler as well.

public void click(final View view) {
view.setEnabled(false);

// Send a postDelayed to turn it on again.
view.postDelayed(new Runnable() {

@Override
public void run() {
view.setEnabled(True);
}

}, 2000L);

// Click logic here.
}

The same thing done with C# inside Unity3d would be:

void OnMouseDown() {
StartCoroutine(this.ClickLogic());
}

private IEnumerator ClickLogic() {
// Click Logic
yield return new WaitForSeconds(2.0f);
}

What happens when you click more than once in a two seconds time frame?
Honestly, I am not sure what happens when you call StartCoroutine() when
a previous coroutine was started, but it works.
I hope that someone can clarify this.

Now try to port this code from Unity3d to android or iOS.

IEnumerator TellMeASecret()
{
PlayAnimation("LeanInConspiratorially");
while(playingAnimation)
yield return null;

Say("I stole the cookie from the cookie jar!");
while(speaking)
yield return null;

PlayAnimation("LeanOutRelieved");
while(playingAnimation)
yield return null;
}

How can this be used in Android/iOS

Ordinary coroutines
Although Unity3d's coroutines are different from the ordinary, I wanted to know if it was possible to implement them in Android/iOS.

Android
My first google search about this was "java coroutines" and I learned that ordinary coroutines would need one of this options:
  • Modified JVMs (Can't be used in Android)
  • Modified Bytecode (Can't be used in Android)
  • Platform-specific JNI mechanisms (Not sure if it would work in Android)
  • Thread abstractions (Not sure how performant would work inside Android)
I feel this is a dead end for Android.

iOS

I didn't research a lot about iOS.
Here is a list of links that look interesting:

Unity3d implementation alike

After reading Richard Fine's blog post I thought it would be interesting to achieve something similar to that in the different platforms.
My big doubt is finding a way to implement something similar to an IEnumerator.

Using scala

Inside cocos2d-iphone
I am not sure if cocos2d's internal would support something like this.

Inside cocos2d-x
This is the real challenge.
Finding a way to implement Unity3d's coroutines but keeping it multiplatform.
Perhaps finding a way of doing it in C++.

What do you guys think?

Friday, January 27, 2012

Google's Android Market vs Apple's App Store

Two years ago we created an app for ios and Android called SteamMobile.
One of our devs from NASA Trained Monkeys is a Steam user and wanted to have a Steam application in his device. There were a lot of forum post asking Steam to create one but there was no official response saying they would, so we made our own.


Yesterday, the official Steam app was released in the App Store and in the Android Market.
I would like to share with you guys what happened to our applications.


Application prices

iOS
  • Steam Mobile for iOS was released as a paid app (2.00 U$s)

Android
Android had two versions.
  • Free with ads
  • Pro version with no ads (1.00 U$s).

When we released the application we felt that selling an app in the Android market was harder so we opted for a free version.


Getting paid

This is how you we set everything up.
Remember we are from Argentina so it might be different for you.

iOS
  • The AppStore allows you to configure a bank account and Apple makes a deposit when you reach certain amount.
  • If you need to change your bank account you can do it without any issue.

Android

  • The Android Market lets you set up your account with a credit card from your country of origin.
  • You CAN'T change the credit card associated with your account once configured.
  • You get paid through Western Union.
  • Western Union limit on transactions per month is USD 8500.00
  • Western Union pays in ARS and the exchange rate is lower than the official.

Even though USD 8500 might be plenty for an indie it's a big limitation.
I would hope that if you make a big release, Google will do something different for you but it's a risk you might need to take.


When we learned about Western Union not paying in american dollars we wanted to find another way of getting the money. The only possible solution is to get a different country credit card to use a different way of payment. BUT you can't change your credit card. You would need to create a new one losing your stats. We also didn't find a way to deal with our taxes correctly since we can't make an invoice for a transfer via WU.

On the other hand, Apple pays in a bank account allowing you to clear your tax issues easily. We needed to change the bank account and there were no issues at all.

This really made us think over releasing stuff in the Android Market.
Although Apple has stricter rules, it's less risky.

Copyright issues

As you might have noticed, Steam Mobile comes with a copyright infringement.
It was clear that our application was going to be reviewed by Valve sooner or later.

That day has come and this is how Apple and Google worked it out.

iOS
On 10/3/11 Apple sent an email saying:

On 9/27/2011, we received a notice from Valve Corporation that Valve Corporation believes your application named "Steam Mobile" infringes Valve Corporation's intellectual property rights. In particular, Valve Corporation states that "...All images in (your application) are owned by Valve Corporation".

You can reach Valve Corporation through XXXXXXX (phone: XXXXXX, email: XXXXXX). Please exchange correspondence directly with Valve Corporation.

We look forward to receiving written assurance that your application does not infringe Valve Corporation's rights, or that you are taking steps to promptly resolve the matter. Written assurance may include confirmation that your application does not infringe Valve Corporation's rights, an express authorization from Valve Corporation, or other evidence acceptable to Apple.

Under our terms of agreement, Apple may remove your application from the App Store at any time. You may remove your application using the steps provided below, for example, while you make any necessary changes to your application.

Visit iTunes Connect at http://itunesconnect.apple.com

1) Access your app in the Manage Your Applications module.
2) Click on the "Rights and Pricing" button from the App Summary Page.
3) Click on the "Deselect All" button to uncheck all App Store territories.
4) Click on the "Save Changes" button.

We look forward to receiving confirmation from you within 5 days.

Thank you for your immediate attention.

This ended in an exchange of emails with Valve and Apple and we modified the application to meet every copyright issue. We needed to change the name and place a text saying that the application was powered by the Steam API. You can see it here.


Android
Yesterday Valve released their official Android and iOS app and Steam Mobile was removed from the Android Market. We got an email from removals at google saying:

Hi,

Google has been notified, according to the terms of the Digital Millennium Copyright Act (DMCA), that your application, SteamMobile Pro, package ID com.nasatrainedmonkeys.steamMobilePro, allegedly infringes upon the copyrights of others, and has been removed from Android Market. Please review the Content Policies and Business and Program Policies before you create or upload additional applications. Please note that violations may result in a suspension of your Android Market Publisher account, and may also result in actions, including possible suspension, taken against any associated Android Market publisher, AdSense, Google Checkout, or AdMob accounts.

Please note that we have included a text copy of the Infringement Notice we received for your reference.

The DMCA is a United States copyright law that provides guidelines for online service provider liability in case of copyright infringement. See http://www.educause.edu/Browse/645?PARENT_ID=254 for more information about the DMCA, and see http://www.google.com/dmca.html for the process that Google requires in order to make a DMCA complaint.

Google may reinstate these materials into Android Market upon receipt of a counter notification pursuant to sections 512(g)(2) and (3) of the DMCA. For more information about the requirements of a counter notification, and a link to a sample counter notification, see
http://www.google.com/support/bin/request.py?contact_type=lr_counternotice&product=androidmarket

If you have legal questions about this notification, you should retain your own legal counsel.

Regards,
The Android Market Team.


Text copy of DMCA complain:
AutoDetectedBrowser: Internet Explorer 8
AutoDetectedOS: Windows 7
IIILanguage: en
IssueType: lr_dmca
Language: en
agree1: checked
agree: checked
android_app_developer_10: xxxx
android_app_developer_11: xxxx
android_app_developer_12: xxxx
android_app_developer_13: Nasa Trained Monkeys
android_app_developer_14: xxxx
android_app_developer_15: xxxx
android_app_developer_1: xxxx
android_app_developer_2: xxxx
android_app_developer_3: Nasa Trained Monkeys
android_app_developer_4: xxxx

...

android_app_name_10: xxxx
android_app_name_11: xxxx
android_app_name_12: xxxx
android_app_name_13: SteamMobile Pro
android_app_name_14: xxxx
android_app_name_15: xxxx
android_app_name_1: xxxx
android_app_name_2: xxxx
android_app_name_3: SteamMobile
android_app_name_4: xxxx

...

android_app_url_10: xxxx
android_app_url_11: xxxx
android_app_url_12: xxxx
android_app_url_13: https://market.android.com/details?id=com.nasatrainedmonkeys.steamMobilePro&feature=search_result
android_app_url_14: xxxx
android_app_url_15: xxxx
android_app_url_1: xxxx
android_app_url_2: xxxx
android_app_url_3: https://market.android.com/details?id=com.nasatrainedmonkeys.steamMobile&feature=search_result
android_app_url_4: xxxx

...

companyname: Valve Corporation
country_residence: US
description_of_copyrighted_work: Steam logo and/or Steam name
dmca_signature: xxxx
dmca_signature_date_day: 26
dmca_signature_date_month: 1
dmca_signature_date_year: 2012
full_name: xxxx
hidden_dmca_category: text
hidden_product: androidmarket
location_of_copyrighted_work:
https://market.android.com/details?id=com.valvesoftware.android.steam.community
represented_copyright_holder: Valve Corporation



Conclusion

Apple has shown that it has a more mature market and it has solved the issue way better than Google. Don't get me wrong, I still prefer coding for Android but this type of things makes me wonder.

Google, don't be evil!

Monday, November 14, 2011

Roboinstaller: Install roboguice dependencies in your device

Yesterday I wrote about a crazy idea of installing your application dependencies in the device to make the builds faster. This is just an example of what's possible.

After yesterday's idea I decided to give it a try and install in my rooted nexus one all the roboguice dependencies to see if my build times improved. To test it out I Manfred Moser's roboguice sample code called: roboguice-calculator.

Mike: I was going to test with the Astroboy roboguice's demo, but I didn't feel like dealing with hg. Plz move roboguice to git :)

To do this I have separated the whole process in steps.

Pre-dexing step

First of all, you need to get a pre-dexed jar files of all the dependencies. You can pre-dex your jar files with the following line:

dx -JXmx1024M -JXms1024M -JXss4M --no-optimize --debug --dex --output=./my_dep_dex.jar my_dep.jar

Creating the permissions XMLs
Once you get all your dependencies pre-dexed, you need to create the permissions XMLs which looks like this:

<permissions>
<library name="my.dependency"
file="/data/data/com.nasatrainedmonkeys.roboinstaller/files/my_dependency_dex.jar" />
</permissions>

Installing the dependencies
After some hacking to the scala-android-libs src code I had the code ready to install dependencies on the device.

Modifying the AndroidManifest
Inside the tag you need to add all your dependencies with the <uses-library> tag. It should look like this:

<uses-library name="my.dependency"/>

Modifying the pom.xml
The last step is setting the scope to provided using provided tag.

Results
Building the ordinary app: Total time: 22.212s

With this hack: Total time: 10.431s

Issues
Since mvn doesn't create a jar file with all the dependencies inside, I failed on my first try because the guice dependency needed the javax.inject jar file. I guess there should be a way to create a "fat-jar" with every dependency inside. If that's possible pre-dexing a dependency would be much more easier.

Future work
This has shown the approach is totally useful. Next step is to create an android app that can install pre-dexed files and create the xml without needing to recompile the whole application. This approach would also take me to separate my application into different libraries to develop as fast as possible :)

Source code
I have placed the installer code and the sample application with the modifications in this github repo: Roboinstaller

Installing dependencies on the device

This last two weeks I have been giving it a try to Scala on Android. While learning how to do it, I found something interesting I would like to share.

Developing Android apps using scala

The big problem of developing in Scala is that Android doesn't provide a way to install dependencies on the device. So, if you want to use Scala you need to place the scala's jar in your apk.

Placing the scala jar inside the apk bring another problem, apk size. To fix this, scala developers use proguard to remove all unused classes from the scala jar.

Using proguard to remove unused classes works like charm but it brings a third problem. Compilation time. For me, it takes a whole minute to compile an application with a single Activity coded in scala.

Conclusion:
Coding scala in Android is as frustrating as testing android apps :)

While looking for a solution for this, I asked a question in stackoverflow and it was answered by @jberkel. He pointed me to a project called scala-android-libs created by Johannes Rudolph.

What this project does is very interesting. It installs the scala's jars in a rooted device and allows the application to use it through the AndroidManifest tag uses-library.

How does it work?

It creates a serie of XMLs in /system/etc/permissions that look like this:

file="/data/data/net.virtualvoid.android.scalainstaller/files/scala_actors.jar" />

This means that if inside the AndroidManifest the app says:


It will be able to use the scala_actors.jar file inside the /data/data/net.virtualvoid.android.scalainstaller/files/ folder as a dependency.

Since now we have the jar installed in our device, we can avoid the proguard step and the build times are very similar to build an ordinary java app.

Taking it further
Every time I develop an android application I start creating a maven project because I know that I will use certain dependencies. After learning about this approach I thought about leaving my dependencies inside the device.

Why don't extending scala-android-libs approach to provide a way to manage dependencies inside the device to make the build times faster?
Perhaps having an android app that allows to install/remove jar files and automatically generate this XMLs with the proper permissions.

What do you think?
Would you use it?

Thursday, September 1, 2011

Playing with the new ViewPager class


Some days ago we released our latest work for on-mag.net, a magazine for mobile devices. The application already existed in ios so we did a port to Android.

Since we wanted portability we decided to create an hybrid application. An hybrid application is a mixture of native code and WebViews with HTML+JS+CSS. During the development of the application we found some android issues and some interesting implementation problems which I will describe in the following lines.

Btw the application is ready to download in this link.

APK size limitation
While in the ios world the ipa size limit is 2 GBs in the Android market is just 50MBs. After zipping our resources we ended up with a 200MB zip file.

To solve this we create a splash screen activity where the user get a dialog asking him if he wants to start the download. When the download starts, a Service is created and the download starts.


To avoid the download to halt we decided to add a partial wake lock with the following code:

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
wakeLock.acquire();

In the docs, it says:
Wake lock that ensures that the CPU is running. The screen might not be on.

Even thought the docs don't say if the wifi stays on, using a full wake lock didn't make a lot of sense. I tested on a nexus one and a nexus S and everything went fine, BUT yesterday I was talking to Christopher and he mentioned that his download stopped when the screen turned off. He tested on a Desire Z, running 2.3.3 (CyanogenMod 7.0.3). Let me quote his research:

There doesn't really seem to be a disconnection when the screen is off for a short time. Using "netstat" shows that the HTTP connection is still open; it's just not transferring anything. Usually when I turn the screen back on, the transfer will continue. Probably if it's idle for a long time, the connection is dropped.

I just tested this behaviour between WLAN and 3G. Network activity continues when the screen is turned off and the device is on a mobile network. If the device is on WLAN, the network activity pauses when the screen is turned off.

The Android Market shows the same behaviour on my device. It uses a partial wakelock for its DownloadManager but most network traffic pauses while the screen is off, if using WLAN. When the screen is turned on again soon, the traffic resumes.

Having to create a download Service from scratch was quite a pain. I know there is already a DownloadManager but it's only available in Android >2.3. It would be nice to have something similar to JakeWharton's ActionBarSherlock but with the DownloadManager.

ViewPager
If you never heard about the ViewPager go and read Rich Hyndman's blogpost.

I made a small demo with some stuff I found.
You can get the source code from this link and the apk from here.
I will explain what I am trying to show in each test.

Restarting
The magazine app was meant to be portrait only but it did have some landscape resources.
For example:

Portrait version


Landscape version


So, the Activity holding the ViewPager needed to be portrait only / portrait-landscape depending on the opened page. In the example every page index %2 == 0 has a landscape version. The test is called Restarting because every time we rotate the device, it will recreate the whole view.

WebViews
This tests shows how to deal with WebViews. Nothing strange.

WebViews Accelerated
I would say this is an android bug. If you place WebViews and you make your Activity hardware accelerated you will notice that the WebViews will start to invalidate themselves in a wrong way.

Unfortunately we couldn't find a solution for this and ended up leaving the app without hardware acceleration :(

Here's a screenshot of the issue:
WebViews accelerated

When moving through pages you will see some blue boxes for my blog since the background is blue.

VideoView
We tried really hard to make the HTML5 video tag work in android but we failed.
You can try this link .
The video used in the demo is from that site, I hope the author doesn't get mad about that :)

The first test doesn't say much, just shows VideoViews inside a ViewPager. All the pages are portrait only.

VideoView Resizable
This second VideoView test is more interesting. It tries to reproduce youtube's app behavior.
You can read about this issue in the following stackoverflow's question.

Instead of using the technique in the "Restarting" test we handle the change of orientation by hand changing the videoView's layout params.

VideoView Resizable with Margins
Similar to the last one but with the possibility of using margins. I just placed this test because when testing in the real app when the videoView got resized it didn't end up with the original size. I couldn't reproduce it :(

You will still notice that there is also a bug when you start changing from portrait to landscape. Here's an screenshot:
Media controller in the wrong place


Conclusion
Android 3.x has bugs and some of them will make you wonder how they could make the slip. On the other hand the introduction of the compatibility library brought an excellent weapon to fight fragmentation. For instance, the demo's min sdk is 4. I can be sure that I am leaving just a small group of users out.

PS: Talking about android 3.x bugs/issues. If you try running the demo with target sdk 13 and compile against 3.2 onConfigurationChanged() will never get called. The WTF per second is increasing drastically :)

Thursday, August 25, 2011

Error retrieving parent for item

Some days ago I updated the android platform-tools to r6. Everything went fine and it really called my attention :)

Yesterday I tried to open a one month old honeycomb application and I got errors in my styles.xml file.

Eclipse said:

error: Error retrieving parent for item: No resource found that matches the given name 'android:style/Widget.Holo.Light.ActionBarView_TabView'.

After:
  • Trying to build with eclipse
  • Trying to build with mvn from the cmd line
  • Removing my .m2 repo
  • Replacing my android jar with another
  • Comparing the mvn -X output with someone's who had it working
I discovered issue 18659: aapt cannot resolve parent reference to @android:style/WindowTitle

Formal explanation:

What is happening is that some styles, like WindowTitle are not public (you won't find them in android.R.style). You should not be extending non public resources. aapt used to let you do that but it was a bug which was fixed in platform-tools r6.

Ok, great I can't extend non public resources, but my style code was copy and pasted from @crafty's blog post: Customizing the Action Bar!

After testing his code I noticed that it also didn't work. Note: There is an issue created for this.

Just for the record, here's how to fix it.
What we need to do is avoid extending the non public resources and copying all the items in our own style.

The two styles that generate the error are:

<style name="MyActionBarTabStyle" parent="android:style/Widget.Holo.Light.ActionBarView_TabView">
<item name="android:background">@drawable/actionbar_tab_bg</item>
<item name="android:paddingLeft">32dp</item>
<item name="android:paddingRight">32dp</item>
</style>

<style name="MyDropDownNav" parent="android:style/Widget.Holo.Light.Spinner.DropDown.ActionBar">
<item name="android:background">@drawable/ad_spinner_background_holo_light</item>
<item name="android:popupBackground">@drawable/ad_menu_dropdown_panel_holo_light</item>
<item name="android:dropDownSelector">@drawable/ad_selectable_background</item>
</style>


Let's fix MyActionBarTabStyle.
To fix it, we will need to copy every non modified items to our style.
We need to open styles.xml at $ANDROID_SDK/platforms/android-11/data/res/values

There we see:

<style name="Widget.Holo.Light.ActionBarView_TabView" parent="Widget.Holo.ActionBarView_TabView">
</style>

No items there, let's now search for: Widget.Holo.ActionBarView_TabView.

<style name="Widget.Holo.ActionBarView_TabView" parent="Widget.ActionBarView_TabView">
<item name="android:background">@drawable/tab_indicator_holo</item>
<item name="android:paddingLeft">16dip</item>
<item name="android:paddingRight">16dip</item>
</style>

There we find three items and we still need to continue up with Widget.ActionBarView_TabView:

<style name="Widget.ActionBarView_TabView">
<item name="android:background">@drawable/minitab_lt</item>
<item name="android:paddingLeft">4dip</item>
<item name="android:paddingRight">4dip</item>
</style>


Great. The same three items and we already have it in our own style. We can get rid of the extension. Leaving our style like this:

<style name="MyActionBarTabStyle">
<item name="android:background">@drawable/actionbar_tab_bg</item>
<item name="android:paddingLeft">32dp</item>
<item name="android:paddingRight">32dp</item>
</style>

The fixed MyDropDownNav ends up extending something non public. It should look like this:

<style name="MyDropDownNav" parent="android:style/Widget.Holo.Light.Spinner">
<item name="android:background">@drawable/ad_spinner_background_holo_light</item>
<item name="android:popupBackground">@drawable/ad_menu_dropdown_panel_holo_light</item>
<item name="android:dropDownSelector">@drawable/ad_selectable_background</item>
</style>


I honestly don't understand what makes an style private or not. They only way I found is checking android.R.style class. If someone knows a better way, please let me know!

Conclusion
Android development has this type of tricks. Fortunately the active community report issues and write about workarounds so everyone can avoid some of the pain :)

Happy coding!

Tuesday, July 12, 2011

cursor.getString() vs cursor.copyStringToBuffer()

Some days ago cyrilmottier posted a blog post about ListView's tip and tricks.
In one of his tips he mentions the following:
CharArrayBuffer: Developers are regularly using the getString() method on the Cursor. Unfortunately, it implies creating String objects. These objects are likely to be garbaged once the user starts scrolling. In order to prevent object creation and consequently garbage collection freezes, it is possible to use a CharArrayBuffer that consists on copying data from the Cursor to a raw array of char that will be directly used by our TextViews. Instead of having to create aString object, we will hence reuse a CharArrayBuffer.
My first thought was: Oh my! I am using getString() everywhere! We had some performance issues in the past with a Gallery so it was a great place to start fixing the code.
Yesterday evening I modified the adapter's code to use CharArrayBuffer instead of getString(). When I tested the app it felt slower than before and very blocky. I went to sleep.


Traceview:

Today evening I decided starting from the scratch, but instead of using my app I decided to create a toy app. I stole some code from @vogella and start testing.

You can download the app from this link.
My first test was with the traceview tool:



In the screenshot you see two instances of the traceview tool analyzing the bindView method.
Over the top, you can see
withoutFix.trace (the one using the cursor.getString() method) and below the withFix.trace (which is using the cursor.copyStringToBuffer).

Another thing I took some time trying to understand is this:


Conclusions so far:
* Using cursor.copyStringToBuffer() seems to run the bindView method faster than cursor.getString().
* cursor.getString() is faster than cursor.copyStringToBuffer()

The difference is not much so I wouldn't take care of keeping the fix. The code looks clearer with the getString() method.


MAT:
But wait, let's give it a try to the Memory Analyzer (MAT).
Note: After hearing @dubroy's talk at the googleIO 2011 I wanted to do something like this :)

@dubroy also wrote an article for the Android Developers blog called "Memory Analysis for Android".

What I did was comparing two heaps from both options.




Objects #0 and Shallow Heap #0 are for the cursor.getString() version and
Objects #1 and Shallow Heap #1 are for the cursor.copyStringToBuffer().

Not much to say here.
* The getString() versions has less String objects.
* The copyStringToBuffer uses more heap. (I use three new CharArrayBuffer(128))


Final conclusion:

I am not an expert using this tools but, from what I have tested, I couldn't notice a performance improvement when using cursor.copyStringToBuffer().

What do you guys think?

UPDATE:

I had the following conversation with cyrilmottier over twitter:
cyrilmottier: The actual benefit is you will reduce garbage collection to a minimum. This is less useful in Android 2.3 or higher.

2.3 introduced a generational GC. Hence, CharArrayBuffer is probably more useful on old Android versions.

me: It makes sense. I will keep the getString() calls, knowing that I have the buffer if I need to improve memory usage.

Sunday, July 10, 2011

Android market: Books y Movies en Argentina?

Ayer estuve browseando el android market desde la xoom y se me dio por entrar a Books y Movies. Por suerte ya no son secciones vacías. Veamos qué se puede hacer!

Books
Por ahora se puede browsear los libros,


pero cuando querés entrar en el detalle de alguno muestra un error:


Movies
A diferencia de los libros, las películas muestran otra información.
La pantalla principal se ve así:


El filtrado de las películas todavía no existe. No puedo buscar por año, ni por precio.
En Comedias encontré una que no había visto. Matchstick Men. La pantalla del detalle fue la siguiente:


El problema ocurrió cuando la quise comprar. Lamentablemente no aceptó mi tarjeta de crédito:



GoogleTV
Todavía no hay novedades de honeycomb para googleTV. Aparecieron dos updates pero ninguna interesante.
La versión de googleTV que tengo ahora no permite acceder al market pero hay dos opciones que permiten acceder a Netflix y a Amazon Video.

  • Netflix no entra diciendo que todavía no está en Argentina.
  • Amazon Video te permite browsear pero cuando querés comprar te dice que necesitás tarjeta de crédito de EE.UU. y domicilio de allá.

Conclusión
Existe un pequeño avance desde la última vez que probé, pero, por ahora, seguimos lejos de poder alquilar una película por internet. Netflix ya anunció que va a abrir en Argentina, así que a esperar un poco más :)


Thursday, May 26, 2011

Connecting usb stuff to the Xoom and debug through wifi!


Today I played a lot with my Motorola Xoom trying to connect different devices.

Games
We started connecting the tablet to the television using the hdmi output. We installed Snes9x EX and played some snes games. The great thing about Snes9x is that it allows to connect Wiimotes. The screen over the right shows a Killer Instinct fight!

Kinect
Today at work they bought a Kinect to test stuff. Android 3.1 + usb host == kinect? I entered the freenode irc chat of the openkinect guys. They give me some excellent support but they doubted that it would work. I will try it out. If I found something useful I will do a blogpost about it.

USB keyboard/mouse
The usb keyboard worked fine but the mouse didn't. The mouse turns on, but the pointer doesn't appear in the screen.

Other Android devices
One of the samples of android-12 is called AdbTest. You can connect an android device and it will read the logs. I connect my nexus one and it worked fine.

Hacking
Cool. Good results so far but I felt disappointed with the mouse, so I decided to try to read what the usb say for that device. When I was going to connect the mouse I discovered that I was missing an extra slot for debugging. I first based my code in the AdbTest and place my logs in the TextView.

After failing trying to get the device name I started reading the documentation, and I found there were Debugging considerations when using the USB Host and Accessory. There are five easy steps you need to do to debug without a usb cable.
  1. Connect the Android-powered device via USB to your computer.
  2. From your SDK platform-tools/ directory, enter adb tcpip 5555 at the command prompt.
  3. Enter adb connect device_ip:5555 You should now be connected to the Android-powered device and can issue the usual adb commands like adb logcat.
  4. To set your device to listen on USB, enter adb usb.
It does work!

I needed to post this before continue coding :)

Friday, May 20, 2011

App Review: ESPN 107,9. A real Honeycomb app?

On Thursday I went to the Motorola's MOTODEV. You can find a review of the event here. Thanks @fogo!

One of the sessions was called: "Moving Your Smartphone App to the Tablet". There they showed an app done in Argentina which was ported to tablets. My first thought was: "Cool, someone already ported something here in Argentina". Today I installed it and I found very interesting stuff in this app so I decided to create a review.

Installation and market place
I search for the app in the market and I found this:

This is what happens when you use two different binaries for the same app. Some of the issues are:
  • Different comments for the same app.
  • Different ratings for the same app.
  • Doing an update means uploading two different apps.
Is there a real difference between those binaries? We will see.

Patterns and features explained
In this section I will explain some of the patterns that the app uses. Also some features/issues and a way to solve them.

Splash Screen
This is something used a lot in iPhone's app. While an app loads in iPhone the os shows the image /Default.png or /Default@2x.png. It does make sense to use a splash screen if you need to load something before loading the application itself. One of the best examples is Roboguice's RoboSplashActivity:

An activity that can be used to display a splash page while initializing the guice injector in the background.
To use this kind of patterns the attribute android:noHistory is your friend. In the case of the app it looks like they didn't use it since there is a nasty bug that ends in a FC. If you enter the app and click "Programación" you can actually move back three steps when only two should be possible.

AndroidManifest
If you check their manifest you will notice that they are doing something like:

<activity android:label="@string/app_name" android:name=".ESPN_107_9" android:screenOrientation="portrait">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

intent-filter>

activity>

<activity android:name=".EspnHome" android:screenOrientation="portrait" />

<activity android:name=".EspnProgramacion" android:screenOrientation="portrait" />

<activity android:name=".EventoActivity" android:screenOrientation="portrait" />

<activity android:name=".Prueba" android:screenOrientation="portrait" />

<activity android:name="iphoideas.ESPN_107_9_TABLET.Example" android:screenOrientation="portrait" />


Some issues about this manifest:
  • It doesn't follow the java package name convention.
  • There is an android:screenOrientation="portrait" in every Activity when it can be placed just in the Application tag.
There is also an interesting use of android:name. In the manifest you can place a dot and that will be replaced by the package info placed in the manifest tag. As you can see, they have used both ways. The complete package name and the dot version.

Forced Portrait
This is what pissed me off as a user. No landscape view in the tablet version? Seriously?
The app has basically two Activities. The main one with a play button and some social features.


Social features
You can just send an email or paste something in your facebook's wall. Android has a lovely share intent to handle this stuff. You can get more information here.

System notification when playing
I started playing the radio and no system notification was shown. Not the same use case as the default music player?

Fragments
No fragments? Honeycomb application without fragments? I don't like to have a big play button in the main window and need to move to something else just to see the radio guide.

Creating a landscape layout having the radio controls in the same activity as the guide would have been great.

Stacked activities
In this app from the Home you can go to the radio guide and from the radio guide you can go to the home screen. So, you basically can do Home => Radio Guide => Home => Radio Guide. What happens if you press the back button? In this particular app all the activities get stacked but for this kind of situations android provides a solution. Using FLAG_ACTIVITY_CLEAR_TOP

For example, consider a task consisting of the activities: A, B, C, D. If D calls startActivity() with an Intent that resolves to the component of activity B, then C and D will be finished and B receive the given Intent, resulting in the stack now being: A, B.

Enable Hardware acceleration
Unfortunately this app doesn't use it. To do it you just need to add the android:hardwareAccelerated="true" in the application element.

Using the Holographic theme
This app doesn't use the holographic theme. Everything in this app is custom so you might thing that it's not necessary but when dialog show up they aren't custom and they don't use honeycomb styles.

If you are targeting smartphone and tablet you can use:
<uses-sdk minsdkversion="4" targetsdkversion="11"></uses-sdk>

Different resources for different screen sizes and densities
This app has every resource inside the res/drawable folder. Using the res folder correctly would be enough for this app to live in the same binary. There is a nice explanation about this here.

Conclusion
The conclusion is dead simple. This is not a honeycomb app. It works in honeycomb because it has: <uses-sdk android:minSdkVersion="7" />. It isn't targeted for Honeycomb and it doesn't use android 3.0 features.

Does anyone know if someone in Argentina already did a good honeycomb app?

Tuesday, May 17, 2011

Google IO 2011: Day two

Second day
If you didn't read the view of the day day, you should read that one first.

Breakfast

After eating something we met with Jason Van Anden. Jason worked with me while I worked in Teracode but unfortunately I never met him in person. He has an interesting project called BubbleBeats.

He told us about his plans and his future projects. It feels good to know that Android developers are getting tons of work and they are progressing!


Keynote


While the first keynote was all about android, the second day's keynote was all about chrome os and chrome browser.

Good news about ChromeOS. I think that everything sum ups to this sentence: "No need to bother fixing PC and having more time for yourself". I am particularly happy for that. I am tired of fixing PC with an OS I don't use anymore. As the times passes, it gets harder and harder to find the Control Panel :(


Google decided to give out chromebooks as a present but they are sending them on June 15th. I don't know how that will work for international attendees. I guess I will need to ask Al Sutton (@alsutton) :)


Building Agressively Compatible Android Games

This talk was given by Chris Pruett(@c_pruett). He was a Game Developer Advocate for Android at Google and now he has his own company. He once again talked about his experience with Replica Island and give out a big list of things to do and not to do.

I wish I could talk to him but he was surrounded by other people.

Lunch

After Chris' talk we hang around some stands which were in the third floor. There were a lot of games to try out and also some robots going around. After some of them we decided to head for Lunch. 20 mins to eat before moving to the next session. I need to say that the food was excellent. We even had a Haagen Dazs' ice-cream as dessert!

Building Web Apps for Google TV

Chris Wilson (@cwilso), GTV developer advocate gave an excellent explanation about the TV platform in general. He mentioned that we should get everything away from the boarders since the Over-scan also applies to nowadays televisions.

He also mentioned a lot of recommendations for UI design. Some of the ones that stayed in my head were:
  • Remember the user is in couch-mode. Few interaction.
  • Avoid having a lot of clicks to reach content.
  • Design your app and see it from 10 feet (3 meters) away.
  • Instead of browsing downwards, the user browses rightwards.
  • Avoid scrolling. The user is not used to scroll TV content.
  • Make sure you make the user aware of where he is standing and what options are available.

Building Android Apps for Google TV

Similar to last session, these guys gave an intro to Google TV.

They explained that the API will provide different functionalities/issues. There are two which are pretty interesting or out of the ordinary.

1) You will not be able to know what the user is watching.

Wow! Really?

Actually you can learn which channel he/she is watching but no more than than. If your app/idea depends on that you will need to ask the user which tv provider he/she is using and parse it's tv guide. While it's a big issue right now, I guess some kind of open source project will appear to solve this.

2) Android fw will start to take care of where to place your ui widgets. eg: If you place an ActionBar in your app in a Tablet device it will show in the top right corner horizontally while for GTV it will show in the left vertically. I guess this is what android ice-cream sandwich will be about. Developer placing a ui widget and android deciding how to show it correctly. Third party UI libs will need to take care of that kind of customization if they are willing to stay alive.

I actually asked Roman Nurik what he thought of different third party UI libraries. My question actually was: "Should we continue using libs like GreenDroid or we should wait for this kind of magic customizations by Android?". He replied that for now we are good to use that kind of libs. They are an excellent way of applying android ui patterns.

GTV Office Hours
After the Android GTV talk, we went to the office hours. I wanted to buy a google tv to take back home but I wanted to be sure that I was going to get the 3.1 update with the adb and stuff. We fortunately found Chris Wilson who friendly replied to all our questions. I will try to reproduce:

We: Logitech or Sony?
Chris: It depends. The sony has a bluray but the Logitech is cheaper. If it's just for development I will take the Logitech one.
We: Which one do you use at work?
Chris: Both.
We: Who's in charge of the updates?
Chris: The updates are sent by Logitech and Sony themselves.
We: If we get a gtv and start using in our country, we will get it?
Chris: Yep, you will get it while the device is connected to internet.
We: Is it possible to root the device?
Chris: Official answer: no. On the other hand, there are people who did it. It involves welding.

GTV Conclusion
In general, GTV it's a US-only device for now. I got one for several reasons.

  1. Being able test gtv apps for clients from US.
  2. We want to explore the world of widgets for GTV.
  3. Porting cocos2d-x to GTV. I still need to make it work with Honeycomb but I will definitely want cocos2d-x to run in GTV :)

Bringing C and C++ Games to Android

Since we had some time we decided to go to this session to meet up with @emmby. We reached there for the Q/A. When we entered a guy was leaving and the speaker said: "Try staying, there is a present for everyone in this room". Yep, I also got a xperia play. I guess I will need to discuss with the cocos2d-x's guys how they are willing to support this kind of device.

How to NFC
I didn't attend this session, but @mpan_ did. He said that they spoke about the api in general but for now android devices with NFC will not be able to emulate a NFC card.

After party
After the conference we went out for some drinks with ppl known by @emmby. Going out with ppl that knew SF was excellent. We went to different bars and we ate in an Indian restaurant. It was actually the most spicy meal I ever had, but I enjoyed it a lot. Thanks guys!



Conclusion

The Google IO was excellent. Good amount of sessions, every technology showed it's work in progress and I got an excessive amount of gifts.


Every android release is very ambitious and the next one is going to to support cellphones, tablets and tv. I think that GTV will be the next big thing. I yet don't imagine my dad using an android powered device but I do imagine him using gtv. From my point of view gtv will bring new type of users to the android community.

We also need to pay attention to tablet apps. There are very few apps in the market. The user experience of a tablet user is very frustrating. I hope to see more tablet compatible apps. I guess I should start doing that with my own apps.

There are a lot's of ideas and stuff to do in my head. I will now need to find the time to do them all.

Cheers, and happy coding :D