고급 옵션
설치 리퍼러 수집, 세션 관리, JavaScript 연동, 그리고 특수한 사용 사례를 위한 대체 디바이스 식별자를 포함한 고급 SDK 기능을 구성합니다.
설치 리퍼러 수집 (레거시 디바이스)
개요
설치 리퍼러는 유저가 Google Play Store에서 앱을 설치하기 전에 클릭한 광고를 식별하여 정확한 어트리뷰션을 제공합니다.
지원 중단된 기능:
Google은
INSTALL_REFERRER
인텐트 브로드캐스트를 더 이상 지원하지 않습니다.
Still Using InstallBroadcast? Switch to the Play Referrer API by March 1, 2020
을 참조하세요.
최신 Singular SDK 버전은 자동으로
Google Play Referrer API
를 사용합니다.
자동 수집:
최신 Google Play Store가 설치된 디바이스에서 Singular SDK는 Google Play Referrer API를 사용해 설치 리퍼러를 자동으로 수집합니다. 수동 구성은 레거시 디바이스 지원을 위해서만 필요합니다.
기존 리시버와 연동
앱에 이미
INSTALL_REFERRER
를 처리하는
BroadcastReceiver
가 있는 경우 설치 리퍼러 데이터를 Singular로 전달합니다.
구현:
기존 리시버의
onReceive
메서드 내부에서
SingularInstallReceiver
호출을 추가합니다.
class MyCustomInstallReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Forward install referrer to Singular
SingularInstallReceiver().onReceive(context, intent)
// Your existing logic
// ...
}
}
public class MyCustomInstallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// Forward install referrer to Singular
new SingularInstallReceiver().onReceive(context, intent);
// Your existing logic
// ...
}
}
Singular 리시버 등록
앱에 기존
INSTALL_REFERRER
핸들러가 없는 경우 Singular 설치 리퍼러 리시버를 구성합니다.
AndroidManifest.xml 구성:
<application>
<!-- Other application components -->
<receiver
android:name="com.singular.sdk.SingularInstallReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
</application>
권장 사항: 이 구성은 매우 오래된 디바이스를 지원하는 앱에서만 필요합니다. 최신 구현에서는 자동 Google Play Referrer API 연동을 사용해야 합니다.
세션 관리
자동 세션 관리
Singular SDK는 Android API 14 (Ice Cream Sandwich) 이상에서 추가 구성 없이 세션 관리를 자동으로 처리합니다.
기본 동작:
앱이 백그라운드로 60초 이상 이동한 후 다시 포어그라운드로 돌아오면 SDK는 새 세션을 등록합니다.
세션 타임아웃 구성
앱 사용 패턴에 맞게 세션 타임아웃 기간을 사용자 정의합니다.
메서드 시그니처:
SingularConfig.withSessionTimeoutInSec(int timeoutInSeconds)
// Set session timeout to 120 seconds (2 minutes)
val config = SingularConfig("SDK_KEY", "SDK_SECRET")
.withSessionTimeoutInSec(120)
Singular.init(applicationContext, config)
// Set session timeout to 120 seconds (2 minutes)
SingularConfig config = new SingularConfig("SDK_KEY", "SDK_SECRET")
.withSessionTimeoutInSec(120);
Singular.init(getApplicationContext(), config);
타임아웃 값:
- 기본값: 60초
- 최소값: 0초 (모든 백그라운드/포어그라운드 전환이 새 세션을 생성)
- 권장값: 앱 사용 패턴에 따라 30-180초
수동 세션 관리 (API < 14)
minSdkVersion
이 14 미만인 앱의 경우 각 액티비티에서 라이프사이클 메서드를 호출하여
세션을 수동으로 관리합니다.
이 섹션은 건너뛰세요:
사용 중인
minSdkVersion
이 14 (Ice Cream Sandwich) 이상인 경우 — 거의 대부분 해당됩니다. Singular
SDK는 API 14 이상에서
ActivityLifecycleCallbacks
를 사용해 세션을 자동으로 추적하므로
onActivityResumed()
/
onActivityPaused()
를 수동으로 호출하면 중복되며 세션 이벤트가 이중으로 발생할 수 있습니다.
Android 4.0 이전 디바이스를 명시적으로 타깃으로 하는 경우에만 아래
코드를 구현하세요.
구현
각 액티비티의 라이프사이클 메서드에서
onActivityResumed()
및
onActivityPaused()
를 호출하거나, 기본 액티비티 클래스에서 구현합니다.
class MainActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
Singular.onActivityResumed()
// Your other code
}
override fun onPause() {
super.onPause()
Singular.onActivityPaused()
// Your other code
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onResume() {
super.onResume();
Singular.onActivityResumed();
// Your other code
}
@Override
protected void onPause() {
super.onPause();
Singular.onActivityPaused();
// Your other code
}
}
모범 사례:
공통 베이스 액티비티 클래스가 있다면, 모든 액티비티에서 코드를 중복하지 말고
베이스 클래스의
onResume()
및
onPause()
메서드에서 이 호출을 구현하세요.
하이브리드 앱을 위한 JavaScript 인터페이스
개요
SingularJSInterface
를 사용해 WebView 기반 하이브리드 앱의 JavaScript 코드에서 Singular SDK 기능을
활성화합니다.
지원되는 메서드:
- setCustomUserId: 커스텀 유저 식별자 설정
- unsetCustomUserId: 커스텀 유저 식별자 제거
- event: 속성 유무에 관계없이 이벤트 트래킹
- revenue: 매출 트래킹
WebView 연동 설정
Singular 기능이 필요한 각 WebView에 대해 액티비티의
onCreate()
메서드에서 JavaScript 인터페이스를 구성합니다.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Initialize Singular SDK
val config = SingularConfig("SDK_KEY", "SDK_SECRET")
Singular.init(this, config)
// Configure WebView
val myWebView = findViewById<WebView>(R.id.webview)
myWebView.settings.javaScriptEnabled = true
myWebView.loadUrl("file:///android_asset/index.html")
// Add Singular JavaScript interface
val singularJSInterface = SingularJSInterface(this)
singularJSInterface.setWebViewId(R.id.webview)
myWebView.addJavascriptInterface(singularJSInterface, "SingularInterface")
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize Singular SDK
SingularConfig config = new SingularConfig("SDK_KEY", "SDK_SECRET");
Singular.init(this, config);
// Configure WebView
WebView myWebView = findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.loadUrl("file:///android_asset/index.html");
// Add Singular JavaScript interface
SingularJSInterface singularJSInterface = new SingularJSInterface(this);
singularJSInterface.setWebViewId(R.id.webview);
myWebView.addJavascriptInterface(singularJSInterface, "SingularInterface");
}
여러 WebView:
- 앱의 각 WebView에 대해 JavaScript 인터페이스를 구성합니다
- 일관성을 위해 동일한 인터페이스 이름("SingularInterface")을 사용합니다
- 각 인스턴스에 고유한 WebView ID를 설정합니다
JavaScript 사용
WebView에서 실행되는 JavaScript 코드에서 Singular 메서드를 호출합니다.
이벤트 트래킹
// Simple event without attributes
SingularInterface.event('level_completed');
// Event with attributes (pass as JSON string)
SingularInterface.event('purchase_attempt',
JSON.stringify({
"item_name": "sword",
"item_category": "weapons",
"item_price": 9.99
})
);
매출 트래킹
// Track revenue in USD
SingularInterface.revenue('USD', 9.99);
// Track revenue in other currencies
SingularInterface.revenue('EUR', 8.50);
커스텀 유저 ID 관리
// Set custom user ID
SingularInterface.setCustomUserId('user_12345');
// Remove custom user ID
SingularInterface.unsetCustomUserId();
대체 디바이스 식별자
OAID (Open Advertising ID)
Open Advertising Identifier (OAID)를 사용해 Google Play가 없는 지역의 Android 디바이스에서 트래킹을 활성화합니다.
OAID 지원:
- Huawei 디바이스: Huawei의 독자적인 OAID 구현
- MSA 디바이스: Mobile Security Alliance 회원 브랜드 (OPPO, Vivo, Xiaomi 등)
사전 요구 사항
지원되는 모든 플랫폼에서 OAID를 수집하려면 MSA SDK 와 Huawei OAID SDK 를 모두 연동하세요.
OAID 수집 활성화
트래킹에 OAID를 수집하고 사용하도록 Singular SDK를 구성합니다.
val config = SingularConfig("SDK_KEY", "SDK_SECRET")
.withOAIDCollection()
Singular.init(applicationContext, config)
SingularConfig config = new SingularConfig("SDK_KEY", "SDK_SECRET")
.withOAIDCollection();
Singular.init(getApplicationContext(), config);
자동 감지:
- SDK는 디바이스에 OAID가 있는지 자동으로 감지합니다
- SDK는 디바이스에 따라 적합한 OAID SDK (MSA 또는 Huawei)를 선택합니다
- Amazon Advertising ID (AMID)는 추가 종속성 없이 자동으로 수집됩니다
IMEI (International Mobile Equipment Identity)
Google Play Services가 없는 지역의 디바이스에서 트래킹을 위해 디바이스 IMEI 번호를 수집합니다.
중요 중요: IMEI 수집은 Google Play Services 계약을 위반합니다. Google Play Store 외부에서 배포되는 앱 중 Google 서비스가 없는 지역에서만 IMEI 수집을 사용하세요.
필수 권한 추가
AndroidManifest.xml에
READ_PHONE_STATE
권한을 추가합니다.
<manifest>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application>
<!-- Your application components -->
</application>
</manifest>
IMEI 번호 가져오기
적절한 API 레벨 처리와 함께 TelephonyManager를 사용해 디바이스 IMEI를 가져옵니다.
val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
val imei: String? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
telephonyManager.imei
} else {
@Suppress("DEPRECATION")
telephonyManager.deviceId
}
// Validate IMEI before use
if (imei != null && imei.isNotEmpty()) {
// Send to Singular
Log.d("IMEI", "Retrieved: $imei")
} else {
Log.w("IMEI", "Failed to retrieve IMEI")
}
TelephonyManager telephonyManager =
(TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String imei = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
imei = telephonyManager.getImei();
} else {
imei = telephonyManager.getDeviceId();
}
// Validate IMEI before use
if (imei != null && !imei.isEmpty()) {
// Send to Singular
Log.d("IMEI", "Retrieved: " + imei);
} else {
Log.w("IMEI", "Failed to retrieve IMEI");
}
Singular로 IMEI 전송
SDK 초기화 중에 IMEI를 구성하거나(권장) 초기화 이후에 동적으로 설정합니다.
옵션 1: 구성 메서드 (권장)
// Set IMEI during initialization
val config = SingularConfig("SDK_KEY", "SDK_SECRET")
.withIMEI(imei)
Singular.init(applicationContext, config)
// Set IMEI during initialization
SingularConfig config = new SingularConfig("SDK_KEY", "SDK_SECRET")
.withIMEI(imei);
Singular.init(getApplicationContext(), config);
옵션 2: 런타임 메서드
// Set IMEI after initialization
Singular.setIMEI(imei)
// Set IMEI after initialization
Singular.setIMEI(imei);
모범 사례:
첫 번째 세션부터 IMEI를 사용할 수 있도록 SDK 초기화 전에
SingularConfig
에서 IMEI를 설정하세요. 초기화 이후에 IMEI를 사용할 수 있게 된 경우에만
setIMEI()
를 사용하세요.
BETA 기능
일반 제공 기능 아님: 이 섹션의 기능은 BETA 단계입니다. Singular이 고객님의 계정에 대해 활성화해야 동작하며, 동작 방식이 변경될 수 있습니다. 구현에 착수하기 전에 고객 성공 매니저와 상의하세요.
어트리뷰션 콜백
어트리뷰션 콜백은 설치를 유입시킨 네트워크와 캠페인 등 Singular의 어트리뷰션 결과를, 설치 후 사용자의 첫 세션 중에 디바이스의 앱으로 전달합니다.
활성화가 필요합니다: 이 기능은 기본적으로 비활성화되어 있습니다. 계정에 대해 활성화되지 않은 경우 코드가 올바르더라도 콜백이 전혀 호출되지 않습니다. 활성화를 요청하려면 고객 성공 매니저에게 문의하세요.
설정 방법
- 고객 성공 매니저에게 계정에 대한 어트리뷰션 콜백 활성화를 요청하세요.
- SDK를 초기화하기 전에 SDK 구성 객체에 핸들러를 등록하세요. 시그니처와 코드 샘플은
withSingularDeviceAttribution를 참조하세요. - 앱을 한 번도 실행한 적이 없는 디바이스에서 테스트하세요. 콜백은 첫 세션에서만 호출됩니다.
예상되는 동작
- 첫 세션에서만 호출: 콜백은 설치 후 첫 세션 중에 한 번만 호출되며, 이후 앱 실행 시에는 호출되지 않습니다.
- Organic은 실패가 아니라 결과입니다: 터치포인트를 찾지 못한 경우에도 콜백은 호출되며 네트워크를 "Organic"으로 보고합니다. 콜백이 전혀 호출되지 않는다면 이는 어트리뷰션 문제가 아니라 설정 문제입니다.
- 최종 어트리뷰션이 아닌 최선의 추정치: 결과는 세션이 처리되는 시점에 사용 가능한 마지막 터치포인트를 반영합니다. 더 많은 정보를 바탕으로 나중에 결정되는 Singular 리포트의 어트리뷰션과 항상 일치하지는 않습니다.