So you have an app in the Google Play Store that you want to make ready to put on the Amazon App store for Kindle Fire devices. That's a great idea! I mean, who wouldn't want to reach more users? Wait, who wants to manage two code repositories for the same application? Kindle Fires devices are powered by Android so there has got to be away to do this more efficiently.

If you are thinking this, the good news is that managing one code repository for both Android and Kindle Fire operating systems is more than possible. The bad news is thatAmazon's documentationcontains little information to help you achieve this. There are many key differences between Amazon's forked version of Android and Google's stock version. These differences are discussed in Amazon's Documentation, but no clear direction is given on how to make one application work for both versions of the OS.

That being said, recently a client of mine became interested in making their existing Android application Kindle Fire friendly. However, like you, we did not want to be forced to manage two code repositories. So I navigated to Amazon's Developer website for Kindle Fires and began my research. Shortly after installing the Amazon Mobile plugin and Add-Ons for Eclipse, I was faced with more challenges as a result of the differences between the Android versions than I had originally expected.

Maps
If your application is leveraging Google Maps, you probably got a INSTALL_FAILED_MISSING_SHARED_LIBRARY error when you tried to install your application on a Kindle Fire device. This is because there is no Google Map support on Kindle Fire devices. If you want to leverage maps in your application you will have to do so using Amazon's Map Library, which has a comparable implementation to that of Google Maps v1. If you have chosen to only handle one code repository for both Android and Kindle Fire you will need to include the code snippet I have attached below in your manifest file.

<> android: name="com.google.android.map" android:required="false"/>

This code will allow your application to run on Kindle Fire devices (and any other Android device that is missing Google Play Services). However, keep in mind that this will only allow your application to run and is not the final fix. If you run this, in the place of your map, you will see a note notifying the user to install Google Play Services by pressing the button. If the user tries to do this, your application will crash. To prevent this from happening on both Kindle Fire devices and older Android devices, I would suggest using the following code to run a check to see if the Google Maps Library is installed.

private boolean hasGoogleMaps(Context context){
		boolean installed = false;
		String[] libraries = context.getPackageManager().getSystemSharedLibraryNames();
		if(libraries != null){
		 for(String library : libraries){
		 if(library.equalsIgnoreCase("com.google.android.maps")){
		 	 installed = true;
		 	 break;
		 }
		 }
		}
		return installed;
	}

The Amazon Maps API is so closely related to Google Maps v1 that what Amazon lacks in documentation you should be able to find in Google's documentation. That being said, building your map with Amazon's Maps API is not difficult until you go to test it on a device or emulator. Oh, I forgot to mention that unlike Google Maps, you can actually run your maps on a Kindle Fire Emulator without doing any hacking of the emulator. Anyways, it can be quite a job to actually see more than map tiles on your application. Amazon does not use an API key like Google. They need only the MD5 fingerprint and package name to identify your application. This is the great news, but the bad news is that you have to register your application to Amazon via their application portal. After you have registered your application here, you will need to select it again, choose maps, and enter your debug or production information to see more than tiles on your application. If you have gone through this process and are still seeing only tiles, be aware that it can take a little more than an hour for it to register and work. If you are still having difficulties, double check that your fingerprint and package names are correct.

Landscape Orientation

I ran into some weird orientation behaviors when using my client's application on the Kindle Fire HD and now the HDX devices. If you are experiencing abnormal orientation or accelerometer behaviors I may be able to help you. This is most likely due to Amazon recognizing default landscape mode as being at ROTATION_90 in their standard Kindle Fire devices like the rest of the Android world, but then switching it to ROTATION_270 on their HD and HDX devices. In their HD and HDX devices they included a front facing camera that instead of being at the top of the device, is on the left side of it. When they did this, they decided to change the default Landscape mode to where the Camera would be on top and not on the bottom when in landscape mode. This puts default landscape at ROTATION_270 and reverse landscape at ROTATION_90.

So what's the big deal? Well, if you are experiencing abnormal behaviors with the accelerometer or orientation when in one of the Landscape modes, this is more than likely the culprit. For example, if you are leveraging the device's accelerometer on an HD or HDX device in one of the landscape modes, you will receive opposite metrics then those that you would receive on other Android or non HD Kindle Fire devices. If you are setting the orientation for your application programmatically, it will appear opposite of what is expected when in one of the landscape modes.

I ran into some strange behaviors when trying to limit orientation changes during the loading of data and then setting the view to the orientation that the device is in after the load. If the device were in either of the landscape orientations, the application would appear to flip upside down before returning to the appropriate orientation. This was because I was setting it to the opposite orientation then what was expected on the Kindle Fire HD and HDX devices. Amazon recommends that you avoid this issue by using the below code.

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
<>
....
android:screenOrientation="sensorLandscape"
android:configChanges="orientation|screenSize">
....
>

Display Metrics

Positioning or sizing elements based on the display metrics is usually done as a last resort, but its common enough that I feel it is worth mentioning. Amazon got rid of Android's tool and menu bars and implemented their own. This allowed Amazon to implement 3 different full screen modes on their devices, which you can learn, more about here. Essentially this allows for different handling of the toolbars, some of which only the user has control over.

Keeping that in mind, if you have ever queried your device's display metrics you might have wondered why the numbers returned for the height and width did not match the resolution advertised for that device. This is because the display metrics is returning the height and width that is un-obscured by the tool and menu bar. Due to Amazon's implementation of their own tool and menu bars, the Kindle Fire devices only do this when in "standard" screen mode. In full screen and super full screen modes, the toolbars get drawn on top of your application views. If you query the display metrics in these modes, it will return the advertised screen resolution not just the region that is un-obscured by the tool and menu bars. That may not seem like a big deal (and ultimately the fix isn't difficult) but if you do have an element that is positioned by the display metrics, you might waste time wondering why that element disappears in one orientation and then reappears in the other or in some cases is just gone all together.

Checking For an Amazon Device

Unless you want to manage two code repositories, many of the fixes you implement will be based on determining when an Amazon device is using your application. Below, I have included a little code snippet that will allow you to test for Amazon devices and the specific generations. Once you get this you can then perform an action accordingly. For your reference I have also included a table highlighting the most notable differences between the Kindle Fire devices/generations.

Fire Device Resolution Android API WiFi Camera Build Model
8.9" HDX 2650x1600
xhdpi
17 802.11
a/b/g/n
Yes (front & back) KFAPWA
KFAPWI
7" HDX 1920x1200
hdpi
17 802.11
a/b/g/n
Yes (front facing) KFTHWA
KFTHWI
7"HD (3rd Gen) 1280x800
hdpi
17 802.11
a/b/g/n
Yes (front facing) KFSOWI
8.9" HD 1920x1200
hdpi
15 802.11
a/b/g/n
Yes (front facing) KFJWA
8.9" HD 1920x1200
hdpi
15 802.11
a/b/g/n
Yes (front facing) KFJWI
7" HD (2nd Gen) 1280x800
hdpi
15 802.11
a/b/g/n
Yes (front facing) KFTT
2nd
Generation
1024x600
mdpi
15 802.11
b/g/n
No KFOT
1st
Generation
1024x600
mdpi
10 802.11
b/g/n
No Kindle Fire
if (Build.MANUFACTURER.equalsIgnoreCase("Amazon")) {
	//Do something if it is an Amazon device
 
	if (Build.MODEL.equalsIgnoreCase("KFAPWA")
			|| Build.MODEL.equalsIgnoreCase("KFAPWI")
			|| Build.MODEL.equalsIgnoreCase("KFTHWA")
			|| Build.MODEL.equalsIgnoreCase("KFTHWI")
			|| Build.MODEL.equalsIgnoreCase("KFSOWI")
			|| Build.MODEL.equalsIgnoreCase("KFJWA")
			|| Build.MODEL.equalsIgnoreCase("KFJWI")) {
		// Do something if it is an HD or HDX device
 
	} else {
		// Do something if it not an HD or HDX device
	}
}else{
	//Do something if it not an Amazon device
 
}

Is There More?

As you can probably guess, there are many more changes to the OS that you need to keep in mind when making your application Kindle Fire friendly. So if I did not answer your specific question, I would point you in the direction of Amazon's Forum. Here you can browse through other people's issues and questions or even ask your own. Amazon seems to be very active on here and they answer many of the questions themselves. If they fail to answer your question or you have any questions about my experience, please feel free to contact me directly.