Problems Using Google Analytic in Android in the application class

For a while now you have been able to use Google Analytics to track user Analytics in Android applications.  Its pretty simple to use, but I found one bug that other people may run in to.  The application I’m working on has its static application data stored in a custom instance that implements the Android application class.  When I first started working with Analytics I placed the tracker in the application class, and had the tracker start during the constructor of the application.  This didn’t work at all, as the tracker.startNewSession would throw null pointer exceptions try to create a database.

Lucky for me, all my activities extend a custom activity, so I could add the tracker there.  At first I wasn’t too happy to have an instance of the tracker per activity, but it turns out that getInstance() function is actually getting an instance of a static class, so in reality there is only one instance of the tracker in memory.

Hope this helps someone getting started with Google Analytics in Android.

-James

Reader (or Spammer) used MobFox network to increase revenue, maybe

Mobfox Logo

Update 5/13/11:  Recived the following email from Martin at MobFox:

Hi James,

I just became aware of the article about MobFox on this website.

Could you forward me the spam e-mail which you received? We currently do not have any specific rules for our Affiliates but we’ll introduce some very soon to prevent such a behaviour of our partners / affiliates.

To clarify, Affiliates that promote the MobFox network to sign up other developers usually receive a % of the referred developer’s publisher earnings.

Thank You,
Martin / MobFox.com

 

Update 5/10/11:  Looks like I got spammed, lol.  I disabled the links as I dont’ want to give them any google bounce.

Alessandro De Carli wrote me and let me know that he ditched AdMob for MobFox and saw a major increase in revenue.  He has a blog at http://www.papers.ch Just thought I would pass it along.

-James

Why I’m not publishing on The Amazon AppStore

As I’m sure you have heard Amazon has released there “AppStore” on to the world for Android. Many developers are up in arms over the strange terms that Amazon has required of publishers. There was a pretty good article today why publishers should stay away from the current Amazon AppStore.

I just wanted to add one more comment about the topic. Google makes money from Android in two ways. One is selling the Android + Google Services (like maps/market) to manufactures. The other way is by taking a cut of market sales. Their cut is 30% off the top. But for the 30% they distribute, market, track and most importantly they use some of that money to improve both Android and the services built on top of Android. Frankly its a good value for me. Even if Amazon perfectly matched Google’s terms, I wouldn’t use them.  They just don’t give back to the Android development community like Google does.

-James

How to Add bitmaps from Camera Activity Dynamically to Gallery

So I spent a few hours this morrning looking for a demo on how to add bitmaps that I got from the Camera Activity Dynamicly to a Gallery View.  Here is the code I came up with.  Let me know if there is a better way.

import java.util.ArrayList;
import java.util.Stack;
import java.util.Vector;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.Gallery;
import android.widget.ImageView;

public class Pictures extends Activity implements OnClickListener {
    private static final int PICTURE_RESULT = 1;
    Context ctx = null;
    Button next = null;
    Button addPhoto = null;
    Gallery gal = null;
    ImageAdapter images =null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pictures);
        ctx = this.getBaseContext();

        next = (Button) this.findViewById(R.id.widget30);
        next.setOnClickListener(this);

        addPhoto = (Button) this.findViewById(R.id.widget35);
        addPhoto.setOnClickListener(this);

        images = new ImageAdapter(this);
        gal = (Gallery) this.findViewById(R.id.widget36);
        gal.setAdapter(images);

    }

    @Override
    public void onClick(View v) {
        if (v == next) {
            return;
        } else if (v == addPhoto) {
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            this.startActivityForResult(intent, PICTURE_RESULT);
        }

    }

    @Override
    public void onActivityResult(int reqCode, int resultCode, Intent data) {
        super.onActivityResult(reqCode, resultCode, data);
        if (reqCode == PICTURE_RESULT) {
             if (resultCode == Activity.RESULT_OK) {
                     Bundle b = data.getExtras();
                     Bitmap pic = (Bitmap) b.get("data");

                     if (pic != null) {
                         images.AddImage(pic);
                         gal.setAdapter(images);  //forces the gallery to add the new images.
                     }
                 }               
        }
    }

    public class ImageAdapter extends BaseAdapter {
        private Context mContext;
        private Vector<Bitmap> images = new Vector<Bitmap>();

        public ImageAdapter(Context c) {
            mContext = c;
        }
       
        public void AddImage(Bitmap b)
        {
            images.add(b);
        }

        @Override
        public int getCount() {
            return images.size();
        }

        @Override
        public Object getItem(int arg0) {
            return images.get(arg0);
        }

        @Override
        public long getItemId(int arg0) {
            return arg0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView img;
            if(convertView ==null)
                {
                img = new ImageView(mContext);
                }
            else
            {
                img = (ImageView)convertView;
            }
           
       
            img.setImageBitmap(images.get(position));
            return img;
        }

    }
}

And the xml layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/widget34"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
>
<Button
android:id="@+id/widget35"
android:layout_width="209px"
android:layout_height="wrap_content"
android:text="Add Photo"
>
</Button>
<Gallery
android:id="@+id/widget36"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
</Gallery>
<Button
android:id="@+id/widget30"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Next"
>
</Button>
</LinearLayout>

Android Openness and Fragmentation

There has been a lot of talk about Openness and Fragmentation in Android over the past few months.  Frankly most of the articles have been misleading at best and flat out wrong at times.

There are two major issues surrounding Android right now:

Android 3.0 images was released in Feburary.  Motorola rolled out the Xoom which uses Android 3.0.  Publicly the source code to Android 3.0 isn’t available.  Frankly I don’t know how Google can do this, as many things such as the Linux kernel is GPL licenced and must be released.  Linksys got sued by the FSF for the same issue, you can read about it here.  Frankly this bothers me a lot, Google is flat out disregarding copyright law.  In other words, Google = Evil.

The Second issue is the lack of hardware that is both unlocked and rooted.  Of course  you could root your own phone, but I would much rather just buy an unlocked / rooted phone where everything is on the up and up.  For a long time now Google has sold developer phones that were unlocked and rooted.  Now they are out of stock and have been for quite some time.  Whats the point of having open source if you have closed hardware?  Don’t give me the bull about how the carries want it locked, they sell tons of myfi’s and usb 3g cards that lets anything on to their networks.  It works the same in the phone, there is a little wireless radio chip that handles the network communication.

The lack of open hardware is what is causing the issue of fragmentation.  Users have phones with old Android loads and want to upgrade them to latest and greatest.  Users see their phones as mini-computers where they should be able to upgrade.  In fact due to carrier upgrades, users know they can upgrade them.  Manufactures see phones as consumer electronic devices that get thrown away after 12 months or so, so they stop updating them. In other words Manufactures and Carriers = Evil.

Journalists see all the operating systems in use as fragmentation, but to me its not.  An application that runs on Android 1.0 will run just fine on 3.0.  Its similar to Windows, where you might have windows xp and windows 7 on the same networking, running the same programs, but operating systems are diffrent.  To me fragmentation is more like the Unix enviroments of the 80’s and 90’s where you had things like AIX and Solaris which were pretty close from an operating system view but couldn’t run application written for each other, unless explicitly designed to.  This problem doesn’t exist in Android as of today.

So we get to openness and freedom.  I started thinking about current consumer products and how open/free they are.

Generic PC and Linux: Free/Open software and hardware (most of the time, on the hardware) I would say this as open as it gets

Generic PC and Windows: Open hardware / Closed os, but runs any software.  I would consider this open/free, but not as much as if it was running Linux. I can upgrade and do what I want.

Mac PC and Mac OS: Semi open hardware / Semi Open Hardware.  I don’t consider this free, Apple is stingy with drivers and information at times. You can run Linux pretty well, and Windows, but you can tell its second fiddle.  Start getting a little nervous about my rights…

Android Device: Closed hardware, Open source OS (except for ‘skins’ like sense, and when you can’t get it like 3.0)  Its just not free to me, whats the point of a open source operating system if you can’t run it on your device?  Annoying long term.

iOS Device: Closed Hardware, Closed Source.  Not free.  Won’t use.  Don’t even want to write apps for it.

I have been hearing many people talk about how Android is the Windows of the Phone world.  Nothing could be farther from the truth.  Windows is closed source, Android is mostly open source.  Windows runs on open hardware, Android runs on locked down devices.  The ramifications are totally different.  Locked devices like Android make it hard for things like Linux to happen, how would you get started? I know you can root your phone, but you shouldn’t have to, its YOUR phone.  There may come a day where a phone or device can’t be rooted.

Why does this matter?  Closed hardware makes updates much harder.  Its pissing off users of older devices.  It makes it much harder for developers.  Its unethical to call something open source and then not release it to everyone, because you are worried that the market will flood with cheep tablets.  I hope that the Android team does something about it.  I sincerely believe that Android could be the dominate Operating system stack for all computers in the near future.  I hope they don’t drive it in to the ground and turn it in to cable tv.

If someone from the Microsoft Windows Phone team reads this, if you kept your os closed and hardware open you could win (no pun) the game.  Android developers are getting fed up.

So what do you think?

Sorry, there are no polls available at the moment.

-James

Android 1.x users now make up only about 10% of the market.

I was looking at the platform versions that were using Android Market for the first two weeks of February.  Android 1.x users now make up 10.1% of the users using Android market.  I haven’t been able to figure out how many users use the market in a given month, so I’m unsure how many users 10% is.

For many applications the API changes in 1.x to 2.x isn’t that important.  In fact of all my applications, Only Private Browser could make good use of the 2.x API.  (Photo of the Day uses live wallpapers, so it has to use 2.x, so it doesn’t count.)  I would recommend supporting the lowest API version that fits your applications design, because why cut your market by 10% if you don’t have too.  Also, there might be less competition in the 1.x market, because all the new applications will probably target 2.x just because its newer.

There are a lot of great API improvements in 2.x.  Opengl support is better, the webkit object actually exports the plugin interface, and the you can catch ssl certificate errors, and redirections.  There are a ton of other great changes that are documented in the API differences pages.

So what do you guys think, Should I drop support for 1.x in Private Browser?  Are you going to drop support for 1.x in the near future?  Take the poll and leave a comment and let me know what you think.  Frankly I’m on the fence right now.

-James

Native or HTML5?

View Results

Loading ... Loading ...

Review of Adwhirl

adwhirlI recently tried a product called AdWhirl from AdMob.  AdWhirl is an open source ad aggregation tool.  Basically you put an AdWhirl ad in your application, it will query the various ad agencies and try to find the best ad to place on your page.  In other words, you could run ads AdMob, Quartro, iAd, your own ad network, etc.  The idea is excellent.

The setup is not for the faint of heart.  AdMob will let you use their server, but you should really setup your own AdWhirl server so you are in control.  You will also need to register directly with each and every ad network you will be using.  Registration can take weeks, so you should do it as soon as possible.  On the application side, you will need to include the library (jar) for each platform, which can make for some large applications.  After that there is some minor configuration, but nothing too bad.

I really like the idea, but this implementation isn’t for me.  When there is an update to the ad network libraries you have to update your application.  I would have liked it better if the jars were loaded on the server, so the clients didn’t have to talk directly with each and every client.  I also don’t like having to run the service on my own server, for busy applications, it might eat up a signficant part of the savings.

The absolute worst part is getting paid by multipal ad networks!  In the industry  you have Net-5, Net-30, Net-60, Net-90.  Its really had to stay on top of.  A check can eaisly go missing and you would never know it.

When would I use AdWhirl?  If I had an application that generated a lot of views (inventory). I might want to sell my own inventory, AdWhirl would allow me to sell a portion of my inventory, and still use a network for the remaining.  Excessive inventory is a huge problem publishers, and AdWhirl is a good solution for it.

-James

Android Development