Current version: 0.7.5
Though In-App Billing Version 3 is much easier to use than Version 2 there are still some things you have to face while integrating it, like:
- Concurrency, see, for example, warning in Querying for Items Available for Purchase
- Security, see Security And Design
Checkout has a good test coverage and is build continuously on Travis CI:
- Say it right! (Google Play)
- Calculator++ (Google Play, sources)
- AcDisplay (Google Play, sources)
There are several ways how you can get the library:
- Download sources from github and either copy them to your project or import them as a project dependency
- For Maven users:
<dependency>
<groupId>org.solovyev.android</groupId>
<artifactId>checkout</artifactId>
<version>x.x.x</version>
<type>apklib</type>
</dependency>
- For Gradle users:
compile 'org.solovyev.android:checkout:x.x.x@aar'
- Download artifacts from the repository
Checkout requires com.android.vending.BILLING
permission in runtime.
If you use Checkout as a library project then nothing should be done - permission will be merged automatically during
the manifest merging step. In any other cases you need to include it into your application's manifest:
<uses-permission android:name="com.android.vending.BILLING" />
Checkout contains 3 classes which likely to be used in any app: Billing, Checkout and Inventory. The code for the project with one in-app product might look like this:
public class MyApplication extends Application {
/**
* For better performance billing class should be used as singleton
*/
@Nonnull
private final Billing billing = new Billing(this, new Billing.DefaultConfiguration() {
@Nonnull
@Override
public String getPublicKey() {
return "Your public key, don't forget to encrypt it somehow";
}
});
/**
* Application wide {@link org.solovyev.android.checkout.Checkout} instance (can be used anywhere in the app).
* This instance contains all available products in the app.
*/
@Nonnull
private final Checkout checkout = Checkout.forApplication(billing, Products.create().add(IN_APP, asList("product")));
@Nonnull
private static MyApplication instance;
public MyApplication() {
instance = this;
}
public static MyApplication get() {
return instance;
}
@Nonnull
public Checkout getCheckout() {
return checkout;
}
//...
}
public class MyActivity extends Activity {
@Nonnull
private final ActivityCheckout checkout = Checkout.forActivity(this, MyApplication.get().getCheckout());
@Nonnull
private Inventory inventory;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checkout.start();
// you only need this if this activity starts purchase process
checkout.createPurchaseFlow(new PurchaseListener());
// you only need this if this activity needs information about purchases/SKUs
inventory = checkout.loadInventory();
inventory.whenLoaded(new InventoryLoadedListener())
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
checkout.onActivityResult(requestCode, resultCode, data);
}
@Override
protected void onDestroy() {
checkout.stop();
super.onDestroy();
}
//...
}
Checkout sample app on Google Play. Sources are available here.
Checkout is built by Gradle. The project structure and build procedure are standard for Android libraries. An environmental variable with name ANDROID_HOME must be set before building and should point to Android SDK installation folder (f.e. /opt/android/sdk). Please refer to Gradle User Guide for more information about building.
Android Studio/IDEA project configuration files are also checked into the repository. Use "File->Open..." to open the project.
Checkout contains 3 main classes: Billing, Checkout and Inventory.
Billing class is the main controller which:
- connects to the Billing service
- executes all incoming requests (and caches responses)
- provides access to BillingRequests It should be used as a singleton in order to avoid several connections to the Billing service. Though this class might be used directly usually it's better to interact with Checkout.
Checkout provides access to Billing for set of products. It checks if billing is supported and executes requests if it is ready. ActivityCheckout is a subclass which also provides access to PurchaseFlow.
Inventory contains static information abouts products, purchases and SKUs. It should be reloaded every time the purchase state is changed in order to be actual.
By default Checkout uses simple purchase verification algorithm (see DefaultPurchaseVerifier). As exmplained in Android documentation it's better to verify purchases on remote server. Checkout allows you to provide your own PurchaseVerifier by implementing Billing.Configuration#getPurchaseVerifier
. Note that PurchaseVerifier#verify
is called every time purchases information is requested from Android Billing API and might be called on both main and background threads. BasePurchaseVerifier deals with thread management and it is recommended to extend this class if you want to provide custom verification procedure. It is safe to do network requests from BasePurchaseVerifier#doVerify
as this method is guaranteed to be called on the background thread.
Some users might not have Google Play Services supporting Billing Version 3. As these users might have purchases it should be possible to retrieve purchase information for them. You can provide fallback functionality for such users by returning not null object from Billing.Configuration#getFallbackInventory
method.
If you used Robotmedia Android Billing Library before fallback is already implemented, see RobotmediaInvenotry class (sample code)
You need to include the contents of proguard rules into your proguard configuration.
Copyright 2014 serso aka se.solovyev
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.