Last version of my app has a lot of ANR issues on Google Play Console. However , I have no idea how to detect it because unlike crash - there is no specific info what causes this error. I'm not able to reproduce it as well. I tried to set StrictMode but there is no info. Here's log from Google Play :
Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago. Wait queue length: 15. Wait queue head age: 6275.4ms.)
com.app.activities.MainActivity
"main" prio=5 tid=1 Native
| group="main" sCount=1 dsCount=0 flags=1 obj=0x75575af0 self=0x7d33a14c00
| sysTid=32404 nice=-10 cgrp=default sched=0/0 handle=0x7db97df548
| state=S schedstat=( 856817053 66517026 2057 ) utm=59 stm=26 core=6 HZ=100
| stack=0x7ff86f1000-0x7ff86f3000 stackSize=8MB
| held mutexes=
#00 pc 000000000007cab0 /system/lib64/libc.so (__ioctl+4)
#01 pc 000000000002c8f0 /system/lib64/libc.so (ioctl+132)
#02 pc 000000000005cd88 /system/lib64/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+244)
#03 pc 000000000005db34 /system/lib64/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+60)
#04 pc 000000000005d988 /system/lib64/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+176)
#05 pc 00000000000519a0 /system/lib64/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+72)
#06 pc 0000000000136c34 /system/lib64/libandroid_runtime.so (android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int)+152)
at android.os.BinderProxy.transactNative (BinderProxy.java)
at android.os.BinderProxy.transact (BinderProxy.java:1129)
at com.android.vending.billing.IInAppBillingService$Stub$Proxy.isBillingSupported (IInAppBillingService.java:202)
at com.mill.coders.purchases.payments.IabHelper$1.onServiceConnected (IabHelper.java:244)
at android.app.LoadedApk$ServiceDispatcher.doConnected (LoadedApk.java:1741)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run (LoadedApk.java:1773)
at android.os.Handler.handleCallback (Handler.java:873)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loop (Looper.java:280)
at android.app.ActivityThread.main (ActivityThread.java:6706)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:858)
As you can see , if I'm not mistaken, suspicious is IabHelper class. It's very strange cause it is async method. Also - on the top of the screen you can see that log comes from Main Activity (right?) . IabHelper doesnt exist in MainActivity so WTF ? How can I test it ? :/ Here is how I use setUp method from IabHelper in different activity :
private fun goToOfferScreen() {
offerScreenShown = true
getItemPrice(item)
animateView(whole_card, Techniques.SlideOutDown, 200)
animateView(starImageView, Techniques.SlideOutDown, 200)
ribbons.visibility = View.GONE
levelUpTitle.visibility = View.GONE
levelUpValue.visibility = View.GONE
newLimitLabel.visibility = View.GONE
newLimitValue.visibility = View.GONE
coinBonusTitle.visibility = View.GONE
coinBonusValue.visibility = View.GONE
cashDiff.visibility = View.GONE
delayAction({ showOfferScreen(item) }, 300)
delayAction({ showButtonsWithDelay() }, 800)
}
private fun getItemPrice(bankOfferItem: LevelUpOfferModel) {
if (AppPreferences.isSamsungBuild) {
val iapHelper = IapHelper.getInstance(context)
iapHelper.setOperationMode(HelperDefine.OperationMode.OPERATION_MODE_TEST)
iapHelper.getProductsDetails(bankOfferItem.bundle.name) { errorVo, arrayList ->
errorVo?.let {
priceBtn.text = arrayList[0].itemPriceString
}
}
} else {
val sku = bankOfferItem.bundle.name
val list = mutableListOf<String>()
list.add(sku)
purchaseHelper = InAppPurchaseRetry(InAppPurchase(a, Utilities.getApiKey()), 200, 5)
purchaseHelper.setUp(context, object : InAppPurchase.Callback<IabResult> {
override fun onSuccess(p0: IabResult?) {
purchaseHelper.getAllPurchases(list) { p0, p1 ->
try {
p1?.let {
inv = p1
if (it.hasDetails(sku)) {
priceBtn.text = it.getSkuDetails(sku).price
} else
priceBtn.visibility = View.GONE
}
} catch (e: NullPointerException) {
Toast.makeText(context, context.resources.getString(R.string.alert_title_ooops), Toast.LENGTH_SHORT).show()
}
}
}
override fun onError(p0: Exception?) {
priceBtn.visibility = View.GONE
}
})
}
}