IAPing.
34
desktop/src-common/advent/iap.clj
Normal file
@@ -0,0 +1,34 @@
|
||||
(ns advent.iap
|
||||
(:import [com.badlogic.gdx Gdx Application])
|
||||
(:require [clojure.core.async :as a]
|
||||
[advent.utils :as utils]))
|
||||
|
||||
(def purchase-chan (a/chan 1))
|
||||
(def has-purchased? (atom false))
|
||||
(def can-purchase? (atom false))
|
||||
|
||||
(defn set-purchase-pref [val]
|
||||
(println "setting preference purchased:" val)
|
||||
(let [prefs (.getPreferences (Gdx/app) "purchases")]
|
||||
(.putBoolean prefs "has-purchased?" val)
|
||||
(.flush prefs))
|
||||
(reset! has-purchased? val)
|
||||
(a/go (a/>! purchase-chan val)))
|
||||
|
||||
(defn check-purchase-pref []
|
||||
(let [prefs (.getPreferences (Gdx/app) "purchases")]
|
||||
(if (.contains prefs "has-purchased?")
|
||||
(.getBoolean prefs "has-purchased?")
|
||||
false)))
|
||||
|
||||
(defn use-pref []
|
||||
(swap! has-purchased? #(or % (check-purchase-pref)))
|
||||
(println "preferences purchased:" @has-purchased?))
|
||||
|
||||
(defn start-purchase []
|
||||
(utils/platformify
|
||||
(do
|
||||
(require '[advent.ios])
|
||||
(@(resolve 'advent.ios/start-purchase)) )
|
||||
(.triggerPurchase (Gdx/app))
|
||||
(set-purchase-pref true)))
|
||||
BIN
ios/resources/Icon-1024x1024.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
ios/resources/Images.xcassets/AppIcon.appiconset/1024x1024.png
Normal file
|
After Width: | Height: | Size: 263 KiB |
BIN
ios/resources/Images.xcassets/AppIcon.appiconset/29x29.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
ios/resources/Images.xcassets/AppIcon.appiconset/29x29@2x-1.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
ios/resources/Images.xcassets/AppIcon.appiconset/29x29@2x.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
ios/resources/Images.xcassets/AppIcon.appiconset/29x29@3x.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
116
ios/resources/Images.xcassets/AppIcon.appiconset/Contents.json
Normal file
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-large20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-large20x20@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "29x29@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-large40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-large40x40@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-60@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-60@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-large20x20.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-large20x20@2x-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "29x29.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "29x29@2x-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-large40x40.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-large40x40@2x-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-large76x76.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-large76x76@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-83.5@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"filename" : "1024x1024.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 25 KiB |
BIN
ios/resources/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
BIN
ios/resources/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
ios/resources/Images.xcassets/AppIcon.appiconset/Icon-76.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
ios/resources/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 13 KiB |
BIN
ios/resources/Images.xcassets/AppIcon.appiconset/Icon.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
ios/resources/Images.xcassets/AppIcon.appiconset/Icon@2x.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 12 KiB |
6
ios/resources/Images.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
55
ios/src/clojure/advent/ios.clj
Normal file
@@ -0,0 +1,55 @@
|
||||
(ns advent.ios
|
||||
(:require [advent.iap :as iap])
|
||||
(:import [org.robovm.apple.storekit SKProductsResponse SKProduct SKMutablePayment SKPaymentQueue SKPaymentTransactionState]))
|
||||
|
||||
(def product (atom nil))
|
||||
|
||||
(defn products-did-receive-response [request ^SKProductsResponse response]
|
||||
(reset! iap/can-purchase? true)
|
||||
(reset! product (first (seq (.toArray (.getProducts response))))))
|
||||
|
||||
(defn products-did-fail [request error]
|
||||
)
|
||||
|
||||
(defn products-did-finish [request]
|
||||
)
|
||||
|
||||
(defn start-purchase []
|
||||
(try
|
||||
(.addPayment (SKPaymentQueue/getDefaultQueue)
|
||||
(doto (SKMutablePayment. @product)
|
||||
(.setQuantity 1)))
|
||||
(catch Exception e
|
||||
(println e))))
|
||||
|
||||
|
||||
|
||||
(defn updated-transactions [queue, transactions]
|
||||
|
||||
(let [purchased-states #{SKPaymentTransactionState/Purchased SKPaymentTransactionState/Restored}
|
||||
finished-states #{SKPaymentTransactionState/Purchased SKPaymentTransactionState/Restored SKPaymentTransactionState/Failed SKPaymentTransactionState/Deferred}
|
||||
is-finished (->> transactions
|
||||
.toArray
|
||||
seq
|
||||
(every? #(finished-states (.getTransactionState %))))
|
||||
|
||||
has-purchased (->> transactions
|
||||
.toArray
|
||||
seq
|
||||
(filter #(purchased-states (.getTransactionState %)))
|
||||
(map #(-> % (.getPayment) (.getProductIdentifier)))
|
||||
(filter #(= % "fullgame"))
|
||||
seq)]
|
||||
(when is-finished
|
||||
(iap/set-purchase-pref (if has-purchased true false))
|
||||
(doseq [^SKPaymentTransaction trans (->> transactions .toArray seq)]
|
||||
(.finishTransaction (SKPaymentQueue/getDefaultQueue) trans)))))
|
||||
|
||||
(defn updated-downloads [queue, downloads]
|
||||
(println "updated downloads" downloads))
|
||||
(defn restore-completed-transactions-finished [queue]
|
||||
(println "transactions finished"))
|
||||
(defn restore-completed-transactions-failed [queue, error]
|
||||
(println "transactions failed"))
|
||||
(defn removed-transactions [queue, transactions]
|
||||
(println "transactions removed" transactions))
|
||||
33
ios/src/java/advent/core/ProductDelegate.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package advent.core;
|
||||
|
||||
import java.util.*;
|
||||
import clojure.lang.RT;
|
||||
import clojure.lang.Symbol;
|
||||
import clojure.lang.IFn;
|
||||
|
||||
import com.badlogic.gdx.*;
|
||||
import com.badlogic.gdx.backends.iosrobovm.*;
|
||||
|
||||
import org.robovm.apple.foundation.*;
|
||||
import org.robovm.apple.uikit.UIApplication;
|
||||
import org.robovm.apple.glkit.GLKViewDrawableColorFormat;
|
||||
import org.robovm.apple.glkit.GLKViewDrawableDepthFormat;
|
||||
import org.robovm.apple.storekit.*;
|
||||
|
||||
public class ProductDelegate extends SKProductsRequestDelegateAdapter {
|
||||
|
||||
@Override
|
||||
public void didReceiveResponse(SKProductsRequest request, SKProductsResponse response) {
|
||||
((IFn) RT.var("advent.ios", "products-did-receive-response").deref()).invoke(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didFail(SKRequest request, NSError error) {
|
||||
((IFn) RT.var("advent.ios", "products-did-fail").deref()).invoke(request, error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didFinish(SKRequest request) {
|
||||
((IFn) RT.var("advent.ios", "products-did-finish").deref()).invoke(request);
|
||||
}
|
||||
}
|
||||
43
ios/src/java/advent/core/TransactionObserver.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package advent.core;
|
||||
|
||||
import java.util.*;
|
||||
import clojure.lang.RT;
|
||||
import clojure.lang.Symbol;
|
||||
import clojure.lang.IFn;
|
||||
|
||||
import com.badlogic.gdx.*;
|
||||
import com.badlogic.gdx.backends.iosrobovm.*;
|
||||
|
||||
import org.robovm.apple.foundation.*;
|
||||
import org.robovm.apple.uikit.UIApplication;
|
||||
import org.robovm.apple.glkit.GLKViewDrawableColorFormat;
|
||||
import org.robovm.apple.glkit.GLKViewDrawableDepthFormat;
|
||||
import org.robovm.apple.storekit.*;
|
||||
|
||||
public class TransactionObserver extends SKPaymentTransactionObserverAdapter {
|
||||
|
||||
@Override
|
||||
public void updatedTransactions(SKPaymentQueue queue, NSArray<SKPaymentTransaction> transactions) {
|
||||
((IFn) RT.var("advent.ios", "updated-transactions").deref()).invoke(queue, transactions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatedDownloads(SKPaymentQueue queue, NSArray<SKDownload> downloads) {
|
||||
((IFn) RT.var("advent.ios", "updated-downloads").deref()).invoke(queue, downloads);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreCompletedTransactionsFinished(SKPaymentQueue queue) {
|
||||
((IFn) RT.var("advent.ios", "restore-completed-transactions-finished").deref()).invoke(queue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreCompletedTransactionsFailed(SKPaymentQueue queue, NSError error) {
|
||||
((IFn) RT.var("advent.ios", "restore-completed-transactions-failed").deref()).invoke(queue, error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removedTransactions(SKPaymentQueue queue, NSArray<SKPaymentTransaction> transactions) {
|
||||
((IFn) RT.var("advent.ios", "removed-transactions").deref()).invoke(queue, transactions);
|
||||
}
|
||||
}
|
||||