Category Archives: Programming

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

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 images = new Vector();

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:








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

[poll id=”2″]

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 Stereo Right and Left PCM Raw Audio

I have been playing with raw audio generation (PCM) in Android using AudioTrack.  It’s pretty easy to do, but I had trouble finding information about stereo byte formatting when streaming, in other words how to mix between the left and right stream.  After playing with the code for a while, i figured it out and boy is it simple, the even bytes are the left channel and the odd is the right channel.

In other words:

byte[] = stereo_sound = {right,left,right,left,right,left};

I hope this saves you some time!
-James

Huge Android Canceled Sales Numbers

I have noticed lately that I have been getting more and more sales that canceled after a few minutes.  I believe that users are starting to learn that they can try out a paid application for 24 hours (soon to be changed to 15 minutes) and get a refund if they uninstall it.  There are a few other reasons this might happen:

  • A user doesn’t like the application, or it doesn’t provide value for the whole return window
  • A user wants to review the application, but not buy it.
  • A user can strip the DRM and get a refund (i.e. piracy)
  • A website could download the application to learn about it, (i.e. the unofficial android application websites)
  • People might hate Google and are trying to raise the charge backs.

Regarding the last point, When you buy an app on the market, Google charges the card and waits for authorization.  You can verify this by looking at the declines, I get about one decline a week.  If a user uninstalls in 24 hours, then Google will have to do a charge back, which credit card companies hate to do.   Maybe its a way for Google’s competitors to cost Google some extra cash.  (If you can’t tell this last point is tongue in cheek).

-James

Importance of inital ranking in Android Market

I have read online that its best to publish your app as soon as possible and do updates as much as possible.  Think the mantra “deploy early and often”.  Initial I subscribed to this idea, because its super easy to push out updates via Android Market, but I have found its not a good idea, and here is why.

The majority of my sales happen on days I do updates, the reason is Google tends to promote them.  I have noticed that apps that have a good ranking (4+ stars) tend to get promoted longer and get much more play.   Which makes you a lot more money.

The market doesn’t facilitate feedback to developers very well, so to file a bug report, users leave feed back and a ranking.  If you have a bad bug, you might get a bunch of one start ratings, and even if you fix the bug in minutes, the users aren’t going to download your app again, and aren’t going to change their ranking.  These poor rankings really hurt long term, especially for new applications that don’t have a lot of marketing behind them.

Lesson learned, TEST TEST TEST, your reputation on Android market counts!

-James