Skocz do zawartości
piotrzinderberg

hms Jak pogodzić HMS z Kotlinem?

    Rekomendowane odpowiedzi

    Napisano (edytowane)

    Cześć, w swojej aplikacji używam In app purchase z Google Play Services. Chciałbym dodać obsługę HMS, jednak odrzuca mnie nieco brak wsparcia dla Kotlina.

    W przypadku  usług Google, całość logiki do płatności miałem wydzielone w zewnętrznej klasie, która obsługiwała wszystko, co związane z płatnościami (było to dość proste, bo w w play services mamy specjalną libkę, dostosowaną do kotlina). Chciałbym ukryć tę klasę za interfejsem, i dopisać drugi egzemplarz klasy, obsługującej HMS, jednak tutaj pojawia się problem:

    Przy kilku metodach, HMS wymusza odbieranie callbacka w onActivityResult, w zewnętrznej klasie nie chciałbym mieć dostępu do aktywności. Nie można też użyć ActivityResultContract, bo HMS nie daje dostępu do uruchamianego Intenta. Dodatkowo w HMS, wszystkie metody wymagają callbacka, nie ma metod typu suspend tak jak w przypadku biblioteki Google.

    Może jest na forum ktoś, kto już sobie poradził z tym tematem i doradzi, w którym kierunku mam iść.

    Edytowane przez piotrzinderberg

    Udostępnij tę odpowiedź


    Odnośnik do odpowiedzi
    Udostępnij na innych stronach

    Faktycznie, trzeba trochę się namęczyć, żeby wydzielić HMS billing do osobnej klasy, przez używanie onActivityResult. Ja u siebie zrobiłem do tego taki mały hack, przy pomocy daggera.

    Zrobiłem sobie klasę o nazwie ActivityResultObserver, która żyje w scope aktywności. Wygląda to mniej więcej tak:

     

    Później musisz wstrzyknąć tę klasę w aktywności, która będzie otrzymywać rezultat.

    @Inject
    lateinit var activityResultObserver: ActivityResultObserver

    Oraz przekazać rezultat z onActivityResult (w tej samej aktywności co wcześniej wstrzykiwaliśmy zależność)

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            super.onActivityResult(requestCode, resultCode, data)
    
            activityResultObserver.onResultReceived(requestCode, resultCode, data)
        }

    Później w swojej klasie, zajmującej się obsługą billingu deklarujesz sobie result receiver, na przykład tak:

    private val huaweiIdLoginInResultReceiver: ResultReceiver = { resultCode: Int, data: Intent? ->
            //akcja po przyjściu rezultatu
        }

    I dodajesz go, przed wywołaniem akcji HMS, na przykład tak:

      activityResultObserver.addResultReceiver(
                HUAWEI_ID_LOG_IN_REQUEST_CODE,
                huaweiIdLoginInResultReceiver
            )
      //akcja HMS wymagająca obsługi onActivityResult

    Pamiętaj, żeby ActivityResultObserver nie żył dłużej, niż sama aktywność, bo może to doprowadzić do wycieków pamięci.

     

    Co do problemu z callbackami, można to łatwo ogarnąć przy pomocy suspend coroutine, na przykłąd tak jak tutaj:

    private suspend fun checkEnvReady() =
            suspendCoroutine { coroutineContinuation: Continuation<Unit> ->
                client.isEnvReady
                    .addOnSuccessListener {
                        coroutineContinuation.resume(Unit)
                    }
                    .addOnFailureListener {
                        coroutineContinuation.resumeWithException(it)
                    }
            }

     

    Udostępnij tę odpowiedź


    Odnośnik do odpowiedzi
    Udostępnij na innych stronach

    Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

    Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

    Zarejestruj nowe konto

    Załóż nowe konto. To bardzo proste!

    Zarejestruj się

    Zaloguj się

    Posiadasz już konto? Zaloguj się poniżej.

    Zaloguj się

    • Ostatnio przeglądający   0 użytkowników

      Brak zarejestrowanych użytkowników przeglądających tę stronę.

    x