In questa seconda puntata spieghiamo brevemente come funziona l’architettura del billing in-app e cominciamo a inserire i primi metodi e classi nel nostro progetto.
L’Architettura
La gestione delle richieste dall’in-app billing utiliza principalmente una sequenza di messaggi asincroni per soddisfare le richieste fra l’applicazione e i server di google. Tutte le richieste che fa la nostra applicazione relative agli acquisti, non interagiscono direttamente con i server di google, bensí inviano le loro richieste tramite IPC al servizio relativo nell’applicazione del Google Play store. Ovviamente se noi vogliamo possiamo interagire con dei nostri server per gestire gli acquisti, una volta effettuati, degli utenti. Ma mai la nostra applicazione, ne il nostro server entreranno nel merito della transazione (tranne per i suoi contenuti quali risultato, oggetti ordinati, etc).
Come detto precedentemente i componenti fondamentali su cui si basa una implementazione dell’in-app billing sono il Servizio, il BroadCastReceiver e una componente relativa alla sicurezza.
Ovviamente se necessario la nostra applicazione deve gestire anche il salvataggio delle impostazioni dopo l’acquisto.
Lo schema in figura rappresenta brevemente come avviene la comunicazione fra il servizio in-app di google play e la nostra applicazione.
Questa é una versione semplificate dello schema sul sito di google (http://developer.android.com/guide/market/billing/billing_overview.html#billing-arch), ho cercato di tirare fuori l’essenziale per il funzionamento e concentrarmi nella spiegazione di questi. Breveemente lo schema delle interazioni é il seguente:
1. L’app fa una richiesta tramite Il billingService. Che é la componente demandata di inviare i messagi al servizio in-app di Google Play.
2. L’app google play invierá le sue risposte sincrone direttamente al BillingService tramite un bundle, mentre quelle asincrone saranno inviate tramite Intent e ricevute dalla classe BillingReceiver.
3. Il billingreceiver risponde se necessario utilizzando di nuovo il billingService
4. Mentre la componente security si occupa semplicemente di gestire la verifica della firma dei messaggi ricevuti dalla nostra applicazione.
Richieste al google market (e risposte)
Le richieste che possono essere fatte al google market sono le seguenti:
- CHECK_BILLING_SUPPORTED che controlla se il supporto al billing in-app é attivo.
- REQUEST_PURCHASE con il quale richiediamo le componenti da acquistare.
- GET_PURCHASE_INFORMATION ci ritorna tutti i dettagli sul cambio di stato della richiesta.
- CONFIRM_NOTIFICATIONS la utilizza l’app per inviare un ack alle notifiche ricevute dal market.
- RESTORE_TRANSACTIONS questa ritorna lo stato di tutte transazioni di un utente (solo per quelle di tipo MANAGED che vedremo piú avanti).
Mentre le risposte asincrone che ci invierá il market saranno:
- com.android.vending.billing.RESPONSE_CODE Spedita ogni volta che si fa una richiesta di billing in-app la risposta indica se la nostra richiesta é stata consegnata correttamente o meno a Google Play
- com.android.vending.billing.IN_APP_NOTIFY questo invece viene spedito quando é avvenuto un cambio di stato nella nostra transazione. Questa contiene uno o piu notification ids che indicano le transazioni per le quali é intervenuto il cambio di stato. Per ottenere i dettagli sul cambio di stato dobbiamo inviare una richiesta di GET_PURCHASE_INFORMATION.
- com.android.vending.billing.PURCHASE_STATE_CHANGED contiene invece i dettagli su una o piú transazioni. Le informazioni sono contenute all’interno di una stringa JSON. Questa stringa viene firmata e la firma viene inviata insieme all stringa json. In questo modo noi possiamo verificare la firma per controllare la veridicitá della transazione.
Piú avanti vedremo in dettaglio il contenuto della stringa JSON.
Come fare le richieste – Binding del servizio
Bene ora che abbiamo visto quali sono i comandi disponibili, vediamo come effettuarli. Come detto precedentemente, la nostra applicazione invierá le proprie richieste di billing in-app tramite il servizio che andremo a creare. Che a sua volta invierá messaggi vengono inviati tramite un metodo IPC che viene fornito dal MarketBillingService (sendBillingRequest()).
Per ottenere questo metodo dobbiamo effettuare quello che viene chiamato “Bind” della nostra classe servizio con il MarketBillingService, che sará il server in una interfaccia client-server. Tale servizio server permette ai compnenti che hanno effettuato il bind con esso di spedirgli richieste, ricevere delle risposte ed effettuare chiamate IPC (InterProcessCommunication). Questo servizio comunque non gira in background continuamente, ma entra in funzione solo quando un risponde ad una richiesta ricevuta da un componente dell’applicazione.
Prima di trutto creiamo una nuova classe, che estende Service e implementa l’interfaccia ServiceConnection:
public class BillingService extends Service implements ServiceConnection { @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } public void onServiceConnected(ComponentName arg0, IBinder arg1) { // TODO Auto-generated method stub } public void onServiceDisconnected(ComponentName arg0) { // TODO Auto-generated method stub } } |
Dove:
- onBind(…) viene richiesto dalla classe Service
- onServiceConnected(…) e onServiceDisconnected(…) sono richiesti dall’interfaccia ServiceConnection
Aggiungiamo anche il metodo onCreate(), al cui interno effettueremo il bind al MarketBillingService dal nostro servizio:
public void onCreate() { super.onCreate(); bindToMarketBilling(); } |
Dove bindToMarketBilling é un metodo creato per comoditá e contiene semplicemente la connessione vera e propria al servizio (ma volendo questo lo possiamo fare direttamente all’interno di onCreate):
boolean bindResult = bindService(new Intent("com.android.vending.billing.MarketBillingService.BIND"), this, Context.BIND_AUTO_CREATE); |
Visto che torna true se l’operazione é andata a buon fine e false viceversa possiamo se vogliamo aggiungere anche del controllo di errore.
Inoltre dobbiamo creare un rifermineto all’interfaccia IMarketBillingService, che contiene il metodo sendBillingRequest, per fare questo dichiariamo prima di tutto una variabile statica (in modo che andrá istanziata una sola volta per tutto il ciclo di vita del programma) :
private static IMarketBillingService mService; |
Il metodo che si occuperá di effettuare il bind é onServiceConnected (ereditato come detto prima da ServiceConnection), questo metodo non viene chiamato direttamente ma bensí in fase di avvio del servizio (e normalmente una sola volta). Quindi avremo:
public void onServiceConnected(ComponentName name, IBinder service) { mService = IMarketBillingService.Stub.asInterface(service); } |
onServiceConnected é un metodo che viene chiamato nel momento in cui la connessione col servizio é andata a buon fine. In questo modo abbiamo collegato il nostro servizio al MarketBillingService e mediante mService abbiamo ottenuto accesso al metodo che utilizzeremo per ogni nostra richiesta (sendBillingRequest()).
Visto che mService é una variabile statica potrebbe essere utile azzerarla nel momento in cui decidiamo di smettere di utilizzare il servizio. Quindi avremo il metodo onServiceDisconnected che diventerá cosí:
public void onServiceDisconnected(ComponentName arg0) { Log.w(TAG, "Billing service disconnected"); mService = null; } |
Infine notiamo che ci occorrerá associare l’Activity chiamante al nostro servizio, e questo lo potremo fare mediante il costruttore. Quindi per ora il nostro costruttoré sará:
public BillingService(Activity activity){ super(); myActivity = activity; } |
Dove myActivity é una variabile di classe, anch’essa definita static:
private static Activity myActivity; |
Il costruttore non é finito, ma vedremo piú avanti cosa dovremo aggiungere.
Per oggi mi fermo qui, nella prossima lezione vedremo i metodi necessari per effettuare le richieste, e gestire le risposte ricevute dal market.
First comment using facebook plugin!
ma la terza puntata?
Anche se l’hai gia trovata: http://www.italialinux.com/wp-admin/post.php?post=963&action=edit
Domani comunque le inserisco fra gli articoli a puntate, che almeno sono più facilmente individuabili!
Ciao e complimenti per l’articolo, è molto interessante.
A quando la terza puntata?