App Performance Management (APM) of AppGallery Connect provides minute-level app performance monitoring capabilities. By integrating the APM SDK, you can quickly integrate APM without coding. APM allows you to view and analyze app performance data collected in AppGallery Connect to comprehensively understand the performance features of your app, and quickly and accurately rectify performance problems to continuously improve user experience.
In this codelab, you will build an app that integrates APM. In addition, you can manually trigger network requests to test whether APM can monitor network performance and learn how to view and analyze app performance problems.
To integrate APM of AppGallery Connect, you must complete the following preparations:
For details, please refer to Preparations for Integration in AppGallery Connect.
buildscript {
repositories {
// Add the maven repository
maven { url 'http://developer.huawei.com/repo/' }
}
dependencies {
// To benefit from the latest APM feaures, update your Android Gradle Plugin
// dependency to at least v3.5.3
classpath 'com.android.tools.build:gradle:3.5.3'
// Add agc plugin dependence
classpath 'com.huawei.agconnect:agcp:1.4.1.300'
// Add the dependency for the APM plugin
classpath 'com.huawei.agconnect:agconnect-apms-plugin:1.5.1.301'
}
}
apply plugin: 'com.android.application'
// Apply the AppGallery Connect plug-in.
apply plugin: 'com.huawei.agconnect'
// Apply the APM plug-in.
apply plugin: 'com.huawei.agconnect.apms'
dependencies {
//..
}
If you are using Android Studio, you need to integrate the APM SDK into your Android Studio project before development.
dependencies {
// Add APM SDK library dependency
implementation 'com.huawei.agconnect:agconnect-apms:1.5.1.301'
}
-keep class com.huawei.agconnect.apms.**{*;}
-dontwarn com.huawei.agconnect.apms.**
-keep class com.hianalytics.android.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
-keep interface com.huawei.hms.analytics.type.HAEventType{*;}
-keep interface com.huawei.hms.analytics.type.HAParamType{*;}
-keepattributes Exceptions, Signature, InnerClasses, LineNumberTable
You can create a page in your Android Studio project and design the UI according to the following figure, with six buttons required: One button is used to trigger network monitoring events and the other two are used to enable and disable APM performance data reporting.
You can manually trigger a network request and check whether the network performance indicators are normal on the performance management page of APM. The app launch and screen rendering events are automatically reported when an app is launched.
static private String URL = "https://developer.huawei.com/consumer/cn/";
static private MediaType MEDIATYPE = MediaType.parse("text/x-markdown; charset=utf-8");
static private String REQUESTBODY = "apms http request test";
static public void oneRequest() {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(URL)
.post(RequestBody.create(MEDIATYPE, REQUESTBODY))
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d("apmsAndroidDemo", "onFailure: " + e.toString());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("apmsAndroidDemo", "onResponse: Success");
}
});
}
Button sendNetworkRequestBtn = findViewById(R.id.btn_network);
sendNetworkRequestBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d("apmsAndroidDemo", "send network request.");
HttpUtil.oneRequest();
}
});
In this codelab, you can manually trigger the reporting of custom indicators and check whether the indicators can be displayed properly on the app performance management page.
Add three buttons, namely Send Custom Event, Send Custom Event By annotation, and Send Custom Network Event, to the activity layout file of your app, to report custom events by calling an API, report custom events through annotation, and report custom network events by calling an API, respectively.
findViewById(R.id.custom_normal_event).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("apmsAndroidDemo", "send a custom event");
sendCustomEvent();
}
});
// Define a custom event.
public void sendCustomEvent() {
CustomTrace customTrace = APMS.getInstance().createCustomTrace ("CustomEvent1")
customTrace.start();
businessLogicStart(customTrace);
businessLogicEnd(customTrace);
customTrace.stop();
}
public void businessLogicStart(CustomTrace customTrace) {
customTrace.putMeasure("ProcessingTimes", 0);
for (int i = 0; i < 5; i++) {
customTrace.incrementMeasure("ProcessingTimes",1);
}
}
public void businessLogicEnd(CustomTrace customTrace) {
customTrace.putProperty("ProcessingResult","Success");
customTrace.putProperty("Status","Normal");
}
findViewById(R.id.custom_normal_event_by_annotation).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("apmsAndroidDemo", "send a custom event by annotation");
sendCustomEventByAnnotation();
}
});
private void sendCustomEventByAnnotation() {
customEventHandle();
}
// define custom event by annotation
@AddCustomTrace (name = "CustomEvent2")
public void customEventHandle() {
}
findViewById(R.id.custom_network_event).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("apmsAndroidDemo", "send a custom network event");
new Thread(new Runnable() {
@Override
public void run() {
HttpUtil.customNetworkEvent();
}
}).start();
}
});
static private String URL = "https://developer.huawei.com/consumer/cn/";
static private MediaType MEDIATYPE = MediaType.parse("text/x-markdown; charset=utf-8");
static private String REQUESTBODY = "apms http request test";
static public void customNetworkEvent() {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(URL)
.post(RequestBody.create(MEDIATYPE, REQUESTBODY))
.build();
// define custom network event
NetworkMeasure networkMeasure = APMS.getInstance().createNetworkMeasure(URL, "POST");
networkMeasure.setBytesSent(request.headers().byteCount());
long bytesRecive = 0L;
networkMeasure.start();
try {
Response response = okHttpClient.newCall(request).execute();
networkMeasure.setStatusCode(response.code());
if (response.body() != null) {
networkMeasure.setBytesReceived(response.body().contentLength());
networkMeasure.setContentType(Objects.requireNonNull(response.body().contentType()).toString());
bytesRecive = dealResponseBody(response.body());
response.body().close();
}
networkMeasure.putProperty("TrasnmittedBytes", String.valueOf(bytesRecive));
networkMeasure.stop();
} catch (IOException e) {
networkMeasure.setStatusCode(0);
classErrorMessage(networkMeasure, e);
networkMeasure.putProperty("ErrorInformation", e.getMessage());
networkMeasure.putProperty("TrasnmittedBytes", String.valueOf(bytesRecive));
networkMeasure.stop();
}
}
private static void classErrorMessage(NetworkMeasure networkMeasure, Exception e) {
if (e instanceof UnknownHostException) {
networkMeasure.putProperty("ErrorInformation", "DNS resolution failed.");
}
}
private static long dealResponseBody(ResponseBody body) throws IOException {
InputStream inputStream = body.byteStream();
byte[] result = new byte[1000];
long len = 0;
long readBytes = 0;
while ((len = inputStream.read(result)) != -1) {
readBytes += len;
}
return readBytes;
}
In this codelab, you can manually trigger the reporting of an ANR error and check whether the ANR data can be displayed properly on the app performance management page.
public void initAnrTestButton() {
findViewById(R.id.anr_test).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("apmsAndroidDemo", "trigger anr");
anrTestEnable = true;
}
});
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (anrTestEnable) {
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return super.dispatchKeyEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (anrTestEnable) {
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return super.dispatchTouchEvent(ev);
}
findViewById(R.id.enable_apms_on).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
APMS.getInstance().enableCollection(true);
}
});
findViewById(R.id.enable_apms_off).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
APMS.getInstance().enableCollection(false);
}
});
findViewById(R.id.enable_apms_on).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
APMS.getInstance().enableAnrMonitor(true);
}
});
findViewById(R.id.enable_apms_off).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
APMS.getInstance().enableAnrMonitor(false);
}
});
Package and run your app, and tap the TRIGGER ANR button to trigger an ANR error.
On the Request success rate page, the status code distribution is displayed, and the request success rate statistics are collected from different dimensions (version number, country/region, device model, level-1 region, system version, carrier, and network).
Well done. You have successfully created an app that integrates APS of AppGallery Connect and learned how to view and analyze app performance data on the app performance management page.
For details about APM APIs, please refer to API Reference.
Download the demo source code used in this codelab from the following address: