2011/01/26

SIMBL For Poking Inside Mac Application Internals

SIMBL is, according to it's Home Page:

Problem:
Some applications do about 90% of what I want.
Solution:
Develop my own applications.
Better Solution:
Patch the application myself...
SIMBL (SIMple Bundle Loader) - pronounced like "symbol" or "cymbal" - enables hacks and plugins. For instance, SIMBL enables PithHelmet to enhance Safari.

So, let's say we have a naughty program that has a behaviour we don't like. How would we treat that problem?


  1. class-dump TargetProgram
  2. Look at the list of classes and note the one that seems to be the issue. Let's call that class Victim.
  3. Inside, find your naughty method, let's call it '- (BOOL) victimMethod;'
  4. Open Info.plist of the victim, and note the bundle name and version
  5. Create new Cocoa bundle in XCode according to the steps on SIMBL site
  6. Fill in the bundle name as stated
  7. Use the following code: 
  8. Restart the target app
  9. ???
  10. Profit!

2010/11/25

Gallery, clicking and selecting

Android SDK includes a nice-looking component named Gallery.
It's supposed to provide you with functionality of flickable view-changer.
It get's an BaseAdapter and displays views it receives.
All good until you actually start using it.

First issue: 
setSelection(index, animated) method ignores the second parameter. There's no 'todo' anywhere, 'deprecated' or even acknowledgement from Google. It just doesn't give a crap what you pass there. It always navigates to your item without animation.
Now let's say that I want to change items in the gallery every X seconds. How can I make a pretty animation showing this lovely change? By hacking the bastard. Basically, the animations are initiates by the Fling motion that the component detects. If you simulate the correct fling - you will get the View flip animation.

gallery.onRealFling(null, null, -800, 0);
Here's a tricky part - the X velocity parameter needs to be adjusted per application, because to fling a larger view, you need a bigger velocity. So play with that value until you get a smooth transition.


Second issue:
Items inside the layout that you return in your adapter cannot receive click events. They just can't. No good reason for it, but someone botched up the bubbling up of mouse events in the Gallery, so now you can't have clickable items. If you set any one of them as clickable - the gallery stops handling dragging.
But fear not - you can fix it!
The solution is as follows - you add a touch listener to the gallery, and catch a Single Tap event (I did it with gesture listener), to differentiate it from the dragging that the gallery needs to handle.
Then, from the the location of the touch event, you can calculate where exactly inside your sub view the click was made - and from that you can handle the actual click.

Here's the code:

2010/10/24

Making a real marquee out of Android TextView

Android TextView supports a Marquee ellipsis method, which starts animating the text in the TextView if it's width exceeded the width of the view.
But let's say you want it to animate the text constantly? Here's a classic trick - pad the string until it goes out of the width of the view, so it will start the scrolling.


The hard part here was to find out how to calculate the line width (since the TextView itself doesn't supply that info. Had to dig android sources for that.

2010/09/22

A PDF Intent

Here's a naughty bit of behavior from the Android's Intents.
When you want to customize the mime-type of the requested intent, the setter for reason resets the previously set Data parameter. Cute right?
And to overcome this great issue, the API has another method setDataAndType(). See what they did there?
Anyways - here's a correct method (opening a PDF in this example):



NullPointerException Confusion

It's good to know that our field is called Computer Science. We're scientists. We like facts, laws and rules... Yeah, right. You think that if you've learned the basics of Data Structures, Algorithms and other courses in your B.Sc. it would prepare you for the real world. Nope. It's craaaaazy out there.

Today I had a real head-scratching moment when a completely innocent 'hashtable.put(key,val)' started giving me NullPointerException. Now, since I do know how hashes work, all I checked was - is the table itself null ? Nope, it's good. So what the hell?

Here comes the scary part:

put

public V put(K key,
             V value)
Maps the specified key to the specified value in this hashtable. Neither the key nor the value can be null.The value can be retrieved by calling the get method with a key that is equal to the original key.
Specified by:
put in interface Map<K,V>
Specified by:
put in class Dictionary<K,V>

Parameters:
key - the hashtable key.
value - the value.
Returns:
the previous value of the specified key in this hashtable, or null if it did not have one.
Throws:
NullPointerException - if the key or value is null.
Apparently the usual approach is not good for the Java folk. They don't want no stinking nulls in their precious hashes!
The reasoning behind the idiocity is this - the default behavior of get() method in hashtable is to return null if key was not found. So when the designers of the API chose that wrong path, they had to follow it up with a wronger path, since they couldn't distinguish between a null from 'no key found' and 'null found  as a value'.

I hate people.

2010/09/15

GridViews, Buttons, Oh My.

In Android, there is a versatile class called GridView which can display any custom designed cells. You provide it with a layout for each item, fill in the values - and voila - it's working.
All is well, until you try to add something interactive to the Grid cell - like a button - you come across an interesting effect.
If you add a onClick listener to both the GridView and the Button inside the GridView - only one will get the click event. And you won't guess which one :) (hint: it's the button)
So basically, you can have interactivity - but not paired with OnItemClick events of the Grid.
Bummer, right?
Wrong. This can be rather easily fixed, and the problem lays in the way Android handles focus resolution between parent and child Views. For ListView you can play with Focusability parameter which controls who reacts first, and on GridView, just the the Button's Focusable parameter to false - and it just works. It still gets the touch events which cause the click, but it doesn't interfere with the focus mechanics of the Grid.
You're welcome!

2010/07/18

The Saga of COMException (0x800736b1)

So I had a very lovely weekend being sexually assaulted by a pesky problem while installing an ASP.NET application on a Windows XP IIS server.


Server Error in '/AppName' Application.


This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem. (Exception from HRESULT: 0x800736B1)



Exception Details:System.Runtime.InteropServices.COMException: This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem. (Exception from HRESULT: 0x800736B1)


Ok, this is lovely. Tracing the error code was pretty straight forward and pointed to the lack of VC++ Redistributable DLLs on the target machine. They are present on the developer box, but are missing on target. Sounds easy enough, downloaded vc_redistx86.exe , installed - same result.

Excellent. So, using depends.exe, I checked that the DLL in question is looking for msvcr80.dll and friends. Curiously enough - they were installed on the system, but the problem persisted, the application just didn't pick them up.

So I dug some more, and came across a folder \Windows\WinSxS (http://msdn.microsoft.com/en-us/library/aa376307(VS.85).aspx). It's Microsoft's solution to DLL Hell. There are several versions of the same CRT DLLs, in subfolders with different version names.

Which pointed me to the fact that it's not that the DLL is missing, but it's of incorrect version. So what was left is to discover how exactly does the application select which DLL to load. (it's obviously not by name!). So after frantic Google searches I came across a beast whom I met before but didn't pay attention to - "XP Manifest". 

It's a XML file which is embedded inside the application/DLL as a resource, and can define properties like 'Dll dependency'. So a quick run of ResHacker, patching the XP Manifest, saving the new app, re running, seeing that it works and then promising my self to tear away the nads of whomever though it would be a great idea to make me spend my weekend tracking this shit, and not just showing me a freaking help message!