2011-09-14

Android ongoing notifications for foreground services

It took several hours to find the solution for my issue, so I describe it for you.

Issue
The ongoing notification will only shortly be displayed in the notification center, then it disappears.
Solution
The following key points must be fulfilled
- Override, onStartCommand in your service, don't try to use onHandleIntent()
- Don't call super.onStartCommand()
- Return START_STICKY
- Use proper icons as described in the user guide

public int onStartCommand(Intent intent, int flags, int startId) {
	Notification notification = new Notification(R.drawable.status_bar_icon, "text", System.currentTimeMillis());

	Intent main = new Intent(this, Main.class);
	main.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
	PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, main,	PendingIntent.FLAG_UPDATE_CURRENT);

	notification.setLatestEventInfo(this, "title", "text", pendingIntent);
	notification.flags |= Notification.FLAG_ONGOING_EVENT |	Notification.FLAG_FOREGROUND_SERVICE | Notification.FLAG_NO_CLEAR;

	startForeground(2, notification);

	return START_STICKY;
}

2011-07-28

Safari 5.x memory leak, bad performance - a disaster

It's enough. I tried really hard, but I can't. Safari 5.x is unusable for me under both, Lion and Snow Leopard.
Reasons:

  • Safari consumes more than 1.5 GB memory in scenarios, where Safari and Chrome are still under 200 MB i.e. it has at least one memory leak
  • The leak has severe impact on the overall system performance, because it forces other apps' data to swap out
  • Loading pages is slower than in other browsers
  • Reopening tabs takes ages
  • HTML5 video replay CPU consumption is unacceptably higher than with Flash (YouTube-based comparison)

2011-07-27

OS X Lion (10.7) crash due to kernel panic

This is very disappointing: I already had the second crash of Lion. Similar to this case I reported the first one, too, but Apple didn't reply so far, although they did it in approximately 50% of the issues (I reported 40 so far). I saw several reports on this issue.
A kernel panic is an indicator of a commercial operating system being far away from complete. I had kernel panics years (more than a decade) ago when I was building my Debian kernels. In contrast to now I not only could find the cause (since it was my fault), but I was able to either repair it or implement a workaround. This would probably be possible in case of OS X, too, but exactly this one of the reasons why I switched from Linux to OS X: I didn't want low-level hassle anymore.
Apple, your QA is insufficient.

2011-07-20

OS X 10.7 Lion - review and crashes

Due to my excellent internet connectivity Lion has been downloaded in a few minutes. The installation took longer, but the whole process was less than one hour of effort (for the iMac). Meanwhile I also upgraded my girlfriend's MacBook Pro and it went smooth as well.
In this post I will record and share my experiences (be positive, negative or neutral).

Positives
  • Performance has been significantly improved in all areas (system, already and newly installed Apple- and non-Apple software products)
  • The UI has been refined and thus everything looks and moves smoother
  • Mail 5 has really become excellent for mail reading
  • The kernel is 64-bit on my Core 2 Duo iMac, too
  • Mission control significantly improves the efficiency in a multi-desktop work environment
  • The iOS-like spell and grammar check with the instant proposal reduces the time of error corrections
  • FaceTime is included
  • Launchpad makes starting of apps only with the mouse possible (I always used Spotlight)
  • Many self-evident features such as the merging of identically named folders when copying with Finder have finally arrived
Mission Control
Neutrals
  • Dashboard on an own space doesn't make sense to me, but it also doesn't hurt as the original setting can be restored
  • The "natural" scrolling direction is as beneficial to me as the traditional and it can be restored as well
Negatives
  • Launchpad is unstable: Crashes and rebuilds the database, thus the folders are only temporary
  • appleprofilepolicyd is running even without a server and there is no way to turn it off
  • applepushserviced is running even without a server and there is no way to turn it off
  • Lion crashed due to a kernel panic after a few hours of usage (bug report submitted)
  • Safari consumes more than 1.5 GB memory in scenarios, where Safari and Chrome are still under 200 MB

2011-07-18

OS X 10.7 (Lion) release date - 2011-07-20

There were tons of speculations by all well-known Mac rumors sites regarding the release date of Lion, but all turned out to be completely wrong, because they predicted to see the new cat last week...
All missed one point which was always incorporated by speculations in the past: The release date of previous OS X versions.
Here is a list of release dates as listed in Wikipedia:
- 10.0 - 2001-03-24 (Saturday)
- 10.1 - 2001-09-25 (Tuesday)
- 10.2 - 2002-08-24 (Saturday)
- 10.3 - 2003-10-24 (Friday)
- 10.4 - 2005-04-29 (Friday)
- 10.5 - 2007-10-26 (Friday)
- 10.6 - 2009-08-28 (Friday)
- 10.7 - 2011-07-20 (Wednesday)

It is obvious that:
- all new versions have been released on the twenty-Xth of a month
- the last four releases were on a Friday.

Since this July there will be two more Fridays, the release will most probably happen on the 22nd or the 29th. My bet is this Friday, the 22nd.

UPDATE: Lion will be released today, on the 20th of July - I was as good (or as bad) with my prediction as all the rumor sites out there… ^^

2011-07-08

Why should I use Selenium?

There was a short discussion on Twitter between Ron Jeffries and me which ended up in the following two questions:
- me: "Why don't you use #selenium?"
- Ron Jeffries: "let me turn the question around ... why SHOULD i use selenium?"

Here you can find a list of reasons why I use Selenium and why I think others should use it, too:
  • Designed for web test automation
  • It's very easy and fun to implement tests
  • Can be integrated with test and issue management tools (e.g. FitNesse, Zephyr, JIRA, …)
  • Provides various language APIs (e.g. Java, JavaScript, Ruby, …)
  • Supports all major browsers (IE, Firefox, Chrome, Safari, Opera)
  • Supports all major platforms, where applicable (Windows, Mac, Linux)
  • Supports not only traditional, but also advanced technologies, such as AJAX or Flex (via plugin)
  • Supports UI abstraction concepts, such as UI maps and the PageObject pattern
  • There are several ways to execute tests: Locally with Firefox plugin, remotely (from integration tests or test management tools) and in grid
  • It is trivial to incorporate in CI
  • All APIs are extensible
  • Open source
The Selenium headquarter: http://seleniumhq.org/

2011-07-07

Apple and security patches

So, there is another PDF security flaw in iOS that will be already utilized by an exploit on jailbreakme.com. I'm no jailbreaker and usually only visit sites I already know or which I know can be trusted. Therefore I don't think that my data will be leaked or damaged.
But as far as I remember last time it took several weeks for Apple to solve a similar problem - how long will it take this time? I hope Apple somehow improves its patch delivery time both on iOS and OS X. Otherwise I suspect that it will become the next Microsoft and I really don't want it...

2011-06-28

iCloud to replace GMail?

I've been using GMail for more than 6 years by now and I was satisfied with the reliability of the service and the amount of space available for free. There was no reason to change - until iCloud has officially been announced.
As an iOS developer I have early access not only to the developer previews of iOS 5, but I've also got access to iCloud. This fact also implicates that I've obtained a me.com e-mail address which I can already use for sending and receiving mails. MobileMe will be replaced by iCloud, and I cannot set it up on my iMac, because I have only an e-mail address, but no account and iCloud is only available for Mac developers with the preview version of Lion.
But I can already replace my GMail address used as my Apple ID with my me.com/iCloud e-mail address and use this as login on all the pages requiring authentication. I think it will only be a first step of a complete transition from GMail to iCloud - why would I want to use a 3rd party mail provider if I have an integrated and better solution (push to all devices)? As soon as it has been released I will start with the migration of my contacts, accounts and connections.

2011-06-17

AdSense account has been disabled due to invalid activity

Two days ago I received a notification from Google stating that my AdSense account has been disabled due to invalid activity - they wrote exactly the following:
"After reviewing our records, we've determined that your AdSense account poses a risk of generating invalid activity."

Although I sent an appeal to clarify the situation I haven't received any useful answer and they didn't change their decision.
Since this is a blog heavily focusing on development, therefore most visitors are themselves developers, too. As such, they most probably use ad-blockers, so I didn't really have any income from the ads and it was thought as an experience anyway.
However, I think that Google was neither fair, nor professional in handling of this issue, so I'm quite disappointed.
The site is now ad-free and it is OK so, but I wanted to decide this myself and not let others decide it for me based on random metrics.

2011-06-10

iOS 5: iTunes finally doesn't block while syncing

iOS 5: The iTunes sync finally doesn't block the device, only a tiny symbol in the status bar will be shown.

AdSense and AdWords

It is trivial for Blogger blogs to enable AdSense as it can be added as a widget just like my tweets, links or images.
Although I know that people landing on these pages most probably have an ad blocker I also hope that when they find the content useful and interesting they add an exception in their settings :)

That not everyone uses an ad blocker is proven by the fact that the AdWords campaign, which I started two days ago, is working: Not only will the ad several thousand times be displayed, but it also motivates users to click on it and hopefully to download iOszkar. The more clicks, the more visitors to ioszkar.andrashatvani.com and the greater chance to increase the number of downloads.

However, it's not trivial to reach the target audience, because it requires the exact understanding of what keywords

  • your subject is the most related with
  • people search for
  • are synonyms of the trivial ones
  • have better composite forms.
Search engine optimization (SEO) and search engine marketing (SEM) are two very interesting and also sophisticated empirical sciences which require you to understand the language. 

2011-06-08

Remove border around Blogger images

The usage of the "Available on the App Store" badge is strictly defined by the App Store Marketing Guidelines. Therefore, the default border applied to each and every image uploaded to Blogger isn't acceptable and needed to be removed.
The best place to put the badge in is in an image widget in the sidebar, but there is no option to disable the border around the images, so I had to find a way to disable it in the HTML template.
It was easier as I thought, because searching for img in the template lead me to the following CSS-definition line:

.post-body img, .post-body .tr-caption-container, .Image img,
.BlogList .item-thumbnail img {
  padding: $(image.border.small.size);

  background: $(image.background.color);
  border: 1px solid $(image.border.color);

  -moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1);
  -webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1);
  box-shadow: 1px 1px 5px rgba(0, 0, 0, .1);
}

As it can be seen the border and the shadow definitions apply to the image widget as well, therefore simply removing the reference to the desired class (in my case .Image img) resulted in the outcome visible in the sidebar.

2011-06-07

iOS 5 screenshots

iCloud
iCloud
  
Find My iPhone - free for 3GS, too
Hopefully no diagnostics-gate...


Notification Center

Safari 5.1 developer preview

Along with other exciting updates Apple has released the developer preview of Safari 5.1, too.
Almost all new features are targeted at developers, but there are also under-the-hood changes indirectly improving the user experience:

  • More stability and responsiveness due to the new process and plugin architectures, which separate rendering and plugin execution from the application process
  • New CSS3 features (vertical text, text emphasis, auto-hyphenation)
  • New extension features (events, popovers, menus)
  • WebGL can be enabled in the Develop menu
  • The sending of the Do Not Track HTTP header can be enabled in the Develop menu

iOS 5 developer preview

The installation was smooth, although I was a bit surprised as all apps have been reinstalled - most probably due to the account synchronization with iCloud.
During the process my iPhone 3GS became approximately 45°C warm, which is quite unusual, but understandable due to the resource-consuming application restore.
Despite iTunes OTA sync being available (with iTunes 10.5) my recommendation is to do the first sync via USB as it is expected to be a lot stabler and faster.

I've just installed Xcode 4.2 developer preview, too, so I have to quit iTunes and so it reconnected to my iPhone as well, but it ended up in synchronizing all my apps - once more…

More feedback on iOS 5 in separate posts - see the labels on the right.

2011-06-06

WWDC 2011 - my highlights

Mac OS X 10. 7 / Lion
  • Lion will cost $ 29.99 and be available in July
  • All the already known features such as Restore, Auto Save, Resume, Launchpad or Mission Control brought no surprise
iOS 5
  • The new notification system presents multiple notifications clearly laid out instead of the modal pop-up alerts; not only on the top of any window, but also in an own view and also on the lock screen
  • Newsstand and the Twitter integration are currently of no interest for me
  • The Reader feature has finally arrived to Mobile Safari - content-focused full-screen page view
  • Reminders seem to be a useful feature for the iPhone, especially its location-aware functionality
  • Mail has been pimped: Draggable addresses, S/MIME, message flagging, rich text formatting and indentation control
  • Setup, iTunes sync and delta software updates can be done wirelessly i.e. OTA
  • iMessage - kind of chat à la FaceTime, but also via 3G
  • iOS 5 developer preview will be available as early as today - I will provide a review as soon as possible
  • Updated iBookstore and App Store apps
iCloud

  • A better MobileMe
  • FREE and AD-FREE
  • Mail, Calendar, Contacts in the cloud
  • Pages, Numbers, Keynote in the cloud
  • Photo Stream - pushing photos to all devices
  • iTunes in the cloud - anything bought can be downloaded to any authorized device
  • Music can be pushed to up to 10 devices
  • 5 GB for Mail, more for the other previously mentioned apps - awesome!
iTunes Match
  • Formerly known as Lala
  • $ 24.99 p.a.
I'm very excited to try all these new things - what about you?

2011-06-01

Rebuild Xcode index

Since iOszkar 1.1 is still waiting for review I decided to switch to the Object Mapping 2.0 branch of RestKit and update iOszkar to use it to provide feedback on this beta branch and to prepare my project for the future as well.
It took only a few commands and clicks - but it didn't work! Xcode was still missing the 2.0-related classes, so I gone through the whole setup process again - but it didn't work, those classes were still missing for Xcode! I tried several other alternatives without luck…
Then I remembered that there is an exotic directory holding generated data and also the index: DerivedData. I simply erased all the content within it and this indeed forced Xcode to rebuild the index and thus correctly recognize all necessary classes - success!
The location of this directory can be determined by choosing Project Settings… in the File menu:

2011-05-31

eXtreme Programming: You ain't gonna need it (YAGNI)

Although iOszkar 1.0 has already been released and the update 1.1 is also on the way the app is far from being complete. The reason why I'm satisfied, though, is that the basic functionalities are already implemented. The backlog is quite large, but I didn't know (and still don't know) how many users will download and use it and therefore I wanted to limit the initial effort.
I came up with the idea that I'll let the upcoming iterations be controlled by the users so that they can vote on and thus prioritize the backlog.
I want to achieve the following with this approach:

  • Only implement features delivering value to the users
  • Avoid implementing unnecessary features confusing the users, putting constraints on and letting grow the code base
  • Save time for improving the existing code base and increasing the amount of tests
  • Minimize the risk of putting enormous effort into an app which eventually won't be used.
As you can see these are simple rational considerations and therefore I'm glad that they not only can be applied to several similar projects, but they have similarly been expressed in eXtreme Programming and also combined as a principle and acronym: YAGNI - you ain't gonna need it.
The basic idea is comparable to what's present in Test-Driven Development, too:
TDD: Create a failing test, but only implement code which is absolutely necessary to make it pass
YAGNI: Create acceptance tests, but only implement features which make them pass.
Both are applications of the KISS (my favorite interpretation is Keep It Simple and Straightforward) principle, so follow them!

2011-05-28

My first iPhone app: iOszkar

Pretty exactly three months after I came up with the idea and started learning Objective-C, Cocoa, the SDK and so on, my first iPhone app namely iOszkar has been released in the App Store.
It's an iPhone front-end to the excellent Hungarian ride sharing marketplace Oszkar.
I'm proud that the app has been accepted on the first try and I'm also satisfied with the performance of Apple: They managed to process the app within one workweek!




2011-05-26

Understanding EXC_BAD_ACCESS, EXC_BAD_INSTRUCTION/SIGABRT, and zombies

Being primarily a Java developer I was spoilt by the garbage collector of the JVM and therefore I had to face memory management issues when I started learning Objective-C for the iPhone, because that runtime doesn't have a garbage collector.

When an app crashes in most cases access to already released objects is the cause and there are two symptoms which refer to this fact, so let's see who they are and when they occur based on an example related to RestKit.

EXC_BAD_ACCESS
// Here creation and initialization of the params dictionary, etc.
...
SearchDelegate *delegate = [[SearchDelegate alloc] init];
[delegate release];
[[RKObjectManager sharedManager]
    loadObjectsAtResourcePath:@"/search/"
    queryParams:params objectClass:[SearchResult class]
    delegate:delegate];
What's happening here is:
  1. Search request parameters will be prepared
  2. A delegate will be allocated and initialized
  3. The delegate will be released
  4. Some network operation will be done
  5. Last the delegate will be called
The last step fails with EXC_BAD_ACCESS, because the desired object has been released, its assigned memory freed, but not allocated for another object.

EXC_BAD_INSTRUCTION/SIGABRT
SearchDelegate *delegate = [[SearchDelegate alloc] init];
[delegate release];
// Here creation and initialization of the params dictionary, etc.
...
[[RKObjectManager sharedManager]
    loadObjectsAtResourcePath:@"/search/"
    queryParams:params objectClass:[SearchResult class]
    delegate:delegate];
What's happening here is:
  1. A delegate will be allocated and initialized
  2. The delegate will be released
  3. Search request parameters will be prepared
  4. Some network operation will be done
  5. Last the delegate will be called

The last step fails with EXC_BAD_INSTRUCTION/SIGABRT, because the desired object has been released, its assigned memory freed, and also allocated for another object - this is why an exception with a message similar to the following will be thrown:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType objectLoader:didLoadObjects:]: unrecognized selector sent to instance 0x5967460'
We definitely didn't have to do anything with objects of type __NSCFType (it could be __NSCFSet, __NSArrayM, etc), so this is a precise indicator of an object stored on an unwanted memory area.

Ways leading to these errors
  • Over-releasing an object
  • Releasing an object not being an owner of
  • Not retaining an autoreleased object which will be released in the meantime via the autorelease pool
  • Prematurely releasing an object
  • Directly assigning an object to an instance variable instead of the accessor

Finding guilty objects
The exceptions and the subsequent crashes can't be tracked back, because the freed i.e. non-existing object has no information available. The easiest method is to enable the NSZombieEnabled environment variable in the Run phase of the product scheme accessible via the Product | Edit Scheme… menu entry in Xcode:


As a result deallocated memory areas will be allocated by special objects which will be observed by the runtime - these are the so called zombies. Sending a message to a zombie object results in a message similar to the following in the Xcode Console:
-[SearchDelegate respondsToSelector:]: message sent to deallocated instance 0x59be5a0
Furthermore, we can see the following in the Variables View in Xcode:
_delegate = (_NSZombie_SearchDelegate *)0x59be5a0 
Now, this is enough information to solve the issue.

As an alternative the Zombies instrument of Instruments can be used to track down the failure:

SyntaxHighlighter Objective-C brush

I just wanted to write my first post on Objective-C/Cocoa topic when I noticed that SyntaxHighlighter doesn't support this language out of the box. Despite thorough crawling I didn't find anything useful, thus I decided to write my own brush.
It works with SyntaxHighlighter 3.0.83, is available on GitHub, and its brush name is oc.

2011-05-24

UI Automation performance and the Page Object pattern

In one of my previous posts I provided an example which turned out to be of disadvantage:

function LoginView() {
    this.loginCells = window.tableViews()[0].cells();
    this.loginField = this.loginCells["loginFieldCell"].textFields()["loginField"];
    this.passwordField= this.loginCells["passwordFieldCell"].secureTextFields()["passwordField"];
    this.loginButton = this.loginCells["loginButtonCell"].buttons()["loginButton"];
}

Caching element paths in the constructor takes too much time, if:
  • Element variables refer to already cached subelements
  • The view currently isn't displayed.
This issue can be resolved as follows:

function LoginView() {
}

LoginView.prototype.login = function(user, password) {
    UIATarget.localTarget().frontMostApp().mainWindow().tableViews()[0].cells()["loginFieldCell"].textFields()["loginField"].setValue(user);
    UIATarget.localTarget().frontMostApp().mainWindow().tableViews()[0].cells()["passwordFieldCell"].secureTextFields()["passwordField"].setValue(password);
    UIATarget.localTarget().frontMostApp().mainWindow().tableViews()[0].cells()["loginButtonCell"].buttons()["loginButton"].tap();
}

Via this approach I don't put a runtime dependency on the creation of the LoginView object, so I can reuse anytime and anywhere in my test.
Although I use direct access in the UI Automation element tree due to the application of the Page Object pattern it doesn't disturb me, nor did I have to change anything in the test cases.

2011-05-23

UIAKeyboard keys and buttons

I've just discovered that the UI Automation keyboard doesn't only consist of keys, but also of buttons: All elements with light gray background are keys and all those with dark gray background are buttons.

I could write for example:

app.keyboard().keys()["e"].tap();
app.keyboard().buttons()["return"].tap();















But the distinction is only an option, because the elements are also accessible via the elements() method:

app.keyboard().elements()["e"].tap();
app.keyboard().elements()["return"].tap();

2011-05-22

iPhone UI Automation and the Page Object pattern

At the time when I was actively contributing to Selenium I used it only in conjunction with FitNesse and could therefore not directly apply the Page Object pattern. However, one of the key principles was for me the abstraction of the UI elements by creating UI maps which contain simple mappings of logical names to XPath path expressions.

The Page Object pattern defines the same abstraction: Define and use UI elements only in one module, and provide only service functions to the test cases.
Instead of diving deeper into theoretical details here is an example:

#import "Common.js"

function LoginView() {
    this.loginCells = window.tableViews()[0].cells();
    this.loginField = this.loginCells["loginFieldCell"].textFields()["loginField"];
    this.passwordField = this.loginCells["passwordFieldCell"].secureTextFields()["passwordField"];
    this.loginButton = this.loginCells["loginButtonCell"].buttons()["loginButton"];

}

LoginView.prototype.login = function(user, password) {
    this.loginField.setValue(user);
    this.passwordField.setValue(password);
    this.loginButton.tap();
}

LoginView.prototype.waitForDisappear = function() {
    this.loginField.waitForInvalid();
}
So a test looks like as follows:

#import "../TestControllers/LoginView.js"
#import "../TestControllers/UserDetailView.js"

var loginView = new LoginView();
var userDetailView;

test("Valid login leads to user detail page", function(t, a) {
    loginView.login("andras_hatvani","password");
    loginView.waitForDisappear();
    userDetailView = new UserDetailView();
    userDetailView.assertUserData("andras_hatvani", "Andras Hatvani");
},options)};

Although I use tuneup_js as test framework in this example, it could be Jasmine or a custom framework.
Important is that I could formulate the tests in a business-like language i.e. in an own DSL, thus it is not only straightforward to write, but also to read. Furthermore, if the UI changes, then I only need to adapt one single unit, namely LoginView.js to make my tests run again.

2011-05-18

Becoming a blogger

Like most human beings I also have an opinion, questions or answers. But so far communicating these entities was limited to forums, mailing lists, and comments to blog posts.

Now I think the time has come to be proactive and write down my thoughts to make other people react. I have no plans where this way will lead to, but I will definitely share my ideas and concepts on the infinite topic of software engineering.