Android SDK を使用して Android アプリケーションをインストゥルメント化すると、SDK によって公開される API を使用して、コントローラ UI に表示されるアプリケーションのデータをカスタマイズすることもできます。 

Because the agent stores data about events in a local buffer before reporting the information, you are recommended to use the APIs with discretion.

データの追加タイプの収集

Instrumentation クラスには、モバイル RUM を使用して収集および集約できるアプリケーションデータの種類を拡張できる追加のメソッドがあります。作成できる拡張には、次の 6 つの基本タイプがあります。

データのタイプ説明仕様Where Data is Displayed
Info pointsHow often a method is invoked, and how long it takes to run.
  • Data is numeric
  • Names must consist of
    alphanumeric characters and/or spaces
Custom timersAny arbitrary sequence of events within your code timed,
even spanning multiple methods.
  • Data is numeric
  • Metric names must consist of
    alphanumeric characters and/or spaces
Custom metricsAny integer-based data you wish to collect.
  • Data is numeric
  • Metric names must consist of
    alphanumeric characters and/or spaces
ユーザデータAny string key/value pair you think might be useful.
  • Data can be any type
  • Metric names have no restrictions
トピックパス(パンくずリスト)The context for a crash.
  • Data can be any data type
  • Metric names have no restrictions
ユーザインタラクションCapture when users press buttons, click on lists, and select text.
  • Data can be any data type
  • Metric names have no restrictions

情報ポイント、カスタムタイマー、カスタムメトリック、ユーザデータを設定した場合、モバイルエージェントはモバイルビーコンでそのデータをパッケージ化します。通常、ビーコンは、インストゥルメント化されたアプリケーションが HTTP 要求を送信したとき、またはクラッシュ後にアプリケーションが再起動したときに、カスタムデータが収集され、これらのイベントが少なくとも 5 分間発生しなかった場合に送信されます。カスタムデータはその時点で送信されます。

Info Points

Information points allow you to track how your own code is running. メソッドが呼び出される頻度、実行にかかる時間、および例外がスローされたかどうかを確認できます。情報ポイントを設定する最も簡単な方法は、@InfoPoint 注釈を使用することです。例:

@InfoPoint
 public void infoPointMethod(String arg1, int arg2, long value) {
   System.out.println("Executing infoPointMethod!");
 }
CODE

CallTracker インターフェイスを使用して手動で実行することもできます。たとえば、downloadImage メソッドに関する情報を収集するには、次のようなコードを使用できます。

private void downloadImage(URL url) {
     CallTracker tracker =
          Instrumentation.beginCall("com.example.android.awesomeapp.ImageDownloader", "downloadImage")
              .withArguments(url);
     try {
          //download image.
          tracker.reportCallEnded()
     } catch(Exception e) {
         //handle exception thrown
         tracker.reportCallEndedWithException(e);
     }
 }
CODE

This information appears in the Custom Data view of the Controller UI.

カスタムタイマー

Custom timers allow you to time any arbitrary sequence of events within your code, even spanning multiple methods, by using startTimer and stopTimer.

public class MyActivity extends Activity {
   @Override
   protected void onStart(){
       Instrumentation.startTimer("Time Spent on MyActivity");
       //your code here.
   }

   @Override
   protected void onStop(){
       Instrumentation.stopTimer("Time Spent on MyActivity");
       //your code here.
   }
 }
JAVA

メソッド startTimer(String) および stopTime(String) はさまざまなスレッドから呼び出すことができます。Calling startTimer again with the same name value resets a named timer.

This information appears in the Custom Data view of the Controller UI.

Custom Metrics

Any integer-based data can be passed to the agent. The first parameter to the reportMetric call is the name you want the metric to appear under in the Controller UI.  The metric name should only contain alphanumeric characters and spaces. Illegal characters are replaced by their ASCII hex value.

たとえば、ユーザが UI のチェックアウトボタンをクリックした回数を追跡するには、次のようなコードを使用できます。

findViewById(R.id.checkout_button).setOnClickListener(new View.OnClickListener(){
      @Override
      public void onClick(View view){
          //run your checkout routine.
          Instrumentation.reportMetric("Checkout Count", 1);
      }
 });
JAVA

This information appears in the Custom Data view of the Controller UI.

ユーザ データ

You can set any string key/value pair you think might be useful. The first parameter to the setUserData call is the key you want to use, which must be unique across your application. 2 番目はキーに割り当てる値です。

例: 

void onUserLoggedIn(String userid) {
    Instrumentation.setUserData("User ID", userid); 
    ...
}
JAVA

This information is available in Network Request Analyze and is added to any crash snapshots that may be taken. Keys and values are limited to 2048 characters each.

You can also set user data with values of other types (Long, Boolean, Double, Date) using the following methods:

トピックパス(パンくずリスト)

Breadcrumbs allow you to situate a crash in the context of your user's experience. Set a breadcrumb when something interesting happens. If your application crashes at some point in the future, the breadcrumb will be displayed along with the crash report.

There are two ways of leaving breadcrumbs:

Using this method means that breadcrumbs are reported in crash reports only.

public static void leaveBreadcrumb(java.lang.String breadcrumb)
JAVA
Using this method lets you fine tune where the breadcrumbs are reported, either only in crash reports or in crash reports and sessions.
public static void leaveBreadcrumb(java.lang.String breadcrumb, int mode)
JAVA

Where mode is either:

  • CRASHES_ONLY
  • CRASHES_AND_SESSIONS

If the  breadcrumb is over 2048 characters, it is truncated. 空の場合、トピックパスは記録されません。Each crash report displays the most recent 99 breadcrumbs.

Add a Crash Reporting Callback

You may want to make crash report information that Mobile RUM collects available to other parts of your code, for example, to Google Analytics, if you are using it. サマリークラッシュ情報を渡すことができるようにするには、クラッシュレポートのランタイムコールバックを設定します。Android エージェントがクラッシュを検出および報告した場合にコールバックを取得するには、コードに次のインターフェイスを実装する必要があります。

public interface CrashReportCallback {
    void onCrashesReported(Collection<CrashReportSummary> summaries);
}
JAVA

通常は 1 つしかない場合でも、複数のクラッシュが発生する可能性があるため、個々のコールバックの代わりに収集して送信します。 

メソッド onCrashesReported は、クラッシュ発生後のエージェントの次の初期化中に呼び出されます。

このコールバックはアプリケーションの UI スレッドで呼び出されるため、作業は別の作業スレッドで実行する必要があります。

CrashReportSummary に次のプロパティがあります。

public class CrashReportSummary {
    public final String crashId;
    public final String exceptionClass;
    public final String exceptionMessage;
}
JAVA

Google Analytics などの別の分析ツールに情報を送信する場合は、3 つのプロパティすべてを含めることをお勧めします。exceptionClass および exceptionMessage は、クラッシュを迅速に識別するのに役立ちますが、詳細な情報を得るためには、crashId を使用して AppDynamics コントローラ UI でクラッシュを調べることができます。

たとえば、クラッシュ情報を Android のロガーに出力するには、次の CrashReportCallback クラスを実装できます。

public static class MyCrashReportCallback implements CrashReportCallback {
    @Override
    public void onCrashesReported(Collection<CrashReportSummary> summaries) {
        for (CrashReportSummary crash : summaries) {
            Log.e("MyApp", "Crash Detected: " + crash.exceptionClass + " : " + crash.exceptionMessage + " (" + crash.crashId + ")");
        }
    }
}
JAVA

AgentConfiguration オブジェクトを使用してコールバックを設定します。

final AgentConfiguration config = AgentConfiguration.builder()
        .withAppKey(appKey)
        .withContext(context)
        .withCrashCallback(new MyCrashReportCallback())
        .build();
JAVA

コールバックは、メインスレッドで、クラッシュ後の次の初期化中に呼び出されます。詳しくは、Android SDK API の最新の Java ドキュメントを参照してください。

Report Errors and Exceptions

You can report exceptions using the method reportError from the Instrumentation class. Reported exceptions will appear in session details.

また、問題に対して次の重大度レベルの 1 つを設定することもできます。With the severity level, you can filter errors in the Code Issues Dashboard or Code Issues Analyze.

  • ErrorSeverityLevel.INFO
  • ErrorSeverityLevel.WARNING
  • ErrorSeverityLevel.CRITICAL

次の例では、API を使用して考えられる例外を報告し、ファイルへの書き込み時に重大度レベルをErrorSeverityLevel.CRITICAL(クリティカル)に設定します。

private void writeToFile(String filePath, String data) {
    try {
        OutputStream outputStream = new FileOutputStream(filePath);
        Writer outputStreamWriter = new OutputStreamWriter(outputStream);
        outputStreamWriter.write(data);
        outputStreamWriter.close();
    } catch (IOException e) {
        Log.e("Exception", "File write failed: " + e.toString());
        Instrumentation.reportError(e, ErrorSeverityLevel.CRITICAL);
    } 
}
JAVA

ハイブリッドサポートの設定

デフォルトでは、Android エージェントは Android WebViews をインストゥルメント化します。Android エージェントは、JavaScript エージェントを WebViews に注入することでこれを実行できます。 See ハイブリッド アプリケーションのサポート for an overview and an explanation of how it works. 

ハイブリッドサポートのランタイム設定

The code example below disables the injection of the JavaScript Agent. If the client receives a false for this flag, then the JavaScript Agent will be disabled. そのため、WebViews はインストゥルメント化されず、Ajax 要求は監視されません。

Instrumentation.start(AgentConfiguration.builder()
     .withAppKey("<EUM_APP_KEY>")
     .withContext(getApplicationContext())
     .jsAgentInjectionEnabled(false)
     .build());
}
JAVA

The injection occurs during the creation of a new WKWebView. So, if a WKWebView is created when this flag is set to false, that particular WKWebView won't be instrumented even if the flag is subsequently set to true.

Ajax コールの収集およびレポートは、デフォルトでは無効になっています。Ajax コールのインジェクションおよび収集とレポートを有効にするには、次に示すようにインストゥルメンテーションの構成でメソッド jsAgentEnabledtrue を渡します。

Instrumentation.start(AgentConfiguration.builder()
     .withAppKey("<EUM_APP_KEY>")
     .withContext(getApplicationContext())
     .jsAgentAjaxEnabled(true)
     .build());
}
JAVA

プログラムによるセッションの制御

デフォルトでは、ユーザが非アクティブになってからモバイルセッションが終了します。たとえば、ユーザがアプリケーションを開くと、セッションは開始され、ユーザが設定した期間にアプリケーションを使用しなくなった後にのみ終了します。ユーザがアプリケーションの再使用を開始すると、新しいセッションが開始されます。 

Instead of having a period of inactivity to define the duration of a session, however, you can use the following API to programmatically control when sessions begin and end:

void startNextSession()
JAVA

Instrumentation クラスからメソッド startNextSession を呼び出すと、現在のセッションが終了し、新しいセッションが開始されます。API を使用すると、セッションを定義してフレーム化することができます。これにより、ビジネス目標と予想されるユーザフローをより厳密に合わせることができます。たとえば、API を使用して、製品の購入を追跡するセッションを定義したり、新しいユーザを登録したりすることができます。 

この API を過剰に使用すると、セッションが調整されます(過剰使用は Android エージェントごとに 1 分あたり 10 コールを超えた場合になりますが、変更される可能性があります)。API を使用しない場合、セッションは、ユーザが非アクティブになった後、デフォルトの終了にフォールバックします。

プログラムによって制御されるセッションの例

次のコード例では、現在のセッションが終了し、チェックアウトが行われると新しいセッションが開始されます。

public void checkoutCart(){
    if (currentCartItems!=null && currentCartItems.size()>0){
	    CheckoutTask checkoutReq = new CheckoutTask();
		checkoutReq.execute(getEndpoint() + "cart/co");
		currentCartItemsMap.clear();
		convertItemsMaptoList();
        Instrumentation.startNextSession();
	} else {
	    displayToast("There are no items in the cart");
	}
}
JAVA

Start and End Session Frames

You can use the SessionFrame API to create session frames that will appear in the session activity. セッションフレームは、セッション中にユーザが実行している内容のコンテキストを提供します。API を使用すると、ビジネスコンテキスト内のユーザ画面の名前とユーザフローの記録を向上させることができます。 

使用例

次に、SessionFrame API を使用する一般的な使用例を示します。

  • 1 つのアクティビティが複数の機能を実行し、個々の機能をより詳細に追跡します。
  • ユーザフローは、複数のアクティビティまたはユーザのインタラクションに及びます。たとえば、API を使用してセッションフレーム「Login」、「Product Selection」、および「Purchase」を作成して、ユーザが購入のためにフローを記録することができます。
  • ユーザの操作に基づいて動的情報をキャプチャし、オーダー ID などのセッションフレームに名前を付けることができます。

SessionFrame API

次の表に、セッションフレームで使用できる 3 つのメソッドを示します。

クラスメソッド[説明(Description)]
Instrumentation
static SessionFrame startSessionFrame(String sessionFrameName)
JAVA

セッションフレームを開始して名前を付けるには、これを使用します。

Naming session frames enable you to easily identify and track the frames in the Sessions Dialog.

SessionFrame
static void updateName(String updatedSessionFrameName)
JAVA

セッションフレームを開始して名前を付けるには、これを使用します。

Naming session frames enable you to easily identify and track the frames in the Sessions Dialog.

SessionFrame
static void end()
JAVA
セッションフレームを終了します。startSessionFrame から返された SessionFrame オブジェクトからこのメソッドを呼び出すことができます。

セッションフレームの例

次の例では、ShoppingCartActivity クラスが SessionFrame API を使用し、チェックアウトプロセス中にユーザアクティビティを追跡しています。 

public class ShoppingCartActivity extends Activity {

  SessionFrame checkoutSessionFrame;

  public void onCheckoutCartButtonClicked() {
    // The user starts the checkout by clicking the checkout button.
    // This may be after they have updated the quantities of items in the cart, etc.
    checkoutSessionFrame = Instrumentation.startSessionFrame("Checkout");
  }

  public void onConfirmOrderButtonClicked() {
    // Once they have confirmed payment info and shipping information, and they
    // are clicking the "Confirm" button to start the backend process of checking out,
    // we may know more information about the order itself, such as an order ID.
    checkoutSessionFrame.updateName("Checkout: Order ID " + orderId);
  }

  public void onProcessOrderCompleted() {
    // Once the order is processed, the user is done "checking out", so we end the session frame.
    checkoutSessionFrame.end();
    checkoutSessionFrame = null;
  }

  public void onCheckoutCanceled() {
    // If the user cancels or returns to the cart, you'll want to end the session frame also, or else it will be
    // left open and appear to have never ended.
    checkoutSessionFrame.end();
    checkoutSessionFrame = null;
  }
}
JAVA

カスタム HTTP ライブラリの使用

基盤となる実装がサポートされているいずれかのネットワークライブラリによって処理されると、Android エージェントは自動的にネットワーク要求を検出します。Android エージェントがカスタムライブラリからの要求を検出するようにするには、HttpRequestTracker インターフェイスを使用してアプリケーションに手動で要求トラッキングコードを追加します。  

サポート対象のネットワークライブラリ

以下のライブラリは、Android ネットワーク要求の大部分をカバーしています。In some cases, however, mobile applications use custom HTTP libraries.  

  • HttpURLConnection
  • HttpsURLConnection
  • HttpClientクラス
  • OkHttp
  • OkHttp3
  • ch.boye.httpclientandroidlib

To set headers to allow correlation with server-side processing, use the ServerCorrelationHeaders class.  

Add Request Tracking

要求追跡を手動で追加するには、HttpRequestTracker オブジェクトを使用し、要求の開始時と終了時にエージェントに通知して、エージェントに応答のフィールドを報告します。

要求のトラッキング

HTTP 要求の追跡を開始するには、次のインターフェイスのインスタンスを使用します。

このインターフェイスを使用する前に、Instrumentation.start メソッドを使用してエージェントを初期化する必要があります。

public interface HttpRequestTracker {
    public Exception getException();
    public HttpRequestTracker withException(Exception e);
 
    public String getError();
    public HttpRequestTracker withError(String error);
 
    public int getResponseCode();
    public HttpRequestTracker withResponseCode(int responseCode);
 
    public Map<String, List><String>> getResponseHeaderFields();
    public HttpRequestTracker withResponseHeaderFields(Map<String, List><String>> responseHeaderFields);
 
   /**
    * Stops tracking an HTTP request.
    *
    * Immediately after receiving a response or an error, set the appropriate fields and call this method to
    * report the outcome of the HTTP request. You should not continue to use this object after calling this
    * method -- if you need to track another request, obtain a new instance.
    */
    public void reportDone();
}
JAVA

例:

Given a request snippet like this:

public byte[] sendRequest(URL url) throws HttpException {
    try {
        // implementation omitted
        return responseBody;
    } catch (UnderlyingException e) {
        throw new HttpException(e);
    }
}
JAVA

Adding the tracker could look something like this:

public byte[] sendRequest(URL url) throws HttpException {
    HttpRequestTracker tracker = Instrumentation.beginHttpRequest(url);
    try {
        // implementation omitted
        tracker.withResponseCode(theResponseCode)
               .withResponseHeaderFields(theResponseHeaderFields)
               .reportDone();
        return responseBody;
    } catch (UnderlyingException e) {
        tracker.withException(e)
               .reportDone();
        throw new HttpException(e);
    }
}
JAVA

サーバ側の相関を有効にする

要求とサーバ側の処理の相関を有効にするには、サーバ側のエージェントが検出できる発信要求に特定のヘッダーを追加します。

This is done automatically for standard HTTP libraries.

public class ServerCorreleationHeaders {
    public static Map<String, List><String>> generate();
}
JAVA

次の作業が必要です。

  1. Call the generate method and set the generated headers before sending a request to the backend.
  2. withResponseHeaderFields フィールドのデータを使用して、応答ヘッダーを報告します。

要求/応答のコンテンツ長をオーバーライドする

通常は、HttpRequestTracker.withRequestHeaderFields()HttpRequestTracker.withResponseHeaderFields() を使用してヘッダーを渡すことで、ネットワーク要求と応答のコンテンツ長を取得できます。

何らかの理由でこれがカスタム HTTP トラッキングに対して機能しない場合(たとえば、ネットワークライブラリが送信されるまでこれらのフィールドにデータを入力しない場合)、HttpRequestTracker.withRequestContentLength(Long length) および HttpRequestTracker.withResponseContentLength(Long length) を使用して要求と応答のコンテンツの長さを報告できます。

たとえば、コンテンツのバイト配列を持つ要求を追跡するとします。次に示すように、バイト配列のサイズを渡すことで、要求のコンテンツ長を報告できます。

byte[] requestContent;
HttpRequestTracker tracker;
tracker.withRequestContentLength(requestContent.size());
JAVA

エージェント設定のカスタマイズ

エージェント自体の動作をカスタマイズするには、AgentConfiguration オブジェクトを Instrumentation.start メソッドに渡します。AgentConfiguration オブジェクトを使用すると、次の操作を実行できます。

  • オンプレミス EUM サーバをポイントする
  • ロギングを有効にする
  • アプリケーション名をカスタム設定する。これは、基本的に異なるパッケージ名を持つ同じアプリケーションバイナリを異なる地理的領域に展開する場合に便利です。これにより、すべてのデータが同じ名前で処理されるようになります。
  • ネットワーク要求に使用されていないアプリケーション内部の HTTP 要求を無視する
  • カスタム HTTP ライブラリを使用してビーコンを送信するようにエージェントを設定する

構文は次のようになります。

Instrumentation.start(AgentConfiguration.builder()
      .withAppKey("<EUM_APP_KEY>")
      .withContext(getApplicationContext())
      .withCollectorURL(collectorURL*) // The URL of the EUM Server(on-prem)
      .withCompileTimeInstrumentationCheck(true) // Set to false if you are using features of the SDK only, like custom HTTP support, but not to instrument your app.      
      .withLoggingEnabled(true)//set default INFO logging. Tagged "AppDynamics".
      .withApplicationName(applicationName)//set a custom app name
	  .withExcludedUrlPatterns(excludedUrlPatterns) // Set excluded url regex patterns for http tracking
      .withCollectorChannelFactory(collectorChannelFactory()) // The custom HTTP implementation to use
      .build());
JAVA

* EUM サーバのデフォルト URL は https://mobile.eum-appdynamics.com:443 です。EUM サーバの URL のリストについては、「外部アクセスロケーション」を参照してください。 

詳しくは、最新の Java ドキュメントを参照してください。

カスタム HTTP ライブラリを使用するようにエージェントを設定する

Android エージェントは、ビーコンを配信するために HTTP を使用します。To have the agent use your custom HTTP library for this purpose, do the following.

  1. 次の抽象クラスを拡張するクラスを実装します。

    public abstract class CollectorChannel {
        private URL url;
        private int connectTimeout;
        private int readTimeout;
        private Map<String, List><String>> requestProperties = new HashMap<String, List><String>>();
        private String requestMethod;
     
        public void setURL(URL url) {
            this.url = url;
        }
     
        public URL getURL() {
            return url;
        }
     
        public void setConnectTimeout(int connectTimeout) {
            this.connectTimeout = connectTimeout;
        }
     
        public int getConnectTimeout() {
            return connectTimeout;
        }
     
        public void setReadTimeout(int readTimeout) {
            this.readTimeout = readTimeout;
        }
     
        public int getReadTimeout() {
            return readTimeout;
        }
     
        public void addRequestProperty(String property, String value) {
            if (!requestProperties.containsKey(property)) {
                requestProperties.put(property, new ArrayList<String>());
            }
            requestProperties.get(property).add(value);
        }
     
        public Map<String, List><String>> getRequestProperties() {
            return Collections.unmodifiableMap(requestProperties);
        }
     
        public void setRequestMethod(String requestMethod) {
            this.requestMethod = requestMethod;
        }
     
        public String getRequestMethod() {
            return requestMethod;
        }
     
        public abstract OutputStream getOutputStream() throws IOException;
     
        public abstract InputStream getInputStream() throws IOException;
     
        public abstract int getResponseCode() throws IOException;
     
        public abstract Map<String,List><String>> getHeaderFields() throws IOException;
    }
    CODE

    このインターフェイスは、少しだけ HttpURLConnection に基づいています。

  2. CollectorChannelFactory インターフェイスのバージョンを実装します。これは次のようになります。

    public interface CollectorChannelFactory {
    
        /**
         * Returns a new instance of CollectorChannel.
         *
         * If you want to supply a custom CollectorChannel, implement this interface, and return
         * an instance of your concrete implementation of CollectorChannel from this method.
         */
        public CollectorChannel newCollectorChannel();
    }
    JAVA

    newCollectorChannel の実装は、CollectorChannel の実装の新しいインスタンスを返す必要があります。

  3. CollectorChannelFactoryAgentConfiguration オブジェクトに渡します。

ユーザインタラクションの把握

Android エージェントを有効にすると、特定のユーザインタラクションを追跡できます。ユーザインタラクションがキャプチャされると、UI イベントごとにセッションをソートし、セッション ウォーターフォールのタイムラインで UI イベントを表示することができます。 

You can capture when users do one or all of the following:

  • press buttons
  • テキストフィールドの選択
  • リスト項目のクリック

Security and Privacy Concerns

The interaction capture mode is disabled by default for security and privacy reasons as user interactions may contain sensitive information. Moreover, this potential security and privacy issue may be compounded if you enable both the capturing of UI interactions and screenshots. 

Enable User Interaction Capture Mode

ユーザインタラクションのキャプチャモードを有効にするには、AgentConfigurationオブジェクトからメソッド withInteractionCaptureMode() にキャプチャモードを渡します。次のインストゥルメンテーション コードの例では、サポート対象のすべてのタイプのユーザインタラクションをキャプチャするように Android エージェントを設定します。

Instrumentation.start(AgentConfiguration.builder()
      .withAppKey("<EUM_APP_KEY>")
      .withContext(getApplicationContext())
      .withInteractionCaptureMode(InteractionCaptureMode.All)
      .build());
JAVA

また、1 つのタイプのユーザインタラクションのみをキャプチャするように Android エージェントを設定することもできます。

Instrumentation.start(AgentConfiguration.builder()
      .withAppKey("<EUM_APP_KEY>")
      .withContext(getApplicationContext())
      .withInteractionCaptureMode(InteractionCaptureMode.ButtonPressed)
      .build());
JAVA

Configure and Take Screenshots

モバイルスクリーンショットは、Android エージェントでデフォルトで有効になっています。スクリーンショットを自動的に表示するようにコントローラ UI を設定するか、または次に示すように Android SDK を使用して手動でスクリーンショットを取得することができます。

Instrumentation.takeScreenshot(); 
JAVA

たとえば、UI 要素をロードして顧客に表示される方法を表示した後に、スクリーンショットを取得することができます。

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_spinner_with_toast);
   spinner = (Spinner) findViewById(R.id.spnOptions); 
   btnSpinnerVal = (Button) findViewById(R.id.btnSpinnerValue);
   loadSpinner();
   Instrumentation.takeScreenshot();
}
JAVA

Disable Screenshots

コントローラ UI からまたは Android SDK を使用すると、スクリーンショットを無効にすることができます。Android SDK を使用してスクリーンショットを無効にするには、次に示すように AgentConfiguration クラスからメソッド withScreenshotsEnabled(false) を使用します。

Instrumentation.start(AgentConfiguration.builder()
     .withAppKey("<EUM_APP_KEY>")
     .withContext(getApplicationContext())
     .withScreenshotsEnabled(false)
     .build());
}
JAVA

スクリーンショットのブロック/ブロック解除

Android SDK を使用すると、コードブロックの実行中にスクリーンショットが実行されないようにブロックすることもできます。This just temporarily blocks screenshots from being taken until you unblock screenshots.  This enables you to stop taking screenshots in situations where users are entering personal data, such as on login and account screens.

Instrumentation.blockScreenshots()Instrumentation.unblockScreenshots() のメソッドを使用して、スクリーンショットをブロックおよびブロック解除します。スクリーンショットが AgentConfiguration.Builder.withScreenshotsEnabled(true) またはコントローラの UI を使用して無効になっている場合、これらのメソッドは効果がありません。スクリーンショットがブロックされているかどうかを確認するために Instrumentation.screenshotsBlocked() を呼び出すことができます。

次の例は、ユーザ情報を表示するときに API を使用してスクリーンショットをブロックおよびブロック解除する方法を示しています。

public class UserAccountActivity extends Activity {
  ...
  public void displayCustomerAccount() {
    // Check to see if screenshots are blocked
    if (! Instrumentation.screenshotsBlocked()) {
        // If screenshots aren't blocked, block them before showing customer details
        Instrumentation.blockScreenshots();    
    } 
    // Code to display customer details
    displayAccount(this.user);
    // After you're done, unblock screenshots
    Instrumentation.unblockScreenshots();
  }
  ...
}
CPP

Transform URLs for Network Requests

When your application makes network requests, you may not want to report URLs containing sensitive information to the EUM Server. You can instead transform the network request URL before reporting it or ignore it altogether.  

インポートを行うには以下を実行します。

  1. Implement a network request callback that modifies or ignores specific URLs.  
  2. Register the network request callback in the initialization code.

Implement the Network Request Callback

特定の URL を変更または無視するコールバックは、次のインターフェイスの実装です。メソッド onNetworkRequest は同期されているため、関数からすばやく戻ることをお勧めします。

public interface com.appdynamics.eumagent.runtime.NetworkRequestCallback  {
    boolean onNetworkRequest(HttpRequestTracker httpRequestTracker);
}
JAVA

 Transforming URLs

The onNetworkRequest method, in general, should follow the steps below to transform URLs:

  1. Identify specific URLs using techniques such as regex or pattern matching.
  2. Modify the url property of the HttpRequestTracker object.
  3. Assign a valid URL to the url property. (Modifying other properties of the HttpRequestTracker object will be ignored.)
  4. Return true.

The first step is optional as you could choose to transform the URLs of all network requests.  

private static class myNetworkRequestCallback implements com.appdynamics.eumagent.runtime.NetworkRequestCallback  {
    @Override
    public boolean onNetworkRequest(HttpRequestTracker httpRequestTracker) {
        URL urlMask = new URL("http://networkrequest-mask.com");
        httpRequestTracker.withURL(urlMask);
        return true;
    }
}
JAVA

In general, however, you would want to identify and transform URLs that contain sensitive information as implied in the example below.

private static class myNetworkRequestCallback implements com.appdynamics.eumagent.runtime.NetworkRequestCallback  {
    @Override
    public boolean onNetworkRequest(HttpRequestTracker httpRequestTracker) {
        String urlString = httpRequestTracker.getURL().toString();
        try {
            URL url = new URL("http://customer-account.com");
            if (urlString.contains("accountInfo")) {
                // Change the URL for calls to Facebook
                httpRequestTracker.withURL(url);
                return true;
            } 
        } catch (MalformedURLException e) {
            return false;
        }
        return true;
    }
}
JAVA

Ignoring URLs

If the onNetworkRequest method returns false, the beacon is dropped. The general process for ignoring beacons is as follows:

  1. Identify specific URLs using techniques such as regex or pattern matching.

  2. Return false.

理論的には、onNetworkRequest の次の実装によってすべてのネットワーク要求を無視することができます。

private static class myNetworkRequestCallback implements com.appdynamics.eumagent.runtime.NetworkRequestCallback  {
    @Override
    public boolean onNetworkRequest(HttpRequestTracker httpRequestTracker) {
        return false;
    }
}
JAVA

一般的には、この例で暗示されているように、モニタして false を返さないネットワーク要求を特定し、ネットワーク要求を無視します。

private static class myNetworkRequestCallback implements com.appdynamics.eumagent.runtime.NetworkRequestCallback  {
    @Override
    public boolean onNetworkRequest(HttpRequestTracker httpRequestTracker) {
        String urlString = httpRequestTracker.getURL().toString();
        try {
            URL url = new URL("http://socialnetworksite.com");
            if (urlString.contains("avatar")) {
                // Ignore calls for avatars
                return false;
            }
        } catch (MalformedURLException e) {
            return false;
        }
        return true;
    }
}
JAVA

ネットワーク要求のコールバックの登録

コールバックを実装した後、次に示すように初期化コードに登録します。Android エージェントがネットワーク要求ビーコンを作成する準備ができたら、最初に HttpRequestTracker オブジェクトを使用してコールバックを呼び出します。

Instrumentation.start(AgentConfiguration.builder()
        .withContext(getApplicationContext())
        .withAppKey("<EUM_APP_KEY>")
        .withNetworkRequestCallback(new myNetworkRequestCallback())
        .build());
JAVA

ロギングの有効化とロギングレベルの設定

ロギングを有効にし、ロギングレベルを設定するには、AgentConfiguration クラスのメソッド withLoggingLevel を使用します。ロギングは、次のいずれかのレベルに設定できます。

  • LOGGING_LEVEL_NONE
  • LOGGING_LEVEL_INFO
  • LOGGING_LEVEL_VERBOSE

冗長ロギングはトラブルシューティングにのみ使用し、実稼働では無効にしてください。

Example:

AgentConfiguration config = AgentConfiguration.builder()
config.withAppKey(appKey)
config.withContext(context)
 .withLoggingLevel(Instrumentation.LOGGING_LEVEL_VERBOSE)
        .build();
    Instrumentation.start(config);
JAVA

Android SDK のドキュメント

SDK API の完全なマニュアルについては、次に示す最新の Java ドキュメントまたは以前のバージョンを参照してください。

4.5.6 以降、Android エージェントは、コントローラと他の AppDynamics プラットフォーム コンポーネントとは異なるバージョン番号から始まります。すべての Android エージェント機能を完全にサポートするために必要なコントローラおよび EUM サーバの最小バージョンについては、『 Mobile Agent Version And Deployment Support Matrix 』を参照してください。