Groping towards an Android app

FluffyMcDeath

Active Member
Member
Joined
May 17, 2005
Messages
12,256
Reaction score
2,693
Though I don't know if I've really got the patience.
So I finally got a new phone because something decent was offered on a two year term for squat and I was getting more texts and the old 2006 vintage LG was a pain in the butt for texts and it's memory would fill up in only 99 texts or something daft ... but that's beside the point.

On Friday I installed the SDK and plugins into my Eclipse on Ubuntu 13.04 and started playing. I have an idea that I'm working on but this whole thing is very different from how I'm used to working. I haven't done any java since AWT was the latest greatest thing and I did precious little of it then.

I clearly have no idea what I'm doing with things split up between manifest and UI xml and the java classes and there's a lot of programming-by-google going on with plenty of cut and paste goodness.

Sometimes it seems like Eclipse is writing most of this for me, keeps popping up the little red Xs and telling me how I should fix things - or just fixing things when I double click.

Lots of little gotchas like exceptions for doing things in the main thread that google has decided they don't want you to do - makes just plain old fiddling about with an idea turn into a lot more typing... but, I guess it makes the final app better, though it's also making it more like my experiments are really a prototype that going to end up pretty much an app.

In a bit I'm going to install the iOS SDK on one of the Macs in the house and see how that is. I know Mike has worked with Android, what about Robert? Anyone got experience with iOS?
 
I've also just (two days ago) started tinkering with Android but haven't got it to do anything useful yet. Experiencing the same puzzles as you.

iOS is what I'm doing at work. It has it's own collection of weirdities, although I'm getting more used to it as I go along.
 
No experience with iOS here. Don't own a Mac or an iPhone, which puts me at a great disadvantage for that. However, some say it's easier to develop for the iPhone if for no other reason than you have fewer configurations to worry about.

Android probably is more work, no doubt about it. However, to make your life easier I would suggest to worry about API level 10 (Android 3.0) and up. The older 2.x versions of Android now make up less than half of the entire Android world and I suspect by this time next year it'll be less than a quarter. Designing apps that can work on pre-v10 APIs can be a pain in the arse. Navigation is a key issue as the ActionBar is introduced in Honeycomb and many Ice Creamsandwich phones no longer have hardware menu button (Yes, Samsung goes against Google's design guidelines, the S3/S4 really shouldn't have any hardware navigation buttons at all and is the main reason I don't want either). The HTC One for example adhere's to the guidelines much better in that regard.

Coming from a Windows development background, doing things the Android way did present a sharp learning curve. Like you mentioned there are a few constraints you need to deal with. There's even a bit of a catch 22 scenario which forces you to do it the "right way":
1) The Android OS clocks your call back routines to ensure that you're not taking too long (I think you have at most 3 seconds). If you take too long in your callback it offers the user the option to kill your app (ANR).
2) The UI can be updated only from the UI (main) thread, so the threads you spawned to do the slow work can't update the UI. This is actually a Java limitation and is probably the way it is for performance reasons. You gotta do your own marshalling.

So because of #1 above you'll be launching threads to do the slow work, and then jump through a few hoops because of #2 to get the UI updated. But lucky for you, there are some tools that help make the hoops easy to jump through. AsyncTask is one of them, and you should read this: Processes and Threads.

For me one of the biggest gotchas with Android is that you don't have full control of anything. In Windows, you can open a window and be reasonably sure that it'll stay open until you close it. Under Android it's a bit different. No matter how critical or urgent a task might be, it can always be interrupted by something like a phone call. And unlike a Windows window that simply loses focus, on Android your app will be paused, may be stopped and/or even killed - and the user might still wish to return to his task exactly where he left off. So you gotta learn how to preserve state. The OS preserves some state for you, but not all. Opening a dialog for example is something you're responsible for. If you have an About dialog open for example, and the user desides to change the orientation from portrait to landscape, your app will need to note that you had the dialog open, close the dialog, when your activity is recreated you need to check if your flag for the dialog is present and if so, open the new dialog once the Activity resumes. That's just not something you ever need to worry about in Windows or probably most other operating systems.

Anyway, here's some links to useful Android stuffs:
CommonsWare Android Tutorials - You may notice that this guy answers all the tough questions on StackOverflow.
CommonsWare Android Components - Some fun source code to hack/learn from. I used some of his code in Ampwifi.
ActionBar Sherlock - This lib allows for full Action Bar support all the way back to Android 1.6. But adds considerable bloat to your app.
ViewPagerIndicator - Something I'm considering of incorporating into Ampwifi to replace by (depricated) tabhost.
 
@Mike:

Excellent bunch of information in there. Thank you very much.
 
iOS is what I'm doing at work. It has it's own collection of weirdities, although I'm getting more used to it as I go along.
Sounds like I'll be talking to you when I start porting.
 
So because of #1 above you'll be launching threads to do the slow work, and then jump through a few hoops because of #2 to get the UI updated. But lucky for you, there are some tools that help make the hoops easy to jump through. AsyncTask is one of them, and you should read this: Processes and Threads.

Already found the need for AsyncTask. One of the first things I did was try sending a UDP broadcast from a button press - BLAMMO! Exception. Apparently firing off a UDP message could take too long to complete. Suddenly my dumb test app doubles in size! :/

Oh well, lesson learned.

--

Actually, ASyncTask may be a bit much for what I was doing. I have no progress and I have no result so maybe something less...
 
Sounds like I'll be talking to you when I start porting.

Feel free although I should probably point out that I'm still relatively clueless when it comes to writing code.

And with that in mind, I'm away to tinker with another Android tutorial.... :D
 
@Fluffy,

Handler might be what you're looking for. Just use the default Looper and post() a runnable that does the UDP broadcast, and you're done.

You could also set up a worker thread and send it messages and stuff, but that's more work. For that you may want to look at HandlerThread.

The Java purists might instead prefer FutureTask.

And there are other ways still, but that should get you going. :D

And if you wanna get fancy you can make it a Service and allow other apps to make use of whatever your UDP broadcast does.
 
Kinda funny. Fluffy is talking about UDP packets and last night I discovered a major bug in my datagram socket code the basically makes it fail on a number of devices including the HTC One X+. Here's a code snippet (parts removed for clarity):

Code:
@Override
protected Vector<ConnectionProfile> doInBackground(Void... params)
{
    DatagramSocket dsocket = null;
    DatagramPacket dpacket = null;
    Date start_time = new Date();
    Date current_time = new Date();
    byte[] packet_buf = new byte[PACKET_BUFFER_SIZE];
    byte[] work_buf = new byte[WORK_BUFFER_SIZE];
    String server_name = null;
    int server_port = -1;
 
    try {
        dsocket = new DatagramSocket(AJAX_BROADCAST_PORT);
        dsocket.setSoTimeout(SOCKET_ACCEPT_TIMEOUT);
 
        while (!isCancelled() && current_time.getTime() - start_time.getTime() < SOCKET_ACCEPT_TIMEOUT) {
            dpacket = new DatagramPacket(packet_buf, packet_buf.length);
            dsocket.receive(dpacket);
 
            if (!isCancelled()) {
                // Do a bunch of stuffs
            }
        } // while()
    } catch (IOException e) {
        // If we're here, it's probably because the socket timeout was reached
        e.printStackTrace();
    } finally {
        if (dsocket != null) {
            dsocket.close();
        }
    }
 
    return null;
}

Fairly straight forward and it looks alright (and yes my variable naming convention is unconventional, so sue me). But here's the problem: The DatagramSocket class is from java.net and that was never really designed for mobile. What's special about UDP multicasts on mobile? Well, receiving all that UDP garbage is costly in terms of battery life so some manufacturers simply turn it off. Nice, thanks very much! HTC appears to be one of those manufacturers who's decided to gain a little extra battery life by filtering out the UDP multicasts. Samsung seems to be cool with the UDP multicast packets and so do all the Nexus devices (and so is my ASUS tablet btw), but I get the feeling all HTC devices drop them.

So that's the problem, how about the solution? It took a while to figure it out, but I think there's a solution. I didn't have time to try it out last night (it was my turn to get Sophia back to sleep so that put an end to my debug session), but it seems promising. It requires the use of the android.net.wifi.WifiManager class, or more specifically, the MulticastLock class that resides within it. The word on StackOverflow is that you can use it to acquire() a lock on the multicast packets and direct them to your app for snooping. Once done with multicasts you can release() the lock. So that's what I'm hoping to try out tonight, hope that works.

This bug would have been present since version 1.0 of Ampwifi, released over a year ago. Wow, I'm surprised no one sent me an email complaining. Oh well, luckily I was able to spot it and hope to have the fix out for the next release.
 
What's special about UDP multicasts on mobile? Well, receiving all that UDP garbage is costly in terms of battery life so some manufacturers simply turn it off. Nice, thanks very much! HTC appears to be one of those manufacturers who's decided to gain a little extra battery life by filtering out the UDP multicasts. Samsung seems to be cool with the UDP multicast packets and so do all the Nexus devices (and so is my ASUS tablet btw), but I get the feeling all HTC devices drop them.

I think I'd read something about that and was wondering if I'd have to deal with it because, at some point, I need to be listening for those packets. Unfortunately the way I have things figured at the moment is that I will need to listen whenever I am connected to a wifi network so that could be a battery killer. I think I might want to add a config to only listen when I'm connected to certain networks, most likely my home network.

I have Samsung and ASUS for testing but I'll have to try to keep this in mind because I don't want HTC people to silently uninstall me (which is what people most likely will do - who has time for complaining and rating stuff).

By the way, how much feedback DO you get from the Play Store? Do you know at least what platforms uninstalls are happening on?
 
You do get some feedback on the Play store. It's very much anonymised of course and highly summarized. Here's a screen shot from my dev console:

stats.PNG

Of course you don't know why people uninstall it and you don't get a complete list of every device that has ever uninstalled your app. But it gives you a basic idea.

I don't use any Google analytic software embedded in my app, instead I use Flurry analytics. Why? Just a recommendation from a conference, I hear the Google Analytics is actually pretty good too and I may one day switch to that. But with that you can log whatever it is you want. I use it mostly to log errors and exceptions. I also used it to log how many people actually read the setup guide as I wanted to know if my app was too scary to setup due to all the networking stuff involved. Btw, for some reason most of my negative feedback is from German speakers. Weird.

As to radios and battery life, Google has a recommended polling schedule for apps. It's mostly intended for apps that check a central server for updates, and probably run as a background service as opposed to an active app (think Facebook, GMail, etc). They recommend to slow down the polling rate after a certain amount of time, speeding it up again when the user is active with your app. Not sure that makes sense for you, but something to consider I guess. For my app it doesn't make much sense as it's purpose is to be a real time remote so I assume if they're running the app they want to see actual data, not stale data.

And oh yeah, I recommend you start using Fragments for your UI design. You'll thank me when you decide to make it look nice on a tablet. I'm planning a major overhaul just to do that.
 
And oh yeah, I recommend you start using Fragments for your UI design. You'll thank me when you decide to make it look nice on a tablet. I'm planning a major overhaul just to do that.

Nah. I like the old fashioned way, kind of like what you describe. Slap it all together, get it working, think about it a while and the realize how you SHOULD have done it. How can you learn from your mistakes if you start out by deciding not to make them. :D
 
So I had some time to try out that fix on the One X+. It worked very nice!

Borat_Great_Success.jpg


Just needed to add CHANGE_WIFI_MULTICAST_STATE to the manifest, and it was good to go.
 
Nah. I like the old fashioned way, kind of like what you describe. Slap it all together, get it working, think about it a while and the realize how you SHOULD have done it. How can you learn from your mistakes if you start out by deciding not to make them. :D
I so don't like your approach.
 
And just as you start getting used to Eclipse, Google releases Android Studio. A whole new IDE specific to Android development. They don't say, but I'm guessing Eclipse support will soon end.
 
And just as you start getting used to Eclipse, Google releases Android Studio. A whole new IDE specific to Android development. They don't say, but I'm guessing Eclipse support will soon end.

Nice. I'll hopefully get a chance to try that later in the week.
 
Back
Top