Showing posts with label fun. Show all posts
Showing posts with label fun. Show all posts

20 April 2013

Layouts in Android not switching correctly between portrait and landscape

After having followed all the examples on the Android developer site to the letter about supplying multiple layouts for different screen sizes and orientation I was still having issues with them on extra large screens (10" tablets).

Basically the layout would not load when I rotated the tablet while the application was running.

If I started the application in portrait then that layout was correctly selected and when I started the app in landscape that layout was likewise correctly loaded. But after one layout was loaded the orientation change did not trigger Android to switch automatically.

The culprit was in my AndroidManifest.xml file. For some reason when I first created my activity the configChanges attribute had been set automatically for me to:
android:configChanges="keyboardHidden|orientation|screenSize"
removing screenSize solved the issue:
android:configChanges="keyboardHidden|orientation"

Obvious eh...

Edit: This behavior is actually documented in the android development guide.

19 April 2013

Fast Flicking Between Images on Android

So I wanted to be able to have a simple control that supported swapping between a list of images as the user swiped/flicked their finger across the image.

My initial solution was to have a HorizontalScrollView which showed all my images in a row. This worked pretty well but I wasn't able to accurately stop to show each image on the screen as the user flicked between them. They always seemed to end up half off-screen.

After spending a few hours attempting to wrestle the scrolling events in the HorizontalScrollViewer under my control I realised that I must be doing something wrong, surely this isn't this difficult.

ViewPager

And yes, it couldn't have been simpler. More information on the android blog. But basically I ended up creating a simple PagerAdapter like so:

public class ImagePagerAdapter extends PagerAdapter 
{
 Bitmap[] _images = null;

 public ImagePagerAdapter( Bitmap[] images ) 
 {
  _images = images;
 }

 @Override
 public int getCount() 
 {
  return _images == null ? 0 : _images.length;
 }

 @Override
 public boolean isViewFromObject(View view, Object object) 
 {
  return view == ((ImageView)object);
 }
 
 @Override
    public Object instantiateItem(ViewGroup container, int position) 
 {
  ImageView img = null;
  
  if( position >= 0 && position < _images.length )
  {
   final Bitmap bmp = _images[position];
   
   img = new ImageView(container.getContext());
   img.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
   img.setImageBitmap(bmp);
   img.setScaleType(ImageView.ScaleType.CENTER_CROP);
   ((ViewPager)container).addView(img, 0);
  }
  
  return img;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) 
    {
     ((ViewPager)container).removeView((ImageView)object);
    }

}

Then in my Activity/Fragment class it was a simple matter of just assigning the adapter to my pager and that is it!

ImagePagerAdapter adapter = new ImagePagerAdapter(bitmaps);
((ViewPager)v.findViewById(R.id.fragment_bird_banner_viewpager)).setAdapter(adapter);

Lesson: If things that you feel should be basic are becoming too complicated and taking too much time. You're probably doing them wrong. Step back and search/read a little bit. :)

13 April 2013

Is my mobile app really free when it is serving ads?

I use this rather handy app, BaconReader from http://onelouder.com/ to browse Reddit.com.

I connected my tablet to my computer and turned on LogCat as I was about to start debugging my own little app. Instead two little log lines caught my eye:

D/baconreader(25507): Message Service Started
D/baconreader(25507): Checking for messages

That was something I thought shouldn't be running at all, I launched the BaconReader app to double-check that all settings related to notification and background activity for that app were indeed turned off  or set to manual (I do this in effort to conserve battery power). They were all off but still the app was periodically starting up a service to check for messages (thanks for that).

While doing this I glimpsed how much excess network activity the application was performing while I was under the impression that it was "idle" (i.e. I wasn't interacting with it).

Usage and User Profiling

The application is using what seems two different platforms to track users and usage patterns Flurry and Google Analytics. Fair enough, nothing too fishy about that I guess. Both services seemed to communicate very sparingly with the server with only an initial message sent when the application started up and then stayed silent while I let the app sit "idle".

Advertisements

I have no problems with apps that serve ads in exchange for me being able to use them for free. What I found curious was that this app seems to be contacting three different ad services with varying levels of details about both me and my device.

Millennial Media
This component, initiated a HTTP request twice every second, each time with a very verbose URL. Below is an example of the query parameters for one request:

accelerometer:true
adtype:MMBannerAdTop
ar:manual
bl:46
cachedvideo:false
conn:wifi
country:GB
density:2.0
dm:Nexus 10
dv:Android4.2.2
hdid:mmh_94888091071502DC8F18CE0A08CBFA79_6AC9AD8BDA218890306A1DAF963D603E089F82C9
height:53
hpx:2464
hsht:53
hswd:320
language:en
loc:false
mmdid:mmh_94888091071502DC8F18CE0A08CBFA79_6AC9AD8BDA218890306A1DAF963D603E089F82C9
mmisdk:4.6.0-12.07.16.a
pkid:com.onelouder.baconreader
pknm:BaconReader
plugged:true
reqtype:getad
sdkapid:62626
space:16810389504
ua:Mozilla/5.0 (Linux; U; Android 4.2.2; en-gb; Nexus 10 Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30Nexus 10
video:true
width:320
wpx:1

I'd love to know the reason why they need to know why my device is plugged in or not, how much space is free on it and what connection method I'm using to connect to the internet. Seems a little much but still nothing surprising and unexpected from ad requests. The standard tracking-cookie for my device is even included in the hdid variable (I assume) but no GPS information was transmitted (even though GPS was enabled for apps on my tablet).

Google AdMob
Pretty standard AdMob (old doubleclick.net) requests really. Nothing unexpected here, they even try to minimise the amount of characters traveling over the network. How nice of them! Still they sent two requests every second. Below is an example of their querystring:

preqs:0
session_id:6944941379333807684
u_sd:2
seq_num:1
u_w:800
msid:com.onelouder.baconreader
js:afma-sdk-a-v6.2.1
mv:8016014.com.android.vending
isu:94888091071502DC8F18CE0A08CBFA79
cipa:1
bas_off:0
format:320x50_mb
oar:0
net:wi
app_name:38.android.com.onelouder.baconreader
hl:en
gnt:0
u_h:1232
carrier:
bas_on:0
ptime:0
u_audio:1
u_so:p
output:html
region:mobile_app
u_tz:60
client_sdk:1
ex:1
slotname:a14eb80d44ba957
caps:inlineVideo_interactiveVideo_mraid1_th_autoplay_mediation_sdkAdmobApiForAds_di
jsv:46
This by far was the worst offender. AdMarvel was a small mobile ad startup that was recently (in 2010) bought by Opera Software. The device performed 4 requests every second (where two requests were identical except for one querystring variable had changed, that is retrynum had been incremented from 0 to 1). Below is an example of one of their query string:

site_id:23206
partner_id:7b862efbe6c75952
timeout:5000
version:1.5
language:java
format:android
sdk_version:2.3.7.1
sdk_version_date:2013-02-04
sdk_supported:_admob_millennial_amazon
device_model:Nexus 10
device_name:JDQ39
device_systemversion:4.2.2
retrynum:0
excluded_banners:
device_orientation:portrait
device_connectivity:wifi
resolution_width:1600
max_image_width:1600
resolution_height:2464
max_image_height:2464
device_density:2.0
device_os:Android
adtype:banner
device_details:brand:google,model:Nexus 10,width:1600,height:2464,os:4.2.2,ua:Mozilla/5.0 (Linux; U; Android 4.2.2; en-gb; Nexus 10 Build/JDQ39) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2
hardware_accelerated:true
target_params:UNIQUE_ID=>f780070d9537897a||GEOLOCATION=>59.4954954894955%2C-0.99682319125740403||bucket=>4||subreditname=>Front+Page||RTBID=>FBATTRID%3Ae939e527-35db-4e98-8d73-e05fead999b1||APP_VERSION=>2.8.1||RESPONSE_TYPE=>xml_with_xhtml||BNG=>0

What I find worrying here is (besides the size of the request) their final target_params variable which not only includes the ID for my device and exactly what part of the application I am viewing but also a pretty accurate GPS location (disabling GPS access for all apps got rid of that) and what looks to be Facebook related FBATTRID tag to serve ads from Facebook's MoPub Marketplace.

Talk about being tracked between devices.

Conclusion

All of this activity was happening multiple times a second for all three advertising services on my device. So six times a second my device was communicating tracking information and requesting advertisements back.

One of the most battery draining activities is transmitting data through the air on a mobile device. Based on these three services it seems like the industry standard is to query twice every second which to me feels overly aggressive and costly on my battery charge.

So what are we really getting for free? How much money are we spending on electricity to power our devices that is then used directly to serve us advertisements?

Perhaps I should just buy the thing, probably cheaper in the long run!

9 May 2012

Internet Rule Number 36?

In the last few years I've realised that having the attitude that

It's easier to ask for forgiveness than it is to get permission.

is in in many cases the easiest way to get things done. This approach can save you oh-so many pointless arguments and typical corporate ass-covering meetings with people less interested with getting things done and more with their job title and feeling important.
Meetings!
I admire people that just get shit done.

I might not agree with their approach. I might even argue with them, but no one can argue with results!


Unoriginality
When searching for the original author of that comment above I discovered that it is attributed to the late Grace Hopper. A remarkable woman and a great speaker. I think the video below shows possibly one of the best ways to explain intangible concepts. Bring a prop.


5 March 2012

Your code sucks, let's fix it

I found this presentation by Rafael Dohms quite interesting. It has some radical blanket statements and highly objectionable points but also quite a few post publishing edits and corrections.

If you keep a cool head and just take this as it is, you might just learn something (or at least get a refresher). I'll be the first to admit that I did.

4 March 2012

Degoogling

Like so many others I feel it is time to wean myself off my dependency on Google for search. It may come as a no surprise to anyone how relying on a single source for information opens you up to significantly biased view of the world and is inherently dangerous to do unconsciously. Although my field of work does not strictly require me to present an unbiased view of matters, recent policy and privacy changes for Google products have made me realise how, on an unconscious level, I immediately turn to Google search when I need to look something up and how that can impact my online experience in seemingly unrelated systems.


Cold Turkey
So I thought my best course of action was to completely remove Google search as my default go-to search provider. To begin with I chose to try out Bing (as it is the only search provider that offers a similar range of products I use from Google, i.e. search and maps). I am still disappointed that I couldn't use Office365 for free for personal use (I'd even settle for ads) but it seems that suite is solely meant for business users (big mistake I think).

So first I had to identify where my searches were originating from. I identified the following three areas in descending order of importance:
  1. My keyboard launcher, Launchy
    This is by far the most common way that I perform search on my computers. Fast and efficient but has contributed to this mental association that search == google as I need to type in the first letter of the provider I want and then press tab to enter my search term.

     
  2. Browser's address bar
    As I am a heavy user of Google's Chrome browser it has become almost natural to just start typing what I want into the address bar and then either press enter to search directly or pick from the drop down list. This is such a natural thing to do that I do it in any browser I use.




     
  3. Browser's search provider box
    After I stopped using Firefox as much as I used to I've stopped using the search provider box as much. But I still occasionally press Ctrl+K and start typing when I find myself using Firefox now and again. Neither IE or Chrome have this box anymore.

     
  4. Navigating to the search providers website to perform search
    This I almost never do on my main computers but occasionally do when using my phone to search for things. It is slow and annoying

How Easy Is It?
The single biggest difficulty I see is to change my own behaviour and the association I've made with Google and search, it will be hardest for item 1 as I need to stop typing "g <tab> <search term>" and rather type
"b <tab> <search term>"

Not so hard it seems. But I soon realised how instinctive that "g" had become. Most of the time I had already typed it and pressed <tab> before I realised. So that is going to be a challenge to change. Item 4 is so painful to do anyway that I don't see it as a problem at all (although it would be more of an issue if I used the search button on my Android phone more).

The rest is just a matter of configuring the technology to do what I want it to it seems.

Imagine my surprise when the simplest tool to configure to use Bing by far was Google Chrome and the biggest disappointment and betrayer was my old friend Mozilla Firefox.


Google Chrome 18
Simple. Clicking the spanner/wrench icon in the upper right hand side of the browser window, choosing Settings and simply choosing "Bing" from the dropdown list under Search on the Basics tab.
Voilà, now all my searches through Chrome are directed to the Bing website.

Total clicks: 3
Annoyances: None


Microsoft Internet Explorer 9
Strictly speaking then no configuration is needed out of the box for this browser as it comes with Bing already configured as default. However that is also the only search provider it comes with by default. To install any other is more painful that I would have wanted.

IE'sCog Icon
But to choose a different provider it is necessary to click the cog icon in the upper right hand corner of the browser window

Choose Internet Options, clicking the Settings button in the Search section on the first tab. That opens the Add-ons window which allows you to choose a different search provider. I use the term "allows" in a very generous way as it is near to impossible to see at a glance how to use anything else than Bing. But it is there near the bottom left corner disguised as one of those hard to see links.

It annoyed me that they made it this hard to choose as it is obvious that this was a deliberate UI design choice of theirs, one that probably went through a lot of disccusion, refinement etc before being approved and implemented.

Total clicks: 9
Annoyances: Had to close and re-open the Add-on window for the new search provider to appear in the list and manually close all those windows I had opened. Choosing the provider requires you to open an additional browser window to select (plus an extra window opens to confirm settings for the provider after selecting it).

Edit: 
After digging around a little more my curiosity got the better of me and I clicked the little magnifying glass  icon that is present on the far right in the IE address bar. While this gives you convenient access to your browser history and favourites, I discovered that it also lists your search providers and gives you a quicker way to install a new one (step that completely bypasses all the windows mentioned in the previous method). Much much better and actually more clear what provider you're using than it is in Chrome.

The IE magnifying glass (kudos to whoever added the downward
pointing triangle as I would otherwise never have clicked it)

Lists all the provider you have installed and allows easy admin
Total clicks: 6 (2 if you already have the provider installed)
Annoyances: None apart from the aforementioned annoyance having to open a separate website to choose the provider.


Mozilla Firefox 10
"Et tu, Brute?" - Julius Caesar, on seeing his friend among the assassins.

Many know by now that Google made a large contribution (pay off?) to be and stay the default search provider for the Mozilla Firefox browser. The figures from their recent December 2011 deal are estimated to be around $1 billion dollars just to stay the default search provider for the next three years. That sure is one valuable instance of a textbox control.

However it seems rather straight forward to change the default providers, Firefox even comes installed with a choice of a few search engines as alternatives to Google. Simply clicking on the icon in the search providers box gives easy access to choose a different one

That is until you attempt to search directly from the address box!

After choosing Bing search I could not understand why all my address box searches still sent my search query to Google. There was nothing in the configuration section of the browser that hinted that the two boxes did not use the same setting and why one was using Bing as I requested but the address box refused to do as I asked.

It wasn't until I dove under the covers and opened up about:config (which is an advanced configuration system for the browser and not recommended for the layman user). There I discovered quite the jungle of configuration settings related to search in the browser. The one that interested me the most I highlighted in the screenshot below

Sneaky bastards!
Firefox still retains Google as the default search engine even though I've clearly chosen to use Bing as my search provider. Luckily it is relatively simple to change by double clicking on the browser.search.defaultenginename row and type in "Bing". Sorted, now address bar searching will use Bing as default. Bada <pun>! Still I feel this kind of behaviour is deliberately misleading and under-handed.

Total clicks: 2
Annoyances: Does not change provider for address bar search, only for advanced users to discover and change.

Edit: Apparently Microsoft made a deal with Mozilla to produce a special Firefox with Bing browser.

Opera 11
I admit that I don't use the Opera browser on my computers all that much (almost never). However Opera is the only browser I use on my Android phone and it is simply brilliant there. But on desktop systems there are just to many alternatives that are better and sadly they have copied so many things from Firefox (or vice versa) that it just seems redundant to use when I already don't want to use Firefox.

Opera however suffers from a similar problem as Firefox, namely the disconnect between the search provider chosen in the provider box and the one that is used in its main address box. In addition Opera adds on yet another layer of confusion by adding the third search variant on their Speed Dial startup page.

These three boxes can all be set to different search providers. Confused?
Setting the default search engine to use is also not very straight forward as it should be. Same as with Firefox changing the search provider in the search provider box at the top right has no effect on either the address bar (still points to Google) or the Speed Dial box. You need to click the Opera button in the top left corner, choosing Settings and Preferences. Choose the third tab Search in that window and you are presented with a list of all configured search providers for the browser.
Editing the Bing Search Provider in Opera
To set the default search engine you need to double click the entry you want to set (Bing in this case) and click the "Details" button. Then tick the "Use as default search engine". Here you can also control the rather confusing Speed Dial search, reasons why you would want that different from your default one escape me.

Total clicks: 7
Annoyances: Obscurity and the disconnect between address bar and default search provider. Also the Speed Dial page is just plain confusing. But at least you don't have to dive under the hood to change these settings.


Conclusion
The technology can be changed easy enough (if you know where to look). But changing the learned behaviour is going to be harder, but I will give Bing an exclusive try for the next month.

This difficulty with Google in Firefox especially knowing how much Google is paying them for the install defaults feels like a sad regression back to the late 1990s when Microsoft was throwing its weight around in a similar manner bullying itself in a position to dominate the same market. I thought that showed clearly that all that got them was a lot of bad blood and eventually the involvement of US and European authorities when it became obvious to even the non-techies as they were clearly abusing their dominant market position to stifle competitors.

Perhaps moves such as these are the early indicators that the great cosine wave of technology firm's path to success has reached its maxima and has slowly but surely started its inevitable fall from grace. But I guess that might be better saved to a later post.

24 February 2012

Why I Think C# and Java Trump C and C++

Well the title is a bit sensationalist. As a disclaimer I strongly believe that you need to pick the correct tool that best suits the job at hand and that you believe you will be the most productive in.

However when faced with the agonizing task of printing out Trace messages with variable formatting in a bit of C code that I had lying around recently, I realised just how focused C# is on getting things done rather than faffing about with boilerplate code.

As an example, here are two functions that fundamentally do the same thing, print a formatted string to the system Trace listeners using a single format string and then a variable number of arguments:

First the C# function:
void odprintf(string format, params object[] args)
{
    Trace.WriteLine(string.Format(format, args));
}

Compared to the C equivalent:
void __cdecl odprintf(const char *format, ...)
{
    char buf[4096], *p = buf;
    va_list args;
    int n;

    va_start(args, format);
                             // buf-3 is room for CR/LF/NUL
    n = _vsnprintf(p, sizeof buf - 3, format, args);
    va_end(args);

    p += (n < 0) ? sizeof buf - 3 : n;
    while ( p > buf  &&  isspace(p[-1]) )
            *--p = '\0';

    *p++ = '\r';
    *p++ = '\n';
    *p   = '\0';

    OutputDebugStringA(buf);
}
Really, all this magic is necessary to just print to Trace?

I reserve the right to seriously doubt that "lower" level languages have any place but in highly specialised or those extremely few cases where throughput and latency are more important than developer productivity and deadlines are lax and forgiving.

Here is someone that is more eloquent than I am on this issue.
There is no reason to use C++ for new projects. However, there are existing projects in C++ which might be worth working on. Weighting the positive aspects of such a project against the sad fact that C++ is involved is a matter of personal judgement.

If you end up working with C++, don't try to "fix" it (or "boost" it). You'll just add more layers of complexity. The most productive approach is to accept the problems and try to write simple code which people can easily follow.

If you are an expert in the intricacies of C++, please consider this knowledge a kind of martial art - something a real master never uses.

23 February 2012

Calculating Combinations of 1, 2, 3 Step Jumps

So again I was trolling along on Antonio Gulli's website (which has become a bit of a favorite to find fun problems to solve during a quiet evening). I came across this question:
A child can hop either 1, 2, or 3 steps in a stairway of N steps.
How many combinations do you have?
As the first comment mentions then this problem can be solved using recursion. But the question is, how would you translate this into program code?

... want a second to think about this before reading my attempts?

Initial Attempt
After thinking about this problem for a little while I decided that this might be cleanly solved using a recursive tree traversal algorithm. As we have a branching factor of 3 we should not have a branch height of more than N/3 (only taking 3 step jumps) in the best case and N in the worst case (if only taking 1 step jumps).

The initial naive solution I came up with was a simple DFS search using a stack (LIFO):

static Stack<long> nodes = new Stack<long>();
static long Combinations( int n )
{
    long leafs = 0;
    nodes.Push(n);
    while (nodes.Count > 0)
    {
        var x = nodes.Pop();

        // Leaf, just count
        if (x <= 0) leafs++;
        else
        {
            // Only push down options where the child 
            // can actually complete the stair jump
            if (x - 1 >= 0) nodes.Push(x - 1);
            if (x - 2 >= 0) nodes.Push(x - 2);
            if (x - 3 >= 0) nodes.Push(x - 3);
        }
    }
    return leafs;
}

Improved Attempt
It is soon obvious if you run the first code using non-trivial sizes of N that this naive DFS solution is simply too slow. The time that it takes to iterate through the entire tree and generating all the intermediary nodes is just too great and quite quickly the algorithm takes too long to return a solution within a reasonable time.

When you look closer at this ternary tree it might become obvious that since it is a complete tree it has a simple repeating pattern down each of its branches. Basically each branch is a sub-tree of the one preceding it (with node count n-1). Meaning that the (n-1) branch far to the left at height h has an equal amount of nodes in its immediate (n-1) child at h-1 as the second (n-2) branch at h has.

Using this we can simply pre-cache each height in the tree once we have calculated it completely and thus really only need to do one full depth run on a single branch after which we will have all the necessary values calculated for the remaining nodes.

           A
          /|\
         B C D
        /|\
       E F G
      /|\
     H I J
We only need to calculate the A,B,E,H values, after that no extra recursive traversal is necessary into any other subtrees as we can use the cached value for H for F, J for G, E for C, F for D and so forth.

So by adding a simple map that caches the node count for every remaining node number we can significantly speed up this calculation:

static Dictionary<int, BigInteger> map = new Dictionary<int, BigInteger>();
static BigInteger Combinations2(int n)
{
    if (n <= 0) return 1;

    BigInteger leafs = 0;
    if (map.TryGetValue(n, out leafs))
        return leafs;

    // We need to calculate it if not found
    if (n - 1 >= 0)
        leafs += Combinations2(n - 1);
    if (n - 2 >= 0)
        leafs += Combinations2(n - 2);
    if (n - 3 >= 0)
        leafs += Combinations2(n - 3);

    map[n] = leafs;
    return leafs;
}

We can probably do better than this though?

19 February 2012

Symphony of Science

This video still gives me goosebumps every time (the only acceptable use of auto-tune):



And if you haven't watched Jill B. Taylor's TED talk about her first hand experience of how it feels like having a massive brain stroke you should do so now.

18 February 2012

The absolute difference between two double numbers

How would we create a function

      abs( double a, double b )

that returns the absolute value of the difference between a and b?

Edit 21/02/2012:
I embarrassingly have to admit that before posting this entry in the beginning I had spent about an hour attempting some fancy prancy bit masking solution (as one might do in a integer or long abs function) gazing at bit arrangements and getting myself into an utter dead end and 100+ lines of code. I decided that this might simply be the best solution I could come up with:

public static double abs(double a, double b)
{
    double diff = b > a ? b - a : a - b;
    return diff < 0 ? -diff : diff;
}

Too stupid to fail?

17 February 2012

Learning about it makes it better somehow

Stuck on or waiting for the Tube in London?

Hearing the disembodied electronic woman's voice droning on about a "Signal failure"?

Yearning to know more?