API: Etc

    API: Etc


    기사 요약

    ShopLive.mute

    플레이어를 음소거합니다.

    fun mute()


    ShopLive.unmute

    플레이어의 음소거를 해제합니다.

    fun unmute()


    ShopLiveCampaigns.getCampaigns

    accessKey 에 속한 캠페인(방송) 목록과 각 캠페인의 현재 상태를 조회합니다. 호출 전에 ShopLive.setAccessKey(accessKey) 로 accessKey 를 설정해야 합니다. Android SDK 1.8.14 이상에서 사용할 수 있습니다.

    class ShopLiveCampaigns {
        companion object {
            @JvmStatic
            @JvmOverloads
            fun getCampaigns(
                request: ShopLiveCampaignListRequest = ShopLiveCampaignListRequest(),
                listener: ShopLiveCampaignListListener,
            ): ShopLiveCancellable
        }
    }
    
    interface ShopLiveCampaignListListener {
        fun onData(response: ShopLiveCampaignListResponse)
        fun onError(error: ShopLiveCommonError)
    }
    
    interface ShopLiveCancellable {
        fun cancel()
    }

    참고

    • 결과는 onData / onError 중 정확히 한 번, 메인 스레드에서 호출됩니다. 조회 결과가 0건인 것은 오류가 아니며 빈 목록으로 onData 가 호출됩니다.

    • 반환값 ShopLiveCancellable 의 cancel() 로 진행 중인 요청을 취소할 수 있습니다. 취소하면 어떤 콜백도 호출되지 않습니다. SDK 는 Context·Lifecycle 을 받지 않으므로 화면을 벗어날 때(onDestroy) 직접 취소해야 합니다.

    • Kotlin 에서 request 를 생략할 때는 getCampaigns(listener = ...) 처럼 이름을 붙여야 합니다. Java 는 getCampaigns(listener) 로 호출합니다.

    • ShopLiveCampaigns 는 cloud.shoplive:shoplive-sdk-core, 요청·응답 모델과 리스너는 cloud.shoplive:shoplive-common 에 있습니다. 두 아티팩트와 shoplive-network 를 모두 의존성으로 선언해야 합니다.

    • 모든 String 필드는 빈 문자열("")일 수 있으며 이는 "값 없음"을 뜻합니다. 사용 전 isNullOrBlank() 로 확인하세요. Boolean 필드는 서버가 값을 주지 않으면 false 입니다.

    ShopLiveCampaignListRequest

    조회 조건입니다. 모든 파라미터는 선택(optional)이며, 인자 없이 ShopLiveCampaignListRequest() 를 넘기면 서버 기본값으로 전체 상태를 조회합니다. 값을 주지 않은 조건은 쿼리에 붙이지 않습니다.

    Parameter name

    Type

    Description

    page

    Int?

    페이지 번호. 1부터 시작합니다. (Default: 1) 1 미만을 주면 SDK 가 1 로 보정합니다.

    size

    Int?

    페이지당 캠페인 개수. (Default: 10) 1~20 범위를 벗어나면 SDK 가 범위 안으로 보정합니다.

    statuses

    List<ShopLiveCampaignFilterStatus>

    조회할 상태 필터. 비어 있으면 전체 상태를 조회합니다. READY / ONAIR / CLOSED 3종만 지정할 수 있으며 중복 값은 제거됩니다.

    order

    ShopLiveCampaignOrder?

    scheduledAt 기준 정렬 방향. ASCENDING / DESCENDING (Default: DESCENDING, 최신순). ASCENDING 은 지난 방송도 포함한 전 기간 오름차순입니다.

    ShopLiveCampaignListResponse

    조회 결과입니다.

    Property

    Type

    Description

    campaigns

    List<ShopLiveCampaign>

    조회된 캠페인 목록. 0건이면 빈 목록입니다.

    hasMore

    Boolean

    다음 페이지가 있는지 여부. true 이면 page 를 1 증가시켜 다시 조회합니다.

    ShopLiveCampaign

    캠페인 한 건의 정보입니다. 시각 값은 모두 epoch millis 입니다.

    Property

    Type

    Description

    campaignId

    Long

    캠페인 ID

    campaignKey

    String

    캠페인 키. ShopLive.play(...) 의 campaignKey 로 사용합니다. 빈 문자열이면 재생에 사용할 수 없습니다.

    title

    String?

    캠페인 제목

    description

    String?

    캠페인 설명

    campaignUrl

    String

    캠페인 URL. 표시·공유용입니다.

    rerun

    Boolean

    재방송 여부

    archiveStream

    Boolean

    아카이브 스트림(다시보기) 제공 여부

    privateLive

    Boolean

    프라이빗 방송 여부. 목록에 그대로 포함되므로 노출 여부는 앱에서 판단합니다.

    scheduledAt

    Long?

    방송 예정 시각 (epoch millis)

    scheduledEndAt

    Long?

    방송 예정 종료 시각 (epoch millis)

    posterUrl

    String?

    포스터 이미지 URL

    lifecycle

    ShopLiveCampaignLifecycle

    상태와 상태 전환 시각

    metrics

    ShopLiveCampaignMetrics?

    시청 지표. OnAir / Closed 상태에서만 내려오며 그 외 상태에서는 null 입니다.

    ShopLiveCampaignLifecycle

    캠페인의 상태와 상태 전환 시각입니다.

    Property

    Type

    Description

    status

    ShopLiveCampaignStatus

    캠페인 상태. 리허설 중은 Ready, 종료 진행 중은 OnAir 로 표기됩니다.

    rehearsal

    Boolean

    리허설 여부. 리허설 중에도 status 는 Ready 이므로 이 값으로 구분합니다.

    startedAt

    Long?

    방송 시작 시각 (epoch millis)

    closingAt

    Long?

    종료 진행 시작 시각 (epoch millis). status 가 OnAir 이고 이 값이 있으면 종료 진행 중입니다.

    endedAt

    Long?

    방송 종료 시각 (epoch millis)

    ShopLiveCampaignStatus

    캠페인 상태 값입니다. sealed class 이며 rawValue 로 서버 원문을 얻을 수 있습니다. 정의되지 않은 값은 Unknown 으로 전달됩니다. Java 에서는 instanceof 로 비교하고 단일 상태는 ShopLiveCampaignStatus.OnAir.INSTANCE 처럼 참조합니다.

    Case

    Server value

    Description

    Reserved

    RESERVED

    예약된 방송. 요청 필터(statuses)로는 지정할 수 없고 전체 조회 시에만 포함됩니다.

    Ready

    READY

    방송 준비(대기) 중. lifecycle.rehearsal 이 true 이면 리허설 중입니다.

    OnAir

    ONAIR

    방송 중. lifecycle.closingAt 이 있으면 종료 진행 중입니다.

    Closed

    CLOSED

    방송 종료

    Unknown(raw: String)

    그 외

    정의되지 않은 서버 상태 값입니다. 향후 추가되는 상태에 대비해 원본 문자열을 그대로 담습니다.

    ShopLiveCampaignMetrics

    시청 지표입니다. OnAir / Closed 상태에서만 제공됩니다.

    Property

    Type

    Description

    userCount

    Long?

    시청자 수

    adoreCount

    Long?

    좋아요(하트) 수

    showUserCount

    Boolean

    false 이면 userCount / adoreCount 를 UI 에 노출하지 않아야 합니다.

    에러 처리

    실패 시 onError 로 ShopLiveCommonError 가 전달됩니다. 원인은 code 로 판별하세요. 서버 오류·HTTP 오류의 message 는 고정 문구 Failed to fetch campaign list. Refer to the error code. 로 치환되며(서버 원문 미노출), SDK 내부 오류(9000·9900·9901·10000)는 각 오류의 SDK 문구가 실립니다. 서버가 내려준 코드는 ShopLiveCampaignErrorCode 상수와 비교할 수 있고, 전체 코드 목록은 Error codes 문서를 참고하세요.

    Code

    Constant

    Description

    9000

    ShopLiveCommonErrorCode.NOT_INITIALIZED_ACCESS_KEY

    accessKey 가 설정되지 않았습니다. ShopLive.setAccessKey(accessKey) 를 먼저 호출하세요.

    -200

    ShopLiveCampaignErrorCode.SERVICE_NOT_EXIST

    존재하지 않는 accessKey 입니다.

    -201

    ShopLiveCampaignErrorCode.ACCESS_KEY_EXPIRED

    만료된 accessKey 입니다.

    -510

    ShopLiveCampaignErrorCode.INVALID_PARAMETER

    잘못된 요청 인자입니다.

    HTTP 상태 코드

    -

    서버가 오류 본문 없이 응답한 경우 HTTP 상태 코드(예: 404, 500)가 그대로 전달됩니다.

    9900

    ShopLiveCommonErrorCode.FAILED_NETWORK

    네트워크 연결에 실패했습니다.

    9901

    ShopLiveCommonErrorCode.FAILED_JSON_PARSING

    응답 JSON 파싱에 실패했습니다.

    10000

    ShopLiveCommonErrorCode.UNEXPECTED_ERROR

    예기치 못한 오류입니다.

    Sample code (Kotlin)

    import cloud.shoplive.sdk.ShopLive
    import cloud.shoplive.sdk.ShopLiveCampaigns
    import cloud.shoplive.sdk.common.ShopLiveCancellable
    import cloud.shoplive.sdk.common.ShopLiveCommonError
    import cloud.shoplive.sdk.common.campaign.ShopLiveCampaignFilterStatus
    import cloud.shoplive.sdk.common.campaign.ShopLiveCampaignListListener
    import cloud.shoplive.sdk.common.campaign.ShopLiveCampaignListRequest
    import cloud.shoplive.sdk.common.campaign.ShopLiveCampaignListResponse
    import cloud.shoplive.sdk.common.campaign.ShopLiveCampaignOrder
    import cloud.shoplive.sdk.common.campaign.ShopLiveCampaignStatus
    
    class CampaignListActivity : AppCompatActivity() {
    
        // 진행 중인 요청. 화면을 벗어날 때 취소합니다.
        private var pending: ShopLiveCancellable? = null
    
        private val listener = object : ShopLiveCampaignListListener {
            override fun onData(response: ShopLiveCampaignListResponse) {
                pending = null
                // 0건은 오류가 아닙니다. 조건에 맞는 방송이 없다는 뜻입니다.
                response.campaigns.forEach { campaign ->
                    val label = when (val status = campaign.lifecycle.status) {
                        ShopLiveCampaignStatus.Reserved -> "예약"
                        ShopLiveCampaignStatus.Ready -> if (campaign.lifecycle.rehearsal) "리허설 중" else "준비 중"
                        ShopLiveCampaignStatus.OnAir -> if (campaign.lifecycle.closingAt == null) "방송 중" else "종료 진행 중"
                        ShopLiveCampaignStatus.Closed -> "종료"
                        is ShopLiveCampaignStatus.Unknown -> "알 수 없는 상태(${status.raw})"
                    }
                    // String 필드는 빈 문자열("")일 수 있으므로 isNullOrBlank() 로 확인합니다.
                    val title = campaign.title?.takeIf { it.isNotBlank() } ?: "(제목 없음)"
                    Log.d("Campaign", "$label ${campaign.campaignKey} $title")
                }
                if (response.hasMore) {
                    // page 를 1 증가시켜 다음 페이지를 조회합니다.
                }
            }
    
            override fun onError(error: ShopLiveCommonError) {
                pending = null
                // 원인은 code 로 판별합니다. message 로 분기하지 마세요.
                Log.e("Campaign", "getCampaigns failed: code=${error.code} message=${error.message}")
            }
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            // accessKey 설정 (앱에서 최초 1회)
            ShopLive.setAccessKey("{accessKey}")
    
            // 방송 중 · 준비 중인 캠페인을 최신순으로 20개 조회
            pending?.cancel()
            pending = ShopLiveCampaigns.getCampaigns(
                request = ShopLiveCampaignListRequest(
                    page = 1,
                    size = 20,
                    statuses = listOf(ShopLiveCampaignFilterStatus.ONAIR, ShopLiveCampaignFilterStatus.READY),
                    order = ShopLiveCampaignOrder.DESCENDING,
                ),
                listener = listener,
            )
    
            // request 를 생략할 때는 listener 에 이름을 붙여야 합니다.
            // ShopLiveCampaigns.getCampaigns(listener = listener)
        }
    
        override fun onDestroy() {
            // 화면을 벗어나면 요청을 취소합니다. 이후 어떤 콜백도 호출되지 않습니다.
            pending?.cancel()
            pending = null
            super.onDestroy()
        }
    }

    Sample code (Java)

    // Java — request 를 생략하면 getCampaigns(listener) 로 호출할 수 있습니다.
    ShopLiveCancellable pending = ShopLiveCampaigns.getCampaigns(
            new ShopLiveCampaignListRequest(1, 20,
                    Collections.singletonList(ShopLiveCampaignFilterStatus.ONAIR),
                    ShopLiveCampaignOrder.DESCENDING),
            new ShopLiveCampaignListListener() {
                @Override
                public void onData(@NonNull ShopLiveCampaignListResponse response) {
                    for (ShopLiveCampaign campaign : response.getCampaigns()) {
                        ShopLiveCampaignStatus status = campaign.getLifecycle().getStatus();
                        // Java 에서는 instanceof 로 비교하고, 단일 상태는 INSTANCE 로 참조합니다.
                        if (status == ShopLiveCampaignStatus.OnAir.INSTANCE) {
                            Log.d("Campaign", "on air: " + campaign.getCampaignKey());
                        } else if (status instanceof ShopLiveCampaignStatus.Unknown) {
                            Log.d("Campaign", "unknown: " + status.getRawValue());
                        }
                    }
                }
    
                @Override
                public void onError(@NonNull ShopLiveCommonError error) {
                    if (error.getCode() == ShopLiveCampaignErrorCode.SERVICE_NOT_EXIST) {
                        // 존재하지 않는 accessKey
                    }
                }
            });
    
    // 화면을 벗어날 때
    pending.cancel();


    What's Next