Hacker News new | ask | show | jobs
Android Development Tips For iOS Devs (stuartkhall.com)
92 points by appbot 4488 days ago
17 comments

I recently went in the opposite direction (Android -> iOS). Forget all of the flame wars. If you know one, dabbling in the other is a great learning experience. The two platforms are running roughly the same hardware and facing roughly the same challenges, and the software architects at Google & Apple have chosen different ways to solve the problems.

Sometimes the patterns feel similar. You can rig up an iOS tableview/data source delegate/fetched results controller to look almost exactly like an Android listview/adapter/loader. But in other areas they function completely differently. It is well worth the time spent learning the other IDE and language. My Android app is better because of what I have learned in iOS and vice versa.

I agree. I just started learning Android development about a month ago with Xamarin C#. Although its in C#, as a .net developer there are so many other things to learn.

Its exciting really. You see similarities and you also see differences. I think this helps more than it hurts since these "new ideas" will help me with the other environment (and vice versa).

This actually got me interested in learning other languages/frameworks (php, haskell, ruby on rails). After I get the hang of Android, I want to play around with an iOS app from scratch. Sure, I could use some conversion software to do this job. But, I'd rather not. I like to understand what's going on under the hood. I guess its the CompSci in me.

I guess what I'm saying is that I think it is so much better to have a universal understanding of these technologies then to blindly stick to one "team".

As an aside...didn't Facebook mentioned they used PHP not because it was "better" but because it happened to be the technology that worked for what they were doing at that time?

An important correction: Unlike iOS, Android does not come with a simulator. It has an emulator. That explains many of the differences in startup speed and performance. A simulator runs natively and does not have to emulate the ARM machine code on your x86 device. The Android emulator is theoretically more accurate and runs the entire Android OS, but the cost penalty is huge. Therefore, most Android developers test small changes initially on a device.

http://programmers.stackexchange.com/questions/134746/whats-...

Excellent point. Running the x86 images in the emulator is much faster (and Google recently released x86 images w/ Google APIs in them).

Genymotion is a decent alternative to the 1st party emulator, it runs significantly faster.

Genymotion is as close to the speed of the iOS Simulator as you can get today.

However, Genymotion is x86-based, so ARM libraries you use in your app that are designed to run on an ARM device will not work in Genymotion on your computer. However, if your use of those is limited to just a few Activities in your Android app, you should be able to do a lot of things with Genymotion, and just tiptoe around trying out that Activity on your computer and instead use it on-device.

By the time you use special binary ARM libraries you should have figured out the difference between an emulator and a simulator and also maybe discovered the possibility to deploy to a real device.
> Therefore, most Android developers test small changes initially on a device.

That's also because deploying an APK on a test device (or several devices) is way easier than deploying an IPA on an iOS device.

As someone relatively new to iOS this past month or so, I was shocked by the number of hoops I have to jump through just to take a piece of code I've written and put it on a device that I own and is sitting right next to me[0].

Coming from Android development, I never thought twice about this - it's easy to push the APK to my phone as part of the build process, and I don't even have to plug my device in to do so.

[0] Including shelling out $99 for a certificate that gives me the permission to do so.

I would argue that debugging is also infinitely easier in the Android world, since plugging a phone into USB and authorizing ADB gives you full control to see everything on the phone. You can get full logs and debug control over the hardware. You can push and pull stack traces and files to and from the device with a single, three operand command line and obtaining hardware screenshots requires only a click in IDE.

Android also has a plethora of debug options hidden in a special device settings menu that can be hugely helpful for troubleshooting performance issues.

You do realize that all of those capabilities are available in XCode?
Uh. It's way harder to setup an android device for debugging. I just had to plug in my iphone and tap "use for development" at the prompt.

I'm porting an iOS app to android right now, and android is way behind on the development side of things.

After you setup the provisioning profiles correctly, get the build schemes right, etc etc. Oh and don't forget to send Apple your tax id!

I would highly recommend using Android Studio + Gradle over Eclipse. IntelliJ is a significantly better tool for writing and refactoring code than XCode. Some of the tight integrations between XCode and the phone are superior (especially around profiling), but overall I think IntelliJ is a much stronger tool. Even something as simple as doing layout is vastly better on Android. There is no choice between 'in code or in Interface Builder'. XML + the viewer in Android Studio is the best of both worlds.

I also think Relative Layouts accomplish 99% of what auto layout accomplishes in a much friendlier manner.

I didn't have to do any of that. Xcode creates provisioning profiles for you, and appcode created the schemes I needed. I think Xcode does a decent job as well.

And you only need a tax ID if you're trying to imminently release a paid application or an app with IAP. But we're discussing development, not release.

Okay. I guess I mostly used iOS with the simulator and have less experience with their hardware interface. I just found the feature set for ADB to be pretty dang impressive. Most developers never touch even 10% of the the features even though some are very useful. I'd love to see a side-by-side comparison if someone has a link.

On the other hand, having iOS connect easily to a debugger disproves nothing I said.

"Obtaining hardware screenshots is just a click in the IDE"

I shouldn't need a computer attached to get screenshots for my app. Power + home button, or cmd+S in the simulator.

Even my users can easily send me screenshots, some of the time unprompted even.

How is it easier than just pressing the build and run button on XCode?
I think the problem he is having is with how to get to that point. There is a lot of setup to get to the point of just being able to hit the build and run button in Xcode. Of course, once that work is out of the way it's super easy.
What setup work? Install Xcode from the App Store, and log in with your developer account? There is less involved than just downloading and unzipping the Android SDK
(ignoring the creating the developer account) - create certificate(s)

- create provisioning profile(s)

- hit refresh in Xcode and hope it pulls in the profiles you want to use (maybe only an issue if you're a member of multiple teams)

- modify build settings

once you've done that its simple but there is definitely a setup overhead with Xcode and devices

I'm not sure if it has changed since I last made an ios app a while back, but there was a fairly large amount of security certificate provisioning and the interface for it, at that time at least, was unintuitive.
You can also use http://www.bluestacks.com for debugging/testing your applications.
"A trick often used by iOS devs is to use the tag of a view to hold lookup information, such as offset in arrays. With Android you can shove the entire object into the tag; pretty useful."

Yes, but if it's something like a ListView, don't put offset in array there, because the views are recycled (when user scrols), so you're likely to end up with corrupted data. I got bitten by this in the beginning. You can go to great lengths to prevent this from happening, but it will be hard for a reason, because that's abusing the design principles.

I'd recommend reading up on the ViewHolder pattern in this context.

Long story short: cache all the references to all specific sub-views of the row view in the tag (so you don't have to retrieve them again and again) - that's good practice. Just don't store any position-specific data in it.

Watch http://youtu.be/wDBM6wVEO70?t=9m50s - very informative

You can also just create a category on UIView that defines a property which could store a object.

@property (nonatomic, strong) id context;

or

@property (nonatomic, weak) id context;

if you are sure the context will always exist.

If you use ViewHolder, consider using custom views instead:

http://blog.xebia.com/2013/07/22/viewholder-considered-harmf...

I refactored all my code after reading this, and now I consider the ViewHolder an antipattern.

It is incredible how much cleaner and readable my codebase is with custom views. And the performance is the same.

Often used?

Number of times I have used view tags: Once.

"I used to think the iOS simulator was painful, now I realise it's pretty awesome. Skip the Android simulator all together and deploy to a real device, or be prepared to spend a lot of time waiting."

With its "native" emulator, yes, but there are better alternatives like Genymotion. Giving up on them is not good development advice.

The android emulators not only are bitterly slow to launch and use, but they do not reflect actual device performance, unlike the iOS simulator.

This makes automated testing impossible on the simulator, whereas in iOS I can run my full test suite (400-something tests) in the simulator in a couple seconds.

I find the simulator a bit deceptively fast, compared to a low spec iPhone (e.g. iPhone 4).

Also, there's the case sensitivity - iPhone Simulator is not case sensitive (maybe depends on your filesystem settings), while the device is case sensitive. This can be really annoying the first time round.

That is the reason why there are Nexus phones.
Nexus phones are for the development of AOSP, not apps.
Check out Genymotion.
I did, that's why I wrote "there are better alternatives like Genymotion"; I do use it.

It's not a coindidence that it is recommended by very talented developers such as C. Mottier: http://cyrilmottier.com/2013/06/27/a-productive-android-deve...

You can get a pretty responsive emulator if you use an x86 ABI and HAXM[0].

[0] http://software.intel.com/en-us/android/articles/intel-hardw...

Having used both the iOS simulator and the Android emulator, I don't really see why people continue to complain. There are even x86 images for the Google APIs and at least on my MacBook with that the emulator feels comparably snappy.
There is also the excellent Genymotion emulator. http://www.genymotion.com/
You will get a faster emulator, but since x86 is used on like sub 1 percent Android devices, won't that be more like using a simulator, which would make it just as useless/useful as a simulator? Does the x86 image contain support for ARM, too?
For most cases the underlying architecture doesn't really matter. "As useful as a simulator" is also quite a high standard for Android, seeing as there is no simulator available.
Some things I would note:

* Do not use getBaseContext() like he does when he created the new Activity. Use getApplicationContext for most things (unless an Activity is required) as this is guaranteed to be the same throughout the lifetime of your application.

* For log alternatives, checkout Timber by Jake Wharton (https://github.com/JakeWharton/timber)

* I would suggest using the Build.VERSION_CODES when making the check against which version of android the device is (http://developer.android.com/reference/android/os/Build.VERS...)

And if you want colored logcat in a terminal window:

    alias lc="adb logcat | sed -e $'s/^I.*/\e[0;94m&\e[0m/g; s/^D.*/\e[0;92m&\e[0m/g; s/^W.*/\e[0;93m&\e[0m/g; s/^E.*/\e[0;91m&\e[0m/g'"
Jake Wharton also has a neat fork of Jeff Sharkey's colored logout Python script which is pretty awesome:

https://github.com/JakeWharton/pidcat

"Tag A trick often used by iOS devs is to use the tag of a view to hold lookup information, such as offset in arrays. With Android you can shove the entire object into the tag; pretty useful."

No.. Just no. That's considered really bad form. The tag of a view should not be used (Abused) to hold an index etc.. that is linked to the data set.

This is excellent, thanks! Has anyone got similar resources for iOS devs looking to try out Android?
If you're commenting on the ease or difficulty of building iOS/Android native apps in this thread, and you aren't actively building an app for both or have built one before, you probably don't know what you're talking about.

The eco-system for building and deploying apps on both sides has gotten way better in the past couple years. There are pros and cons to both sides of development.

iOS pros: Blazing fast simulator, ability to run tests through xctool or Xcode. Autolayout is extremely powerful, and you don't need to write state suspend/restore code for landscape rotation.

If you're writing a new app, you can probably exclusively target iOS7.

iOS cons: The device limit. This makes deploying apps to your users more difficult than it should be. Xcode is also an extremely weak IDE, but AppCode makes up for it.

Android pros: Faster iteration with releases, because no review process. You're also less likely to fight app review for dumb shit.

The nexus 5 is only ~$420 with shipping.

Intelli-J support.

Android cons: Emulator is for all purposes unusable. You will need to buy a device. Fragmentation of the OS across all devices.

> Android cons: Emulator is for all purposes unusable.

At least on Windows it is quite usable for OpenGL ES emulation, when using Intel's virtualization driver.

UIViewControllers fall somewhere between an Activity and a Fragment.

In particular if you use any kind of view controller containment (custom container view controllers), you can only do that with fragments, and only then with Android 4.0+.

As someone who's looked at building tablet apps, the containment is a good thing to consider. In these cases, iOS makes it easier to combine your existing view controller hierarchies, while there are some idiosyncrasies (only 1 action bar across the top of a "split view controller") on Android still that don't always make things easy (in my opinion).

"When the user rotates the device your activity is completely reset" You just need to set " android:configChanges="orientation|keyboardHidden" in the manifest.

This is very well documented.

This is definitively the wrong way to handle the problem he describes in the article. Even if you set this in the manifest you need to store your state and resume from it correctly. An orientation change is the most common configuration change that causes activities to be restarted, but is far from the only one.
This. The most common other case in which you need to restore state is when your app goes into the background, and is restored.
My experience with ListView was... weird. It doesn't ask you for a height for each row like UITableView does, just for a row count. Then, it measures your views as you return them. This meant that the scrollbar was completely unreliable, it would resize based on the height of the currently visible views. Is there an obvious way around this that I'm missing? ListAdapter doesn't have anything for specifying height.
This is by design in Android. It's very computationally heavy to ask for the heights of each ListView item. Unfortunately I wasn't able to dig up my reference to this. :(

Two more things:

1. The wormy scrollbar is actually standard on Android: the messaging app does it, IIRC even the twitter app on Android does it. So even though your iOS experience tells you it's weird, any users of yours on Android likely won't notice.

2. If your items are all the same height then your scrollbar won't be wormy. So if this is really that important to you, then make your ListView return items that all have the same height.

> It's very computationally heavy to ask for the heights of each ListView item.

Can you expand on that? Do you mean that it's expensive for the OS for some reason, or do you mean that it's expensive for your (client) code to compute the height of each item?

It seems like in most cases it's a simple method like "return isHeader : HEADER_HEIGHT : ITEM_HEIGHT;"

For the OS. Imagine 999 rows containing one line of text and the last one containing a long text spanning maybe 30 lines.

To calculate the scroll accurately you need to calculate the height of 1000 elements to get the full height.

Instead in the common scenario you just calculate the height of the rows displayed on the screen and estimate the height using the average and the count.

I don't have to imagine this, though, I've done it on iOS. It works fine, because you're rarely working with 1000 items at once. With pagination, you cache the old results, and only calculate the new 50 or so rows at a time.
On the other end, pagination is rarely used on Android, and calculating the height of a single row can be more expensive since it has to layout the children hierarchy for a row according to the screen dimensions.
Okay, sounds like you're assuming a scenario where you need to actually create the view to figure out the height, sure.

In other scenarios (contact list, list of artists and albums and songs) you know the height of an item from its type, and you can just return (one of a set of) constants like I said. That shouldn't be expensive at all.

The height is calculated automatically for the rows that are visible and you can fix it to a certain amount.

So, as screigh said, you won't have the wormy effect on contact list, artists, songs, etc. because each row is always x pixels. The same happens if you have for example a series of thin and thick rows because they average out.

Another reason why using a set of constants is not common is that we have different screen sizes and different resolutions to deal with, so what looks like a good value for a resolution might not be the best for another.

Something like this[1] didn't work for you?

[1] http://stackoverflow.com/questions/15039913/android-how-to-m...

If you want a sort of CoffeeScript experience instead of Java you can also go with Xtend [0]. It's supported best in Eclipse but I do find the cleaner syntax a bit more pleasing to work with. It's only transpiling to Java so you can even mix it with Java while updating an existing codebase or for whatever reason.

[0] https://www.eclipse.org/xtend/

> Nemisis7654 said: (https://news.ycombinator.com/item?id=7391380)

> There is also the excellent Genymotion emulator.

> http://www.genymotion.com/

Genymotion deserves to be mentioned in a top level comment. It's the by far the fastest Android emulator and it works brilliantly simple.

Android uses an emulator not a simulator.
And It took me 10 mins to download the proper files andrun it using Intel virtualization, and my app runs faster than on my smartphone..
If you install the Android Intel Atom (x86) drivers and use that emulator, performance is much improved.
If you looking for an simulator instead of an emulator I would can recommend genymotion. (http://www.genymotion.com/). It's VirtualBox based and incredibly fast.