Avviso : quando l'app esegue la procedura di verifica della licenza su lato client, è più facile per i potenziali utenti malintenzionati modificare o rimuovere la logica associata a questo processo di verifica.
Per questo motivo, ti invitiamo vivamente a eseguire l'upgrade sul lato server verifica delle licenze.
Dopo aver configurato un account publisher e un ambiente di sviluppo (consulta la sezione Configurazione delle licenze), puoi aggiungere la verifica della licenza a l'app con la License Verification Library (LVL).
L'aggiunta della verifica della licenza con LVL prevede le seguenti attività:
- Aggiungi l'autorizzazione per la licenza al file manifest della tua applicazione.
- Implementazione di un criterio: puoi scegliere una delle implementazioni complete fornite nella LVL o crearne una personalizzata.
- Implementare un Offuscatore, se
Policy
memorizzerà nella cache i dati delle risposte alle licenze. - Aggiunta di codice per verificare la licenza nella pagina principale dell'applicazione Attività.
- Implementare un DeviceLimiter (facoltativo e non consigliato per per la maggior parte delle applicazioni).
Nelle sezioni seguenti vengono descritte queste attività. Al termine integrazione, dovresti essere in grado di compilare correttamente la tua applicazione e iniziare il test, come descritto in Configurazione del test Ambiente.
Per una panoramica del set completo di file sorgente inclusi nella LVL, consulta il Riepilogo delle classi LVL. e interfacce.
Aggiunta dell'autorizzazione di licenza
Per utilizzare l'applicazione Google Play per inviare un controllo delle licenze al
server, l'applicazione deve richiedere l'autorizzazione appropriata,
com.android.vending.CHECK_LICENSE
. Se la tua applicazione
non dichiara l'autorizzazione per la licenza, ma tenta di avviare un controllo delle licenze,
l'LVL genera un'eccezione di sicurezza.
Per richiedere l'autorizzazione per la licenza nella tua domanda, dichiara un <uses-permission>
come elemento secondario di <manifest>
, come segue:
<uses-permission
android:name="com.android.vending.CHECK_LICENSE" />
Ad esempio, ecco come l'applicazione di esempio LVL dichiara l'autorizzazione:
<?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>
Nota:al momento non puoi dichiarare
CHECK_LICENSE
nel manifest del progetto della libreria LVL,
perché SDK Tools non lo unisce nei manifest dei pod
diverse applicazioni. Devi invece dichiarare l'autorizzazione in ogni dipendente
del file manifest dell'applicazione.
Implementazione di un criterio
Il servizio di licenze di Google Play non determina autonomamente se un
l'utente a cui è stata assegnata una determinata licenza dovrebbe avere accesso alla tua applicazione.
Questa responsabilità è invece lasciata all'implementazione di Policy
che fornisci tu.
nella tua applicazione.
Il criterio è un'interfaccia dichiarata dalla LVL, progettata per contenere le tue
la logica dell'applicazione per consentire o impedire l'accesso dell'utente, in base al risultato
di un controllo delle licenze. Per utilizzare l'LVL, la tua applicazione deve fornire una
implementazione di Policy
.
L'interfaccia Policy
dichiara due metodi, allowAccess()
e
processServerResponse()
, che vengono chiamati da un LicenseChecker
durante l'elaborazione di una risposta dal server delle licenze. Inoltre, dichiara
enum chiamato LicenseResponse
, che specifica la risposta della licenza
valore trasmesso nelle chiamate a processServerResponse()
.
processServerResponse()
ti consente di pre-elaborare la risposta non elaborata i dati ricevuti dal server delle licenze, prima di stabilire se concedere l'accesso.Una tipica implementazione estrae alcuni o tutti i campi dalla licenza di risposta e archiviare i dati localmente in un archivio permanente, ad esempio
SharedPreferences
di spazio di archiviazione per garantire che i dati accessibile tramite chiamate delle applicazioni e cicli di spegnimento e riaccensione dei dispositivi. Ad esempio:Policy
manterrà il timestamp dell'ultimo controllo della licenza riuscito, numero di nuovi tentativi, il periodo di validità della licenza e informazioni simili in un un archivio permanente, anziché reimpostare i valori ogni volta che l'applicazione è stato avviato.Quando i dati delle risposte vengono archiviati localmente,
Policy
deve garantire che i dati offuscato (vedi Implementazione di un offuscatore, di seguito).allowAccess()
stabilisce se concedere all'utente l'accesso a la tua applicazione, in base a tutti i dati disponibili per le risposte alle licenze (da server di licenze o dalla cache) o altre informazioni specifiche dell'applicazione. Per Ad esempio, la tua implementazione diallowAccess()
potrebbe prevedere criteri aggiuntivi dell'account, come l'utilizzo o altri dati recuperati da un di backend. In tutti i casi, un'implementazione diallowAccess()
deve restituiretrue
solo se l'utente dispone della licenza per utilizzare il come stabilito dal server di licenze o se è presente una problema di rete o di sistema che impedisce il completamento del controllo della licenza. Nella in questi casi, la tua implementazione può mantenere un conteggio delle risposte di nuovo tentativo e consentire temporaneamente l'accesso fino al completamento del successivo controllo della licenza.
Per semplificare la procedura di aggiunta delle licenze alla tua applicazione e
fornire un'illustrazione di come dovrebbe essere progettato un Policy
, l'LVL include
due implementazioni complete di Policy
, che puoi utilizzare senza modifiche o
alle tue esigenze:
- ServerManagedPolicy, un'istanza di
Policy
flessibile che utilizza le impostazioni fornite dal server e le risposte memorizzate nella cache per gestire l'accesso su condizioni di rete diverse. - StrictPolicy, che non memorizza nella cache nessuna risposta e consente l'accesso solo se il server restituisce un oggetto la risposta corretta.
Per la maggior parte delle applicazioni, l'uso di ServerManagedPolicy è molto consigliato. ServerManagedPolicy è l'impostazione predefinita di LVL ed è integrata dell'applicazione di esempio LVL.
Linee guida per le norme personalizzate
Nell'implementazione delle licenze, puoi usare una delle norme complete specificato nel valore LVL (ServerManagedPolicy o StrictPolicy) oppure puoi creare un una norma personalizzata. Per qualsiasi tipo di norma personalizzata, esistono diverse impostazioni importanti i punti da comprendere e tenere in considerazione nell'implementazione.
Il server di licenze applica limiti generali alle richieste per evitare un utilizzo eccessivo di risorse che potrebbero causare un denial of service. Quando un'applicazione supera il limite di richieste, il server di licenze restituisce una risposta 503, che trasmesso all'applicazione come un errore generale del server. Ciò significa che la risposta relativa alle licenze sarà disponibile per l'utente fino alla reimpostazione del limite, possono influire sull'utente per un periodo indefinito.
Se stai progettando una norma personalizzata, ti consigliamo di fare in modo che Policy
:
- Memorizza nella cache (e offusca correttamente) la risposta alla licenza più recente con esito positivo nello spazio di archiviazione permanente locale.
- Restituisce la risposta memorizzata nella cache per tutti i controlli delle licenze, finché
la risposta memorizzata nella cache sia valida, anziché effettuare una richiesta al server di licenze.
Impostazione della validità della risposta in base al valore
VT
fornito dal server è vivamente consigliato. Consulta Ulteriori opzioni per le risposte del server per ulteriori informazioni. - Utilizza un periodo di backoff esponenziale se ritenta eventuali richieste del risultato
errori. Tieni presente che i nuovi tentativi automatici del client Google Play non sono andati a buon fine.
pertanto, nella maggior parte dei casi non è necessario che il tuo
Policy
esegua un nuovo tentativo. - Prevede un "periodo di tolleranza" che permette all'utente di accedere per un periodo di tempo limitato o per un numero di utilizzi, mentre è in corso il controllo delle licenze. nuovo tentativo. Il periodo di tolleranza va a vantaggio dell'utente, in quanto consente l'accesso fino al successivo controllo delle licenze può essere completato correttamente e avvantaggiarti inserendo un se non è disponibile una risposta valida per l'accesso alla tua applicazione disponibili.
Progettare il Policy
secondo le linee guida indicate sopra è fondamentale,
perché garantisce la migliore esperienza possibile agli utenti offrendoti
un controllo efficace sull'applicazione anche in condizioni di errore.
Tieni presente che qualsiasi Policy
può utilizzare le impostazioni fornite dal server di licenze per
consentono di gestire la validità e la memorizzazione nella cache, il periodo di tolleranza per i nuovi tentativi e altro ancora. L'estrazione del
le impostazioni fornite dal server sono semplici e il loro utilizzo è molto
consigliato. Vedi l'implementazione di ServerManagedPolicy per un esempio di come
estrarre e utilizzare gli extra. Per un elenco delle impostazioni del server e informazioni su
su come utilizzarle, consulta Risposta del server
Extra.
Criterio gestito dal server
La LVL include un'implementazione completa e consigliata dell'Policy
chiamata ServerManagedPolicy. L'implementazione è integrata
LVL e il valore predefinito è Policy
nella raccolta.
ServerManagedPolicy fornisce tutte le funzionalità di gestione della licenza e riprova
diverse. Memorizza nella cache tutti i dati delle risposte localmente in un
SharedPreferences
, offuscandolo con
dell'applicazione Obfuscator
. Ciò garantisce che la risposta relativa alla licenza
i dati sono sicuri e permangono per tutti i cicli di spegnimento e riaccensione del dispositivo. Criterio gestito dal server
fornisce implementazioni concrete dei metodi di interfaccia
processServerResponse()
, allowAccess()
e anche
include una serie di metodi e tipologie di supporto per la gestione delle licenze
diverse.
È importante sottolineare che una funzionalità chiave di ServerManagedPolicy è l'uso di
le impostazioni fornite dal server come base per la gestione delle licenze in
dell'applicazione in base a diverse condizioni di rete e di errore.
Quando un'applicazione contatta il server di Google Play per un controllo delle licenze,
aggiunge diverse impostazioni sotto forma di coppie chiave/valore nel campo degli extra di alcune
tipi di risposte alle licenze. Ad esempio, il server fornisce valori consigliati per
periodo di validità della licenza dell'applicazione, periodo di tolleranza per i nuovi tentativi e limite massimo consentito
numero di nuovi tentativi. ServerManagedPolicy estrae i valori dalla classe
risposta alla licenza nel relativo metodo processServerResponse()
e nei controlli
nel suo metodo allowAccess()
. Per un elenco dei parametri forniti dal server
utilizzate da ServerManagedPolicy, consulta Risposta del server
Extra.
Per comodità, prestazioni ottimali e vantaggio dell'utilizzo delle impostazioni delle licenze
dal server di Google Play, utilizzando ServerManagedPolicy come
è vivamente consigliata la licenza di Policy
.
Se sei preoccupato per la sicurezza dei dati delle risposte alle licenze che vengono
archiviati localmente in SharedPreferences
, puoi utilizzare un offuscamento più forte
o progettare un Policy
più restrittivo che non archivi i dati delle licenze. LVL
include un esempio di Policy
. Consulta StrictPolicy per ulteriori informazioni.
Per utilizzare ServerManagedPolicy, importalo nella tua attività, crea un
e passiamo un riferimento all'istanza quando crei
LicenseChecker
. Consulta Creare istanze di LicenseChecker e
LicenseCheckerCallback per ulteriori informazioni.
Criteriorigoroso
L'LVL include un'implementazione completa alternativa dell'interfaccia Policy
chiamato StrictPolicy. L'implementazione di StrictPolicy offre una limitazione
rispetto a ServerManagedPolicy, in quanto non consente all'utente di accedere
l'applicazione a meno che non venga ricevuta una risposta relativa alla licenza dal server all'indirizzo
che indica che l'utente dispone della licenza.
La funzionalità principale di StrictPolicy è che non memorizza nessuno
i dati delle risposte alle licenze localmente, in un archivio permanente. Poiché non vengono archiviati dati,
le richieste di nuovo tentativo non vengono monitorate e le risposte memorizzate nella cache non possono essere utilizzate per soddisfare
controlli delle licenze. Policy
consente l'accesso solo se:
- La risposta relativa alla licenza viene ricevuta dal server di licenze e
- La risposta relativa alla licenza indica che l'utente dispone della licenza per accedere al un'applicazione.
L'utilizzo di StrictPolicy è appropriato se la tua principale preoccupazione è garantire che, in tutti i casi possibili, nessun utente sarà autorizzato ad accedere all'applicazione a meno che viene confermato che l'utente è autorizzato al momento dell'utilizzo. Inoltre, Policy Controller offre una sicurezza leggermente superiore rispetto a ServerManagedPolicy, poiché non ci sono dati memorizzati nella cache locale, non c'è modo che un utente malintenzionato possa manomettere con i dati memorizzati nella cache e di ottenere l'accesso all'applicazione.
Allo stesso tempo, questo Policy
rappresenta una sfida per gli utenti normali, poiché
significa che non potranno accedere all'applicazione in assenza di rete
(rete cellulare o Wi-Fi) disponibile. Un altro effetto collaterale è che
invierà al server più richieste di controllo delle licenze, poiché l'uso di
non è possibile ottenere una risposta memorizzata nella cache.
Nel complesso, queste norme rappresentano un compromesso tra la praticità degli utenti
per una sicurezza assoluta
e un controllo sull'accesso. Valuta il compromesso con attenzione
prima di utilizzare questo Policy
.
Per utilizzare StrictPolicy, importalo nella tua attività, crea un'istanza,
e passare un riferimento a quest'ultimo durante la creazione di LicenseChecker
. Consulta
Istanziare LicenseChecker e LicenseCheckerCallback
per ulteriori informazioni.
Una tipica implementazione di Policy
deve salvare i dati delle risposte alle licenze per
di un'applicazione in un archivio permanente, in modo che sia accessibile
le chiamate alle applicazioni e i cicli di spegnimento e riaccensione del dispositivo. Ad esempio, Policy
mantenere il timestamp dell'ultimo controllo
della licenza riuscito, il numero di nuovi tentativi
il periodo di validità della licenza e informazioni simili in un archivio permanente,
anziché reimpostare i valori a ogni avvio dell'applicazione. La
Policy
predefinito incluso in LVL, ServerManagedPolicy, archivia risposta alla licenza
di dati in un'istanza SharedPreferences
, per garantire che
i dati sono permanenti.
Perché Policy
utilizzerà i dati delle risposte alle licenze memorizzati per determinare se
per consentire o negare l'accesso all'applicazione, deve garantire che qualsiasi
i dati archiviati sono sicuri e non possono essere riutilizzati o manipolati da un utente root su un
dispositivo. Nello specifico, Policy
deve sempre offuscare i dati prima di archiviarli
utilizzando una chiave univoca per l'applicazione e il dispositivo. Offuscamento tramite
una chiave specifica per l'applicazione e per il dispositivo è fondamentale,
impedisce la condivisione dei dati offuscati tra le applicazioni
dispositivi mobili.
L'LVL aiuta l'applicazione ad archiviare i dati delle risposte alle licenze in un
sicura e persistente. Innanzitutto, fornisce un valore Obfuscator
che consenta all'applicazione di fornire l'algoritmo di offuscamento
per i dati archiviati. Basandosi su questo, l'LVL fornisce la classe di supporto
PreferenceObfuscator, che gestisce la maggior parte del lavoro di chiamata
Obfuscator
dell'applicazione e di leggere e scrivere i dati offuscati in un
SharedPreferences
istanza.
L'LVL fornisce un'implementazione Obfuscator
completa denominata
AESObfuscator che utilizza la crittografia AES per offuscare i dati. Puoi
Utilizzare AESObfuscator nella tua applicazione senza modifiche o
adattarlo alle tue esigenze. Se utilizzi un Policy
(ad esempio
ServerManagedPolicy) che memorizza nella cache i dati delle risposte alle licenze, utilizzando AESObfuscator come
per la tua implementazione di Obfuscator
.
Per ulteriori informazioni, consulta la sezione successiva.
AESOoffuscatore
La LVL include un'implementazione completa e consigliata dell'Obfuscator
chiamata AESObfuscator. L'implementazione è integrata
L'applicazione di esempio LVL e viene utilizzata come Obfuscator
predefinita nella libreria.
AESObfuscator offre un offuscamento sicuro dei dati utilizzando AES per
crittografare e decriptare i dati mentre sono scritti o letti dallo spazio di archiviazione.
Obfuscator
avvia la crittografia utilizzando tre campi di dati forniti
dall'applicazione:
- Un sale: un array di byte casuali da utilizzare per ogni (non)offuscamento.
- Una stringa identificatore dell'applicazione, in genere il nome del pacchetto dell'applicazione.
- Una stringa di identificazione del dispositivo, derivata da tante origini specifiche del dispositivo il più possibile, in modo da renderla il più possibile unica.
Per utilizzare AESObfuscator, importalo prima nella tua Attività. Dichiara come privato statico finale per contenere i byte di sale e inizializzarli a 20 in modo casuale di byte generati.
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 }; ...
Quindi, dichiara una variabile che contenga un identificatore di dispositivo e genera un valore per
necessario in qualsiasi modo. Ad esempio, l'applicazione di esempio inclusa nella LVL
interroga le impostazioni di sistema
android.Settings.Secure.ANDROID_ID
, univoco per ogni dispositivo.
Tieni presente che, a seconda delle API che utilizzi, la tua applicazione potrebbe dover
richiedere autorizzazioni aggiuntive per acquisire informazioni specifiche del dispositivo.
Ad esempio, per eseguire query su TelephonyManager
per ottenere
l'IMEI del dispositivo o i dati correlati, l'applicazione dovrà inoltre richiedere il
android.permission.READ_PHONE_STATE
autorizzazione nel relativo file manifest.
Prima di richiedere nuove autorizzazioni al unico scopo di acquisire
specifiche per il dispositivo da utilizzare in Obfuscator
, considera l'utilizzo
in che modo questa operazione potrebbe influire sulla tua applicazione o sul suo filtro su Google Play
poiché con alcune autorizzazioni gli strumenti di creazione
dell'SDK possono aggiungere
il relativo <uses-feature>
associato).
Infine, costruisci un'istanza di AESObfuscator, passando il sale,
identificatore dell'applicazione e dell'identificatore del dispositivo. Puoi creare l'istanza
direttamente, mentre crei i tuoi Policy
e LicenseChecker
. Ad esempio:
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. ); ...
Per un esempio completo, vedi MainActivity nell'applicazione di esempio LVL.
Controllare la licenza da un'attività
Dopo aver implementato un'Policy
per la gestione dell'accesso all'applicazione,
il passaggio successivo consiste nell'aggiungere un controllo della licenza alla tua applicazione, che avvia una query
al server di licenze, se necessario, e gestisce l'accesso all'applicazione in base
la risposta sulla licenza. Tutto il lavoro di aggiunta del controllo e della gestione delle licenze
la risposta viene eseguita nel file di origine Activity
principale.
Per aggiungere il controllo della licenza e gestire la risposta, devi:
- Aggiungere importazioni
- Implementa LicenseCheckerCallback come classe interna privata
- Crea un gestore per la pubblicazione di LicenseCheckerCallback nel thread dell'interfaccia utente
- Istante LicenseChecker e LicenseCheckerCallback
- Chiama checkAccess() per avviare il controllo delle licenze
- Incorpora la chiave pubblica per le licenze
- Chiama il metodo onDestroy() di LicenseChecker per chiudere le connessioni IPC.
Nelle sezioni seguenti vengono descritte queste attività.
Panoramica del controllo della licenza e della risposta
Nella maggior parte dei casi, devi aggiungere il controllo delle licenze alla pagina principale
Activity
, nel metodo onCreate()
. Questo
assicura che, quando l'utente avvia direttamente la tua applicazione, il controllo della licenza
verrà richiamato immediatamente. In alcuni casi, puoi aggiungere controlli delle licenze
di questi luoghi. Ad esempio, se la tua applicazione include più attività
componenti che altre applicazioni possono iniziare con Intent
,
potresti aggiungere controlli delle licenze
in queste attività.
Un controllo delle licenze prevede due azioni principali:
- Una chiamata a un metodo per avviare il controllo delle licenze: nell'LVL,
una chiamata al metodo
checkAccess()
di un oggettoLicenseChecker
che che crei. - Un callback che restituisce il risultato del controllo delle licenze. Nel LVL,
un'interfaccia
LicenseCheckerCallback
implementata da te. La dichiara due metodi,allow()
edontAllow()
, che vengono richiamati dalla libreria in base al risultato del controllo delle licenze. Puoi implementare questi due metodi con qualsiasi logica per consentire o impedire l'accesso dell'utente alla tua applicazione. Tieni presente che questi metodi non determinano se consentire l'accesso, ma è responsabilità dell'implementazione diPolicy
. Piuttosto, questi forniscono semplicemente i comportamenti dell'applicazione per come consentire e non consentire l'accesso (e gestire gli errori dell'applicazione).I metodi
allow()
edontAllow()
forniscono un "motivo" per la risposta, che può essere uno dei valoriPolicy
,LICENSED
,NOT_LICENSED
oRETRY
. In particolare, dovresti gestire il caso in cui il metodo riceve la rispostaRETRY
perdontAllow()
e fornisce all'utente una "Riprova" accaduto perché il servizio non era disponibile durante richiesta.
Il diagramma riportato sopra illustra come avviene un tipico controllo delle licenze:
- Il codice nell'Attività principale dell'applicazione crea un'istanza di
LicenseCheckerCallback
eLicenseChecker
di oggetti. Quando si creaLicenseChecker
, il codice passaContext
, un'implementazionePolicy
da usare e chiave pubblica dell'account editore per la licenza come parametri. - Il codice quindi chiama il metodo
checkAccess()
sul OggettoLicenseChecker
. L'implementazione del metodo chiamaPolicy
per determinare esiste una risposta a una licenza valida memorizzata nella cache localmente,SharedPreferences
.- In questo caso, l'implementazione di
checkAccess()
chiamaallow()
. - In caso contrario,
LicenseChecker
avvia una richiesta di controllo della licenza che viene inviata al server di licenze.
Nota: il server di licenze restituisce sempre
LICENSED
quando esegui un controllo della licenza di un'applicazione bozza. - In questo caso, l'implementazione di
- Quando riceve una risposta,
LicenseChecker
crea un LicenseValidator che verifica i dati della licenza firmata ed estrae i campi della risposta, quindi le passa al tuoPolicy
per un'ulteriore valutazione.- Se la licenza è valida,
Policy
memorizza la risposta nella cache inSharedPreferences
e invia una notifica allo strumento di convalida, che chiama lo strumentoallow()
nell'oggettoLicenseCheckerCallback
. - Se la licenza non è valida,
Policy
invia una notifica allo strumento di convalida, che chiama il metododontAllow()
suLicenseCheckerCallback
.
- Se la licenza è valida,
- In caso di errore locale o del server recuperabile, ad esempio quando la rete
non disponibile per inviare la richiesta,
LicenseChecker
passa una rispostaRETRY
a il metodoprocessServerResponse()
dell'oggettoPolicy
.Inoltre, entrambi i metodi di callback
allow()
edontAllow()
ricevono unreason
argomento. In genere, il motivo del metodoallow()
èPolicy.LICENSED
oPolicy.RETRY
, mentredontAllow()
èPolicy.NOT_LICENSED
oPolicy.RETRY
. I valori di risposta sono utili per mostrare una risposta appropriata per l'utente, ad esempio fornendo un "Riprova" quandodontAllow()
risponde conPolicy.RETRY
, il che potrebbe essere dovuto al fatto che il servizio non disponibile. - In caso di errore dell'applicazione, ad esempio quando l'applicazione tenta di
controlla la licenza di un nome pacchetto non valido,
LicenseChecker
passa un errore risposta alapplicationError()
di LicenseCheckerCallback .
Tieni presente che, oltre ad avviare il controllo della licenza e gestire
descritti nelle sezioni seguenti, la tua applicazione deve avere anche
per fornire un'implementazione delle norme e, se Policy
archivia i dati di risposta (ad esempio ServerManagedPolicy), un'implementazione Obfuscator.
Aggiungi importazioni
Per prima cosa, apri il file della classe dell'attività principale dell'applicazione ed esegui l'importazione
LicenseChecker
e LicenseCheckerCallback
del pacchetto 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;
Se utilizzi l'implementazione Policy
predefinita fornita con l'LVL,
ServerManagedPolicy, importalo anche insieme all'AESObfuscator. Se
utilizzando un elemento Policy
o Obfuscator
personalizzato, importali.
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;
Implementare LicenseCheckerCallback come classe interna privata
LicenseCheckerCallback
è un'interfaccia fornita da LVL per la gestione
il risultato di un controllo delle licenze. Per supportare le licenze tramite la LVL, devi:
implementare LicenseCheckerCallback
e
i suoi metodi per consentire o meno l'accesso all'applicazione.
Il risultato di un controllo delle licenze è sempre una chiamata a uno dei
LicenseCheckerCallback
metodi, creati in base alla convalida della risposta
il codice di risposta del server stesso ed eventuali altre elaborazioni fornite
dal tuo Policy
. La tua applicazione può implementare i metodi in qualsiasi modo necessario. Nella
in generale, è meglio mantenere i metodi semplici, limitandoli alla gestione dell'interfaccia utente
lo stato e l'accesso alle applicazioni. Se vuoi aggiungere ulteriori elaborazioni delle licenze
risposte, ad esempio contattando un server di backend o applicando vincoli personalizzati,
ti consigliamo di incorporare questo codice nel tuo Policy
, anziché
inserendolo nei metodi LicenseCheckerCallback
.
Nella maggior parte dei casi, devi dichiarare l'implementazione
LicenseCheckerCallback
come classe privata all'interno dell'istanza principale dell'applicazione
Corso di attività.
Implementa i metodi allow()
e dontAllow()
come
necessaria. Per iniziare, puoi utilizzare semplici comportamenti di gestione dei risultati
come la visualizzazione dei risultati della licenza in una finestra di dialogo. Questo ti aiuta a ottenere
l'esecuzione dell'applicazione prima e può aiutarti con il debug. In seguito, dopo
hai determinato i comportamenti esatti che vuoi, puoi aggiungerne una più complessa.
Alcuni suggerimenti per la gestione delle risposte senza licenza in
dontAllow()
includono:
- Mostrare il messaggio "Riprova" finestra di dialogo all'utente, includendo un pulsante per avviare una
nuova licenza controlla se il valore
reason
fornito èPolicy.RETRY
. - Visualizzare il messaggio "Acquista questa applicazione" di dialogo, tra cui un pulsante Consente di collegare l'utente alla pagina dei dettagli dell'applicazione su Google Play, da cui possono acquistare l'applicazione. Per ulteriori informazioni su come configurare consulta la pagina Collegamento ai tuoi prodotti.
- Mostra una notifica Toast che indichi che le funzioni del sono limitate perché non sono concesse in licenza.
L'esempio seguente mostra come l'applicazione di esempio LVL implementa
LicenseCheckerCallback
, con i metodi che mostrano il controllo delle licenze generano un
.
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); } } }
Inoltre, devi implementare l'applicationError()
che l'LVL chiama per consentire all'applicazione di gestire errori che non sono
non ripetibile. Per un elenco di questi errori, consulta
Codici di risposta nella sezione Riferimento alle licenze. Puoi implementare
il metodo in qualsiasi modo necessario. Nella maggior parte dei casi,
dovrebbe registrare il codice di errore e chiamare dontAllow()
.
Crea un gestore per la pubblicazione da LicenseCheckerCallback al thread della UI
Durante un controllo delle licenze, la LVL passa la richiesta a Google Play.
che gestisce la comunicazione con il server di licenze. LVL
passa la richiesta tramite IPC asincrono (utilizzando Binder
) in modo che
l'elaborazione effettiva e la comunicazione di rete
non avvengono su un thread
gestiti dalla tua applicazione. Analogamente, quando l'app Google Play
riceve il risultato, richiama un metodo di callback su IPC, che a sua volta
viene eseguito in un pool di thread IPC nel processo dell'applicazione.
La classe LicenseChecker
gestisce la comunicazione IPC della tua applicazione con
l'applicazione Google Play, inclusa la chiamata che invia la richiesta e
il callback che riceve la risposta. LicenseChecker
monitora anche una licenza aperta
e gestisce i rispettivi timeout.
In modo che possa gestire correttamente i timeout ed elaborare le risposte in arrivo
senza influire sul thread dell'interfaccia utente della tua applicazione, LicenseChecker
genera un
il thread in background durante la creazione dell'istanza. Nel thread esegue tutta l'elaborazione
risultati del controllo delle licenze, se il risultato è una risposta ricevuta dal server
o un errore di timeout. Al termine dell'elaborazione, la LVL chiama
LicenseCheckerCallback
metodi dal thread in background.
Per la tua applicazione, questo significa che:
- I tuoi metodi
LicenseCheckerCallback
verranno richiamati, in molti casi, da un in background. - Questi metodi non saranno in grado di aggiornare lo stato o richiamare alcuna elaborazione nel Thread UI, a meno che tu non crei un gestore nel thread dell'interfaccia utente e non abbia il callback vengono pubblicati sul gestore.
Se vuoi che i metodi LicenseCheckerCallback
aggiornino il thread dell'interfaccia utente,
crea un'istanza di Handler
nell'elenco delle attività
onCreate()
,
come mostrato di seguito. In questo esempio, il modello di applicazione
LicenseCheckerCallback
metodo (vedi sopra) chiama displayResult()
a
aggiornare il thread dell'interfaccia utente tramite
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(); }
Poi, nei tuoi metodi LicenseCheckerCallback
, puoi utilizzare i metodi Gestori per
pubblicare oggetti eseguibili o messaggi nel gestore. Ecco come funziona l'esempio
L'applicazione inclusa nell'LVL pubblica un elemento Runnable to a Gestori nel thread dell'interfaccia utente
per visualizzare lo stato della licenza.
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); } }); }
Creare un'istanza LicenseChecker e LicenseCheckerCallback
Nella sezione delle attività
onCreate()
metodo,
creare istanze private di LicenseCheckerCallback e LicenseChecker
. Devi
creare prima un'istanza LicenseCheckerCallback
, perché devi passare un riferimento
a quell'istanza quando chiami il costruttore per LicenseChecker
.
Quando crei un'istanza LicenseChecker
, devi passare i seguenti parametri:
- L'applicazione
Context
- Un riferimento all'implementazione di
Policy
da utilizzare per il controllo delle licenze. Nella nella maggior parte dei casi, utilizzerai l'implementazionePolicy
predefinita fornita da LVL, ServerManagedPolicy. - La variabile stringa che contiene la chiave pubblica dell'account publisher per licenze.
Se utilizzi ServerManagedPolicy, non dovrai accedere alla classe
di modo che tu possa creare un'istanza nel costruttore LicenseChecker
,
come mostrato nell'esempio riportato di seguito. Tieni presente che devi passare un riferimento a un nuovo
Istanza di offuscamento durante la creazione di ServerManagedPolicy.
L'esempio seguente mostra la creazione di un'istanza di LicenseChecker
e
LicenseCheckerCallback
dal metodo onCreate()
di un'attività
.
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. ); ... } }
Tieni presente che LicenseChecker
chiama i metodi LicenseCheckerCallback
dall'interfaccia utente
il thread solo se esiste una risposta a una licenza valida memorizzata nella cache localmente. Se
del traffico, il controllo delle licenze viene inviato al server, i callback hanno sempre origine
il thread in background, anche per gli errori di rete.
Chiama checkAccess() per avviare il controllo della licenza
Nell'Attività principale, aggiungi una chiamata al metodo checkAccess()
del
LicenseChecker
istanza. Durante la chiamata, passa un riferimento
LicenseCheckerCallback
istanza come parametro. Se hai bisogno di gestire
effetti speciali dell'interfaccia utente o gestione dello stato prima della chiamata, potrebbe esserti utile
per chiamare checkAccess()
da un metodo wrapper. Ad esempio, il valore LVL
l'applicazione di esempio chiama checkAccess()
da un
Metodo wrapper 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); }
Incorpora la chiave pubblica per le licenze
Per ogni applicazione, Google Play Services automaticamente genera una coppia di chiavi pubbliche/private RSA a 2048 bit che viene utilizzata licenze e fatturazione in-app. La coppia di chiavi è associata in modo univoco un'applicazione. Sebbene sia associata all'applicazione, la coppia di chiavi non corrisponde alla chiave che utilizzi per firmare le tue applicazioni (o che la utilizzi).
Google Play Console espone la chiave pubblica per la licenza a qualsiasi sviluppatore ha eseguito l'accesso a Play Console, ma conserva la chiave privata nascosti a tutti gli utenti in un luogo sicuro. Quando un'applicazione richiede il controllo delle licenze per un'applicazione pubblicata nel tuo account, il server di licenze firma la risposta della licenza utilizzando la chiave privata della coppia di chiavi dell'applicazione. Quando l'LVL riceve la risposta, utilizza la chiave pubblica fornita dalla per verificare la firma della risposta relativa alla licenza.
Per aggiungere licenze a un'applicazione, devi ottenere il chiave pubblica per la licenza e copiarla nella tua richiesta. Ecco come trovare chiave pubblica della tua applicazione per la licenza:
- Vai a Google Play Console ed esegui l'accesso. Assicurati di aver eseguito l'accesso all'account da cui stai utilizzando l'applicazione. licenze pubblicate (o verranno pubblicate).
- Nella pagina dei dettagli dell'applicazione, individua la sezione Servizi e API e fai clic sul link.
- Nella sezione Servizi e API, individua Licenze e Fatturazione in-app. La tua chiave pubblica per la licenza viene fornita Il tuo codice di licenza per questa applicazione.
Per aggiungere la chiave pubblica alla tua applicazione, è sufficiente copiare e incollare la stringa della chiave
dal campo all'applicazione come valore della variabile String
BASE64_PUBLIC_KEY
. Quando effettui la copia, assicurati di avere
selezionata l'intera stringa di chiave, senza omettere alcun carattere.
Ecco un esempio tratto dall'applicazione di esempio 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 ... }
Chiama il metodo onDestroy() di LicenseChecker per chiudere le connessioni IPC
Infine, per consentire la pulizia di LVL prima dell'applicazione
Context
modifiche, aggiungi una chiamata all'app LicenseChecker
onDestroy()
metodo della tua Attività
Implementazione di onDestroy()
. La chiamata fa sì che
LicenseChecker
per chiudere correttamente qualsiasi connessione IPC aperta a Google Play
ilicensingService dell'applicazione e rimuove tutti i riferimenti locali al servizio
e gestore.
Impossibile chiamare il metodo onDestroy()
di LicenseChecker
possono causare problemi durante il ciclo di vita della tua applicazione. Ad esempio, se
l'utente cambia l'orientamento dello schermo mentre è attivo un controllo della licenza, l'applicazione
Eliminazione di Context
completata. Se la tua applicazione non
chiudi correttamente la connessione IPC di LicenseChecker
, l'applicazione avrà un arresto anomalo
quando viene ricevuta la risposta. In modo simile, se l'utente esce dall'applicazione
mentre è in corso un controllo della licenza, l'applicazione avrà un arresto anomalo quando
di risposta, a meno che non abbia correttamente chiamato il
Metodo onDestroy()
di LicenseChecker
per disconnettersi dal servizio.
Ecco un esempio dall'applicazione di esempio inclusa nella LVL, in cui
mChecker
è l'istanza LicenseChecker
:
Kotlin
override fun onDestroy() { super.onDestroy() checker.onDestroy() ... }
Java
@Override protected void onDestroy() { super.onDestroy(); checker.onDestroy(); ... }
Se stai estendendo o modificando LicenseChecker
, potrebbe essere necessario chiamare anche
metodo finishCheck()
di LicenseChecker
, per ripulire eventuali IPC aperti
e connessioni a Internet.
Implementazione di un DeviceLimiter
In alcuni casi, potresti voler limitare il numero di Policy
dispositivi a cui è consentito utilizzare una singola licenza. Questo impedisce a un utente
dalla migrazione di un'applicazione con licenza su più dispositivi all'utilizzo
su tali dispositivi con lo stesso ID account. Inoltre, impedirebbe che
utente da "condivisione" fornendo i dati dell'account
associati alla licenza di altri individui, che potrebbero poi accedervi
sui propri dispositivi e accedere alla licenza dell'applicazione.
L'LVL supporta le licenze per dispositivo fornendo
DeviceLimiter
, che dichiara un singolo metodo,
allowDeviceAccess()
. Quando un LicenseValidator gestisce una risposta
dal server di licenze, chiama allowDeviceAccess()
, trasmettendo una
Stringa dell'ID utente estratta dalla risposta.
Se non vuoi supportare le limitazioni del dispositivo, non dovrai fare nulla
obbligatorio: il corso LicenseChecker
utilizza automaticamente un'istanza
chiamata NullDeviceLimiter. Come suggerisce il nome, NullDeviceLimiter
è una modalità "no-op" il cui metodo allowDeviceAccess()
restituisce semplicemente
una risposta LICENSED
per tutti gli utenti e i dispositivi.
Attenzione:l'assegnazione di licenze per dispositivo non è consigliata per la maggior parte delle applicazioni perché:
- Devi fornire un server di backend per gestire utenti e dispositivi mappatura e
- Potrebbe inavvertitamente comportare la negazione dell'accesso a un un'applicazione che ha legittimamente acquistato su un altro dispositivo.
Offuscamento del codice
Per garantire la sicurezza della tua applicazione, in particolare per un account a pagamento che utilizza le licenze e/o le protezioni e i vincoli personalizzati, per offuscare il codice dell'applicazione. Offuscamento corretto rende più difficile per un utente malintenzionato decompilare il database dell'applicazione in bytecode, modificarlo, ad esempio rimuovendo il controllo delle licenze. e quindi ricompilarlo.
Sono disponibili diversi programmi di offuscamento per le applicazioni Android, tra cui ProGuard, che offre anche di ottimizzazione del codice. L'utilizzo di ProGuard o di un programma simile per offuscare il tuo codice è vivamente consigliato per tutte le applicazioni che utilizzano Licenze Google Play.
Pubblicazione di un'applicazione concessa in licenza
Al termine del test dell'implementazione della licenza, pubblicare l'applicazione su Google Play. Segui la normale procedura per preparare, firmare e pubblicare la richiesta.
Dove trovare assistenza
Se hai domande o riscontri problemi durante l'implementazione o il deployment pubblica nelle tue applicazioni, utilizza le risorse di assistenza elencate nella riportata di seguito. Indirizzando le query al forum corretto, puoi ottenere l'assistenza necessaria più rapidamente.
Tipo di assistenza | Risorsa | Gamma di argomenti |
---|---|---|
Problemi di sviluppo e verifica | Google Gruppi: android-developers | Download e integrazione LVL, progetti libreria, Policy
domande, idee per l'esperienza utente, gestione delle risposte, Obfuscator , IPC, test
configurazione dell'ambiente |
Stack Overflow: http://stackoverflow.com/questions/gtag/android | ||
Problemi relativi ad account, pubblicazione e deployment | Google Play Forum di assistenza | Account publisher, coppia di chiavi di licenza, account di prova, server risposte dei test, deployment e risultati dell'applicazione |
Mercato Domande frequenti sull'assistenza per le licenze | ||
Issue Tracker LVL | Licenze di mercato strumento di monitoraggio dei problemi a livello di progetto | Report su problemi e bug relativi specificamente alle classi del codice sorgente LVL e le implementazioni dell'interfaccia |
Per informazioni generali su come pubblicare post nei gruppi sopra elencati, consulta la sezione Risorse della community nella pagina Risorse di assistenza per gli sviluppatori.
Risorse aggiuntive
L'applicazione di esempio inclusa nella LVL fornisce un esempio completo di come
avviare un controllo della licenza e gestire il risultato, nel
MainActivity
corso.