AppDynamics Application Intelligence Platform
3.9.x Documentation
Watch a quick overview of the main steps of the process.
Direct link: https://appdynamo.wistia.com/medias/gq6toglcej.
Click the Android SDK link in step
. This downloads a file named AndroidAgent.zip. This file unzips to a folder named Android Agent, which contains the files and folders discussed in Set Up Your Environment.You must download the SDK separately for each application that you instrument.
Record the application key generated for this application, displayed in step .
You will need this key when you modify the source code.
Follow these instructions based on your build environment:
If you use Eclipse ADT to produce your builds, first build the application with ant and then follow the instructions for the Android Ant installation.
If your build system is ant-based you must:
ADEumAgent.jar
to the libs
subdirectory in your project.ADEumInjector.jar
to your project's root
directory.Do one of the following:
-- If there is no custom_rules.xml
file in your project:
custom_rules.xml
.<project> <target name="-post-compile"> <taskdef name="injector" classname="com.appdynamics.android.ant.EUMAgentInjectorTask" classpath="ADEUMInjector.jar"/> <injector classfilespath="${out.classes.absolute.dir}" outputlocation="${out.absolute.dir}/instrumented-jars/" instrumentationjarlocation="${jar.libs.absolute.dir}/ADEUMAgent.jar" jarfilesrefid="project.all.jars.path" androidjarlocation="${project.target.android.jar}"/> </target> </project>
-- If there is an existing custom_rules.xml
file in your project but it does not contain a "-post-compile" target:
<target name="-post-compile"> <taskdef name="injector" classname="com.appdynamics.android.ant.EUMAgentInjectorTask" classpath="ADEUMInjector.jar"/> <injector classfilespath="${out.classes.absolute.dir}" outputlocation="${out.absolute.dir}/instrumented-jars/" instrumentationjarlocation="${jar.libs.absolute.dir}/ADEUMAgent.jar" jarfilesrefid="project.all.jars.path" androidjarlocation="${project.target.android.jar}"/> </target>
-- If there is an existing custom_rules.xml
file in your project and it already contains a "-post-compile" target:
<taskdef name="injector" classname="com.appdynamics.android.ant.EUMAgentInjectorTask" classpath="ADEUMInjector.jar"/> <injector classfilespath="${out.classes.absolute.dir}" outputlocation="${out.absolute.dir}/instrumented-jars/" instrumentationjarlocation="${jar.libs.absolute.dir}/ADEUMAgent.jar" jarfilesrefid="project.all.jars.path" androidjarlocation="${project.target.android.jar}"/>
Do not include android.jar
in the list of jar files provided as "jarfilesrefid
" to your injector task.
For example if your build.xml
looks something like this:
<taskdef name="injector" classname="com.appdynamics.android.ant.EUMAgentInjectorTask" classpath="ADEUMInjector.jar"/> <injector classfilespath="${out.classes.absolute.dir}" outputlocation="${out.absolute.dir}/instrumented-jars/" instrumentationjarlocation="${jar.libs.absolute.dir}/ADEUMAgent.jar" jarfilesrefid="project.all.jars.path" androidjarlocation="${project.target.android.jar}"/>
Make sure that android.jar
is not included in the list of files specified by the refid "project.all.jars.path
". Otherwise the injector will fail to instrument your build properly.
If your build system is maven you must:
These instructions assume you are building your application using the android-maven-plugin with Maven 3.1.1+.
adeum-maven-repo
directory that you downloaded to your project directory. This is the directory that contains pom.xml
.<repositories> <repository> <id>adeum</id> <name>AppDynamics Repo</name> <url>file://${project.basedir}/adeum-maven-repo</url> </repository> </repositories>
Add the following code to the <dependencies> section:
<dependency> <groupId>com.appdynamics</groupId> <artifactId>appdynamics-runtime</artifactId> <version>1.0</version> </dependency>
Add the following code to the <plugins> section:
<plugin> <groupId>com.appdynamics</groupId> <artifactId>appdynamics-maven-plugin</artifactId> <version>1.0</version> <executions> <execution> <phase>compile</phase> <goals> <goal>adinject</goal> </goals> </execution> </executions> </plugin>
If your build system is gradle-based you must:
Copy the adeum-maven-repo
directory that you downloaded to your project directory. This is the directory that contains your build.gradle
file.
build.gradle
Make the following changes to build.gradle
:
Edit or create the "buildscript" section and:
Force dependency on the version of the Android plugin used to build your APK files, for example 'com.android.tools.build:gradle:0.8.3'
Add "adeum-maven-repo" as a repository
Add the version of the Android plugin you are using as a classpath dependency
Add the appropriate version of the AppDynamics plugin as a classpath dependency. See the table to determine the correct version.
AppDynamics version | Gradle version | Android Tools plugin version | AppDynamics plugin version |
---|---|---|---|
3.8.0 and later | 1.8 | 0.6.3 | com.appdynamics:appdynamics-gradle-plugin:1.0 |
N/A | 1.9 | 0.7.0, 0.7.1,0.7.3,0.8.3, 0.9.2 | These Android Tools versions do not support this version of Gradle |
3.8.3 and later | 1.10 | 0.7.3,0.8.3, 0.9.2 | com.appdynamics:appdynamics-gradle-plugin:2.0 |
3.9 and later | 1.10 | 0.7.3,0.8.3, 0.9.2, 0.10x, 0.11x, 0.12x | com.appdynamics:appdynamics-gradle-plugin:2.0 |
3.9 and later | 1.12 | 0.10x, 0.11x, 0.12x | com.appdynamics:appdynamics-gradle-plugin:2.0 |
3.9 and later | 2.1 | 0.13.0 | com.appdynamics:appdynamics-gradle-plugin:2.0 |
Add "adeum-maven-repo" as a repository.
After you have added all the AppDynamics Android Agent requirements, your build.gradle
resembles this:
buildscript { configurations.classpath.resolutionStrategy.force('com.android.tools.build:gradle:0.8.3') repositories { maven {url uri("adeum-maven-repo") } //mavenCentral() or whatever repo definitions you are using } dependencies { classpath 'com.android.tools.build:gradle:0.8.3', 'com.appdynamics:appdynamics-gradle-plugin:2.0' } } apply plugin: 'android' apply plugin: 'adeum' repositories { maven { url uri('adeum-maven-repo') } } dependencies { compile 'com.appdynamics:appdynamics-runtime:1.0' }
If you use ProGuard to verify or optimize your code, add the following lines to your Proguard configuration file, by default proguard.cfg.
Depending on your environment, this file may renamed by your build.
-keep class com.appdynamics.eumagent.runtime.DontObfuscate -keep @com.appdynamics.eumagent.runtime.DontObfuscate class * { *; }
If you use Proguard to obfuscate your code, note the name and location of the mapping file that ProGuard produces, because AppDynamics needs this file to create human-readable stack traces for crash snapshots. For details about why you should do this, see Get Human-Readable Crash Snapshots. For more information on the process, see Uploading the ProGuard Mapping File.
Every time the application is changed and recompiled the ProGuard mapping file changes, so you need to upload the new mapping file to AppDynamics every time you modify your app.
Modify the source code to initialize the mobile agent as soon as the app launches. A good place to do this is the onCreate() method of your application's primary Activity. This registers your application, and only needs to be done once in your code.
In the source file that defines your application's primary Activity, add the following import:
import com.appdynamics.eumagent.runtime.Instrumentation;
In your primary Activity's onCreate() method, add the following line:
Instrumentation.start("$CURRENT_APP_KEY", getApplicationContext());
Save the file.
Your code should look something like this.
import com.appdynamics.eumagent.runtime.Instrumentation; ... @Override public void onCreate(Bundle savedInstanceState) { ... Instrumentation.start($CURRENT_APP_KEY", getApplicationContext()); }
Open your application's AndroidManifest.xml
file and verify that it has these permissions:
<uses-permission android:name="android.permission.INTERNET"></uses-permission> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
If both of these permissions are not present, add them.
Rebuild your application.
After your build has run, make sure that the post-compile target has completed by checking the build output. Some of the lines in the post-compile section output should be prefixed with [injector]
, for example:
-post-compile: [injector] Path to class files: /Users/username/android/networklogger/bin/classes [injector] Path to instrumentation jar: /Users/username/android/networklogger/libs/ADEUMAgent.jar [injector] Path to Android jar: /Users/username/android-2/platforms/android-18/android.jar [injector] Copying /Users/username/android/networklogger/libs/ADEUMAgent.jar to /Users/username/android/networklogger/bin/instrumented-jars/d5672e56-062a-479b-ba88-88b367319497.jar
If the target does not run successfully, your app will not be properly instrumented.
After your build has run, make sure your application has been instrumented. Check the console output of your build and make sure there is a line that contains "Injecting:
"
After your build has run, make sure your application has been instrumented. Check the console output of your build and make sure there is a line that contains "Inject:
"
If you did not obfuscate your application source code, you can skip this step.
This step is optional but highly recommended if you obfuscated your code and plan to monitor crashes. AppDynamics needs the mapping file for the application to produce human-readable stack traces for crash snapshots. By default, the mapping file is named mapping.txt
, unless you have renamed it in your build.
If you update your application, you need to upload the new version of the mapping file.
To associate the mapping file with the correct version of the application, you need to provide:
AndroidManifest.xml
fileYou can either upload the mapping file using the instrumentation screen in the Controller UI or use a special REST API. Perform the upload separately for each ProGuard mapping file that you are providing.
If the application is already registered with the controller, you can select its package which is listed in the dropdown list.
If the application is not yet registered, enter the package name in the New Package field.
versionCode
property in the AndroidManifest.xml
of the application for which this mapping file was generated.mapping.txt
.The api uses HTTP basic authentication to send a PUT request to AppDynamics. The username is your AppDynamics account name and the password is your EUM license key.
1. Set up your HTTP basic authentication credentials
Send the ProGuard mapping file as as a text file in the body of the PUT request to the following URI:
https://api.eum-appdynamics.com/eumaggregator/crash-reports/proguardMappingFile/<androidPackageName>/<versionString>
These parameters are required:
androidPackagename
: the name of the Android package for which this mapping file was generatedversionString
: the string representation of the "versionCod"e property in the AndroidManifest.xml
of the application for which this mapping file was generatedThe request body contains the mapping file. The content type of the body is either text/plan or gzip if the body was ended with gzip.
This is a sample request and response using the REST API.
The following example uses curl to send a mapping file. The account name is "Example account" and the license key/password is "Example-License-Key-4e8ec2ae6cfe". The plus signs replace spaces in the account name when the account name is URL-encoded. The package name for the Android application is "com.example.networklogger". The mapping file corresponds to the version with versionCode 1.
curl -v --upload-file mapping.txt --user Example+account:Example-License-Key-4e8ec2ae6cfe https://api.eum-appdynamics.com/eumaggregator/crash-reports/proguardMappingFile/com.example.networklogger/1
The successful output of the example request looks like this:
* About to connect() to api.eum-appdynamics.com port 443 (#0) * Trying ::1... * connected * Connected to api.eum-appdynamics.com (::1) port 443 (#0) * Server auth using Basic with user 'Example+account' > PUT /eumaggregator/crash-reports/proguardMappingFile/com.example.networklogger/1 HTTP/1.1 > Authorization: Basic SW50ZXJuYWwrdGVzdCthY2NvdW50OlRlc3RBY2N0LTFlMzktNDVkMy05MzAzLTRlOGVjMmFlNmNmZQ== > User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5 > Host: app.eum-appdynamics.com > Accept: */* > Content-Length: 4 > Expect: 100-continue > < HTTP/1.1 100 Continue * We are completely uploaded and fine < HTTP/1.1 200 OK < Content-Length: 0 < Server: Jetty(8.1.4.v20120524) < * Connection #0 to host app.eum-appdynamics.com left intact * Closing connection #0
The Instrumentation
class has additional methods to allow you to extend the kinds of application data you can collect and aggregate using Mobile EUEM. There are three basic kinds of extensions that you can create:
In addition, if you are using an environment with an on-premise version of the EUEM Processor, you need to update your code to indicate the URL to which your agent should send its beacons.
For more information, see Customize Your Android Mobile Instrumentation.