and still may not

Category: Android

On my phone, scrolling web pages on Chrome recently became unbearably ugly. Every few seconds when scrolling Chrome will freeze completely, apparently no longer reacting to touch input, only to come back to life a split second later.

I haven’t seen this suggestion around, and it’s the only workaround that actually worked on my Samsung Galaxy Note III Neo.

Open chrome, and type chrome://flags in the address bar.

Look for the “Touch Scrolling Mode” setting (#touch-scrolling-mode), and set it to touchcancel.

On my phone, that fixed the scrolling problem completely, and the only drawback seems to be that I don’t have that fancy decelerated animation anymore. He, it never was that smooth to begin with, so I guess I’ll live with that 🙂

Your mileage may vary, but it shouldn’t take significantly longer than a couple of hours. If you’re not too unlucky, it should probably take just one hour, both when you’re publishing an app for the first time, and when you’re releasing an update for an existing app.

If it’s taking significantly longer than that (I’m talking more than one day here), you may have been fooled by Google’s peculiar requirements for deployments.

This fooled me twice (so I guess, shame on me).

When you publish an app for the first time, you need to create a Google Group or a Google+ community for testers before the link to your app becomes available. If you try to access the link (even using your own Google account) without being a member of the configured group/community, you’re greeted with a 404 page.

Last time I published an app though, setting an existing Google Group for testers (one that I had configured for a different app) didn’t seem to work. When I created a new Community on Google+, it worked right away. I don’t know if I was just unlucky or if you need a dedicated Google Group for every app, but if you still get a 404 after setting up the Google Group, just try with Google+.

After you’ve become a tester for the app (by visiting your app’s page on the Play Store) it usually takes another hour or so before the APK becomes available for download.

Of course, I only discovered chrome2phoneafter I was already done writing the app. Luckily, they’re a little different. My little app exists to make sharing links using any sharing app (any IM app, email, clipboard, whatever accepts text), whereas Google’s app is more to share links with browsers. Also, the reason why I started writing the app in the first place was to let me share stuff with my friends on Whatsapp, and that’s waaaay more easily done with my app than with Google’s.

All the code is released under a GPLv3 license, so you can take inspiration (wink, wink) from GitHub: the Android app is here, the Chrome extension is here.

This is something I put together for WhatsHare, a small open source app that I published; I couldn’t find a tutorial that had all of this together in one place.

My app (actually, just one particular Activity) has no UI: it receives an Intent, does its thing and finish()es. The only way I found to notify the user that it’s done something is to add a Notification, as dialogs would get too in the way.

I want the notification to be shown every single time, as it must tell the user “ok, I did something” or “an error occurred”, because she has no other way of knowing if the app even worked!

On the other hand, I don’t want to pollute the notification area with lots of “Success!” notifications, as they’re ultimately pointless once the user has seen them.

The options were to either:

automatically cancel() the notification once the message has been displayed, or

show the message every time, but collapse all notifications into a single one, with an increasing counter

I preferred the latter approach, as I think it feels a little more predictable for the user (also, the other solution requires dedicated services/timers, so it’s probably more complicated).

you define a static counter for all your notifications, so that the NotificationManager treats them as separate

AUTO_CANCEL is set so when the user taps on the notification it disappears

setDeleteIntent() is called to have an Intent routed to the Activity’s onNewIntent() method whenever the notification is discarded, so we can reset the counter. If users tap on the notification, onNewIntent() is also called because of notificationIntent being set as content intent

since this activity has an intent-filter for action.SEND of type text/plain, we know that an Intent with no EXTRA_TEXT field can only be passed explicitly — that is, by setting the class target when creating the Intent –. We could add some other extra if we wanted to make extra sure that the Intent comes from that specific class

whenever a notification needs to be stacked, we cancel() the previous one (using its id, which is always the current counter minus one) and create a new one with the updated count

That’s the magic behind stacked notifications: Android does not show your notifications if you’re just updating them, so you need to cancel the old one and add the new one. If you don’t need to show the message every time, just update the previous notification using its id (that must not change, so no counter at all).

About JellyBean: if you don’t raise the notification’s priority to at least PRIORITY_HIGH it won’t show the counter on phones/phablets for some reason. Also, to make sure that messages are displayed every time on phone/phablets you must set them as tickers; tablets instead show the full message set by setContentText() anyway.

A final note: I’m using NotificationCompat.Builder instead of plain Notification.Builder to support older devices. You can find that class in the support library (android.support.v4.app package). If you’re targeting honeycomb and higher, just use Notification.Builder.

This is something I noticed on Android, but from what I read it also involves the desktop Java version.

I was sending POST requests to an API server, and I was getting some random 400 Bad Request responses from time to time. I wish Apache provided an easy way to log the plain text version of Http requests, but I couldn’t find a better way to see what the app was sending than sending the same request to my PC when failing.

I don’t know if it’s my router, but sometimes connections from the Android device to my PC get blocked: to make them work I just open a browser on the Android, go to some website and then try again with my internal IP (192.168.0.whatever). It always works, no idea why.

Using this code I discovered that my post requests were executed 4 times each, nearly at the same time. I discovered that it’s the default behavior, and you must provide your own RetryHandler if you want the HttpClient to work otherwise.

In my case, my calls are sent to Google’s shortener service, and for some reason sometimes it just rejects requests. If you wait a little bit between attempts you increase your chance of getting valid responses. So this is what I did:

where debugPost() is a method that calls my PC to log the request, and Utils.debug() is just a small utility method I wrote to log messages with logcat using String.format() if format args are passed to it (it also takes care of splitting messages that would be truncated by logcat itself).

You could choose to implement exponential backoff very easily, but since it’s a blocking operation for the user in my case I preferred not to.

Keeping all your strings.xml files synchronized in Android projects can be painful, as Eclipse doesn’t tell you which strings have no localized version in which language. Android is perfectly happy with it as well, it just uses the default (usually English) string in the app, much for the joy of your non-English users.

I came up with a simple Python script that just scans your res/values-** folders for strings.xml files and, using your default res/values/strings.xml as reference, outputs a list of missing strings for each file, along with the original value set for the key.

So the idea is that you can cut and paste those lines in the appropriate files to translate them.

The script also outputs some warnings in case it finds duplicate keys in any of the strings.xml files.
Your localized strings.xml files may have more <string> items than the default, as no check is performed against that.

I put the script it in a folder within my Android projects that is simply ignored by Android (I usually call it not_in_apk or something like that), so if you put it elsewhere remember to change the path at line 23

path_to_default = '../res/values/strings.xml'

to the path to your default strings.xml file (absolute or relative, it should work anyway).

I didn’t do much testing, so it may not work for you… Worst thing that can happen is.. it doesn’t work 🙂
It won’t mess with your files, I promise you that.

I’ve seen two bad things about working with several workspaces thus far:

you lose all your settings when creating a new workspace (Eclipse only asks to copy perspectives from the current workspace, which is something but not enough)

Eclipse kept showing me a bogus workspace that I never created in the File/Switch Workspace menu, plus it didn’t understand when I renamed one, so it started showing that workspace with both names (old and new)

The first issue can be solved by following these steps (which of course I discovered after doing them by hand… silly me).

As for the second, on MacOS go to your Eclipse installation folder (I have it in Applications), then open configuration/.settings/org.eclipse.ui.ide.prefs with a text editor.

The variable you’re looking for is called RECENT_WORKSPACES, where workspaces are listed one for each line (I can actually see the ‘\n’ as line separators). Delete the silly ones, restart Eclipse, done!