All posts by Manish

Problems with ESP32 configures as both Client and AP

In one project I had an ESP32 configured both as Access Point (AP) and as a Wifi Client. Everything was fine, until I changed my home Wifi password.

After changing the home Wifi password I wanted to change the Wifi password set on the device through the Web UI I made and hosted on the device. The problem started there. I was unable to access the UI.

Reviewing the code realised that the Wifi Client is continuously trying to re-establish the connection in a loop. And hence is unable to process the incoming request and process the page.

So either need to stop the scanning from time to time or stop the scanning when an AP client is connected. For short and fast resolution I stopped the wifi connection retry when a client is connected to AP.

WiFi.softAPgetStationNum()

FASTLed Library and RGB Led

Recently I was trying to make a device that will indicate different status through different light colors.

Now after developing everything a strange thing started to happen – the RGB LED was not showing the colors properly. For example – suppose the current color is Green and then I put Red. It is not glowing pure RED, the Green pixel (the individual green pixel of the LED) is still faintly on.

After some thoughts and searches found the solution is to first turn of the LED fully

leds[0] = CRGB::Black;
FastLED.show();

and then show the new color.

Hope this helps someone.

 

Self hosted Gitlab and 500 error

In my case the 500 error started after migration to new server. Everything was done as per the official guide. The server started fine, the repositories, comments, issues also showed fine. The problem – on clicking a repository it showed 500 error.

Checking the error logs (under /var/log/gitlab/) didn’t reveal the problem. The best way to check Gitlab logs is to use the command –

gitlab-ctl tail

Checking the logs with the above command revealed a permission issue in these folders

drwxr-sr-x 5 git git 4096 Jul 30 22:29 /mnt/repo_storage2/git-data/repositories/+gitaly
drwxr-s--- 250 git git 4096 Jul 5 16:20 /mnt/repo_storage2/git-data/repositories/@hashed
drwxr-sr-x 9 git git 4096 Jul 17 20:18 /mnt/repo_storage2/git-data/repositories/@pools

Don’t know why/how “git-redis” became the owner of the subfolders. Changing the owner to “git” solved the 500 error.

 

 

Unsigned Int, Mathematical operations and pitfalls in Arduino or C

Let’s consider the below code:


unsigned long startTime = 1940, stopTime = 0;

if( (stopTime - startTime) > 5000ul)
{
Serial.println("Hello World!");
}

Will this say Hello World?

Yes, it will. If this sounds new or surprising to you, please continue reading below.

Note the variables have been defined as unsigned long. So the result of mathematical operations will also be in unsigned value. Hence though the result of the operation apparently looks to be -1940 but in practise it will be 4294965356

And thus the comparison in the if() will evaluate to true.

State changes during an in-app purchase in Ionic Cordova

Here is a cleaner and summarized version of the data/state changes that are crucial for recording the transaction.

For raw dumps view this article – Ionic Cordova In-App Purchase Plugin Events Data Dumps

---------------------------------
START OF NEW PURCHASE 
---------------------------------
state:requested
canPurchase: false
owned: false

state:initiated
canPurchase: false
owned: false

state:initiated
canPurchase: false
owned: false

state:approved
canPurchase: false
owned: false

state:approved
canPurchase: false
owned: false

state:approved
canPurchase: false
owned: false

state:approved
canPurchase: false
owned: false

state:finished
canPurchase: false
owned: false

AT THIS POINT - OWNED event listener is fired

"state":"owned"
"canPurchase":false
"owned":true

state:owned
canPurchase: false
owned: true


-----------------------------------------
AFTER CANCELLED AND CANCELLATION COMPLETE
-----------------------------------------
state:valid
owned:false
canPurchase:true

state:valid
owned:false
canPurchase:true


PURCHASE CANCELLED is called when the 
	Popup is cancelled
	When an expired Subscription is removed from Google Play


-----------------------------------------------------------------------------------------
WHEN THE SUBSCRIPTION IS VALID IT IS GIVING the below on screen change or app open
-----------------------------------------------------------------------------------------
state:valid
owned:false
canPurchase:true

state:valid
owned:false
canPurchase:true

state:approved
canPurchase: false
owned: false

state:approved
canPurchase: false
owned: false

state:approved
canPurchase: false
owned: false

state:approved
canPurchase: false
owned: false

AT THIS POINT - OWNED event listener is fired

state:owned
canPurchase: false
owned: true

state:owned
canPurchase: false
owned: true


The Transaction ID (GPA.3341-6605-8567-18617) changes after new purchases are made
The Purchase Token (cpfjfhlbkagpjhgcoejgmajg.AO-J1Oxa8jFURcHtEBngM5zuU...) changes after new purchases are taken. 

Please note the purchase token will remain same as long the Subscription doesn’t fail or cancelled. The subscription auto-renews and will have the same “Purchase Token“. But if the renewal fails and the grace period is over or the subscription is cancelled and re-subscribed, a new “Purchase Token” will be generated.

Ionic Cordova In-App Purchase Plugin Events Data Dumps

Below are the dumps of data received in ionic cordova app from Google billing or in-app purchase plugin events.

See this article for a summarized version – State changes during an in-app purchase in Ionic Cordova

this.store.get(my_product_id)

{"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"valid","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":true,"owned":false,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":null,"transaction":null,"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true}


this.store.products

Products: [{"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"valid","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":true,"owned":false,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":null,"transaction":null,"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true}]



this.store.when(my_product_id).updated((product: IAPProduct) 

Updated{"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"valid","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":true,"owned":false,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":null,"transaction":null,"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true}


AFTER THE PURCHASE INITIATED -- Not Owned or Expired

Updated{"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"requested","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":false,"owned":false,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":{"applicationUsername":""},"transaction":null,"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true}
login.page.ts:108 

this.store.order("com.myapp.annualsubscription2").then(async (result) 

store.Product {id: 'com.myapp.annualsubscription2', alias: 'com.myapp.annualsubscription2', type: 'paid subscription', group: 'default', state: 'initiated', …}
login.page.ts:80 

Updated{"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"initiated","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":false,"owned":false,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":{"applicationUsername":""},"transaction":null,"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true}


------------------------------
When already purchased and valid - if tried to purchase it will call "Updated" and the below data will be returned. Owned is true and canPurchase is false

Updated{"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"requested","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":false,"owned":true,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":{"applicationUsername":"","oldSku":"com.myapp.annualsubscription2","oldPurchaseToken":"imggoijiflaahpaefffokpom.AO-J1OyBHUqG13A6fFZjQ2wVGo08oGFHh5ilnnwlnJ1-5dUGTEr7xt2IhejvGmuYPxNMSVyKnzcZHx93X7d0lkPgX9jOGRiSCgj2Iw7gXnYHfJ_l231h-I8"},"transaction":{"type":"android-playstore","id":"GPA.3345-8962-9923-27341","purchaseToken":"imggoijiflaahpaefffokpom.AO-J1OyBHUqG13A6fFZjQ2wVGo08oGFHh5ilnnwlnJ1-5dUGTEr7xt2IhejvGmuYPxNMSVyKnzcZHx93X7d0lkPgX9jOGRiSCgj2Iw7gXnYHfJ_l231h-I8","purchaseState":0,"receipt":"{"orderId":"GPA.3345-8962-9923-27341","packageName":"com.synchrodipity.psychiccircuit","productId":"com.myapp.annualsubscription2","purchaseTime":1672226442183,"purchaseState":0,"purchaseToken":"imggoijiflaahpaefffokpom.AO-J1OyBHUqG13A6fFZjQ2wVGo08oGFHh5ilnnwlnJ1-5dUGTEr7xt2IhejvGmuYPxNMSVyKnzcZHx93X7d0lkPgX9jOGRiSCgj2Iw7gXnYHfJ_l231h-I8","autoRenewing":true,"acknowledged":true}","signature":"EZEp+5T/YNruAJwcJL0xBYxV9ZZDTMxM5cj3UZArlrS3F2aToJx8G7ZE7YJyl2iv99QyaLrjJGeqlFVRtUmW+zEzV/JtyYGwPdUqtatejYkZGTijFF01k/396HFJK29kE0MOV89EQr/6AncpuVjVGrP9Akg7/jdqk5LDgiQSBygT+ISZPTRBZQsQhx2rZoT+l2FabxRmxU3ojt/93bvWFKRaPVb9CNWmGkiw55E/652CDlkxbV8SzoaSRkW08vSFz3T1cKWW/BcRwLCjVdmdOHQzvm4tbUMJkHPgt+XimI7FdQBkvCRWtWujBA63Hus80hwAqseGaGzZaiaC3+WpKg=="},"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true,"acknowledged":true,"renewalIntent":"Renew"}



AFTER PURCHASE IS DONE
---------------------------------

Updated{"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"initiated","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":false,"owned":true,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":{"applicationUsername":""},"transaction":{"type":"android-playstore"},"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true,"acknowledged":true,"renewalIntent":"Renew"}

login.page.ts:80 
Updated{"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"approved","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":false,"owned":true,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":{"applicationUsername":""},"transaction":{"type":"android-playstore","id":"GPA.3316-7182-4489-05118","purchaseToken":"geeofnjlooihoghajeghgfah.AO-J1Ozu_V7ScY_5aC2hM-t0sMMgERU56UNaypCX4FjJ_yGPpLAxiMbvN4oraW_iUfqlGyAiSLgbTbofrv4-81HP-AQGY_FtCAc05xLRrd2GXb31Cr3IO0o","purchaseState":0,"receipt":"{"orderId":"GPA.3316-7182-4489-05118","packageName":"com.synchrodipity.psychiccircuit","productId":"com.myapp.annualsubscription2","purchaseTime":1672228274746,"purchaseState":0,"purchaseToken":"geeofnjlooihoghajeghgfah.AO-J1Ozu_V7ScY_5aC2hM-t0sMMgERU56UNaypCX4FjJ_yGPpLAxiMbvN4oraW_iUfqlGyAiSLgbTbofrv4-81HP-AQGY_FtCAc05xLRrd2GXb31Cr3IO0o","autoRenewing":true,"acknowledged":false}","signature":"PZ/BRKILYTgVhQV8ZRe4Gxnqw9GcwSItEcreABctaMLGvNaGYLmNwM/bUHJc/C293TK4RFPJOBaGMgKD72zaOPkxeffFoe9zzh+1zRbCdCuUce4xPdsIepxhO30kIpdT+0jXoASM8U4duRGYiMcaPlBpVQOTQwtcnmjtOhHQbKtF7kosE8Mev3cpn5PTh2lPcNpio4LSuEc6akZtgXctMkkCOw5asrg8g9dUdgzavMgPc1vofcWQxU7L4XyvuQJsNW55MWNV4aMpIu6+yNJ8nfjSXRK77x130v8CtzHaN5taX7DQff5dYvtx5zcWrxjWfIJUNuuAWEwkIP3k/nCLtw=="},"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true,"acknowledged":true,"renewalIntent":"Renew"}

login.page.ts:80 
Updated{"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"approved","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":false,"owned":true,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":{"applicationUsername":""},"transaction":{"type":"android-playstore","id":"GPA.3316-7182-4489-05118","purchaseToken":"geeofnjlooihoghajeghgfah.AO-J1Ozu_V7ScY_5aC2hM-t0sMMgERU56UNaypCX4FjJ_yGPpLAxiMbvN4oraW_iUfqlGyAiSLgbTbofrv4-81HP-AQGY_FtCAc05xLRrd2GXb31Cr3IO0o","purchaseState":0,"receipt":"{"orderId":"GPA.3316-7182-4489-05118","packageName":"com.synchrodipity.psychiccircuit","productId":"com.myapp.annualsubscription2","purchaseTime":1672228274746,"purchaseState":0,"purchaseToken":"geeofnjlooihoghajeghgfah.AO-J1Ozu_V7ScY_5aC2hM-t0sMMgERU56UNaypCX4FjJ_yGPpLAxiMbvN4oraW_iUfqlGyAiSLgbTbofrv4-81HP-AQGY_FtCAc05xLRrd2GXb31Cr3IO0o","autoRenewing":true,"acknowledged":false}","signature":"PZ/BRKILYTgVhQV8ZRe4Gxnqw9GcwSItEcreABctaMLGvNaGYLmNwM/bUHJc/C293TK4RFPJOBaGMgKD72zaOPkxeffFoe9zzh+1zRbCdCuUce4xPdsIepxhO30kIpdT+0jXoASM8U4duRGYiMcaPlBpVQOTQwtcnmjtOhHQbKtF7kosE8Mev3cpn5PTh2lPcNpio4LSuEc6akZtgXctMkkCOw5asrg8g9dUdgzavMgPc1vofcWQxU7L4XyvuQJsNW55MWNV4aMpIu6+yNJ8nfjSXRK77x130v8CtzHaN5taX7DQff5dYvtx5zcWrxjWfIJUNuuAWEwkIP3k/nCLtw=="},"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true,"acknowledged":false,"renewalIntent":"Renew"}

login.page.ts:80 
Updated{"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"approved","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":false,"owned":true,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":{"applicationUsername":""},"transaction":{"type":"android-playstore","id":"GPA.3316-7182-4489-05118","purchaseToken":"geeofnjlooihoghajeghgfah.AO-J1Ozu_V7ScY_5aC2hM-t0sMMgERU56UNaypCX4FjJ_yGPpLAxiMbvN4oraW_iUfqlGyAiSLgbTbofrv4-81HP-AQGY_FtCAc05xLRrd2GXb31Cr3IO0o","purchaseState":0,"receipt":"{"orderId":"GPA.3316-7182-4489-05118","packageName":"com.synchrodipity.psychiccircuit","productId":"com.myapp.annualsubscription2","purchaseTime":1672228274746,"purchaseState":0,"purchaseToken":"geeofnjlooihoghajeghgfah.AO-J1Ozu_V7ScY_5aC2hM-t0sMMgERU56UNaypCX4FjJ_yGPpLAxiMbvN4oraW_iUfqlGyAiSLgbTbofrv4-81HP-AQGY_FtCAc05xLRrd2GXb31Cr3IO0o","autoRenewing":true,"acknowledged":false}","signature":"PZ/BRKILYTgVhQV8ZRe4Gxnqw9GcwSItEcreABctaMLGvNaGYLmNwM/bUHJc/C293TK4RFPJOBaGMgKD72zaOPkxeffFoe9zzh+1zRbCdCuUce4xPdsIepxhO30kIpdT+0jXoASM8U4duRGYiMcaPlBpVQOTQwtcnmjtOhHQbKtF7kosE8Mev3cpn5PTh2lPcNpio4LSuEc6akZtgXctMkkCOw5asrg8g9dUdgzavMgPc1vofcWQxU7L4XyvuQJsNW55MWNV4aMpIu6+yNJ8nfjSXRK77x130v8CtzHaN5taX7DQff5dYvtx5zcWrxjWfIJUNuuAWEwkIP3k/nCLtw=="},"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true,"acknowledged":false,"renewalIntent":"Renew"}

login.page.ts:80 
Updated{"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"approved","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":false,"owned":true,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":{"applicationUsername":""},"transaction":{"type":"android-playstore","id":"GPA.3316-7182-4489-05118","purchaseToken":"geeofnjlooihoghajeghgfah.AO-J1Ozu_V7ScY_5aC2hM-t0sMMgERU56UNaypCX4FjJ_yGPpLAxiMbvN4oraW_iUfqlGyAiSLgbTbofrv4-81HP-AQGY_FtCAc05xLRrd2GXb31Cr3IO0o","purchaseState":0,"receipt":"{"orderId":"GPA.3316-7182-4489-05118","packageName":"com.synchrodipity.psychiccircuit","productId":"com.myapp.annualsubscription2","purchaseTime":1672228274746,"purchaseState":0,"purchaseToken":"geeofnjlooihoghajeghgfah.AO-J1Ozu_V7ScY_5aC2hM-t0sMMgERU56UNaypCX4FjJ_yGPpLAxiMbvN4oraW_iUfqlGyAiSLgbTbofrv4-81HP-AQGY_FtCAc05xLRrd2GXb31Cr3IO0o","autoRenewing":true,"acknowledged":false}","signature":"PZ/BRKILYTgVhQV8ZRe4Gxnqw9GcwSItEcreABctaMLGvNaGYLmNwM/bUHJc/C293TK4RFPJOBaGMgKD72zaOPkxeffFoe9zzh+1zRbCdCuUce4xPdsIepxhO30kIpdT+0jXoASM8U4duRGYiMcaPlBpVQOTQwtcnmjtOhHQbKtF7kosE8Mev3cpn5PTh2lPcNpio4LSuEc6akZtgXctMkkCOw5asrg8g9dUdgzavMgPc1vofcWQxU7L4XyvuQJsNW55MWNV4aMpIu6+yNJ8nfjSXRK77x130v8CtzHaN5taX7DQff5dYvtx5zcWrxjWfIJUNuuAWEwkIP3k/nCLtw=="},"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true,"acknowledged":false,"renewalIntent":"Renew"}

login.page.ts:80 
Updated{"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"finished","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":false,"owned":true,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":{"applicationUsername":""},"transaction":{"type":"android-playstore","id":"GPA.3316-7182-4489-05118","purchaseToken":"geeofnjlooihoghajeghgfah.AO-J1Ozu_V7ScY_5aC2hM-t0sMMgERU56UNaypCX4FjJ_yGPpLAxiMbvN4oraW_iUfqlGyAiSLgbTbofrv4-81HP-AQGY_FtCAc05xLRrd2GXb31Cr3IO0o","purchaseState":0,"receipt":"{"orderId":"GPA.3316-7182-4489-05118","packageName":"com.synchrodipity.psychiccircuit","productId":"com.myapp.annualsubscription2","purchaseTime":1672228274746,"purchaseState":0,"purchaseToken":"geeofnjlooihoghajeghgfah.AO-J1Ozu_V7ScY_5aC2hM-t0sMMgERU56UNaypCX4FjJ_yGPpLAxiMbvN4oraW_iUfqlGyAiSLgbTbofrv4-81HP-AQGY_FtCAc05xLRrd2GXb31Cr3IO0o","autoRenewing":true,"acknowledged":false}","signature":"PZ/BRKILYTgVhQV8ZRe4Gxnqw9GcwSItEcreABctaMLGvNaGYLmNwM/bUHJc/C293TK4RFPJOBaGMgKD72zaOPkxeffFoe9zzh+1zRbCdCuUce4xPdsIepxhO30kIpdT+0jXoASM8U4duRGYiMcaPlBpVQOTQwtcnmjtOhHQbKtF7kosE8Mev3cpn5PTh2lPcNpio4LSuEc6akZtgXctMkkCOw5asrg8g9dUdgzavMgPc1vofcWQxU7L4XyvuQJsNW55MWNV4aMpIu6+yNJ8nfjSXRK77x130v8CtzHaN5taX7DQff5dYvtx5zcWrxjWfIJUNuuAWEwkIP3k/nCLtw=="},"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true,"acknowledged":false,"renewalIntent":"Renew"}

login.page.ts:80 
Updated{"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"owned","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":false,"owned":true,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":{"applicationUsername":""},"transaction":{"type":"android-playstore","id":"GPA.3316-7182-4489-05118","purchaseToken":"geeofnjlooihoghajeghgfah.AO-J1Ozu_V7ScY_5aC2hM-t0sMMgERU56UNaypCX4FjJ_yGPpLAxiMbvN4oraW_iUfqlGyAiSLgbTbofrv4-81HP-AQGY_FtCAc05xLRrd2GXb31Cr3IO0o","purchaseState":0,"receipt":"{"orderId":"GPA.3316-7182-4489-05118","packageName":"com.synchrodipity.psychiccircuit","productId":"com.myapp.annualsubscription2","purchaseTime":1672228274746,"purchaseState":0,"purchaseToken":"geeofnjlooihoghajeghgfah.AO-J1Ozu_V7ScY_5aC2hM-t0sMMgERU56UNaypCX4FjJ_yGPpLAxiMbvN4oraW_iUfqlGyAiSLgbTbofrv4-81HP-AQGY_FtCAc05xLRrd2GXb31Cr3IO0o","autoRenewing":true,"acknowledged":false}","signature":"PZ/BRKILYTgVhQV8ZRe4Gxnqw9GcwSItEcreABctaMLGvNaGYLmNwM/bUHJc/C293TK4RFPJOBaGMgKD72zaOPkxeffFoe9zzh+1zRbCdCuUce4xPdsIepxhO30kIpdT+0jXoASM8U4duRGYiMcaPlBpVQOTQwtcnmjtOhHQbKtF7kosE8Mev3cpn5PTh2lPcNpio4LSuEc6akZtgXctMkkCOw5asrg8g9dUdgzavMgPc1vofcWQxU7L4XyvuQJsNW55MWNV4aMpIu6+yNJ8nfjSXRK77x130v8CtzHaN5taX7DQff5dYvtx5zcWrxjWfIJUNuuAWEwkIP3k/nCLtw=="},"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true,"acknowledged":true,"renewalIntent":"Renew"}


this.store.order("com.myapp.annualsubscription2").then

First it is giving the OLD details //NOTE 
"state" is "initiated"
"purchaseState" is "0",
"renewalIntent" is "Lapse"
{
    "id": "com.myapp.annualsubscription2",
    "alias": "com.myapp.annualsubscription2",
    "type": "paid subscription",
    "group": "default",
    "state": "initiated",
    "title": "Annual Subscription",
    "description": "Play unlimited with an Annual Subscription",
    "priceMicros": 4000000,
    "price": "₹4.00",
    "currency": "INR",
    "countryCode": null,
    "loaded": true,
    "canPurchase": false,
    "owned": true,
    "introPrice": "",
    "introPriceMicros": "",
    "introPricePeriod": null,
    "introPriceNumberOfPeriods": null,
    "introPricePeriodUnit": null,
    "introPriceSubscriptionPeriod": null,
    "introPricePaymentMode": null,
    "ineligibleForIntroPrice": null,
    "discounts": [],
    "downloading": false,
    "downloaded": false,
    "additionalData": {
        "applicationUsername": ""
    },
    "transaction": {
        "type": "android-playstore",
        "id": "GPA.3399-8293-2056-78889",
        "purchaseToken": "gihamknkcpkdldnpbbknpopk.AO-J1Ox79aJrQexjiainR5XBKtsk-WmcJ70bhYzps1khZ6U53b91n2-U8eIKZUnOh9jZqVOcE-a12eqJtp_GowFcEaLrxMkq2b5bCzIPCQ207rFWVMPQBz8",
        "purchaseState": 0,
        "receipt": "{"orderId":"GPA.3399-8293-2056-78889","packageName":"com.synchrodipity.psychiccircuit","productId":"com.myapp.annualsubscription2","purchaseTime":1672254433028,"purchaseState":0,"purchaseToken":"gihamknkcpkdldnpbbknpopk.AO-J1Ox79aJrQexjiainR5XBKtsk-WmcJ70bhYzps1khZ6U53b91n2-U8eIKZUnOh9jZqVOcE-a12eqJtp_GowFcEaLrxMkq2b5bCzIPCQ207rFWVMPQBz8","autoRenewing":false,"acknowledged":true}",
        "signature": "rRZXyzwlehHBYcQir2QFYiAEncB8uFPyVX5OoS2whERDS+yObqtDV4GQTZ6vSRt6NzmU1PXMXLRoWR5vW82PhZ9FlNqLvQ6Z3EYe/NfUy3xAtKE5fxpFlVxqiiJ70S9RWsN0WfDTkluj7Tp4Jkm2eH1ciHBlnxkYWkuWtxmQlL3s7DI1W/PpIDh/ao+w5IJI/H1/QJ7svZezu/Da4dtz8TZoxX7nI8sib14ryjjU40zvcDc4i5B1wdJ+SdWrByHlEsGr/ZvwR7SkXVp6Oeq0bm47uIyqu+vN6X8RM0cdtGQ08w0UeHPtHM9ssKWrYJvZS9S4lIO8IAT+tD/F7Gxc9w=="
    },
    "trialPeriod": null,
    "trialPeriodUnit": null,
    "billingPeriod": 1,
    "billingPeriodUnit": "Year",
    "valid": true,
    "acknowledged": true,
    "renewalIntent": "Lapse"
}


/////// THE AUTO RENEW KEEPS RENEWING AUTOMATICALLY -- THE PURCHASE TIME REMAINS SAME, THE ORIGINAL PURCHASE TIME. 
Owned: {"id":"com.myapp.annualsubscription2","alias":"com.myapp.annualsubscription2","type":"paid subscription","group":"default","state":"owned","title":"Annual Subscription","description":"Play unlimited with an Annual Subscription","priceMicros":4000000,"price":"₹4.00","currency":"INR","countryCode":null,"loaded":true,"canPurchase":false,"owned":true,"introPrice":"","introPriceMicros":"","introPricePeriod":null,"introPriceNumberOfPeriods":null,"introPricePeriodUnit":null,"introPriceSubscriptionPeriod":null,"introPricePaymentMode":null,"ineligibleForIntroPrice":null,"discounts":[],"downloading":false,"downloaded":false,"additionalData":null,"transaction":{"type":"android-playstore","id":"GPA.3375-4850-7157-68633","purchaseToken":"oonhpdlmpllpgdgejmamjcbl.AO-J1Ow5YVxekuyW31hJVFx0klzO40IaO3_CKwCYE41Wp-GHLPM8OcPxIM1oUcuxfVY70cldN52tT3MS79yDewB6VI6xPctTihxRKKh_os7Z9Jk7LIqm-HI","purchaseState":0,"receipt":"{"orderId":"GPA.3375-4850-7157-68633","packageName":"com.synchrodipity.psychiccircuit","productId":"com.myapp.annualsubscription2","purchaseTime":1672304595703,"purchaseState":0,"purchaseToken":"oonhpdlmpllpgdgejmamjcbl.AO-J1Ow5YVxekuyW31hJVFx0klzO40IaO3_CKwCYE41Wp-GHLPM8OcPxIM1oUcuxfVY70cldN52tT3MS79yDewB6VI6xPctTihxRKKh_os7Z9Jk7LIqm-HI","autoRenewing":true,"acknowledged":true}","signature":"HepM1z7VCy1S/faOftTsIx0RsntF4HmNPwzeY8WsoGwPyec2y9RLThCNx0zlaFcD21EGBV7ljLDCQD6WHC8WrBrzJwHqqFFZpF7JD/WbwiiWz4MbIoSIePoq8pLO8LMDEp2RDt+PquvYF8H55wqIlUiOPCxofHWU74NejI3w7xJ+k0njASpUj1lYgkA3nW+Yr5DpuK+OoYd0p3M7Ve2tR9kKpvTxfIiDL1ZIoS7cDtYm9/9RzsZakqp7CI7Y3a5dDyl1JYKLN5DQBsJhkClMavde9o6EakREWspeLqarh98xtUbff1kqdZQNEIMY8KXpYOS2bjrjQjsfP3GbT+dm5Q=="},"trialPeriod":null,"trialPeriodUnit":null,"billingPeriod":1,"billingPeriodUnit":"Year","valid":true,"acknowledged":true,"renewalIntent":"Renew"}


///ON CANCELLED 
The RENEWAL INTENT becomes : Lapse

///////////PURCHASE CANCELLED IS CALLED WHEN THE USER CANCELS THE SUBSCRIPTION POPUP


Please note the plugin doesn’t return any expiry date

Compiling Old Ionic Cordova Projects for Android API 32 and Google Billing Client 4.0

You have developed a good and nice project with Cordova a few years back and now need to publish an update then chances are you are stuck like me.

My project was just 2 years old and now while trying to update Google wanted support for API level 31 and Google Billing Client 4.0.0 at minimum. I expected this would be a piece of cake – update the Android platform and the libraries. But, no, I was welcomed by the perils of  community driven softwares with frequent core updates.

While trying to update I found that most libraries had never been updated in the past few years. And there started the first problem – library incompatibility.

After spending a lot of time in finding and troubleshooting the API level compatibility was achieved. I must mention that it was only with help of Android Studio it was possible to  understand what was going wrong. Android Studio’s logcat was more verbose and showed proper errors (Ionic cordova verbose mode was showing errors being thrown from core – and didn’t have any useful information).

And then came the second problem – the Billing library update. Which needed an update of the Purchase plugin also. Now the guide links mentioned in the plugin’s page on NPMJS takes to guides that has least to none to irrelevant information. After searching around got the actual useful guides.

And after all that I was happy that all issues are solved now time to publish the update. But no, there was more hurdles 🙂 . The splash screen icon changed back to Cordova default. That was my fault I missed the point that the splash screen policy changed. I thought – no problem – let me regenerate the splash and the icons using the cordova-res command. But the plan didn’t work  – cordova-res command didn’t generate the proper splash and icons required for Android 31+
Tried to generate through Android Studio ( https://developer.android.com/studio/write/image-asset-studio ), that generated the icons properly but it somehow broke the application (added configs in AndroidManifest which didn’t work). But I believe with a little time and analysis that could be solved.
As I was in a hurry, I created the icons manually following Google’s guide on splash ( https://developer.android.com/develop/ui/views/launch/splash-screen ) and little trial and error.
Also needed to add the below line under ‘<platform name=”android”>‘. The color needs to be what you want

<preference name="AndroidWindowSplashScreenBackground" value="#ffffff" />

Below are some of the strange issues I encountered and what I did:

First I needed to find the appropriate Cordova version that supports API level 31 and 32 and install it. Here this guide helped
https://cordova.apache.org/docs/en/11.x/guide/platforms/android/
After updating the Cordova version and other plugins. I tried to build the app but it failed. Tried building using Android Studio and found that "GradlePluginGoogleServicesVersion" need an updated version - Android Studio suggested the min version and I used that. I added the following in config.xml

<preference name="GradlePluginGoogleServicesVersion" value="4.3.14" />

also needed to do the below. Even after adding the above there were errors. Someone suggested to set that false. I did and there was no problem. 

<preference name="GradlePluginGoogleServicesEnabled" value="false" />
I needed the app to run full screen and hide the navigation bar. The internet is full of some weird solution - changing the color and transparency of the navigation bar. Albeit that didn't work. 
I tried some native codes - modifying the generated native codes in Android studio and that did work. But that was little cumbersome process. On more and more searching for a simpler and better way found this - 

Add this to config.xml
<preference name="Fullscreen" value="true" />
For the icons and the splash I did this

Created a square frame/layer of 288x288px with the same background colour as the page your loading the icon on and put your logo in the middle of this square. Your logo needs to fit within 192px or 160px as the case maybe. (https://developer.android.com/develop/ui/views/launch/splash-screen)

This website can help - https://easyappicon.com/
Was having problems with Native audio. Found that initialization at proper point is important. Initializing in the constructor and within platform.ready is working best

this.platform.ready().then(() => {

});
Talking about Native Audio - the first was I was getting the error - "Native Audio Plugin is not installed or added". But it was. 

This issue of plugin not found while the plugin is installed and added to code is due to version incompatibility. Wished the message was appropriate - the message with respect to the problem is complete haywire.
Needed to add the following to config.xml

<preference name="AndroidXEnabled" value="true" />
<preference name="enableJetifier" value="true" />
Started getting Annotation error at one point. Solved by adding the following 

ionic cordova plugin add cordova-plugin-androidx-adapter
ionic cordova plugin add cordova-plugin-androidx
After adding cordova in-app purchase plugins started getting Lint errors. Needed to add the following to build.gradle in the app folder

android {
   lintOptions {
      checkReleaseBuilds false
   }
}
This guide helped in implementing in-app purchase. But this doesn't have a direct link in the plugin page. 
https://ionicframework.com/docs/v5/native/in-app-purchase-2

This has the methods but all haven't been implemented
https://github.com/j3k0/cordova-plugin-purchase/tree/master/api
I am very thankful to Damian Tarnawsky The author of https://ionic.zendesk.com/hc/en-us/articles/7891143965975-Migrating-to-Cordova-Android-11

In summary the main things to work on

  1. Plugin versions update
  2. Appropriate Gradle and JAVA versions
  3. Appropriate Cordova and android versions
  4. Proper logo and splash sizes
  5. Appropriate entries in config.xml

And most importantly if Ionic and Cordova is throwing errors that doesn’t make sense – try building in Android Studio.