If you're that close to using the max size of the heap, you may just be getting lucky (or unlucky). Calling recycle() directly vs. calling it from the finalizer may change the timing and behavior of the GC in such a way that you see differences.
Are you certain that your finalizer (and recycle()) are being called before you try re-allocating the bitmap? Finalizers are unreliable, and can be deferred indefinitely. Even if it you currently see the finalizer being called before re-allocation during your testing, there's no guarantee that this will always happen (especially for different heap states or future/different versions of Dalvik).
If you can, try as hard as you can to call recycle() from outside of the finalizer. If you know when you're done, just call the method; otherwise consider using a ReferenceQueue (https://stackoverflow.com/a/10879076/150001).
It's been a while since I looked at Dalvik, but I seem to remember that bitmap buffers could take a few GC cycles to be cleaned up, because the VM needed to be sure that no native code had any remaining pointers into it. So, the buffer may not be freed exactly when you expect it to be.
There's also the possibility that heap fragmentation is causing a problem, though there's a good chance that large buffers are allocated using mmap() and will not contribute to fragmentation (again, depending on the current version of Dalvik).