How to test with Omniture for Google install referral tracking

Overview:

If you’ve ever had to work with the Omniture SDK you may eventually be tasked with enabling tracking for campaign referral tracking.

I won’t go into the details of setting up your receivers and doing the SDK setup. That’s pretty well covered in the documentation.

What’s not covered however, is how in the world you would test that.

Never fear! there are a couple of ways actually test this by faking an install event.

First, a word on how the referral is normally processed

Referral tracking happens at installation time, when the apk is installed, a broadcast intent is created by the system and fired sometime after your app has installed and its broadcast receivers registered.

That’s the gist of it. So if your app is properly set up with a broadcast receiver filtering for that intent you should be good to go.

What to do if you need to process the same intent with multiple receivers

You may run into a situation where you already have some other receiver consuming the broadcast. Because you can’t register two receivers for the same intent filter in your manifest, you’ll have to employ a technique called broadcast intent forwarding. You basically select a receiver to get the intent and in its meta-data you  specify the next receiver that will receive that intent. I will cover that in more detail later, but I hope you get the idea.

So now on to our two ways of faking the broadcast!

Method 1

Our friend adb

With a device or emulator connected, you can go into the adb shell and type the following command:

am broadcast -a com.android.vending.INSTALL_REFERRER --es "referrer" "utm_source=test_source&utm_medium=test_medium&utm_term=test_term&utm_
content=test_content&utm_campaign=test_name"

I’ll break the command down with you.

the first parameter -a is the action, in this case an install referrer action

–es is a string extra where the field name is “referrer” and the value consists of all of the referral data from the google campaign.

As a side note, google provides a handy url builder tool to make testing easier: https://support.google.com/analytics/answer/1033867?hl=en

That’s it! that’s all you need to do with this approach.

Method 2

Create your intent in code

You can create an intent and code and send out a broadcast. This makes it easier to test with unit tests or even manually by a QA person.

// Create an intent to be broadcast containing the referrer url
        Intent referrerIntent = new Intent();
        referrerIntent.setAction("com.android.vending.INSTALL_REFERRER");
        referrerIntent.putExtra("referrer", "utm_source=test_source&utm_medium=test_medium&utm_term=test_term&utm_
content=test_content&utm_campaign=test_name");
        this.getBaseContext().sendBroadcast(referrerIntent);

A word on testing

You’ll no doubt want to verify that the Omniture is firing off the proper calls. This can be a little tricky because the referral tracking is tied to Omniture’s lifecycle tracking which may not always fire when you expect it to. In order to get lifecycle tracking to fire when you want it to, here’s what you have to do.

  • Launch the app.
  • Exit the app and clear cache but DO NOT force stop.
  • Use method 1 or 2 to broadcast the intent.
  • Launch the app
  • You should see the request be made into your tracking suite. FYI I use the every awesome and simple Charles Proxy to do this kind of testing. Or when unit testing I just examine the response.

Conclusion:

There isn’t very clear documentation on Omniture’s side on how you should be testing this. Manual testing is not feasible because it would mean having to upload to the play store, download the app and hope you did everything right the first time. No es bueno.

The only way to feasibly test is to fake the events and understand a little bit about the process. Hopefully with this humble post, now you do!

Once again my gratitude goes to StackOverflow for helping me find the answer: http://stackoverflow.com/questions/5890914/how-to-test-android-referral-tracking

Happy coding

How to customize actionbar items

I just wanted to point out this really handy method that lets you specify your own layout for an action item.

<strong>android:actionlayout=”@layout/action_layout”</strong>

Super cool albeit a bit obscure!

This is all you need to do:

In your menu xml:

<item android:id="@+id/menu_item"
android:showAsAction="always|withText"
android:actionLayout="@layout/action_layout"
android:title="@string/menu_settings"/>

It’s that simple!

Your layout can be anything! in my case i just tried it out with a button.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context=".CacheTestActivity" >
<ImageButton
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:contentDescription="Custom button!"
android:scaleType="fitCenter"
android:src="@drawable/logo" />
</LinearLayout>

This really makes it simple to customize your actionbar action items!
Hope this helps!

TD Ameritrade released!

scan to download

scan to download

The last app I had the privilege of working on released back in early december!
We’ve updated our TD Ameritrade Mobile app for Android, making it more powerful and easier to use. Third-party research is now available, so you can investigate new trade ideas. We’ve added more news sources, giving you more ways to track the market. And we’ve improved our charting so you can carry out deeper analysis of the stocks you’re watching.TD Ameritrade Mobile gives you the freedom you need to stay on top of your account, wherever you are. It’s focused on the essentials and ideal for users of the tdameritrade.com web site. Use it for on-the-go access to equity and option trading, streaming quotes, real-time balances and positions, news and more.Features:- Real-time streaming quotes
- Charts
– Level II quotes
– Option chains
– Market data
– Trade stocks and options
– Order status
– News
– Account information
– Balances and positions
– Transaction history
– Much more!

https://play.google.com/store/apps/details?id=com.tdameritrade.mobile3&feature=search_result#?t=W251bGwsMSwxLDEsImNvbS50ZGFtZXJpdHJhZGUubW9iaWxlMyJd

Customizing the Action Bar

If you’ve ever worked with the Action Bar apis you’ll probably agree that it’s not the most fun to work with. I have seen a fair share of projects now using ActionBar Sherlock which is great and all (especially for the backwards compatibility) but that doesn’t really save you from needing to understand many of the intricacies of customizing the Action Bar UI. This  post from the Android Developers Blog goes a long way in helping make sense of things.

Android Developers Blog: Customizing the Action Bar.

How to Debug / View source of Android Support Library (compatibility package)

This is a cool trick that will allow you to view the source of your android-support library (Compatibility package).

Here’s what you need to do

Make sure you have the correct version of ADT.

You need to be on ADT 20 or later. Go here to get the latest ADT installed. 

Add the support library to your project

After adding your Support Library, (project properties > android tools > add compatibility package.

 

Create a .properties file for your jar and set the path to the support source. It is in your SDK

Now go to your project’s libs folder and create a file that is the same name as your android-support-v4.jar file and add .properties at the end.

Something like this:

Your path will be in your <SDK_PATH>/extras/android/support/v4/src

src=/android-sdk-macosx/extras/android/support/v4/src

Now close your project and open it back up.

You should now be able to open up the source code for your library. To confirm, go under Android Dependencies, find the android-support-v4.jar
Expand down to the classes inside the package, clicking one should open up the source in your editor.

Library source!

This neat feature works for any Jar library you have the source to. Enjoy! thanks to Simon for showing me this cool feature.

Summary:

You can set a source attachment for your android-support or any other JAR that doesn’t allow source attachments by adding a properties file. It’s easy and works for any jar you have the source to.

And it only takes a few easy steps:

  • Make sure you have the correct version of ADT.
  • Create a .properties file for your jar and set the src=/path/to/your/source inside it.
  • Close and re-open your project

How to properly use the viewHolder pattern on a listView adapter with multiple viewTypes.

The viewHolder pattern is great for making your listViews feel more responsive. Examples abound.
It seems to work great up until you start doing more complex things with it. Things can get a bit tricky once you have more than viewType that your adapter needs to provide.
Consider this code:



package com.oner.test;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class Adapter_testActivity extends Activity {
	private ListView mListView;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		mListView = (ListView) findViewById(android.R.id.list);
		mListView.setAdapter(new AdapterTest((Context) this));
	}

	private class AdapterTest extends BaseAdapter {
		String[] items = { "a", "b", "c", "d", "e", "a", "b", "c", "d", "e",
				"a", "b", "c", "d", "e", "a", "b", "c", "d", "e", "a", "b",
				"c", "d", "e", "a", "b", "c", "d", "e", "a", "b", "c", "d", "e" };
		private Context mContext;
		private LayoutInflater inflater;
		

		public AdapterTest(final Context context) {
			mContext = context;
			inflater = LayoutInflater.from(mContext);
		}

		@Override
		public int getCount() {
			return items.length;
		}

		@Override
		public Object getItem(int position) {
			return items[position];
		}

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

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View v = convertView;
			ViewHolder holder;

			int type = getItemViewType(position);
			Log.d("Adapter test","setting type:"+type);
			if (v == null) {

				holder = new ViewHolder();
				if (type == 0) {
					v = inflater.inflate(R.layout.item_type_one, null);
					holder.txtOne = (TextView) v.findViewById(R.id.txt_one);
				}else if(type ==1){
					v = inflater.inflate(R.layout.item_type_two, null);
					holder.txtTwo = (TextView) v.findViewById(R.id.txt_two);
				}
				else {
					v = inflater.inflate(R.layout.item_type_three, null);
					holder.txtThree = (TextView) v.findViewById(R.id.txt_three);
				}
				holder.type = type;
				v.setTag(holder);
			} else {
				holder = (ViewHolder) v.getTag();
				Log.d("Adapter test", " holder ::" + holder);
			}
                        String item = (String) getItem(position);
			if (item != null) {
				if (type == 0) {
					holder.txtOne.setText(item);

				} else if(type ==1 ) {
					holder.txtTwo.setText(item);
				}else{
					holder.txtThree.setText(item);
				}

			}
			return v;

		}

		

		@Override
		public int getItemViewType(int position) {
                        String item = (String) getItem(position);
                        if(item.equals("a"))return =0;
			else if(item.equals("b"))return=1;
			else   (item.equals("c"))return=2;
		}

		@Override
		public int getViewTypeCount() {
			return 3;
		}

	}

	static class ViewHolder {
		public int type;
		TextView txtOne;
		TextView txtTwo;
		TextView txtThree;
		@Override
		public String toString() {
			return "ViewHolder [type=" + type + ", txtOne=" + txtOne
					+ ", txtTwo=" + txtTwo + ", txtThree=" + txtThree + "]";
		}

	}
}

For the purposes of this example the list items being inflated all contain the same TextView with just a different id. I’m sure you get the idea.
Here’s what the layout for the items looks like in case you’re feeling lazy.





The listView will keep a cache of every view type you give it. The trick to avoid problems is to make sure that you properly implement getViewItemType().

                @Override
		public int getItemViewType(int position) {
                        String item = (String) getItem(position);
                        if(item.equals("a"))return =0;
			else if(item.equals("b"))return=1;
			else   (item.equals("c"))return=2;
		}

A common mistake (my first mistake) was to implement that logic inside of getView instead of getItemViewType. Prior to getting one of the view types out of it’s cache the listView will call getItemViewType for its cache lookup, so you need to make sure it knows how to do so. Also make sure that your getItemId return something other than just 0. This will also make sure things work smoothly.

In my example I determine the item type by looking at the data.
After that it’s a simply matter of looking at the type to re-populate the viewHolder.

I hope this helps. Thanks to Simon and Noah for helping me work through the problems.

eclipse – autocomplete has stopped working with android sdk

After my recent update to the latest ADT the autocomplete features of eclipse suddenly stopped working.
Luckily a quick search lead to the indispensable stackoverflow.

The way to fix it is to go to:
Window -> Preferences -> Java -> Editor -> Content Assist -> Advanced

And check the boxes labeled “Java Proposals” and hit Apply.

Thanks to dchimento for the answer.

Link to the question / answer here:

eclipse – autocomplete has stopped working with android sdk – Stack Overflow.

How to find unused resources in your Android project

UPDATE:

This was written prior to the release of Android Lint, so it’s no longer really necessary. Running lint will do the same thing.

Design changes!
They happen all the time. At least they do on our project, and let’s face it, designers don’t always stick to naming conventions meant to prevent asset duplication.
In any case, i’m not casting blame. Orphaned resources happen pretty easily. Luckily there’s a great tool to help you keep track of the stuff in your project that’s not being used.
With it you can find unused strings in your android project.
Find unused raw assets in your android project.
Find unused drawables in your android project.
Find unused layouts in your android project.

Check it out!
android-unused-resources – Android Unused Resource Detector – Google Project Hosting

android-unused-resources – Android Unused Resource Detector – Google Project Hosting.

It does have some imperfections. You’ll sometimes get false positives. For example:
If you’re getting a dynamic reference to a resource, this tool won’t catch that (not that I would expect it to). But that’s just a minor thing.
Anyway thanks @google!