Ostrzeżenie: gdy aplikacja przeprowadza proces weryfikacji licencji po stronie klienta, potencjalnym hakerom łatwiej jest zmodyfikować lub usunąć zasady powiązane z tym procesem.
Dlatego zdecydowanie zachęcamy do wykonywanie po stronie serwera weryfikacji licencji.
Po skonfigurowaniu konta wydawcy i środowiska programistycznego (zobacz Konfigurowanie licencjonowania) możesz dodać weryfikację licencji z biblioteką weryfikacji licencji (LVL).
Dodanie weryfikacji licencji w LVL obejmuje te zadania:
- Dodawanie uprawnień dotyczących licencjonowania do pliku manifestu aplikacji.
- Wdrażanie zasad – możesz wybrać jedną z pełnych implementacji dostępnych w LVL lub utworzyć własną.
- Wdrożenie zaciemniającego, jeśli
Policy
zapisze którykolwiek z nich w pamięci podręcznej. danych odpowiedzi licencji. - Dodawanie kodu w celu sprawdzenia licencji w głównej aplikacji aplikacji Aktywność.
- Implementowanie ograniczenia liczby urządzeń (opcjonalne i niezalecane w przypadku: dla większości aplikacji).
Poniżej znajdziesz opis tych zadań. Gdy skończysz korzystać z musisz być w stanie skompilować aplikację i można rozpocząć testowanie, zgodnie z opisem w sekcji Konfigurowanie testu Środowisko.
Omówienie pełnego zestawu plików źródłowych w LVL znajdziesz w artykule Podsumowanie klas LVL i interfejsy.
Dodawanie uprawnienia dotyczącego licencji
Aby użyć aplikacji Google Play do wysłania sprawdzenia licencji do
serwer, aplikacja musi żądać odpowiedniego uprawnienia
com.android.vending.CHECK_LICENSE
Jeśli Twoja aplikacja
nie zadeklaruje uprawnień dotyczących licencji, ale próbuje rozpocząć sprawdzanie licencji,
LVL zgłasza wyjątek bezpieczeństwa.
Aby poprosić o uprawnienia licencyjne w aplikacji, zadeklaruj <uses-permission>
jako element podrzędny elementu <manifest>
w ten sposób:
<uses-permission
android:name="com.android.vending.CHECK_LICENSE" />
Oto jak przykładowa aplikacja LVL zadeklaruje to uprawnienie:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" ..."> <!-- Devices >= 3 have version of Google Play that supports licensing. --> <uses-sdk android:minSdkVersion="3" /> <!-- Required permission to check licensing. --> <uses-permission android:name="com.android.vending.CHECK_LICENSE" /> ... </manifest>
Uwaga: obecnie nie można zadeklarować,
CHECK_LICENSE
w pliku manifestu projektu biblioteki LVL,
bo narzędzia SDK nie łączą go z plikami manifestu zależnych
aplikacji. Zamiast tego musisz zadeklarować to uprawnienie w każdym
plik manifestu aplikacji.
Wdrażanie zasad
Usługa licencjonowania Google Play nie określa tego, czy
użytkownik z daną licencją powinien otrzymać dostęp do Twojej aplikacji.
Odpowiedzialność spoczywa na implementacji Policy
, którą dostarczysz.
w Twojej aplikacji.
Policy to interfejs deklarowany przez LVL, który służy do przechowywania
reguły zezwalania na dostęp użytkownika lub go blokowania w zależności od wyniku
weryfikacji licencji. Aby korzystać z LVL, aplikacja musi zawierać
po wdrożeniu zmiennej Policy
.
Interfejs Policy
deklaruje 2 metody: allowAccess()
oraz
processServerResponse()
, które są wywoływane przez LicenseChecker
podczas przetwarzania odpowiedzi z serwera licencji. Deklaruje też
wyliczenie o nazwie LicenseResponse
, które określa odpowiedź dotyczącą licencji
wartość przekazana w wywołaniach funkcji processServerResponse()
.
processServerResponse()
umożliwia wstępne przetworzenie nieprzetworzonej odpowiedzi danych otrzymanych z serwera licencjonowania przed podjęciem decyzji o przyznaniu dostęp.Typowa implementacja spowoduje wyodrębnienie niektórych lub wszystkich pól z licencji i przechowują dane lokalnie w magazynie trwałym, np. przez
SharedPreferences
pamięci masowej, aby zapewnić, że dane będą dostępne w ramach wywołań aplikacji i cykli zasilania urządzenia. Przykład:Policy
zachowa sygnaturę czasową ostatniego pomyślnego sprawdzenia licencji, wartość liczbę ponownych prób, okres ważności licencji i podobne informacje w pamięci trwałej, zamiast resetowania wartości za każdym razem, gdy aplikacja który został już wprowadzony.W przypadku przechowywania danych odpowiedzi lokalnie obiekt
Policy
musi zapewniać, zaciemniony (patrz Implementowanie zaciemnionego kodu, poniżej).allowAccess()
określa, czy przyznać użytkownikowi dostęp do: aplikacji, na podstawie wszelkich dostępnych danych odpowiedzi licencyjnych (z serwera licencjonowania lub pamięci podręcznej) bądź inne informacje dotyczące aplikacji. Dla: np. implementacjaallowAccess()
może wziąć pod uwagę dodatkowych kryteriów, takich jak wykorzystanie lub inne dane pobierane z z serwera backendu. We wszystkich przypadkach implementacjaallowAccess()
powinien zwracać wartośćtrue
tylko wtedy, gdy użytkownik ma licencję na używanie aplikacji, zgodnie z ustawieniami serwera licencjonowania, a jeśli występuje przejściowy problem, problem z siecią lub systemem, który uniemożliwia ukończenie sprawdzania licencji. W takich przypadków implementacja może utrzymać liczbę ponownych odpowiedzi tymczasowo zezwolić na dostęp do momentu zakończenia następnego sprawdzania licencji.
Aby uprościć proces dodawania licencji do wniosku oraz
ilustracja przedstawiająca zaprojektowanie elementu Policy
,
dwóch pełnych implementacji Policy
, których możesz używać bez modyfikacji lub
dostosuj do swoich potrzeb:
- ServerManagedPolicy, elastyczny
Policy
który korzysta z ustawień dostarczonych przez serwer i odpowiedzi w pamięci podręcznej do zarządzania dostępem w różnych warunkach sieci - StrictPolicy, który nie buforuje żadnej odpowiedzi. danych i umożliwia dostęp tylko wtedy, gdy serwer zwraca licencjonowaną .
W większości aplikacji zastosowanie zasad zarządzania serwerem zalecane. ServerManagedPolicy to domyślna zasada LVL, która jest zintegrowana z przykładową aplikację LVL.
Wytyczne dotyczące zasad niestandardowych
Przy wdrażaniu licencji możesz zastosować jedną z pełnych zasad w LVL (ServerManagedPolicy lub StrictPolicy) albo możesz utworzyć niestandardowe zasady. W przypadku każdego typu zasad niestandardowych jest kilka ważnych które warto zrozumieć i uwzględnić w implementacji.
Serwer licencjonowania stosuje ogólne limity żądań, aby chronić się przed nadużywaniem zasobów, które mogą doprowadzić do ataku typu DoS. Jeśli aplikacja przekracza lub limit żądań, serwer licencjonowania zwraca odpowiedź 503, która zwraca przekazywane do aplikacji jako ogólny błąd serwera. Oznacza to, że odpowiedź dotycząca licencji będzie dostępna dla użytkownika do momentu zresetowania limitu, co mogą wpływać na użytkownika przez czas nieokreślony.
Jeśli projektujesz zasady niestandardowe, zalecamy, aby Policy
:
- Zapisuje w pamięci podręcznej (i odpowiednio zaciemnia) ostatnią pomyślną odpowiedź dotyczącą licencji w lokalnej pamięci trwałej.
- Zwraca odpowiedź z pamięci podręcznej w przypadku wszystkich kontroli licencji, dopóki
odpowiedź z pamięci podręcznej jest prawidłowa i nie wysyła żądania do serwera licencjonowania.
Ustawianie poprawności odpowiedzi zgodnie z zasadą
VT
dostarczonej przez serwer jest zdecydowanie zalecane. Zobacz Dodatki do odpowiedzi serwera . - Wykorzystuje rosnący wykładniczo okres do ponowienia, jeśli ponowienie próby powoduje wyświetlenie wyniku
. Pamiętaj, że klient Google Play automatycznie ponawia próbę
więc w większości przypadków
Policy
nie ma potrzeby, aby je ponawiać. - Zapewnia „okres prolongaty” która pozwala użytkownikom przez ograniczony czas lub w określonej liczbie zastosowań, podczas sprawdzania licencji podjęto próbę ponowienia próby. Okres prolongaty jest korzystny dla użytkownika, ponieważ zezwala na dostęp do następnego okresu można pomyślnie przejść weryfikację licencji, co jest korzystne dla Ciebie, umieszczając stały limit na dostęp do Twojej aplikacji, gdy nie ma ważnej odpowiedzi na pytanie o licencję i dostępności informacji.
Zaprojektowanie urządzenia Policy
zgodnie z powyższymi wskazówkami jest bardzo ważne.
ponieważ zapewnia użytkownikom najlepsze wrażenia, a jednocześnie
efektywną kontrolę nad aplikacją nawet w przypadku błędów.
Pamiętaj, że każdy Policy
może używać ustawień skonfigurowanych przez serwer licencjonowania, aby
ułatwiają zarządzanie weryfikacją i buforowaniem, okres prolongaty ponawiania prób i nie tylko. Wyodrębnianie
ustawienia po stronie serwera są proste, a korzystanie z nich
zalecane. Zapoznaj się z implementacją ServerManagedPolicy, aby dowiedzieć się, jak
wyodrębniania i używania dodatków. Lista ustawień serwera oraz informacje o
jak ich używać, patrz Odpowiedź serwera
Dodatki.
Zasada zarządzania serwerem
Ocena LVL obejmuje pełną i zalecaną implementację interfejsu Policy
o nazwie ServerManagedPolicy. Implementacja jest zintegrowana z
Klasy LVL i służy jako domyślny obiekt Policy
w bibliotece.
ServerManagedPolicy (zarządzane zasady) zapewniają pełną obsługę licencji i ponawianie próby
odpowiedzi. Wszystkie dane odpowiedzi są zapisywane lokalnie w pamięci podręcznej
SharedPreferences
, ukrywając go za pomocą funkcji
implementacji Obfuscator
w aplikacji. Dzięki temu odpowiedź licencji
są bezpieczne i pozostają bez zmian po każdym cyklach zasilania urządzenia. Zasada zarządzania serwerem
zapewnia konkretne implementacje metod interfejsu,
processServerResponse()
i allowAccess()
, a także
obejmuje zestaw dodatkowych metod i typów zarządzania licencją
odpowiedzi.
Co ważne, kluczową funkcją usługi ServerManagedPolicy jest użycie
udostępnianych przez serwer ustawień jako podstawy zarządzania licencjami w
z określonego okresu zwrotu środków i przy różnych warunkach sieci i błędów.
Gdy aplikacja kontaktuje się z serwerem Google Play w celu sprawdzenia licencji,
Serwer dołącza kilka ustawień jako pary klucz-wartość w polu Dodatki określonych
typów odpowiedzi licencji. Na przykład serwer podaje zalecane wartości dla atrybutu
okres ważności licencji aplikacji, okres prolongaty ponawiania próby i maksymalna dozwolona liczba
liczbę ponownych prób. ServerManagedPolicy wyodrębnia wartości z pliku
odpowiedź licencji w jej metodzie processServerResponse()
i kontroli
je w metodzie allowAccess()
. Aby uzyskać listę wartości dostarczonych przez serwer,
ustawień używanych przez ServerManagedPolicy, patrz odpowiedź serwera
Dodatki.
Dla wygody, najlepszej wydajności i zalet korzystania z ustawień licencji
z serwera Google Play, przy użyciu ServerManagedPolicy jako
zalecamy licencjonowanie Policy
.
Jeśli masz wątpliwości co do bezpieczeństwa danych odpowiedzi dotyczących licencji,
przechowywane lokalnie w: SharedPreferences
, możesz użyć silniejszego zaciemniania kodu
lub zaprojektuj bardziej rygorystyczny algorytm Policy
, w którym nie są przechowywane dane licencji. POZIOM
zawiera przykład takiego elementu Policy
– więcej informacji znajdziesz na stronie StrictPolicy.
Aby użyć ServerManagedPolicy, po prostu zaimportuj ją do aktywności, utwórz
i przekazać odniesienie do instancji podczas tworzenia
LicenseChecker
Patrz sekcja Przeprowadzanie narzędzia do sprawdzania licencji
LicenseCheckerCallback, aby dowiedzieć się więcej.
Rygorystyczne zasady
LVL obejmuje alternatywną pełną implementację interfejsu Policy
StrictPolicy. Implementacja StrictPolicy zapewnia bardziej restrykcyjne
zasady niż ServerManagedPolicy, ponieważ nie pozwala ona użytkownikowi na dostęp
do aplikacji, o ile odpowiedź licencji nie zostanie odebrana z serwera
czasu dostępu, który wskazuje, że użytkownik ma licencję.
Podstawową cechą StrictPolicy jest to, że nie przechowuje ona żadnych
lokalnie, w magazynie trwałym. Żadne dane nie są przechowywane,
żądania ponawiania nie są śledzone, a odpowiedzi z pamięci podręcznej nie mogą służyć do realizacji
kontrole licencji. Policy
zezwala na dostęp tylko wtedy, gdy:
- odpowiedź dotycząca licencji zostanie odebrana z serwera licencjonowania.
- Odpowiedź dotycząca licencji wskazuje, że użytkownik ma licencję na dostęp do aplikacji.
Użycie zasady StrictPolicy jest odpowiednie, jeśli głównym celem jest zapewnienie, we wszystkich możliwych przypadkach żaden użytkownik nie będzie mógł uzyskać dostępu do aplikacji, chyba że potwierdza, że ma on licencję w chwili używania. Dodatkowo Zasada zapewnia nieco większe bezpieczeństwo niż ServerManagedPolicy, ponieważ dane nie są przechowywane lokalnie w pamięci podręcznej, więc szkodliwy użytkownik nie ma możliwości z danymi w pamięci podręcznej i uzyskać dostęp do aplikacji.
Jednocześnie Policy
stanowi wyzwanie dla zwykłych użytkowników, ponieważ
co oznacza, że aplikacja nie będzie dostępna, gdy nie będzie dostępna sieć.
(sieci komórkowe lub Wi-Fi). Kolejnym efektem ubocznym jest
będzie wysyłać do serwera więcej żądań sprawdzenia licencji, ponieważ
odpowiedź z pamięci podręcznej jest niemożliwa.
Zasadniczo ta zasada stanowi kompromis w pewnym stopniu wygody użytkowników
dla absolutnego bezpieczeństwa i kontroli dostępu. Dobrze zastanów się nad kompromisem
przed użyciem tego elementu (Policy
).
Aby użyć StrictPolicy, po prostu zaimportuj ją do aktywności, utwórz instancję
i przekazać odniesienie do niego podczas tworzenia LicenseChecker
. Zobacz
Instancje LicenseChecker i LicenseCheckerCallback
.
Typowa implementacja Policy
musi zapisać dane odpowiedzi licencji na:
aplikacji do pamięci trwałej, tak aby była dostępna
wywołań aplikacji i cykli zasilania urządzenia. Na przykład Policy
będzie
zachowaj sygnaturę czasową ostatniego pomyślnego sprawdzenia licencji, liczbę ponownych prób,
okresu ważności licencji i podobne informacje w trwałym magazynie,
zamiast resetowania wartości przy każdym uruchomieniu aplikacji.
domyślna wartość Policy
w LVL, ServerManagedPolicy, przechowuje odpowiedź licencji
w instancji SharedPreferences
, aby zapewnić,
są trwałe.
Ponieważ Policy
będzie wykorzystywać zapisane dane odpowiedzi licencji do określenia, czy
zezwala na dostęp aplikacji lub go nie zezwala, musi zagwarantować, że
przechowywane dane są bezpieczne i nie mogą być ponownie wykorzystywane ani modyfikowane przez roota w
urządzenia. W szczególności Policy
musi zawsze zaciemniać dane przed ich zapisaniem.
używając klucza, który jest unikalny dla aplikacji i urządzenia. Zaciemnianie kodu za pomocą
który jest kluczowy zarówno dla aplikacji, jak i urządzenia.
zapobiega udostępnianiu zaciemnionych danych między aplikacjami
urządzenia.
LVL pomaga aplikacji przechowywać dane odpowiedzi licencji w pliku
w bezpieczny i trwały sposób. Najpierw udostępnia Obfuscator
interfejsu, który pozwala aplikacji dostarczać algorytm zaciemniania kodu jej
wyboru zapisanych danych. Na tej podstawie LVL oferuje klasę pomocniczą,
PreferenceObfuscator, który obsługuje większość zadań związanych z wywoływaniem
klasy Obfuscator
aplikacji i odczytywanie i zapisywanie zaciemnionych danych w
SharedPreferences
instancję.
LVL zapewnia pełną implementację Obfuscator
o nazwie
AESObfuscator, który używa szyfrowania AES do zaciemniania danych. Dostępne opcje
używaj AESObfuscator w swojej aplikacji bez modyfikacji lub
aby dostosować ją do swoich potrzeb. Jeśli używasz Policy
(np.
ServerManagedPolicy), który buforuje dane odpowiedzi licencji przy użyciu AESObfuscator jako
jako podstawę wdrożenia Obfuscator
.
Więcej informacji znajdziesz w następnej sekcji.
AESObfuscator
Ocena LVL obejmuje pełną i zalecaną implementację interfejsu Obfuscator
interfejsu AESObfuscator. Implementacja jest zintegrowana z
Przykładowa aplikacja LVL służąca jako domyślna Obfuscator
w bibliotece.
AESObfuscator zapewnia bezpieczne zaciemnianie danych za pomocą AES do
szyfrować i odszyfrowywać dane w miarę ich zapisywania lub odczytywania.
Obfuscator
rozpoczyna szyfrowanie za pomocą 3 podanych pól danych
przez aplikację:
- Sól – tablica losowych bajtów, które mają być używane do każdego (usunięcia) zaciemnienia kodu.
- Ciąg identyfikatora aplikacji, zwykle nazwa pakietu aplikacji.
- Ciąg identyfikatora urządzenia pobrany na podstawie jak największej liczby źródeł związanych z określonym urządzeniem aby była jak najbardziej unikalna.
Aby używać AESObfuscator, najpierw zaimportuj go do aktywności. Deklarowanie prywatnego charakteru statyczna tablica końcowa do przechowywania bajtów zaburzających i inicjowania ich losowo na 20 wygenerowanych bajtów.
Kotlin
// Generate 20 random bytes, and put them here. private val SALT = byteArrayOf( -46, 65, 30, -128, -103, -57, 74, -64, 51, 88, -95, -45, 77, -117, -36, -113, -11, 32, -64, 89 )
Java
... // Generate 20 random bytes, and put them here. private static final byte[] SALT = new byte[] { -46, 65, 30, -128, -103, -57, 74, -64, 51, 88, -95, -45, 77, -117, -36, -113, -11, 32, -64, 89 }; ...
Następnie zadeklaruj zmienną do przechowywania identyfikatora urządzenia i generowania wartości dla:
w dowolny sposób. Na przykład przykładowa aplikacja uwzględniona w LVL
wysyła zapytanie do ustawień systemowych
android.Settings.Secure.ANDROID_ID
, która jest unikalna dla każdego urządzenia.
Pamiętaj, że w zależności od używanych interfejsów API aplikacja może wymagać
zażądać dodatkowych uprawnień w celu uzyskania informacji o urządzeniu.
Aby na przykład wysłać zapytanie do funkcji TelephonyManager
w celu uzyskania
numeru IMEI urządzenia ani powiązanych danych, aplikacja będzie musiała również
android.permission.READ_PHONE_STATE
w pliku manifestu.
Zanim poprosisz o nowe uprawnienia wyłączne w celu pozyskania
dotyczące konkretnego urządzenia na potrzeby Obfuscator
, rozważ
Jak to może wpłynąć na Twoją aplikację lub jej filtrowanie w Google Play?
(ponieważ niektóre uprawnienia mogą powodować, że narzędzia do kompilacji SDK
powiązany <uses-feature>
).
Na koniec utwórz instancję AESObfuscator, przekazując ciąg zaburzający,
identyfikatora aplikacji i urządzenia. Możesz utworzyć instancję
bezpośrednio podczas tworzenia Policy
i LicenseChecker
. Na przykład:
Kotlin
... // Construct the LicenseChecker with a Policy. private val checker = LicenseChecker( this, ServerManagedPolicy(this, AESObfuscator(SALT, packageName, deviceId)), BASE64_PUBLIC_KEY ) ...
Java
... // Construct the LicenseChecker with a Policy. checker = new LicenseChecker( this, new ServerManagedPolicy(this, new AESObfuscator(SALT, getPackageName(), deviceId)), BASE64_PUBLIC_KEY // Your public licensing key. ); ...
Pełny przykład znajdziesz w sekcji MainActivity w przykładowej aplikacji LVL.
Sprawdzanie licencji z działania
Gdy zaimplementujesz interfejs Policy
służący do zarządzania dostępem do aplikacji,
następnym krokiem jest dodanie do aplikacji sprawdzania licencji, co spowoduje uruchomienie zapytania
do serwera licencjonowania i w razie potrzeby zarządza dostępem do aplikacji na podstawie
odpowiedź dotyczącą licencji. Cała praca związana z dodawaniem sprawdzania licencji i obsługą
odpowiedź jest wykonywana w głównym pliku źródłowym Activity
.
Aby dodać sprawdzanie licencji i obsługiwać odpowiedź, musisz:
- Dodawanie importów
- Wdrożenie LicenseCheckerCallback jako prywatnej klasy wewnętrznej
- Utwórz moduł obsługi do publikowania z interfejsu LicenseCheckerCallback w wątku interfejsu użytkownika
- Instancje LicenseChecker i LicenseCheckerCallback
- Wywołaj funkcję checkAccess(), aby zainicjować sprawdzanie licencji
- Umieszczanie klucza publicznego na potrzeby licencjonowania
- Wywołaj metodę onDestroy() narzędzia LicenseChecker, aby zamknąć połączenia IPC.
Poniżej znajdziesz opis tych zadań.
Omówienie sprawdzania licencji i reagowania na nie
W większości przypadków należy dodać sprawdzanie licencji do głównego
Activity
w metodzie onCreate()
. Ten
pozwala zagwarantować, że przy
bezpośrednim uruchomieniu aplikacji przez użytkownika
zostanie wywołana natychmiast. W niektórych przypadkach możesz dodać kontrole licencji w innych
lokalizacji firmy. Jeśli na przykład aplikacja zawiera wiele aktywności
komponenty, które inne aplikacje mogą uruchamiać przez Intent
,
możesz dodać kontrole licencji do tych działań.
Sprawdzanie licencji składa się z 2 głównych działań:
- Wywołanie metody inicjowania sprawdzania licencji. W LVL jest to
wywołanie metody
checkAccess()
obiektuLicenseChecker
, tworzyć. - Wywołanie zwrotne, które zwraca wynik sprawdzania licencji. W LVL
implementowanego przez Ciebie interfejsu
LicenseCheckerCallback
. interfejs deklaruje 2 metody:allow()
orazdontAllow()
, które są wywoływane przez bibliotekę na podstawie argumentu w wyniku sprawdzania licencji. Implementujesz te dwie metody z dowolną logiką aby zezwolić użytkownikowi na dostęp do aplikacji lub go zablokować. Pamiętaj, że te metody nie określają, czy zezwolić na dostęp – za implementacjęPolicy
spoczywa na Tobie odpowiedzialność. raczej po prostu podają zachowania aplikacji i określają, jak zezwolić na zablokować dostęp (i obsługiwać błędy aplikacji).Metody
allow()
idontAllow()
podają „przyczynę” za odpowiedź, która może być jedną z wartościPolicy
,LICENSED
,NOT_LICENSED
, czyRETRY
. Zwróć szczególną uwagę na przypadki, w których metoda odbiera odpowiedźRETRY
dla zapytaniadontAllow()
i udostępnia użytkownikowi „Spróbuj ponownie” (Może się tak zdarzyć, gdy usługa była niedostępna w okresie użytkownika.
Na diagramie powyżej widać, jak odbywa się typowa weryfikacja licencji:
- Kod w głównej aktywności aplikacji tworzy instancję
LicenseCheckerCallback
iLicenseChecker
obiektów. Podczas tworzenia obiektuLicenseChecker
kod przekazujeContext
, implementacjaPolicy
, której należy użyć, oraz klucz publiczny konta wydawcy do licencjonowania jako parametry. - Następnie kod wywołuje metodę
checkAccess()
wLicenseChecker
obiekt. Implementacja metody wywołujePolicy
, aby określić, czy prawidłowa odpowiedź dotycząca licencji znajduje się w pamięci podręcznej lokalnie,SharedPreferences
- Jeśli tak, implementacja
checkAccess()
wywołujeallow()
- W przeciwnym razie
LicenseChecker
wysyła żądanie sprawdzenia licencji. do serwera licencjonowania.
Uwaga: serwer licencjonowania zawsze zwraca
LICENSED
podczas sprawdzania licencji wersji roboczej aplikacji. - Jeśli tak, implementacja
- Po otrzymaniu odpowiedzi
LicenseChecker
tworzy obiekt LicenseValidator, który weryfikuje dane podpisanej licencji i wyodrębnia pola odpowiedzi, a następnie przekazuje je doPolicy
do dalszej oceny.- Jeśli licencja jest ważna,
Policy
zapisuje odpowiedź w pamięci podręcznej wSharedPreferences
i powiadamia walidatora, który wywołuje metodęallow()
na obiekcieLicenseCheckerCallback
. - Jeśli licencja jest nieważna,
Policy
powiadamia walidatora, który wywołuje metodę metodędontAllow()
w tabeliLicenseCheckerCallback
.
- Jeśli licencja jest ważna,
- W przypadku możliwego do naprawienia błędu lokalnego lub serwera, np. gdy sieć
nie można wysłać żądania,
LicenseChecker
przekazuje odpowiedźRETRY
do metodyprocessServerResponse()
obiektuPolicy
.Ponadto metody wywołania zwrotnego
allow()
idontAllow()
otrzymują błądreason
argument. Przyczyna zastosowania metodyallow()
to zwyklePolicy.LICENSED
lubPolicy.RETRY
, a przyczynadontAllow()
to zwyklePolicy.NOT_LICENSED
lubPolicy.RETRY
. Te wartości odpowiedzi są przydatne, bo pokazują, odpowiednią odpowiedź dla użytkownika, na przykład „Ponów próbę”. gdydontAllow()
odpowiada przy użyciu elementuPolicy.RETRY
. Przyczyną może być to, że usługa niedostępna. - W przypadku błędu aplikacji, np. gdy aplikacja próbuje
sprawdź licencję na nieprawidłową nazwę pakietu,
LicenseChecker
zwraca błąd odpowiedź na żądanieapplicationError()
usługi LicenseCheckerCallback .
Pamiętaj, że oprócz zainicjowania sprawdzenia licencji i obsługi
które zostały opisane w poniższych sekcjach, aplikacja musi również
aby udostępnić wdrożenie zasad, a jeśli Policy
przechowuje dane odpowiedzi (takie jak ServerManagedPolicy) jako implementacja Obfuscator.
Dodaj importy
Najpierw otwórz plik zajęć w głównym działaniu aplikacji i zaimportuj
LicenseChecker
i LicenseCheckerCallback
z pakietu LVL.
Kotlin
import com.google.android.vending.licensing.LicenseChecker import com.google.android.vending.licensing.LicenseCheckerCallback
Java
import com.google.android.vending.licensing.LicenseChecker; import com.google.android.vending.licensing.LicenseCheckerCallback;
Jeśli używasz domyślnej implementacji Policy
udostępnionej w LVL,
ServerManagedPolicy, zaimportuj ją wraz z AESObfuscator. Jeśli jesteś
za pomocą niestandardowych Policy
lub Obfuscator
, zaimportuj je.
Kotlin
import com.google.android.vending.licensing.ServerManagedPolicy import com.google.android.vending.licensing.AESObfuscator
Java
import com.google.android.vending.licensing.ServerManagedPolicy; import com.google.android.vending.licensing.AESObfuscator;
Wdrożenie LicenseCheckerCallback jako prywatnej klasy wewnętrznej
LicenseCheckerCallback
to interfejs udostępniany przez LVL
w wyniku sprawdzania licencji. Aby zapewnić obsługę licencjonowania z użyciem LVL, musisz:
zaimplementuj LicenseCheckerCallback
i
oraz metody zezwalania na dostęp do aplikacji lub jej blokowania.
Wynikiem sprawdzenia licencji jest zawsze wywołanie jednego z
LicenseCheckerCallback
metod, utworzonych na podstawie weryfikacji odpowiedzi
ładunek, kod odpowiedzi serwera i wszelkie dodatkowe
przez Policy
. Aplikacja może implementować te metody w dowolny potrzebny sposób. W
więc metody powinny być proste, ograniczając się do zarządzania interfejsem użytkownika
stanu i dostępu do aplikacji. Jeśli chcesz dodać dalsze przetwarzanie licencji
odpowiedzi, na przykład przez skontaktowanie się z serwerem backendu lub zastosowanie niestandardowych ograniczeń,
spróbuj użyć kodu w Policy
, zamiast
w metodach LicenseCheckerCallback
.
W większości przypadków należy zadeklarować implementację
LicenseCheckerCallback
jako klasa prywatna w głównej aplikacji
Zajęcia.
Zaimplementuj metody allow()
i dontAllow()
jako
niezbędną. Na początek można skorzystać z prostych sposobów obsługi wyników w interfejsie
takie jak wyświetlenie wyniku licencji w oknie. Dzięki temu uzyskasz
która działa szybciej i może pomóc w debugowaniu. Później, po
możesz określić
żądane przez Ciebie zachowania, możesz dodać bardziej złożoną obsługę.
Niektóre sugestie dotyczące postępowania z nielicencjonowanymi odpowiedziami w
dontAllow()
, w tym:
- Wyświetl komunikat „Spróbuj ponownie”. okno, w tym przycisk do rozpoczynania
sprawdzanie nowej licencji, czy dostarczony
reason
toPolicy.RETRY
. - Wyświetlaj tekst „Kup tę aplikację”. wraz z przyciskiem precyzyjny link do strony z informacjami o aplikacji w Google Play, na której użytkownik może kupić tę aplikację. Więcej informacji na temat konfigurowania przeczytaj artykuł Tworzenie linków do Twoich produktów.
- Wyświetli powiadomienie Toast informujące, że funkcje aplikacji są ograniczone, ponieważ nie jest objęta licencją.
Poniższy przykład pokazuje, jak przykładowa aplikacja LVL implementuje
LicenseCheckerCallback
, przy użyciu metod, które wyświetlają sprawdzenie licencji,
.
Kotlin
private inner class MyLicenseCheckerCallback : LicenseCheckerCallback { override fun allow(reason: Int) { if (isFinishing) { // Don't update UI if Activity is finishing. return } // Should allow user access. displayResult(getString(R.string.allow)) } override fun dontAllow(reason: Int) { if (isFinishing) { // Don't update UI if Activity is finishing. return } displayResult(getString(R.string.dont_allow)) if (reason == Policy.RETRY) { // If the reason received from the policy is RETRY, it was probably // due to a loss of connection with the service, so we should give the // user a chance to retry. So show a dialog to retry. showDialog(DIALOG_RETRY) } else { // Otherwise, the user isn't licensed to use this app. // Your response should always inform the user that the application // isn't licensed, but your behavior at that point can vary. You might // provide the user a limited access version of your app or you can // take them to Google Play to purchase the app. showDialog(DIALOG_GOTOMARKET) } } }
Java
private class MyLicenseCheckerCallback implements LicenseCheckerCallback { public void allow(int reason) { if (isFinishing()) { // Don't update UI if Activity is finishing. return; } // Should allow user access. displayResult(getString(R.string.allow)); } public void dontAllow(int reason) { if (isFinishing()) { // Don't update UI if Activity is finishing. return; } displayResult(getString(R.string.dont_allow)); if (reason == Policy.RETRY) { // If the reason received from the policy is RETRY, it was probably // due to a loss of connection with the service, so we should give the // user a chance to retry. So show a dialog to retry. showDialog(DIALOG_RETRY); } else { // Otherwise, the user isn't licensed to use this app. // Your response should always inform the user that the application // isn't licensed, but your behavior at that point can vary. You might // provide the user a limited access version of your app or you can // take them to Google Play to purchase the app. showDialog(DIALOG_GOTOMARKET); } } }
Dodatkowo należy zaimplementować applicationError()
którą LVL wywołuje, aby umożliwić aplikacji obsługę błędów, które nie są
można spróbować ponownie. Listę takich błędów znajdziesz w sekcji Serwer
Kody odpowiedzi w dokumentacji dotyczącej licencji. Możesz zastosować
przy użyciu tej metody. W większości przypadków
powinna rejestrować kod błędu i wywoływać funkcję dontAllow()
.
Utwórz moduł obsługi publikowania z poziomu LicenseCheckerCallback do wątku UI
Podczas sprawdzania licencji LVL przekazuje żądanie do Google Play.
która obsługuje komunikację z serwerem licencji. POZIOM
przekazuje żądanie przez asynchroniczny IPC (za pomocą Binder
), więc
faktyczne przetwarzanie i komunikacja sieciowa nie odbywają się w wątku.
zarządzane przez Twoją aplikację. Gdy aplikacja Google Play
odbiera wynik, wywołuje metodę wywołania zwrotnego przez IPC, która z kolei
są wykonywane w puli wątków IPC w procesie aplikacji.
Klasa LicenseChecker
zarządza komunikacją IPC aplikacji z
aplikacji Google Play, m.in. wywołania, które wysyła żądanie,
wywołanie zwrotne, które otrzyma odpowiedź. LicenseChecker
śledzi także licencję otwartą
i zarządza ich limitami czasu.
Aby poprawnie obsługiwał czas oczekiwania i przetwarzał przychodzące odpowiedzi
bez wpływu na wątek UI aplikacji, funkcja LicenseChecker
tworzy
wątku w tle podczas tworzenia wystąpienia. W wątku przetwarza w całości
wyniki sprawdzania licencji, czy wynik to odpowiedź otrzymana z serwera;
lub błąd przekroczenia limitu czasu. Po zakończeniu weryfikacji LVL wywołuje
LicenseCheckerCallback
metod z wątku w tle.
Dla Twojej aplikacji oznacza to, że:
- W wielu przypadkach Twoje metody
LicenseCheckerCallback
będą wywoływane z w wątku w tle. - Te metody nie będą w stanie zaktualizować stanu ani wywołać żadnego przetwarzania w wątku UI, chyba że utworzysz w wątku interfejsu moduł obsługi i otrzymasz wywołanie zwrotne. do modułu obsługi.
Jeśli chcesz, aby metody LicenseCheckerCallback
aktualizowały wątek UI,
utwórz instancję Handler
w głównym działaniu
onCreate()
,
jak pokazano poniżej. W tym przykładzie kod LVL przykładowej aplikacji
Metody LicenseCheckerCallback
(patrz wyżej) wywołują metodę displayResult()
do
zaktualizuj wątek UI za pomocą
post()
.
Kotlin
private lateinit var handler: Handler override fun onCreate(savedInstanceState: Bundle?) { ... handler = Handler() }
Java
private Handler handler; @Override public void onCreate(Bundle savedInstanceState) { ... handler = new Handler(); }
Następnie w metodach LicenseCheckerCallback
możesz używać metod modułu obsługi, aby
po przesłaniu obiektów Runnable lub Message do modułu obsługi. Przykład
aplikacja uwzględniona w LVL przesyła element wykonywalny do modułu obsługi w wątku UI
aby wyświetlić stan licencji.
Kotlin
private fun displayResult(result: String) { handler.post { statusText.text = result setProgressBarIndeterminateVisibility(false) checkLicenseButton.isEnabled = true } }
Java
private void displayResult(final String result) { handler.post(new Runnable() { public void run() { statusText.setText(result); setProgressBarIndeterminateVisibility(false); checkLicenseButton.setEnabled(true); } }); }
Tworzenie instancji LicenseChecker i LicenseCheckerCallback
W sekcji Aktywność
onCreate()
,
Tworzenie prywatnych instancji LicenseCheckerCallback i LicenseChecker
. Musisz
utwórz najpierw instancję LicenseCheckerCallback
, ponieważ trzeba przekazać odwołanie
do tej instancji przy wywołaniu konstruktora dla LicenseChecker
.
Podczas tworzenia instancji LicenseChecker
musisz przekazać te parametry:
- Aplikacja
Context
- Odwołanie do implementacji
Policy
, która ma być używana do sprawdzania licencji. W w większości przypadków należy użyć domyślnej implementacjiPolicy
udostępnionej przez LVL, ServerManagedPolicy. - Zmienna String zawierająca klucz publiczny Twojego konta wydawcy dla licencji.
Jeśli korzystasz z ServerManagedPolicy, nie potrzebujesz dostępu do klasy
bezpośrednio, co pozwala utworzyć jej instancję w konstruktorze LicenseChecker
,
jak widać w przykładzie poniżej. Pamiętaj, że musisz przekazać odwołanie do nowego elementu
Instancja zaciemniania kodu podczas tworzenia instancji ServerManagedPolicy.
Przykład poniżej pokazuje utworzenie instancji LicenseChecker
oraz
LicenseCheckerCallback
z metody onCreate()
aktywności
zajęcia.
Kotlin
class MainActivity : AppCompatActivity() { ... private lateinit var licenseCheckerCallback: LicenseCheckerCallback private lateinit var checker: LicenseChecker override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ... // Construct the LicenseCheckerCallback. The library calls this when done. licenseCheckerCallback = MyLicenseCheckerCallback() // Construct the LicenseChecker with a Policy. checker = LicenseChecker( this, ServerManagedPolicy(this, AESObfuscator(SALT, packageName, deviceId)), BASE64_PUBLIC_KEY // Your public licensing key. ) ... } }
Java
public class MainActivity extends Activity { ... private LicenseCheckerCallback licenseCheckerCallback; private LicenseChecker checker; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // Construct the LicenseCheckerCallback. The library calls this when done. licenseCheckerCallback = new MyLicenseCheckerCallback(); // Construct the LicenseChecker with a Policy. checker = new LicenseChecker( this, new ServerManagedPolicy(this, new AESObfuscator(SALT, getPackageName(), deviceId)), BASE64_PUBLIC_KEY // Your public licensing key. ); ... } }
Pamiętaj, że funkcja LicenseChecker
wywołuje z interfejsu metody LicenseCheckerCallback
.
do wątku tylko wtedy, gdy poprawna odpowiedź dotycząca licencji znajduje się w pamięci podręcznej. Jeśli
informacje o sprawdzaniu licencji są wysyłane do serwera, wywołania zwrotne zawsze pochodzą z adresu
w tle, nawet w przypadku błędów sieci.
Wywołaj funkcję checkAccess(), aby rozpocząć sprawdzanie licencji
W głównej aktywności dodaj wywołanie do metody checkAccess()
funkcji
LicenseChecker
instancję. Podczas rozmowy przekaż odniesienie do swojego
wystąpienie LicenseCheckerCallback
jako parametr. Jeśli chcesz zareagować
efekty specjalne lub zarządzanie stanem przed rozmową, może Ci się przydać
aby wywołać checkAccess()
z metody kodu. Na przykład parametr LVL
przykładowa aplikacja wywołuje metodę checkAccess()
z
Metoda opakowań doCheck()
:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ... // Call a wrapper method that initiates the license check doCheck() ... } ... private fun doCheck() { checkLicenseButton.isEnabled = false setProgressBarIndeterminateVisibility(true) statusText.setText(R.string.checking_license) checker.checkAccess(licenseCheckerCallback) }
Java
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // Call a wrapper method that initiates the license check doCheck(); ... } ... private void doCheck() { checkLicenseButton.setEnabled(false); setProgressBarIndeterminateVisibility(true); statusText.setText(R.string.checking_license); checker.checkAccess(licenseCheckerCallback); }
Umieszczanie klucza publicznego na potrzeby licencjonowania
W przypadku każdej aplikacji Usługa Google Play automatycznie generuje 2048-bitową parę kluczy RSA (publiczny/prywatny), która jest używana i rozliczenia w aplikacji. Para kluczy jest jednoznacznie powiązana z aplikacji. Chociaż są powiązane z aplikacją, para kluczy jest inny niż klucz, którego używasz do podpisywania aplikacji (lub pochodnego od niego).
Konsola Google Play ujawnia klucz publiczny do licencjonowania zalogowany do Konsoli Play, ale zachowuje klucz prywatny ukryte przed wszystkimi użytkownikami w bezpiecznej lokalizacji. Gdy aplikacja poprosi o sprawdzanie licencji na aplikację opublikowaną na Twoim koncie, serwer licencjonowania podpisuje odpowiedź licencji przy użyciu klucza prywatnego pary kluczy aplikacji. Gdy LVL otrzyma odpowiedź, używa klucza publicznego dostarczonego przez aplikacji do zweryfikowania podpisu odpowiedzi licencji.
Aby dodać licencję do aplikacji, musisz uzyskać: klucz publiczny do licencjonowania i skopiuj go do aplikacji. Oto jak znaleźć: klucz publiczny aplikacji do licencjonowania:
- Otwórz Konsolę Google Play i zaloguj się. Pamiętaj, aby zalogować się na konto, z którego aplikacja została stworzona licencji zostanie opublikowane (lub zostanie opublikowane).
- Na stronie z informacjami o aplikacji znajdź sekcję Usługi i Interfejsy API i kliknij go.
- W sekcji Usługi i API, znajdź Licencjonowanie Rozliczenia w aplikacji. Twój klucz publiczny dla jest udzielana w Twój klucz licencyjny tej aplikacji.
Aby dodać klucz publiczny do aplikacji, po prostu skopiuj i wklej ten klucz
z pola do aplikacji jako wartość zmiennej String,
BASE64_PUBLIC_KEY
Przy kopiowaniu upewnij się, że masz
zaznaczono cały ciąg klucza, nie pomijając żadnych znaków.
Oto przykład z przykładowej aplikacji LVL:
Kotlin
private const val BASE64_PUBLIC_KEY = "MIIBIjANBgkqhkiG ... " //truncated for this example class LicensingActivity : AppCompatActivity() { ... }
Java
public class MainActivity extends Activity { private static final String BASE64_PUBLIC_KEY = "MIIBIjANBgkqhkiG ... "; //truncated for this example ... }
Wywoływanie metody onDestroy() używanego narzędzia LicenseChecker zamykanie połączeń IPC
Pozwól LVL oczyścić się przed zgłoszeniem
Context
– zmiany, dodaj wywołanie do: LicenseChecker
Metoda onDestroy()
z modułu aktywności
onDestroy()
. Wywołanie powoduje, że
LicenseChecker
, aby prawidłowo zamknąć otwarte połączenie IPC z Google Play.
ILicensingService aplikacji i usunie wszelkie lokalne odwołania do tej usługi.
i moduł obsługi.
Nie udało się wywołać metody onDestroy()
metody LicenseChecker
może powodować problemy w trakcie cyklu życia aplikacji. Na przykład, jeśli plik
użytkownik zmieni orientację ekranu, gdy jest aktywne sprawdzanie licencji,
Element Context
został zniszczony. Jeśli Twoja aplikacja nie
poprawnie zamknij połączenie IPC LicenseChecker
, aplikacja ulegnie awarii
po otrzymaniu odpowiedzi. Podobnie, jeśli użytkownik zamknie aplikację
a w trakcie sprawdzania licencji aplikacja ulegnie awarii, gdy
otrzymano odpowiedź, chyba że poprawnie wywołała
Metoda onDestroy()
przeglądarki LicenseChecker
do odłączenia od usługi.
Oto przykład z przykładowej aplikacji uwzględnionej w LVL, gdzie
mChecker
to instancja LicenseChecker
:
Kotlin
override fun onDestroy() { super.onDestroy() checker.onDestroy() ... }
Java
@Override protected void onDestroy() { super.onDestroy(); checker.onDestroy(); ... }
Jeśli rozszerzasz lub modyfikujesz numer LicenseChecker
, konieczne może być również wywołanie
metody finishCheck()
interfejsu LicenseChecker
, aby wyczyścić otwarte IPC.
połączeń.
Stosowanie ograniczenia liczby urządzeń
W niektórych przypadkach Policy
może ograniczać liczbę rzeczywistych
które mogą korzystać z 1 licencji. Uniemożliwiłoby to użytkownikowi
przeniesienia licencjonowanej aplikacji na wiele urządzeń
aplikacji na tych urządzeniach z tym samym identyfikatorem konta. Zapobiegłoby to również
użytkownik z „udostępniania” przez podanie informacji o koncie,
związane z licencją
innych osób, które mogą się do niej zalogować
konta na swoich urządzeniach i uzyskać dostęp do licencji na aplikację.
LVL wspiera licencjonowanie dla poszczególnych urządzeń, udostępniając
DeviceLimiter
, który deklaruje jedną metodę,
allowDeviceAccess()
Gdy zasób LicenseValidator obsługuje odpowiedź
z serwera licencjonowania wywołuje funkcję allowDeviceAccess()
, przekazując w ten sposób
identyfikator użytkownika wyodrębniony z odpowiedzi.
Jeśli nie chcesz stosować ograniczeń dotyczących urządzeń, żadna praca nie jest
wymagane – klasa LicenseChecker
automatycznie używa wartości domyślnej
implementacji o nazwie NullDeviceLimiter. Jak sama nazwa wskazuje, NullDeviceLimiter
nie jest operacją klasa, której metoda allowDeviceAccess()
zwraca po prostu
odpowiedź LICENSED
dla wszystkich użytkowników i urządzeń.
Uwaga: licencjonowanie na poziomie urządzenia nie jest zalecane w przypadku dla większości aplikacji, ponieważ:
- Wymaga udostępnienia serwera backendu do zarządzania użytkownikami i urządzeniami mapowanie,
- Odebranie użytkownikowi dostępu do które w uprawniony sposób kupiły na innym urządzeniu.
Zaciemnianie kodu
Aby zapewnić bezpieczeństwo aplikacji, zwłaszcza w przypadku płatnej aplikacji korzystającej z licencjonowania lub niestandardowych ograniczeń i zabezpieczeń, ważne jest, aby zaciemniać kod aplikacji. Prawidłowo zaciemnianie kodu utrudnia złośliwemu użytkownikowi dekompilację kodu bajtowego, modyfikować go, np. usuwając weryfikację licencji – i skompilować go na nowo.
Dostępnych jest kilka programów do zaciemniania kodu dla aplikacji na Androida, w tym ProGuard, która oferuje również funkcje optymalizacji kodu. użycie ProGuard lub podobnego programu do zaciemniania kodu. Twój kod jest zdecydowanie zalecany dla wszystkich aplikacji, które korzystają z usług Google Zagraj w Licencjonowanie.
Publikowanie licencjonowanej aplikacji
Po zakończeniu testowania implementacji licencji możesz opublikować aplikację w Google Play. Wykonaj zwykłe czynności, aby przygotować, podpisać, a następnie opublikować aplikację.
Gdzie uzyskać pomoc
W przypadku pytań lub problemów przy wdrażaniu podczas publikowania w aplikacjach, skorzystaj z zasobów pomocy wymienionych w tabeli poniżej. Kierując swoje pytania na właściwe forum, uzyskasz uzyskać pomoc w krótszym czasie.
Typ pomocy | Zasób | Zakres tematów |
---|---|---|
Problemy podczas programowania i testowania | Grupy dyskusyjne Google: android-developers | Pobieranie i integracja LVL, projekty biblioteczne, Policy
pytania, pomysły na wrażenia użytkownika, obsługa odpowiedzi, Obfuscator , IPC, test
konfiguracja środowiska |
Stack Overflow: http://stackoverflow.com/questions/tagged/android | ||
Problemy z kontami, publikowaniem i wdrażaniem | Google Play. Forum pomocy | Konta wydawcy, para kluczy licencyjnych, konta testowe, serwer odpowiedzi, odpowiedzi testowe, wdrażanie aplikacji i wyniki |
Rynek Pomoc dotycząca licencji – najczęstsze pytania | ||
Tracker problemów LVL | Licencjonowanie rynkowe narzędzie do rejestrowania problemów w projekcie | Zgłoszenia błędów i problemów związane konkretnie z klasami kodu źródłowego LVL i implementacjach interfejsu |
Ogólne informacje o publikowaniu w grupach wymienionych powyżej znajdziesz w sekcji Zasoby społeczności. na stronie Zasoby pomocy dla programistów.
Dodatkowe materiały
Przykładowa aplikacja dołączona do LVL zawiera pełny przykład tego,
aby rozpocząć sprawdzanie licencji i obsługować wynik,
MainActivity
zajęcia.