menu
Is this helpful?

# Android 앱 푸시 통합 가이드

# 앱 푸시 자동 수집 방법

자동 수집 방법은 SDK 내부에서 각 플랫폼(현재 단계에서는 FCM)의 푸시 토큰 및 푸시 메시지 클릭 이벤트(te_ops_push_click)를 자동으로 전송하는 방법입니다.

  1. 데이터 수집 SDK의 버전을 3.0.1-beta.1로 업그레이드하십시오.
implementation 'cn.thinkingdata.android:ThinkingAnalyticsSDK:3.0.1-beata.1'
  1. 자동 수집 플러그인을 도입합니다. 버전은 2.1.0입니다.
buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'cn.thinkingdata.android:android-gradle-plugin2:2.1.0'
    }
}

프로젝트의 build.gradle 파일에서 플러그인 관련 매개변수를 설정합니다.

apply plugin: 'cn.thinkingdata.android'
android {

}
  1. 자동 수집 푸시 링크를 활성화합니다.
val config = TDConfig.getInstance(
    this,
    TA_APP_ID,
    TA_SERVER_URL
)
//자동 수집을 활성화로 설정하기
config.enableAutoPush()
TDAnalytics.init(config)
  1. 계정 전환

계정을 전환한 후에는 login을 호출해야 합니다. SDK 내부에서는 자동으로 푸시 토큰이 user_set 인터페이스를 통해 새 계정으로 전송됩니다.

TDAnalytics.login("new_account_id")

#

# FCM 푸시

커스텀 FirebaseMessagingService는 컴파일 시점에 FirebaseMessagingService의 onNewToken 메소드를 후크하는 원리이며, 이를 위해 이 클래스를 제공해야 합니다.

class MyFirebaseMessagingService extends FirebaseMessagingService {
    @Override
    public void onNewToken(@NonNull String token) {
        
    } 
}

manifest 파일에 등록합니다

<service
    android:name="service"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

# 앱 푸시 수동 수집 방법

# FCM 푸시

# 1.1 "pushID" 전송

  • 로그인 또는 계정 전환 후 FCM 토큰을 업로드합니다.
//SDK의 초기화
ThinkingAnalyticsSDK instance = ThinkingAnalyticsSDK.sharedInstance(this, APPID, SERVER_URL);
instance.login("user_id");
FirebaseMessaging.getInstance().getToken()
    .addOnCompleteListener(new OnCompleteListener<String>() {
        @Override
        public void onComplete(@NonNull Task<String> task) {
          if (!task.isSuccessful()) {
            Log.w(TAG, "Fetching FCM registration token failed", task.getException());
            return;
          }

          // Get new FCM registration token
          String token = task.getResult();
          JSONObject properties = new JSONObject();
          properties.put("fcm_token",token);
          instance.user_set(properties);
        }
 });
  • FCM 토큰이 변경된 경우 유저 속성을 업데이트합니다.
@Override
public void onNewToken(@NonNull String token) {
    JSONObject properties = new JSONObject();
    properties.put("fcm_token",token);
    instance.user_set(properties);
}

# 1.2. 클릭 이벤트 수집 및 전송

유저가 푸시를 클릭할 때 푸시 클릭 이벤트를 업로드할 수 있으며, onCreate 또는 onNewIntent에서 푸시 매개변수를 얻을 수 있습니다.

public class PushOpenClickActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handlePushOpen();
    }
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        handlePushOpen();
    }

    private void handlePushOpen() {
        try {
            Intent intent = getIntent();
            if (intent == null) {
                return;
            }
            Bundle bundle = intent.getExtras();
            if (bundle == null) {
                return;
            }
            String teExtras = bundle.getString("te_extras");
            TEPushUtil.trackAppOpenNotification(teExtras);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

# 1.3. 푸시 메시지 처리

다음 두 가지 방법 중 하나를 선택하세요.

  • 일반 매개변수: handleTEPushAction 메소드를 호출합니다.
  • 투명 매개변수: handleTEPassThroughAction 메소드를 호출합니다.
public class PushOpenClickActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handlePushOpen();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        handlePushOpen();
    }

    private void handlePushOpen() {
        try {
            Intent intent = getIntent();
            if (intent == null) {
                return;
            }
            Bundle bundle = intent.getExtras();
            if (bundle == null) {
                return;
            }
            String teExtras = bundle.getString("te_extras");          
            // 일반 파라미터
            TEPushUtil.handleTEPushAction(teExtras);
            // Pass Through파라미터
            TEPushUtil.handleTEPassThroughAction(teExtras);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

# 부록

# 클라이언트가 받은 푸시 매개변수 예시

{
    "te_extras": {
         //푸시 알림의 링크 방법

        "ops_loading_type": "OPEN_APP",
        //매개변수를 통해

        "passthrough_params": {
                "param1": "abc",
                "param2": 101,
                "param3": [{
                        "subText1": "xyz",
                        "subText2": 2
                }]
        },
        //TE 운영에서의 채널 리시트 속성

        "#ops_receipt_properties": {
                "ops_task_id": "0082",
                "ops_project_id": 1,
                "ops_task_instance_id": "0082_20230331",
                "ops_push_language": "default",
                "ops_task_exec_detail_id": "55"
        }
    }
}

# 자동 수집이 성공했는지 확인하는 방법은?

  1. 푸시 알림에 액세스한 후, 첫 시작이나 토큰 변경 시 다음 이벤트가 전송되었는지 확인합니다.
{
    "#type": "user_set",
    "#time": "2023-11-13 15:50:55.729",
    "#distinct_id": "distinct",
    "properties": {
        "FCM_id": "190e35f7e15c8481caa"
    },
    "#uuid": "9f233c31-a664-46ff-94d6-f767a3098c3a"
}
  1. 푸시 알림을 클릭하여 앱을 시작하고, te_ops_push_click 이벤트가 전송되는지 관찰하고, 이벤트 속성에 ops_receipt_properties가 포함되어 있는지 확인합니다.
{
    "#type": "track",
    "#time": "2023-03-16 16:08:32.191",
    "#distinct_id": "90d80464-6832-43f1-80d9-bd93fc09c4fe",
    "#event_name": "te_ops_push_click",
    "properties": {
        "#lib_version": "3.0.1-beata.1",
        "#carrier": "au",
        "#os": "Android",
        "#device_id": "6262ca7f71e6aca3",
        "#screen_height": 2400,
        "#bundle_id": "jp.thinkingdata.random",
        "#device_model": "M2012K11AC",
        "#screen_width": 1080,
        "#system_language": "jp",
        "#install_time": "2023-03-10 11:24:44.285",
        "#simulator": false,
        "#lib": "Android",
        "#manufacturer": "Galaxy",
        "#os_version": "11",
        "#app_version": "1.0",
        "#fps": 60,
        "#network_type": "WIFI",
        "#ram": "2.7\/7.4",
        "#disk": "4.6\/106.3",
        "#device_type": "Phone",
        "ops_receipt_properties": {
            "ops_project_id": 1,
            "ops_request_id": "3b21d2a8-8d3d-44fa-b460-3bb311ed3bcd"
        },
        "#zone_offset": 9
    },
    "#uuid": "7a977e23-b78a-4433-baae-ead17ad2fde9"
}

# trackAppOpenNotification

public static void trackAppOpenNotification(String extras) {
    try {
        if (TextUtils.isEmpty(extras)) {
            return;
        }
        JSONObject jsonObject = new JSONObject(extras);
        JSONObject properties = new JSONObject();
        Object obj = json.opt("#ops_receipt_properties");
        JSONObject ops = null;
        if (obj instanceof String) {
            ops = new JSONObject(( String ) obj);
        } else if (obj instanceof JSONObject) {
            ops = ( JSONObject ) obj;
        }
        properties.put("#ops_receipt_properties", ops);
        ThinkingAnalyticsSDK instance = ThinkingAnalyticsSDK.sharedInstance(null, "appId", "serverUrl");
        instance.track("te_ops_push_click", properties);
         //즉시 전송

        instance.flush();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

# handleTEPushAction

public static void handleTEPushAction(String extras) {
    try {
        if (TextUtils.isEmpty(extras)) {
            return;
        }
        JSONObject jsonObject = new JSONObject(extras);
        String type = jsonObject.optString("ops_loading_type");
        if ("OPEN_APP".equals(type)) {
         // TODO 앱을 열 메시지 처리--> App을 시작해주세요

        } else if ("OPEN_URL".equals(type)) {
            String url = jsonObject.optString("ops_url");
            if (!TextUtils.isEmpty(url)) {
        // TODO 업로드 URL을 열 메시지의 처리, --> 업로드 URL을 처리해주세요
            }
        } else if ("CUSTOMIZED".equals(type)) {
            String custom = jsonObject.optString("ops_customized");
            if (!TextUtils.isEmpty(custom)) {
        // TODO 사용자 정의 메시지의 처리,--> 맞춤형 메시지를 처리해 주세요

            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

# handleTEPassThroughAction

public static void handleTEPassThroughAction(String extras) {
    try {
        if (TextUtils.isEmpty(extras)) {
            return;
        }
        JSONObject jsonObject = new JSONObject(extras);
        String params = jsonObject.optString("passthrough_params");
       //params는 투명 매개변수이며, 다음에 구체적인 로직의 구현이 이어집니다.
    } catch (Exception e) {
        e.printStackTrace();
    }
}

# TEPushUtil 클래스

public class TEPushUtil {

    public static void trackAppOpenNotification(String extras) {
        try {
            if (TextUtils.isEmpty(extras)) {
                return;
            }
            JSONObject jsonObject = new JSONObject(extras);
            JSONObject properties = new JSONObject();
            Object obj = json.opt("#ops_receipt_properties");
            JSONObject ops = null;
            if (obj instanceof String) {
                ops = new JSONObject(( String ) obj);
            } else if (obj instanceof JSONObject) {
                ops = ( JSONObject ) obj;
            }
            properties.put("#ops_receipt_properties", ops);
            ThinkingAnalyticsSDK instance = ThinkingAnalyticsSDK.sharedInstance(null, "appId", "serverUrl");
            instance.track("te_ops_push_click", properties);
            //즉시 전송
            
            instance.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
public static void handleTEPushAction(String extras) {
    try {
        if (TextUtils.isEmpty(extras)) {
            return;
        }
        JSONObject jsonObject = new JSONObject(extras);
        String type = jsonObject.optString("ops_loading_type");
        if ("OPEN_APP".equals(type)) {
         // TODO 앱을 열 메시지 처리--> App을 시작해주세요

        } else if ("OPEN_URL".equals(type)) {
            String url = jsonObject.optString("ops_url");
            if (!TextUtils.isEmpty(url)) {
        // TODO 업로드 URL을 열 메시지의 처리, --> 업로드 URL을 처리해주세요
            }
        } else if ("CUSTOMIZED".equals(type)) {
            String custom = jsonObject.optString("ops_customized");
            if (!TextUtils.isEmpty(custom)) {
             // TODO 맞춤형 메시지의 처리,--> 맞춤형 메시지를 처리해 주세요

            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
    
    public static void handleTEPassThroughAction(String extras) {
        try {
            if (TextUtils.isEmpty(extras)) {
                return;
            }
            JSONObject jsonObject = new JSONObject(extras);
            String params = jsonObject.optString("passthrough_params");
        //params는 투명 매개변수이며, 다음에 구체적인 로직의 구현이 이어집니다.
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getPushExtras(Object notificationExtras) {
        String teExtras = "";
        try {
            if (notificationExtras != null) {
                if (notificationExtras instanceof String) {
                    teExtras = new JSONObject((String) notificationExtras).optString("te_extras");
                } else if (notificationExtras instanceof Map) {
                    teExtras = new JSONObject((Map) notificationExtras).optString("te_extras");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return teExtras;
    }

}