MPM 설정

안드로이드 MPM SDK 설정 방법을 한 눈에 확인하실 수 있습니다.

1. MPM 설치 옵션

Gradle File

gradle을 이용해 IMQA MPM 설치 모드를 변경할 수 있습니다.

app.gradle
ext {
    /**
     * @Default false
     * MPM 의 모든 Injecting 과정을 실행합니다. 
     * true 설정시 모든 실행과정이 무시됩니다.
     */
    IMQAStop = false

    /**
     * @Default true
     * Activity Lifecycle Injecting 을 허용합니다. 
     * false 설정시 액티비티 맵이 보이지 않습니다.
     */
    IMQALifecycle = true

    /**
     * @Default true
     * Event Listener Injecting 을 허용합니다.
     * false 설정시 이벤트 정보를 수집하지 않습니다.
     */
    IMQAEventListener = true

    /**
     * @Default false
     * WebView 관련 Injecting 을 허용합니다.
     * false 설정시 웹뷰내 HTTP/S 요청을 수집하지 않습니다.
     */
    IMQAWebview = false

    /**
     * @Default true
     * Fragment 수집 여부를 설정합니다.
     * false 설정시 Fragment 의 렌더링 속도를 수집하지 않습니다.
     */
    IMQAFragment = true

    /**
     * @Default true
     * Network 수집 메소드를 감쌉니다.
     * false 설정시 Network 관련 응답속도를 수집하지 않습니다.
     */
    IMQANetwork = true

    /**
     * @Default ""
     * 현재 빌드 환경의 Flavor 를 직접 설정합니다.
     * 미 설정시 플러그인이 자동으로 찾습니다.
     */
    IMQAFlavor = "debug";

    /**
     * @Default "/build/intermediates/manifests/full/"
     * 현재 빌드 환경의 Manifest 위치를 직접 설정합니다.
     * 미 설정시 플러그인이 자동으로 찾습니다.
     */
    IMQAManifestLocation = "/build/intermediates/manifests/full/"

    /**
     * @Default true
     * Repackaging 모드를 설정합니다.
     * false 설정시 Compile 중에 Inject 를 수행합니다.
     */
    IMQARepackaging = false

    /**
     * @Default true
     * Mapping File 생성시 자동으로 업로드 합니다.
     * 미 설정시 IMQA 에 접속하여 앱 버전별 mapping.txt 를 올려주어야 합니다.
     */
    IMQAMappingUpload = true

    /**
     * @Default ""
     * 현재 앱의 프로젝트 키를 설정합니다.
     * mapping.txt 파일을 바로 올리게 할경우 설정이 필요합니다.
     * 미 설정시 Build Log에 업로드 실패 메세지가 뜰 수 있습니다.
     */
    IMQAProjectKey = "";

    /**
     * @Default "http://main.mpm.imqa.io"
     * mapping.txt 파일을 업로드할 Host 명을 넣습니다.
     * mapping.txt 파일을 바로 올리게 할경우 설정이 필요합니다.
     * 미 설정시 Build Log에 업로드 실패 메세지가 뜰 수 있습니다.
     */
    IMQAMapUploadServer = "http://main.mpm.imqa.io"

}

File 빌드 설정 값 설명

MPM Run Option

IMQA MPM 모드를 파라미터나 Option을 이용해 변경할 수 있습니다.

MyApplication.java
@Override
public void onCreate() {
    super.onCreate();
    
    io.imqa.core.IMQAOption imqaOption = new io.imqa.core.IMQAOption();

    /*
     *  기본값 : false 
     *  IMQA의 데이터 수집 여부를 설정합니다.
     *  true : 데이터를 수집하지 않습니다.
     *  false : 데이터를 수집합니다.
    */
    imqaOption.setBuildType(false);

    /*
     * 기본값 : false
     * Log 출력 여부를 설정합니다. 
     * true : IMQA 의 Log가 출력됩니다.
    */
    imqaOption.setPrintLog(true);

    /*
     * 기본값 : 30000 (ms)
     * 덤프 간격을 ms(밀리초) 단위로 설정합니다.
    */
    imqaOption.setDumpInterval(30000);

    /*
     * 기본값 : 5 (분)
     * 덤프가 저장되는 파일 간격을 분단위로 설정합니다.
    */
    imqaOption.setFileInterval(5);

    /*
     * 기본값 : false
     * 파일 업로드를 주기적으로 보내는지 설정합니다. 
     * true : 앱이 실행되는 동안 FileInterval 간격에 맞춰 업로드를 합니다.
     * false : 앱 재실행시에만 수집데이터를 업로드 합니다.
    */
    imqaOption.setUploadPeriod(true);

    /*
     * Deprecated
     * 기본값 : true
     * Socket 관련 정보 수집기능을 설정합니다.
     * true : 앱이 실행되는 동안 Socket 을이용 네트워크 통신 정보를 수집하여 저장합니다.
     * false : IMQA Socket 수집 기능이 설정되지 않습니다.
    */
    imqaOption.setNetworkTracing(false);

    /*
     * 기본값 : true
     * Socket 관련 정보 수집기능을 설정합니다.
     * true : 앱이 실행되는 동안 Socket 을이용 네트워크 통신 정보를 수집하여 저장합니다.
     * false : IMQA Socket 수집 기능이 설정되지 않습니다.
    */
    imqaOption.setSocketTracing(false);

    /*
     * 기본값 : true
     * HTTP 관련 정보 수집기능을 설정합니다.
     * true : 앱이 실행되는 동안 HTTP 정보를 수집하여 저장합니다.
     * false : IMQA HTTP 수집 기능이 설정되지 않습니다.
    */
    imqaOption.setHttpTracing(false);

    /*
     * 기본값 : true
     * 측정된 성능 파일을 성공할 때까지 남겨두는지 설정합니다.
     * true : 업로드에 성공할 때까지 파일을 내부에 보관합니다.
     * false : 업로드에 실패하더라도 파일을 삭제합니다.
    */
    imqaOption.setKeepFileAtUploadFail(false);

    /*
     * 기본값 : false
     * 업로드 서버의 인증서(SSL)를 무시하고 HTTPS 통신을 합니다.
     * true : 인증서를 무시하고 HTTPS 통신을 실행합니다.
     * false : 인증서를 확인하고 HTTPS 통신을 실행합니다.
     */
    imqaOption.setForceHttps(true);

    /*
     * 기본값 : null
     * 종료 날짜를 설정합니다.
     * Date : 종료 날짜
     */
    imqaOption.setEndDate(Date);

    /*
     * 기본값 : false
     * 옵션 설정을 서버로부터 받아옵니다. setServerUrl 로 설정한 수집 서버에 요청합니다.
     * 최우선 옵션으로 설정되며, 미 응답시 코드상으로 설정한 옵션으로 동작합니다.
     * true : 서버로 부터 옵션을 받아옵니다.
     * false : 코드상으로 설정한 옵션으로 동작합니다.
     */
    imqaOption.setRemoteConfig(true);

    /*
     * 기본값 : 3000
     * 원격 서버 옵션을 받아올때 타임아웃을 지정합니다.
     * 타임아웃 발생 시 코드상으로 설정한 옵션으로 동작합니다.
     * int : timeout (ms)
     */
    imqaOption.setRemoteTimeout(3000);

    /*
     * 기본값 : ArrayList<Integer>
     * 동작할 OS 버전을 설정합니다.
     * int : 동작 OS 버전
     */
    imqaOption.addOSVersionLimitList(Build.VERSION_CODES.O);

    /*
     * 기본값 : OSProhibit
     * 해당 버전 이하에서 SDK를 동작시키지 않습니다.
     * int : 동작 OS 버전
     */
    imqaOption.getOSProhibitVersionLimitList().addOSProhibitVersionLimitBelow(Build.VERSION_CODES.M);

    /*
     * 기본값 : ArrayList<String>
     * 동작할 앱 버전을 설정합니다.
     * String : 동작 앱 버전
     */
    imqaOption.addAppVersionLimitList("1.1");


    /*
     * 기본값 : null
     * 수집 제외할 url 을 지정합니다.
     * 기본으로 host 와 pathname 을 따르며 옵션으로 query 값 매칭을 추가할 수 있습니다.
     * String : 대상 url
     * boolean : query matching 여부 (ex: https://abc.com/search?foo=bar 의 ? 뒤 부분)
     */
    imqaOption.getURLBlacklist().addBlacklistURL("https://abc.com/search", false);

    /*
     * 기본값 : ArrayList<AccessPoint>
     * 동작할 앱 버전을 설정합니다.
     * AccessPoint 객체 하나당 한개의 ap 이며, 3개의 고유 값중 설정하지 않은 값은 true 로 판단합니다.
     * SSID, BSSID 는 위치 권한이 필요하므로 이를 사용할 경우
     * 'ACCESS_FINE_LOCATION' 또는 'ACCESS_COARSE_LOCATION' 를 추가해 주어야 합니다.
     * AccessPoint : 동작 SSID, BSSID, IP
     */
    io.imqa.core.network.AccessPoint ap = new io.imqa.core.network.AccessPoint();
    ap.setSsid("IMQA");
    ap.setBssid("cc:40:d0:f7:a5:d7");
    ap.setIpAddress("192.168.0.1");
    imqaOption.addWifiLimitList(ap);

    /*
     * 기본값 : 10
     * 덤프 데이터 최대 용량을 설정합니다.
     * int : 최대 용량 (단위 MB)
     */
    imqaOption.setDumpSizeMax(10);

    /*
     * 기본값 : 15
     * 행동분석 데이터 최대 갯수를 설정합니다.
     * int : 최대 갯수
     */
    imqaOption.setBehaviorLengthMax(15);

    /*
     * 기본값 : 'IMQA-ADDITIONAL-KEY'
     * HTTP 통신시 추가 헤더 정보를 입력합니다.
     * String : 추가헤더 키 이름
     */
    imqaOption.setAdditionalHeader(true, "MY-HEADER");
    // 또는
    imqaOption.setAdditionalHeader(true);
    imqaOption.setAdditionalHeaderKey("MY-HEADER");
    
    io.imqa.mpm.IMQAMpmAgent.getInstance()
        .setOption(imqaOption) // MPM 의 동작 방식을 정하는 옵션을 설정합니다.
        .setContext(this, BuildConfig.FLAVOR) // Application Context 를 초기화합니다.
        .setProjectKey("PROJECT_KEY") // IMQA MPM Client 의 Project Key 를 설정합니다.
        .init() // 등록한 옵션을 초기화합니다.

File 런타임 설정 값 설명

MPM 독립 실행

특정 Task에서 IMQA MPM Injector를 실행할 수 있습니다. 단, 위 방법을 사용하는 경우 실행 위치에 따라 정상적으로 코드 삽입이 이루어지지 않을 수 있습니다.

app.gradle
// apply plugin: 'io.imqa' // 독립 실행시에는 비활성화 시켜야 함

// 자동 삽입 기능이 해제되어 직접 삽입이 필요.
dependencies {
       implementation 'io.imqa:imqa-core:2.29.13'
       implementation 'io.imqa:imqa-mpm-client:2.29.13'
       implementation 'io.imqa:imqa-crash-client:2.29.13'
 }

// Plugin 객체라 생성자로 생성 (내부적으로 Static 사용)
io.imqa.IMQAPlugin imqaPlugin = new io.imqa.IMQAPlugin()
// IMQA 기본 옵션(IMQAOption, BuildOption, imqa-service.json)을 설정함
imqaPlugin.init(project)

// Action 객체라 생성자로 생성 (내부적으로 Static 사용)
// app.gradle 내 IMQA 옵션 반영함, 개발 환경의 기본정보들(빌드 툴, Variants 등)을 반영함, IMQA Dependency 를 자동 삽입함
new io.imqa.injector.GJavacAction(project.name).setConfiguration(project)

android.applicationVariants.all { variant ->
    // 설정시에 반드시, doLast 람다에 변수명을 줘서 넣어야 함
    // 변수명을 주지 않는 경우, gradle 내장 변수인 task를 불러와서 에러가 발생 함.
    variant.javaCompile.doLast { task ->
        // 위 설정들을 토대로 현재 위치에서 CompileAction 을 수행

        // 프로젝트에 코틀린이 존재하는 경우, 아래 코드 추가.
        new io.imqa.injector.CompileAction(
                io.imqa.injector.util.BuildOption.BUILD_LOCATION_TYPE.kotlin,
                project.name,
                io.imqa.injector.GJavacAction.convertBuildType(variant.getBuildType()),
                io.imqa.injector.GJavacAction.makeFlavor(variant.getBuildType().name,   variant)
            )
            .execute(task)

        // Gradle 3.2 ~ 3.4, 4.0, 4.1 :  io.imqa.injector.util.BuildOption.BUILD_LOCATION_TYPE.javacCompileClasses

       // Gradle 3.5 이상  io.imqa.injector.util.BuildOption.BUILD_LOCATION_TYPE.javacClasses

       // 나머지 버전 : io.imqa.injector.util.BuildOption.BUILD_LOCATION_TYPE.classes

        new io.imqa.injector.CompileAction(
                io.imqa.injector.util.BuildOption.BUILD_LOCATION_TYPE.javacCompileClasses,
                project.name,
                io.imqa.injector.GJavacAction.convertBuildType(variant.getBuildType()),
                io.imqa.injector.GJavacAction.makeFlavor(variant.getBuildType().name,   variant)
            )
            .execute(task)
    }
}

네트워크 수집 설정

IMQA MPM 프레임워크에서는 네트워크 수집에 대해서 자동으로 측정 하나 특정 라이브러리의 경우 수동으로 설정을 진행해주어야 합니다.

AsyncHttpClient 대응

AsyncHttpClient 라이브러리를 사용하여 네트워크 요청시 다음과 같이 추가해 주십시오.

MainActivity.java
...
AsyncHttpClient client = new AsyncHttpClient();
...
HttpData httpData = new HttpData();
client.get(this, url, new AsyncHttpResponseHandler() {
    @Override
    public void onStart() {
       // 네트워크 요청 정보 입력 
        URI uri = this.getRequestURI();
        httpData.setHostName(uri.getHost());
        httpData.setMethod("get"); // get | post 
        httpData.setProtocol(uri.getScheme());
        httpData.setPathName(uri.getPath());
    }
    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
          // 네트워크 응답 코드 입력 ( 성공 시 ) 
           httpData.setStatus(statusCode + "");
    }
    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
          // 네트워크 응답 코드 입력 ( 실패 시 ) 
        httpData.setStatus(statusCode + "");
    }
    @Override
    public void onFinish() {
        // 네트워크 수집 진행 ( 요청 완료 시 ) 
        httpData.setEndTime(System.currentTimeMillis());
        HttpCollector.collect(httpData);
    }
});

...

Custom User ID 등록

성능 데이터 수집 시 특정 사용자를 식별하기 위한 ID 정보를 설정할 수 있습니다. 사용자 ID 정보를 설정한 후, MPM 행동분석 에서 사용자 ID 정보로 행동 흐름을 조회할 수 있습니다.

Custom User ID 등록시, 사용자 식별을 위해 사용자 로그인 후의 화면, 홈 화면 또는 스플래시 화면에 추가해 주세요.

SDK 옵션 상, MethodName은 사용자ID, 사용자 이름, 사용자 이메일로 작성되었으나 사용 예시이며, 실제 개인을 특정할 수 있는 직접 식별 정보 (특정 이름, 주민등록번호, 이메일 주소, 기타 유사 데이터) 보다는 2차 가공한 임의의 식별 정보를 사용하시기를 권고 드립니다. 예를 들어, 2차 가공한 식별자 (예: 2013133, A39233 등), 등급 정보 (예: VIP, Gold, Member), 유입 경로 (예: Google, N, K) 등으로 사용자의 유형 분류에 따른 분석이 가능합니다.

IdentifierCollector.setCustomUserId("A100032"); // 사용자 ID-1 (Primary)
IdentifierCollector.setCustomUserName("VIP"); // 사용자 ID-2
IdentifierCollector.setCustomUserMail("G****"); // 사용자 ID-3

SDK에서 사전 정의한 사용자의 ID 정보가 수집되었을 경우, MPM 행동분석 및 Crash 사용자별 에러 목록에서 사용자 ID 정보로 데이터 조회가 가능합니다.

Custom Screen 측정

IMQA에서 연속 선상의 네이티브 화면을 묶어 하나의 가상 화면 단위를 정의하고, 해당 단위의 성능을 분석할 수 있습니다. 가상 화면으로 정의할 시작 네이티브 화면에서 startScreen, 종료 네이티브 화면에서 endScreen 정의하여 손쉽게 가상 화면 단위 생성 및 추적이 가능합니다. 가상 화면명은 동일한 텍스트로 정의해 주세요.

가상 화면 측정은 IMQA가 초기화 완료된 이후부터 시작합니다.

Custom Screen 측정을 통해 연속 선상의 네이티브 화면을 구간으로 측정 가능합니다. 예를 들어, 'SplashActivity 시작 ~ MainActivity 완료 ' 까지를 'AppLaunchSequence'라는 새로운 네이티브 화면으로 정의하고, 성능을 분석할 수 있습니다.

가상 화면 측정 시, 연속 선상이 아닌 네이티브 화면을 구간으로 정의하는 경우, 정확한 단위 성능이 측정되지 않을 수 있습니다.

가상 화면 측정 시작

CustomScreenName 에 설정하고자 하는 화면명을 입력합니다.

###Activity.java
...
IMQAMpmAgent imqaAgent = IMQAMpmAgent.getInstance();

imqaAgent.setInitListener(new IMQAMpmAgent.IMQAInitListener() {
	@Override
	public void onInitComplete(boolean success) { //초기화 완료 시점
		imqaAgent.startScreen("CustomScreenName"); // 가상 화면명 정의 
	}
});
...
###Activity.kt
...
 val imqaAgent = IMQAMpmAgent.getInstance()
   imqaAgent.setInitListener { success ->
     if (success) {	// 초기화 완료 시점 
     	imqaAgent.startScreen("CustomScreenName") // 가상 화면명 정의 
     }
   }
...

가상 화면 측정 종료

측정을 끝내고자 하는 액티비티에서 함수를 종료합니다. 종료 시점은 onResume 로 고정합니다. startScreen 함수에서 입력한 화면명과 동일하게 입력합니다.

###Activity.java
...
IMQAMpmAgent.getInstance().endScreen("CustomScreenName"); // startScreen과 동일한 가상 화면명
...
###Activity.kt
...
IMQAMpmAgent.getInstance().endScreen("CustomScreenName") // startScreen과 동일한 가상 화면명
...

SDK에서 사전 정의한 Custom Screen이 수집되었을 경우, IMQA에서 새로운 네이티브 화면 단위로 성능 분석이 가능합니다.

2. ProGuard 설정

ProGuard 설정

ProGuard는 사용하지 않는 리소스를 제거하고 클래스나 메소드 이름을 짧게 축소하여 APK를 최대한 작게 만드는데 사용하는 도구입니다. ProGuard 또는 DexGuard를 사용하는 경우에는 아래 내용을 참고하여 매핑 파일을 업로드하여 원본 클래스, 메소드 이름으로 충돌 보고서에 표시 할 수 있습니다.

사전 준비

개발 중인 프로젝트에서 Proguard를 사용할 경우, 소스코드가 난독화 되어 해석이 어려워집니다. 이때, 생성되는 mapping.txt 파일을 이용하여 난독화된 코드를 해석할 수 있게 됩니다.

Proguard 규칙(proguard-rules.pro)에 다음의 내용을 추가해주세요.

proguard-rules.pro
 -keepattributes SourceFile,LineNumberTable
 -printmapping map.txt

 # IMQA Proguard
 -keep class io.imqa.** { *; }
 -dontwarn io.imqa.**

 # okhttp3 Proguard
 -dontwarn okhttp3.**
 -dontwarn okio.**oj

app/build/outputs/mapping/debug(또는 release)/mapping.txt 위치에 파일이 생성됩니다. (buildType 과 flavor 에 따라서 파일 위치가 조금 상이할 수 있습니다.) 이렇게 생성된 파일을 업로드해야 합니다.

안드로이드의 경우 ‘mapping.txt’, ‘map.txt’ 와 같은 ‘txt’ 파일을 업로드합니다.

업로드 과정

1. 프로젝트 메뉴에서 프로가드 설정으로 들어갑니다.

2. [파일 선택] 버튼을 눌러 업로드 창을 열어 줍니다.

3. gradle 에 명시된 App version 에 맞는 매핑 파일을 업로드 합니다.

4. [등록] 버튼을 누르면 해당 버전에서 발생한 크래시 정보가 해석되어 보이게 됩니다.

최신 앱 버전이 릴리즈 된 경우, 해당 버전에서 발생한 크래시 정보를 보기 위해서는 동일한 앱 버전의 매핑 파일을 추가 등록해 주세요.

3. MPM Webview Guide

MPM 단독 사용 (WebviewAgent 설치)

MPM 서비스만을 이용하며, 모바일 애플리케이션 구성에서의 웹뷰 성능 분석을 위한 webviewAgent 설치 방법입니다.

MPM / WPM 통합 사용시 Agent 설치 방법은 ‘IMQA WPM/WCrash 설치 가이드 > 1.2. WPM / MPM 통합 사용 (WebAgent + WebviewAgent 설치)'를 참고하세요.

웹뷰 데이터 수집을 원한다면 웹뷰를 제공하는 웹 페이지에 IMQA Webview Javascript 라이브러리를 삽입해 주어야 합니다. 원하는 경우 파일을 다운받아 웹 서버에서 직접 제공할 수 있습니다. (크로스 오리진 문제 발생시 직접 import 해서 쓰시는걸 권장드립니다.)

IMQA WebviewAgent는 2가지 방식으로 설치 방법을 제공하고 있습니다. CDN 서버로 연결하거나, 설치형 혹은 CDN으로 요청을 못하시는 경우 해당 스크립트를 다운로드 받아서 사용 가능합니다. 아래의 링크를 통해서 마우스 오른쪽 버튼을 누른 후 “다른 이름으로 저장”을 눌러서 연결해 주세요.

WebviewAgent : https://cdn.imqa.io/agent/webview-agent.js

CDN 서버에서 받아오기

IMQA WebviewAgent는 스크립트를 html의 <head> 내부 최상단에 삽입해 주셔야 합니다.

webview-agent.js 연결 할 html <head>
// IMQA webview-agent.js 연결
<script src="https://cdn.imqa.io/agent/webview-agent.js"></script>

// IMQA webview-agent 스크립트 필수 값
<script>
    ((w, c, _wv, _w, _wk, _mh, _b) => {
       w[c] = w[c] || {};                      
       w[_wv](w); // 웹뷰 에이전트 실행함수
    })(window, 'imqaClientConfig', 'IMQAWebviewMain', 'IMQAWebMain', 'webkit', 'messageHandlers', 'ImqaBridge')
</script>

로컬에 설치하기

설치형 혹은 CDN으로 요청을 못하시는 경우 해당 스크립트를 다운로드 받아서 사용 가능합니다. 이 링크를 통해서 마우스 오른쪽 버튼을 누른 후 “다른 이름으로 저장”을 눌러서 연결해 주세요.

webview-agent.js 연결 할 html <head>
// 로컬에 받은 IMQA webview-agent.js 연결
<script src="사용자 경로/webview-agent.js"></script>

// IMQA webview-agent 스크립트 필수 값
<script>
    ((w, c, _wv, _w, _wk, _mh, _b) => {   
       w[c] = w[c] || {};                    
       w[_wv](w); // 웹뷰 에이전트 실행함수
    })(window, 'imqaClientConfig', 'IMQAWebviewMain', 'IMQAWebMain', 'webkit', 'messageHandlers', 'ImqaBridge')
</script>

Android Agent 설정

MPM은 WebView 에 관련된 페이지 및 요청을 수집합니다. WebviewInterface 와 WebViewBridge 를 추가해 주어야 WebView에서 발생한 에러 정보를 수집할 수 있습니다.

  • Webview Crash 수집을 위해서는 WebViewErrorBridge 를 추가해 주어야 합니다.

  • Custom Web Crash 수집을 위해서는 CustomWebViewErrorBridge 를 추가해 주어야 합니다.

MyWebViewActivity.java
...
public void onCreate() {
    WebView webView = (WebView) findViewById(R.id.webview);
    webView.getSettings().setJavaScriptEnabled(true); // Javascript Enable

    // WebView Interface 삽입 (ImqaBridge 필수)
    io.imqa.mpm.network.webview.WebviewInterface imqaJavascript = 
        new io.imqa.mpm.network.webview.WebviewInterface();

    // 추가 설정 코드 (Webview Agent (1.1.2버전 이상) WebView Crash, Custom Crash 수집)
    imqaJavascript.setWebViewErrorBridge(new WebViewErrorBridge());
    imqaJavascript.setCustomWebViewErrorBridge(new CustomWebViewErrorBridge()); 
    webView.addJavascriptInterface(imqaJavascript, "ImqaBridge");
    ...
    }
...
MyWebViewActivity.kt
...
override fun onCreate() {
    // IMQA 설정 부분
    val webview:WebView = findViewById(R.id.webview_sample)
    webview.settings.javaScriptEnabled = true // Javascript Enable

    // WebView Interface 삽입 (ImqaBridge 필수)
    val imqaJavascriptInterface = WebviewInterface()

    // 추가 설정 코드 (Webview Agent (1.1.2버전 이상) WebView Crash, Custom Crash 수집)
    imqaJavascriptInterface.setWebViewErrorBridge(WebViewErrorBridge())
    imqaJavascriptInterface.setCustomWebViewErrorBridge(CustomWebViewErrorBridge())
    webview.addJavascriptInterface(imqaJavascriptInterface,"ImqaBridge")	
    ...
    }
...   

Android WebView 화면 모드 전환 대응

웹뷰가 호출한 웹 페이지에서 가로, 세로 화면 모드 전환이 있는 경우, 화면 모드 전환에 대한 상태 수집이 필요합니다. MPM 행동분석 표시 및 웹뷰 화면 단위 성능 수집시, 정확한 화면 구분을 위해 화면 모드 전환 상태를 웹뷰에 전달합니다.

모바일 애플리케이션 구조 상 웹뷰가 있고, 가로, 세로 화면 모드 전환이 있을 수 있는 경우 적용이 필요하며, 웹뷰가 없거나 세로 모드 고정으로 배포된 앱의 경우 적용하지 않으셔도 됩니다.

MyWebViewActivity.java
private WebviewInterface imqaJavascript;
...
public void onCreate() {
    WebView webView = (WebView) findViewById(R.id.webview);
    webView.getSettings().setJavaScriptEnabled(true); // Javascript Enable

    // WebView Interface 삽입 (ImqaBridge 필수)
   WebviewInterface imqaJavascript = new WebviewInterface();

    // 추가 설정 코드 (Webview Agent (1.1.2버전 이상) WebView Crash, Custom Crash 수집)
    imqaJavascriptInterface.setWebViewErrorBridge(WebViewErrorBridge())
    imqaJavascriptInterface.setCustomWebViewErrorBridge(CustomWebViewErrorBridge())
    webView.addJavascriptInterface(imqaJavascript, "ImqaBridge");
    ...
    }
...

//화면 회전 상태 웹뷰에 전달. 세로고정인 경우 불필요
public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (imqaJavascript != null) {
            imqaJavascript.onOrientationChange(newConfig.orientation);
        }
    }
MyWebViewActivity.kt
private lateinit var imqaJavascript: WebviewInterface
...
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
  
    val webView: WebView = findViewById(R.id.webview)
    webView.settings.javaScriptEnabled = true // JavaScript 활성화

    // WebView Interface 삽입 (ImqaBridge 필수)
    imqaJavascript = WebviewInterface()

    // 추가 설정 코드 (Webview Agent (1.1.2버전 이상) WebView Crash, Custom Crash 수집)
    imqaJavascriptInterface.setWebViewErrorBridge(WebViewErrorBridge())
    imqaJavascriptInterface.setCustomWebViewErrorBridge(CustomWebViewErrorBridge())
    webView.addJavascriptInterface(imqaJavascript, "ImqaBridge")
    
    // 다른 추가 설정이 있을 경우 여기에 추가
}
...

//화면 회전 상태 웹뷰에 전달. 세로고정인 경우 불필요
override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    imqaJavascript.onOrientationChange(newConfig.orientation)
}

SPA 전용 옵션

SPA에서는 하나의 index.html을 기준으로 수집되기에 page 변경에 대한 이벤트가 없습니다. SPA 전용 옵션을 설정하여 path가 변경되었을 때 기준으로 일정 시간까지를 수집하실 수 있습니다. SPA에서는 path 변경 시 특정 DOM이 교체되므로, 이 특정 DOM을 Agent 옵션에 타겟으로 설정하면 정상적으로 SPA에서도 페이지 로딩시간을 수집할 수 있습니다.

필수 설정과 SPA 전용 옵션을 적용한 스크립트는 아래와 같습니다.

webview-agent.js 연결 할 html <head>
// IMQA webview-agent.js 연결
<script src="https://cdn.imqa.io/agent/webview-agent.js"></script>

// IMQA webview-agent 스크립트 필수 값
<script>
    ((w, c, _wv, _w, _wk, _mh, _b) => {
        w[c] = w[c] || {};
    function imqaConf(key, value){w[c][key]=value};

    // SPA 전용 옵션 설정
    imqaConf("SPACollectInitTime", 5000); // SPA 수집시간설정
    imqaConf("SPARootDom", "#container"); // SPA ROOT DOM            
                                                    
       w[_wv](w); // 웹뷰 에이전트 실행함수
    })(window, 'imqaClientConfig', 'IMQAWebviewMain', 'IMQAWebMain', 'webkit', 'messageHandlers', 'ImqaBridge')
</script>

WebviewAgent Console.log 표시 옵션

IMQA WebviewAgent의 콘솔 로그를 표시하거나 끌 수 있습니다.

필수 설정과 console.log 표시 옵션을 적용한 스크립트는 아래와 같습니다.

webview-agent.js 연결 할 html <head>
// IMQA webview-agent.js 연결
<script src="https://cdn.imqa.io/agent/webview-agent.js"></script>

// IMQA webview-agent 스크립트 필수 값
<script>
    ((w, c, _wv, _w, _wk, _mh, _b) => {
        w[c] = w[c] || {};
    function imqaConf(key, value){w[c][key]=value};

    // console.log 표시 옵션 설정
    imqaConf("imqa_log", false); // IMQA Agent 콘솔 로그 끔
                                                          
       w[_wv](w); // 웹뷰 에이전트 실행함수
    })(window, 'imqaClientConfig', 'IMQAWebviewMain', 'IMQAWebMain', 'webkit', 'messageHandlers', 'ImqaBridge')
</script>

그 외 WebviewAgent Custom Web Crash 발생, 특정 웹 크래시 수집 제한 옵션을 설정할 수 있습니다. 'Android > Crash 설정 > Custom Web Crash 발생' 및 'Android > Crash 설정 > 특정 웹 크래시 수집 제한 옵션'을 참고하세요.

5. MPM HTTPS Guide

HttpsURLConnection 대응

IMQA Client는 HttpsURLConnection 기반의 네트워크 요청을 수집할 수 있습니다. HttpsURLConnection 기반의 네트워크 요청 시 다음과 같이 추가해 주세요.

HttpsURLConnection

MainActivity.java
...
// HttpsURLConnection 객체를 ConnectionWrapper 로 감쌈
URL url = new URL("https://some.host.com");
HttpsURLConnection conn = (HttpsURLConnection) ConnectionWrapper.wrap((HttpsURLConnection) url.openConnection());
...
MainActivity.kt
...
// HttpsURLConnection 객체를 ConnectionWrapper 로 감쌈
var url : URL = URL("https://some.host.com")
var conn : HttpsURLConnection = 
    ConnectionWrapper.wrap(
        url.openConnection() as HttpsURLConnection
    ) as HttpsURLConnection
...

OkHttp 대응

IMQA Client는 OkHttp 기반의 네트워크 요청을 수집할 수 있습니다. OkHttp 기반의 네트워크 요청 시 다음과 같이 추가해 주세요.

OkHttp Client

1. OkHttp3

MainActivity.java
...
// OkHttpClient 에 MPMInterceptor 를 추가
OkHttpClient client = new OkHttpClient.Builder()
    .addNetworkInterceptor(new MPMInterceptor())
    .build();
...

// Interceptor 가 추가된 OkHttpClient 실행
Response response = client.newCall(request).execute();
...
MainActivity.kt
...
// OkHttpClient 에 MPMInterceptor 를 추가
val builder : OkHttpClient.Builder = OkHttpClient.Builder()
val client : OkHttpClient = IMQAManager.wrapOkhttp(builder)
    .addNetworkInterceptor(MPMInterceptor())
    .build();
...

// Interceptor 가 추가된 OkHttpClient 실행
val response : Response = client.newCall(request).execute()
...

2. Retrofit 2.0

MainActivity.java
...
// OkHttpClient 에 MPMInterceptor 를 추가
OkHttpClient client = new OkHttpClient.Builder()
    .addNetworkInterceptor(new MPMInterceptor())
    .build();
...

new Retrofit.Builder()
    .baseUrl(host)
    .client(client) // Interceptor 가 추가된 OkHttpClient 사용
    .build();
...
MainActivity.kt
...
// OkHttpClient 에 MPMInterceptor 를 추가
val builder : OkHttpClient.Builder = OkHttpClient.Builder()
val client : OkHttpClient = IMQAManager.wrapOkhttp(builder)
    .addNetworkInterceptor(MPMInterceptor())
    .build();
...

val retrofit = Retrofit.Builder()
    .baseUrl(host)
    .client(client) // Interceptor 가 추가된 OkHttpClient 사용
    .build()
...

이미지 로딩 라이브러리 대응

1. Picasso

picasso 의 경우 okhttp 사용시 기본 downloader로 okhttp를 선택하게 됩니다. 이 downloader에 언터셉터를 추가하기 위해 아래와 같이 추가해 줍니다. 먼저 OkHttp3Downloader 의존성을 추가합니다.

compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
MainActivity.java
// Picasso의 Singleton instance 를 초기화 하기전에 미리 MPMInterceptor가 추가된 다운로더를 넣어주어야 합니다.
Picasso.setSingletonInstance(
    new Picasso.Builder(this)
            .downloader(new OkHttp3Downloader(
                    new OkHttpClient.Builder()
                            .addInterceptor(new MPMInterceptor())
                            .build()
            )).build());

2. Glide

Glide의 경우 HttpUrlConnection을 기본 http 라이브러리로 사용합니다. okhttp 사용을 원할 경우 OkHttpClient를 registry에 설정해 줍니다.

compile "com.github.bumptech.glide:okhttp3-integration:4.8.0"
MainActivity.java
@GlideModule
public class MyAppGlideModule extends AppGlideModule {

    @Override
    public void registerComponents(Context context, Glide glide, Registry registry) {
        super.registerComponents(context, glide, registry);
        OkHttpClient client = new OkHttpClient.Builder()
                .addNetworkInterceptor(new MPMInterceptor())
                .build();
        registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(client));
    }
    ...
}

HttpClient 대응

IMQA Client는 HttpClient 기반의 네트워크 요청을 수집할 수 있습니다. HttpClient 기반의 네트워크 요청 시 다음과 같이 추가해 주세요.

HttpClient

1. HttpClient (org.apache.http.legacy)

MainActivity.java
...
// DefaultHttpClient 에 HttpClientInterceptor 를 추가
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpClientInterceptor.setIMQAInterceptor(httpClient);
...
MainActivity.kt
...
// DefaultHttpClient 에 HttpClientInterceptor 를 추가
val httpClient : DefaultHttpClient = DefaultHttpClient()
HttpClientInterceptor.setIMQAInterceptor(httpClient)
...

2. HttpClient (cz.msebera.android.httpclient)

MainActivity.java
...
// DefaultHttpClient 에 OldHttpClientInterceptor 를 추가
DefaultHttpClient httpClient = new DefaultHttpClient();
OldHttpClientInterceptor.setIMQAInterceptor(httpClient);
...
MainActivity.kt
...
// DefaultHttpClient 에 HttpClientInterceptor 를 추가
val httpClient : DefaultHttpClient = DefaultHttpClient()
OldHttpClientInterceptor.setIMQAInterceptor(httpClient)
...

Volley 대응

IMQA Client는 Volley 기반의 네트워크 요청을 수집할 수 있습니다. Volley 기반의 네트워크 요청 시 다음과 같이 추가해 주세요.

Volley

1. Volley (com.android.volley)

MainActivity.java
...


StringRequest request = new StringRequest(
   ....
)

// RequestQueue 에 IMQAHurlStack 을 추가
RequestQueue requestQueue = Volley.newRequestQueue(this, new IMQAHurlStack());
requestQueue.add(request);
...

현재 버전에서의 이슈 사항

Interceptor 기능을 수동으로 삽입해 주어야 합니다. (현재 HTTPUrlConnection, Okhttp, Retrofit, HttpClient(org.apache, cz.msebera) 자동 설치를 지원하고 있습니다.)

Last updated