Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

It says AndroidIAPP singleton not found #11

Open
GuacGameDev opened this issue Aug 21, 2024 · 13 comments
Open

It says AndroidIAPP singleton not found #11

GuacGameDev opened this issue Aug 21, 2024 · 13 comments

Comments

@GuacGameDev
Copy link

GuacGameDev commented Aug 21, 2024

I downloaded this and put the android_IAPP (extracted) folder in my addons folder. When running the example for purchases as a singleton and I get the error message: "AndroidIAPP singleton not found"

I used Engine.get_singletons and this is what I get
["Performance", "TextServerManager", "PhysicsServer2DManager", "PhysicsServer3DManager", "NavigationMeshGenerator", "ProjectSettings", "IP", "Geometry2D", "Geometry3D", "ResourceLoader", "ResourceSaver", "OS", "Engine", "ClassDB", "Marshalls", "TranslationServer", "Input", "InputMap", "EngineDebugger", "Time", "GDExtensionManager", "ResourceUID", "WorkerThreadPool", "ThemeDB", "JavaClassWrapper", "JavaScriptBridge", "AudioServer", "CameraServer", "DisplayServer", "NativeMenu", "NavigationServer2D", "NavigationServer3D", "RenderingServer", "PhysicsServer2D", "PhysicsServer3D", "XRServer"]

@code-with-max
Copy link
Owner

Did you turn on it on project settings?

@xzls-protik
Copy link

Did you turn on it on project settings?

i am having the same problems . when i extracted the files , it didnt create any folder named android_IAPP. so i went on and created a folder in my addons dir and put all four files in that directory . when i opened project settings -> plugins , i had the option to enable the plugin , did that and when i run my game it sends out error saying "AndroidIAPP singleton not found" , do i add the AndroidIAPP.gd script as singleton that came with the plugin ?

@xzls-protik
Copy link

extends Node

var billing = null

const ITEM_CONSUMATED: Array = [
"gold_pack_1", "gold_pack_2", "gold_pack_3", "gold_pack_4",
"xp_pack_1", "xp_pack_2", "xp_pack_3", "xp_pack_4"
]

signal purchase_successful(product_id)
signal purchase_failed(error)

func _ready():
if Engine.has_singleton("AndroidIAPP"):
billing = Engine.get_singleton("AndroidIAPP")
print("AndroidIAPP singleton loaded")
_setup_billing()
else:
printerr("AndroidIAPP singleton not found")

func _setup_billing():
billing.startConnection.connect(_on_start_connection)
billing.connected.connect(_on_connected)
billing.disconnected.connect(_on_disconnected)
billing.query_purchases.connect(_on_query_purchases)
billing.query_purchases_error.connect(_on_query_purchases_error)
billing.query_product_details.connect(_on_query_product_details)
billing.query_product_details_error.connect(_on_query_product_details_error)
billing.purchase_updated.connect(_on_purchase_updated)
billing.purchase_error.connect(_on_purchase_error)
billing.purchase_consumed.connect(_on_purchase_consumed)
billing.purchase_consumed_error.connect(_on_purchase_consumed_error)

billing.startConnection()

func _on_start_connection() -> void:
print("Billing: start connection")

func _on_connected() -> void:
print("Billing successfully connected")
if billing.isReady():
billing.queryProductDetails(ITEM_CONSUMATED, "inapp")
billing.queryPurchases("inapp")

func _on_disconnected() -> void:
print("Billing disconnected")

func _on_query_purchases(response) -> void:
print("Query purchases response:")
print(JSON.stringify(response, " "))
for purchase in response["purchases_list"]:
_process_purchase(purchase)

func _on_query_purchases_error(error) -> void:
print("Query purchases error:")
print(JSON.stringify(error, " "))

func _on_query_product_details(response) -> void:
print("Product details:")
for product in response["product_details_list"]:
print(JSON.stringify(product, " "))

func _on_query_product_details_error(error) -> void:
print("Query product details error:")
print(JSON.stringify(error, " "))

func _on_purchase_updated(response) -> void:
print("Purchase updated:")
print(JSON.stringify(response, " "))
for purchase in response["purchases_list"]:
_process_purchase(purchase)

func _process_purchase(purchase) -> void:
if purchase["products"][0] in ITEM_CONSUMATED:
billing.consumePurchase(purchase["purchase_token"])

purchase_successful.emit(purchase["products"][0])

func _on_purchase_error(error) -> void:
print("Purchase error:")
print(JSON.stringify(error, " "))
purchase_failed.emit("purchase_failed", error)

func _on_purchase_consumed(response) -> void:
print("Purchase consumed:")
print(JSON.stringify(response, " "))

func _on_purchase_consumed_error(error) -> void:
print("Purchase consume error:")
print(JSON.stringify(error, " "))

func initiate_purchase(product_id: String) -> void:
if billing and billing.isReady():
billing.purchase([product_id], false)
else:
purchase_failed.emit("purchase_failed", "Billing not available")

func is_billing_ready() -> bool:
return billing != null and billing.isReady()

heres how my script looks like , and im using it as an autoload .

@GuacGameDev
Copy link
Author

Did you turn on it on project settings?

Indeed! Like Protik, I too have it as an autoload and the addon enabled in product settings

@xzls-protik
Copy link

Did you turn on it on project settings?

Indeed! Like Protik, I too have it as an autoload and the addon enabled in product settings

Run it on android, the singleton doesn't work on desktop or laptop. The singleton will be found.

@alfredogarciaw
Copy link

alfredogarciaw commented Sep 27, 2024

image
image
image

Run it on android emulator with google play services
used adb logcat
09-27 18:20:12.369 10174 10332 I godot : AndroidIAPP singleton not found

Has the AndroidIAPP.gd to be added as autoload?
ChatGpt suggested to put the plugin on res://android/plugins could this work?

@Suthameow
Copy link

I am having the same problems, did anyone solve this issue?

@code-with-max
Copy link
Owner

@Suthameow
How you run your app?
Plugin will works only on Android with arm v8 platform

@Suthameow
Copy link

@code-with-max
I run my app on Sumsung note 8 and poco f6 pro. It says AndroidIAPP singleton not found. But google library 7.0 is working fine.

Could you please provide us a step by step link. (The AndroidIAPP plug in was checked.)

Thank you very much

@alfredogarciaw
Copy link

I made it work finally!
1)Test it in Closed testing (google play developer console) testing not in internal testing.
2)Don't release with debug option
3)Await 1 second
func iniciar_facturacion():
print("Intentando cargar singleton AndroidIAPP ")
await get_tree().create_timer(1).timeout
if Engine.has_singleton("AndroidIAPP"):
billing = Engine.get_singleton("AndroidIAPP")

func _on_connected() -> void:
await get_tree().create_timer(1).timeout
print("Conexión con Google Play Billing establecida.")
# Consultar detalles de productos disponibles
billing.queryProductDetails(ITEM_CONSUMABLES, "inapp")
# Consultar compras no consumidas
billing.queryPurchases("inapp")

@Suthameow
Copy link

@alfredogarciaw @code-with-max

Thank you, all.
I finally have passed the "AndroidIAPP singleton not found" issue.
My game has to run in the closed testing or Android remote debug.

Right now I met a new issue: "Invalid call. Nonexistent function 'purchase' in base "'JNISingleton'.""
It occurs when I click on the button that calls billing.purchase(purchase_id).

Thank you very much

@alfredogarciaw
Copy link

alfredogarciaw commented Oct 19, 2024

Remember to add ITEM_CONSUMABLES in google play console with price
Then look if your code looks like this

Code

  func iniciar_facturacion():
      print("Intentando cargar singleton AndroidIAPP ")
      await get_tree().create_timer(1).timeout
      if Engine.has_singleton("AndroidIAPP"):
	      billing = Engine.get_singleton("AndroidIAPP")
	      print("AndroidIAPP singleton cargado")
	      
	      # Conectar señales
	      billing.connected.connect(_on_connected)
	      billing.disconnected.connect(_on_disconnected)
	      billing.purchase.connect(_on_purchase)
	      billing.purchase_error.connect(_on_purchase_error)
	      billing.purchase_updated.connect(_on_purchase_updated)
	      billing.purchase_cancelled.connect(_on_purchase_cancelled)
	      billing.purchase_consumed.connect(_on_purchase_consumed)
	      billing.purchase_consumed_error.connect(_on_purchase_consumed_error)
	      billing.purchase_acknowledged.connect(_on_purchase_acknowledged)
	      billing.purchase_acknowledged_error.connect(_on_purchase_acknowledged_error)
	      billing.query_product_details.connect(_on_query_product_details)
	      billing.query_product_details_error.connect(_on_query_product_details_error)
	      billing.query_purchases.connect(_on_query_purchases)
	      billing.query_purchases_error.connect(_on_query_purchases_error)
	      
	      # Iniciar conexión
	      billing.startConnection()
      else:
	      print("No se encontró el singleton AndroidIAPP")
  
  func _on_connected() -> void:
      await get_tree().create_timer(1).timeout
      print("Conexión con Google Play Billing establecida.")
      # Consultar detalles de productos disponibles
      billing.queryProductDetails(ITEM_CONSUMABLES, "inapp")
      # Consultar compras no consumidas
      billing.queryPurchases("inapp")
  
  func _on_disconnected() -> void:
      print("Desconectado de Google Play Billing.")
  
  func _on_query_product_details(response) -> void:
      for product in response["product_details_list"]:
	      var product_id = product["product_id"]
	      var price = product["price"]
	      print("ID de producto: %s, Precio: %s" % [product_id, price])
	      # Puedes almacenar los detalles del producto para mostrarlos en la interfaz
  
  func purchase_item(product_id: String, is_personalized: bool = false):
      billing.purchase([product_id], is_personalized)
  
  
  func _on_purchase(response) -> void:
      print("Compra iniciada:")
      print(JSON.stringify(response, "  "))
  
  func _on_purchase_updated(response):
      for purchase in response["purchases_list"]:
	      process_purchase(purchase)
  
  # Procesa cada compra y decide si debe consumirse
  func process_purchase(purchase):
      for product in purchase["products"]:
	      if product in ITEM_CONSUMABLES:
		      if not purchase["is_acknowledged"]:
			      # Almacena el mapeo
			      purchase_token_to_product[purchase["purchase_token"]] = product
			      # Inicia el consumo
			      billing.consumePurchase(purchase["purchase_token"])
		      else:
			      print("Compra ya reconocida.")
	      else:
		      print("Producto no reconocido: %s" % product)
  
  # Este método se llama cuando el consumo del producto es exitoso
  func _on_purchase_consumed(response) -> void:
      print("Producto consumido con éxito.")
      print("Contenido de response:", response)
      
      if response.has("purchase_token"):
	      var purchase_token = response["purchase_token"]
	      if purchase_token in purchase_token_to_product:
		      var product = purchase_token_to_product[purchase_token]
		      print("Producto consumido: %s" % product)
		      grant_item_to_player(product)
		      # Remueve el token consumido del mapeo
		      purchase_token_to_product.erase(purchase_token)
	      else:
		      print("Error: No se encontró el producto asociado al purchase_token.")
      else:
	      print("Error: No se encontró purchase_token en el response.")
  
  
  
  
  func grant_item_to_player(product_id: String):
      var coins_to_add = coin_values.get(product_id, 0)
      if coins_to_add > 0:
	      monedas_recogidas += coins_to_add
	      print("A otorgar %d monedas al jugador. Total monedas: %d" % [coins_to_add, monedas_recogidas])
	      guardar_monedas_encriptado()
	      emit_signal("update_label", str(monedas_recogidas))
	      print("Otorgando %d monedas al jugador. Total monedas: %d" % [coins_to_add, monedas_recogidas])
      else:
	      print("Producto no reconocido: %s" % product_id)
  
  # Manejo de errores y otras señales
  func _on_purchase_error(error) -> void:
      print("Error en la compra:")
      print(JSON.stringify(error, "  "))
  
  func _on_purchase_cancelled(response) -> void:
      print("Compra cancelada:")
      print(JSON.stringify(response, "  "))
  
  func _on_purchase_consumed_error(error) -> void:
      print("Error al consumir el producto:")
      print(JSON.stringify(error, "  "))

@Suthameow
Copy link

@alfredogarciaw @code-with-max

Thank you very much; now it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants