With New Relic's Android NDK agent, you can capture native crashes resulting from raised signals and uncaught runtime exceptions from C and C++ code used in your Android app.
During startup, the native agent installs handlers for important signals, a C++ unhandled exception handler and a monitor to detect ANR conditions.
In the event of a crash, the native agent will generally not have enough time or stability to process the report. Instead, the report data is quickly written to local storage, to be processed the next time the app is launched. It is up to the app to request reports when ready.
Android NDK agent releases follow semantic versioning conventions. See Android agent release notes for full details on releases and downloads. Android NDK agent artifacts can also be found on Maven Central.
The native agent will report three types of native events:
- Raised signals (crash)
- Unhandled exceptions
- Application Not responding (ANR)
See the getting started guide as well as the compatibility and requirements documentation for an overview of what is supported by the Android NDK agent.
See the following documentation for specific use cases of the Android NDK agent:
To add the Android NDK agent to your app, you simply need to declare a dependency in your app-level Gradle build file:
dependencies {
implementation 'com.newrelic.agent.android:agent-ndk:<version>'
}
The report listener is used to pass native reports from the agent to your app. Reports are represented as JSON strings. The format of the JSON report is here.
Implement the following interface, and pass a reference when starting the native agent:
class Listener : AgentNDKListener {
/**
* A native crash has been detected and forwarded to this method
* @param String containing backtrace
* @return true if data has been consumed
*/
override fun onNativeCrash(crashAsString: String?): Boolean {
return false
}
/**
* A native runtime exception has been detected and forwarded to this method
* @param String containing backtrace
* @return true if data has been consumed
*/
override fun onNativeException(exceptionAsString: String?): Boolean {
return false
}
/**
* ANR condition has been detected and forwarded to this method
* @param String containing backtrace
* @return true if data has been consumed
*/
override fun onApplicationNotResponding(anrAsString: String?): Boolean {
return false
}
}
Finally, instantiate the agent in either the Application or launcher Activity class, passing the application context and a reference to your report listener implementation:
// construct an agent instance
var agentNDK = AgentNDK.Builder(context)
.withReportListener(Listener())
.build()
// when ready, start the agent
agentNDK.start()
// when finished, stop the agent
agentNDK.stop()
// Alternatively, the agent can be stopped by calling the static method
AgentNDK.shutdown()
The agent exists as a single instance (singleton), and any further uses of the builder will replace the instance
var agentNDK = AgentNDK.getInstance()
AgentNDK.Builder(context)
.withReportListener(Listener())
.build()
// agentNDK is now invalid
In the event of a crash, the native agent will generally not have enough time or stability to process the report. Instead, the report data is quickly written to local storage, to be processed the next time the app is launched. It is up to the app to request reports when it is ready for them by calling:
agentNDK.flushPendingReports()
Reports that remain in the cache longer that remain in the cache longer than the configured expiration duration will be removed, but only after a final post to the listener.
// The expiration time is set during agent creation by adding this build method
val REPORT_TTL = TimeUnit.SECONDS.convert(3, TimeUnit.DAYS)
val agentNDK = AgentNDK.Builder(context)
.withReportListener(Listener())
.withExpiration(REPORT_TTL)
.build()
// But can also be set at runtime
agent.managedContext?.expirationPeriod = REPORT_TTL
The agent will inject a 40-character build id into each generated report. A random UUID will be created, but can also be specified when the agent is built.
The agent will inject a 40-character session id into each generated report. A random UUID will be created, but can also be specified when the agent is built.
// the default values are UUIDs
val buildId = UUID.randomUUID().toString()
val sessionId = UUID.randomUUID().toString()
AgentNDK.Builder(context)
.withBuildId(buildId)
.withSessionId(sessionId)
.build()
Sets the agent's report directory inside of the passed storage location, creating the subdirectories as needed.
// the default location is /data/data/<app>/cache/newrelic/reports
AgentNDK.Builder(context)
.withStorageDir(context?.cacheDir)
Stacks will be reported with the symbols provided by the app. If symbols are stripped prior to release, nine will be available for crash stack frames. We are working to address this.
The Android NDK agent requires the following tools to build:
Dependency | Version | |
---|---|---|
New Relic Android Agent | 6.11.0 or higher | The NDK agent 1.0.0-1.0.2 is compatible with Android agent 6.10.0 and lower |
Java | JDK 8 or higher | |
Android Gradle Plugin | 4.1 or higher | AGP 7 requires JDK 11 |
Gradle | 6.7.1 | AGP 7 requires Gradle 7 or higher |
NDK | 21.4.7075529 or higher | |
CMake | 3.18 | |
minSDK | 24 | |
NDK | 21.4.7075529 or higher | |
Cmake | 3.18.1 or higher |
Dependencies must to be installed and configured for your environment prior to building.
The Android NDK agent (agent-ndk
) requires JDK 8 or higher to build; your JAVA_HOME
must be set to this JDK version.
To build the agent-ndk
AAR, run the following command from the project root directory:
./gradlew clean assemble
To build and run all checks:
./gradlew clean build
After building, Android NDK agent artifacts are located in agent-ndk/build/outputs/aar
Android Studio must be configured with the Android Native Development Kit (NDK) installed.
Update cmake
in Tools -> SDK Manager -> SDK Tools
The unit tests are conventional JUnit tests. The supporting framework is the industry-standard JUnit dependency. Unit tests rely on a variety of different mock object frameworks combined with complex test initialization patterns that simulate agent initialization.
To run all unit tests from the command line:
./gradlew clean test
New Relic hosts and moderates an online forum where customers can interact with New Relic employees as well as other customers to get help and share best practices. Like all official New Relic open source projects, there's a related Community topic in the New Relic Explorers Hub. You can find this project's topic/threads on the New Relic Explorer's Hub.
- New Relic Documentation: Comprehensive guidance for using our platform
- New Relic Community: The best place to engage in troubleshooting questions
- New Relic Developer: Resources for building a custom observability applications
- New Relic University: A range of online training for New Relic users of every level
- New Relic Technical Support 24/7/365 ticketed support. Read more about our Technical Support Offerings.
Github Issues are not open to the public at the moment. Please contact our support team or one of the support channels to submit your issues, feature requests, etc.
At New Relic, we take your privacy and the security of your information seriously and are committed to protecting your information. We must emphasize the importance of not sharing personal data in public forums, and ask all users to scrub logs and diagnostic information for sensitive information, whether personal, proprietary, or otherwise.
We define “Personal Data” as any information relating to an identified or identifiable individual, including, for example, your name, phone number, post code or zip code, Device ID, IP address and email address.
Please review New Relic’s General Data Privacy Notice for more information.
See our feature roadmap, to learn more about our product vision, understand our plans, and provide us valuable feedback.
We encourage your contributions to improve the New Relic Android Agent! Keep in mind that when you submit your pull request, you'll need to sign the CLA via the click-through using CLA-Assistant. You only have to sign the CLA one time per project.
If you would like to contribute to this project, review these guidelines.
To all contributors, we thank you! Without your contribution, this project would not be what it is today. If you have any questions, or to execute our corporate CLA (which is required if your contribution is on behalf of a company), drop us an email at [email protected].
As noted in our security policy, New Relic is committed to the privacy and security of our customers and their data. We believe that providing coordinated disclosure by security researchers and engaging with the security community are important means to achieve our security goals.
If you believe you have found a security vulnerability in this project or any of New Relic's products or websites, we welcome and greatly appreciate you reporting it to New Relic through HackerOne.
android-agent-ndk
is licensed under the Apache 2.0 License.
The android-agent-ndk
also uses source code from third-party libraries. You can find full details on which libraries are used and the terms under which they are licensed in the third-party notices document and our Android NDK agent licenses public documentation.