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://mpm.imqa.io" * mapping.txt 파일을 업로드할 Host 명을 넣습니다. * mapping.txt 파일을 바로 올리게 할경우 설정이 필요합니다. * 미 설정시 Build Log에 업로드 실패 메세지가 뜰 수 있습니다. */ IMQAMapUploadServer ="http://mpm.imqa.io"}
MPM Run Option
IMQA MPM 모드를 파라미터나 Option을 이용해 변경할 수 있습니다.
MyApplication.java
@OverridepublicvoidonCreate() { 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);/* * 기본값 : 5000 (ms) * 덤프 간격을 ms(밀리초) 단위로 설정합니다. */imqaOption.setDumpInterval(3000);/* * 기본값 : 5 (분) * 덤프가 저장되는 파일 간격을 분단위로 설정합니다. */imqaOption.setFileInterval(1);/* * 기본값 : 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() // 등록한 옵션을 초기화합니다.
MPM 독립 실행
특정 Task에서 IMQA MPM Injector를 실행할 수 있습니다. 단, 위 방법을 사용하는 경우 실행 위치에 따라 정상적으로 코드 삽입이 이루어지지 않을 수 있습니다.
app.gradle
// apply plugin: 'io.imqa' // 독립 실행시에는 비활성화 시켜야 함
// 자동 삽입 기능이 해제되어 직접 삽입이 필요.
dependencies {
implementation 'io.imqa:imqa-core:2.27.5'
implementation 'io.imqa:imqa-mpm-client:2.27.9'
implementation 'io.imqa:imqa-crash-client:2.27.5'
}
// 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 =newAsyncHttpClient();...HttpData httpData =newHttpData();client.get(this, url,newAsyncHttpResponseHandler() { @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); }});...
2. ProGuard 설정
ProGuard 설정
ProGuard는 사용하지 않는 리소스를 제거하고 클래스나 메소드 이름을 짧게 축소하여 APK를 최대한 작게 만드는데 사용하는 도구입니다. ProGuard 또는 DexGuard를 사용하는 경우에는 아래 내용을 참고하여 매핑 파일을 업로드하여 원본 클래스, 메소드 이름으로 충돌 보고서에 표시 할 수 있습니다.
사전 준비
개발 중인 프로젝트에서 Proguard를 사용할 경우, 소스코드가 난독화 되어 해석이 어려워집니다. 이때, 생성되는 mapping.txt 파일을 이용하여 난독화된 코드를 해석할 수 있게 됩니다.
app/build/outputs/mapping/debug(또는 release)/mapping.txt 위치에 파일이 생성됩니다.
(buildType 과 flavor 에 따라서 파일 위치가 조금 상이할 수 있습니다.)
이렇게 생성된 파일을 http://crash.imqa.io로 접속하여 업로드해야 합니다.
안드로이드의 경우 ‘mapping.txt’, ‘map.txt’ 와 같은 ‘txt’ 파일을 업로드합니다.
업로드 과정
1. 프로젝트 메뉴에서 프로가드 설정으로 들어갑니다.
2. [파일 선택] 버튼을 눌러 업로드 창을 열어 줍니다.
3. gradle 에 명시된 App version 에 맞는 매핑 파일을 업로드 합니다.
4. [등록] 버튼을 누르면 해당 버전에서 발생한 크래시 정보가 해석되어 보이게 됩니다.
최신 앱 버전이 릴리즈 된 경우, 해당 버전에서 발생한 크래시 정보를 보기 위해서는 동일한 앱 버전의 매핑 파일을 추가 등록해 주세요.
3. MPM Webview Guide
WebView HTTP 요청
Web Server 설정
웹뷰 데이터 수집을 원한다면 웹뷰를 제공하는 웹 페이지에 IMQA Webview Javascript 라이브러리를 삽입해 주어야 합니다. 원하는 경우 파일을 다운받아 웹 서버에서 직접 제공할 수 있습니다.
(크로스 오리진 문제 발생시 직접 import 해서 쓰시는걸 권장드립니다.)
<!-- IMQA Webview Agent (1.1.5버전 이상. 항상 최신 버전으로 업데이트) 입니다. --><scripttype="text/javascript"src="https://cdn.imqa.io/agent/webview-agent.js"crossorigin></script><script> ((w, c, _wv, _w, _wk, _mh, _b) => { w[_wv](w); // 웹뷰 에이전트 실행함수 })(window,'imqaClientConfig','IMQAWebviewMain','IMQAWebMain','webkit','messageHandlers','ImqaBridge')</script>
<!-- IMQA Webview Agent(1.1.3버전 이하) 입니다. --><scripttype="text/javascript"src="https://imqawebviewagent.blob.core.windows.net/agent/webview-agent-1.1.2.js"crossorigin></script><!-- min 파일로 적용할 경우 --><scripttype="text/javascript"src="https://imqawebviewagent.blob.core.windows.net/agent/webview-agent-1.1.2.min.js"crossorigin></script>
Android Agent 설정
MPM은 WebView에 관련된 페이지 및 요청을 수집합니다. 수집을 하기위해서는 WebviewInterface 를 추가해 주어야 합니다. 또한 WebView에서 발생한 에러 정보를 수집할 수 있습니다. Webview Crash 수집을 위해서는 CrashWebviewBridge 를 추가해 주어야 합니다.
MyWebViewActivity.java
...publicvoidonCreate() {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 수집)imqaJavascript.setSendErrorBridge(new io.imqa.crash.webview.CrashWebviewBridge(this));webView.addJavascriptInterface(imqaJavascript,"ImqaBridge");... }...
MyWebViewActivity.kt
...public void onCreate() {// IMQA 설정 부분val webview:WebView=findViewById(R.id.webview_sample) webview.settings.javaScriptEnabled =true; // Javascript Enable// WebView Interface 삽입 (ImqaBridge 필수) val imqaJavascriptInterface:io.imqa.mpm.network.webview.WebviewInterface = io.imqa.mpm.network.webview.WebviewInterface();
// 추가 설정 코드 (Webview Agent (1.1.2버전 이상) WebView Crash 수집) imqaJavascriptInterface.setSendErrorBridge(CrashWebviewBridge(this)) webview.addJavascriptInterface(imqaJavascriptInterface,"ImqaBridge") ... }...
4. MPM HTTPS Guide
HttpsURLConnection 대응
IMQA Client는 HttpsURLConnection 기반의 네트워크 요청을 수집할 수 있습니다. HttpsURLConnection 기반의 네트워크 요청시 다음과 같이 추가해 주세요.
...// 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(newMPMInterceptor()).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(newMPMInterceptor()).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 의존성을 추가합니다.
IMQA Client는 HttpClient 기반의 네트워크 요청을 수집할 수 있습니다. HttpClient 기반의 네트워크 요청시 다음과 같이 추가해 주세요.
HttpClient
1. HttpClient (org.apache.http.legacy)
MainActivity.java
...// DefaultHttpClient 에 HttpClientInterceptor 를 추가DefaultHttpClient httpClient =newDefaultHttpClient();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 =newDefaultHttpClient();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 =newStringRequest(....)// RequestQueue 에 IMQAHurlStack 을 추가RequestQueue requestQueue =Volley.newRequestQueue(this,newIMQAHurlStack());requestQueue.add(request);...
현재 버전에서의 이슈 사항
Interceptor 기능을 수동으로 삽입해 주어야 합니다.(현재 HTTPUrlConnection, Okhttp, Retrofit, HttpClient(org.apache, cz.msebera) 자동 설치를 지원하고 있습니다.)