/*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.checkout;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static android.database.sqlite.SQLiteDatabase.OPEN_READONLY;
import static android.database.sqlite.SQLiteDatabase.openDatabase;
public final class RobotmediaDatabase {
static final String NAME = "billing.db";
@Nonnull
private final Context mContext;
public RobotmediaDatabase(@Nonnull Context context) {
mContext = context;
}
public static boolean exists(@Nonnull Context context) {
final File file = getDatabaseFile(context);
return file != null && file.exists();
}
@Nullable
private static File getDatabaseFile(@Nonnull Context context) {
return context.getDatabasePath(NAME);
}
@Nullable
static String getDatabasePath(@Nonnull Context context) {
final File file = getDatabaseFile(context);
return file != null ? file.getPath() : null;
}
@Nonnull
static Inventory.Products toInventoryProducts(@Nonnull Collection<String> products) {
final Inventory.Products result = new Inventory.Products();
for (String productId : products) {
result.add(new Inventory.Product(productId, true));
}
return result;
}
@Nonnull
static String makeInClause(int count) {
Check.isTrue(count > 0, "Should be positive");
final StringBuilder sb = new StringBuilder(count * 2 + 1);
sb.append("(");
sb.append("?");
for (int i = 1; i < count; i++) {
sb.append(",?");
}
sb.append(")");
return sb.toString();
}
@Nonnull
Inventory.Products load(@Nonnull Inventory.Request request) {
SQLiteDatabase db = null;
try {
final String databasePath = RobotmediaDatabase.getDatabasePath(mContext);
db = openDatabase(databasePath, null, OPEN_READONLY);
return loadProducts(request, db);
} catch (RuntimeException e) {
Billing.error(e);
} finally {
if (db != null) {
db.close();
}
}
return toInventoryProducts(ProductTypes.ALL);
}
@Nonnull
private Inventory.Products loadProducts(@Nonnull Inventory.Request request, @Nonnull SQLiteDatabase db) {
final Inventory.Products result = new Inventory.Products();
for (String productId : ProductTypes.ALL) {
final Inventory.Product product = new Inventory.Product(productId, true);
final List<String> skus = request.getSkus(productId);
if (!skus.isEmpty()) {
product.setPurchases(loadPurchases(skus, db));
} else {
Billing.warning("There are no SKUs for \"" + product.id + "\" product. No purchase information will be loaded");
}
result.add(product);
}
return result;
}
@Nonnull
private List<Purchase> loadPurchases(@Nonnull List<String> skus, @Nonnull SQLiteDatabase db) {
Check.isNotEmpty(skus);
final List<Purchase> purchases = new ArrayList<>(skus.size());
final String[] columns = {"_id", "state", "productId", "purchaseTime", "developerPayload"};
final String packageName = mContext.getPackageName();
Cursor c = null;
try {
c = db.query("purchases", columns, "productId in " + makeInClause(skus.size()), skus.toArray(new String[skus.size()]), null, null, null);
if (c.moveToFirst()) {
do {
final String orderId = c.getString(0);
final int state = c.getInt(1);
final String sku = c.getString(2);
final long time = c.getLong(3);
final String payload = c.getString(4);
final Purchase p = new Purchase(sku, orderId, packageName, time, state, payload, "", false, "", "");
purchases.add(p);
} while (c.moveToNext());
}
} finally {
if (c != null) {
c.close();
}
}
return purchases;
}
}