Just updated to the 3.2 release candidate (22.214.171.1240) and the problem remains. Our software wont be able to update past 3.0 for the foreseeable future, which means we can't upgrade to Flex 4.6 SDK either, not without removing a significant feature of our application. This doesn't inspire us to the future of AIR in our company.
There are a few solutions and work around we might be able to employ to fix our specific feature, but there is still a concern over the effects of having an ever ballooning invoke queue that never clears. That could have additional issues over extended use of the application.
The issue is we can't tell if the event being caught is a duplicate because of this issue or legitimately requested by the user. Imagine having a mouse click handler that mis-fires when the user does various other activities that are clearly not a clicks. The human brain can easily tell that isn't a click, but the code just knows MouseEvent.CLICK was dispatched on that item and our handlers catch it and act on it. It doesn't have the context to know whether the user intended that event to be dispatched or not.
There are a few server-side changes we will be making to help with this specific issue, such as adding a time stamp to each invocation request. Then we can compare if the cloned event has a newer timestamp or not. If not, we ignore it. The solution isn't perfect and still has some usability issues regarding stale URLs that could be legitimately used, but it would solve the issue to some satisfaction.
However, that doesn't solve the underlying issue of the invoke queue constantly growing as you try to use the application. Each time you rotate the application it will try to process this queue. Even if we found work arounds for each individual feature we need InvokeEvent for, the application dispatching the InvokeEvent each and every time you change orientation will continue to cause issues.
Replying to LinkedIn group thread: http://lnkd.in/bzF36F
You are right that I could have and probably should have provided a lot more details, but the issue is very easily reproduced by the small code samples provided. I'll spend an hour or so going through the process in much greater detail though.
Flex SDK isn't related, nor is Apache Flex. I almost didn't post to the group because of this and I've made comments specifically about why I posted and it wasn't for a Stackoverflow replacement. However, AIR SDK is related and the issue details demonstrates that. InvokeEvent works as documented in AIR 3.0 SDK, but not in 3.1 or 3.2, regardless of run-time. It doesn't happen on iOS devices because iOS doesn't include the AIR run-time at all, unlike Android. And all but one Android device shows this behavior. I'm not sure why my LG Slate is exempt though. I really can't explain that.
queueEvents isn't in the docs because it is a private variable that you can only see via debugging. If it was protected or public then I could work with it directly to clear it out, if that would even resolve the issue.
Now, onto the details.
For our application we are utilizing InvokeEvent to jump to specific content based on a registered URL. In the mobile manifest.xml files you can register a custom protocol for your application to catch, much like iTunes.
<data android:scheme="flrreader" android:host="*"/>
Now if you were to click on URL in your browser that looked like: flrreader://open?url=myBookUrl, then AIR will dispatch an InvokeEvent with the "arguments" array populated with the first element being the full custom URL: "flrrreader://open?url=myBookUrl". We can then watch for this, parse it, and act on it.
When building against AIR 3.0 SDK running on AIR 3.0, AIR 3.1, or AIR 3.2 run-times we see the following behavior:
1. The application launches and onInvoke is triggered with an empty argument array, so we don't act on it.
2. Switch to browser and click button that calls custom URL
3. onInvoke is hit with the event.arguments having 1 element, which is our full URL string.
4. event.target is NativeApplication and it's private queuedEvents property has 2 elements. The first elements is a generic InvokeEvent with no arguments. The second element is an InvokeEvent which has the same arguments as the one we caught. It is not the same event, however. Their identifiers are unique, so there is cloning taking place at some point.
5. Processing our URL has us launch right into the requested book. We exit the book and return to the book list.
6. We then rotate the tablet, changing orientation. Views change as expected. onInvoke is not called again, as you would expect.
7. Switch to browser, click on URL again, onInvoke is triggered with arguments populated.
8. queueEvents now has 3 entries.
Now we change to build against AIR 3.1 SDK or AIR 3.2 SDK. Not other changes are made. Flex SDK and AIR run-times remain the same on all devices.
1-5. Remains the same as above
6. We rotate the tablet, changing orientation. onInvoke is immediately triggered with a new InvokeEvent that has our last arguments on it. Since the arguments exist, we act on them an launch you into the book.
7. queuedEvents now has 3 entries, as if we clicked on the URL from the browser again.
Each time you change orientation you repeat 6 and 7. These events aren't references, they are all unique. If I clear event.arguments in the handler, the next onInvoke call still has arguments. If I clear queuedEvents or update events inside queuedEvents (which can only be done via debugger, as it is private to NativeApplication), the next onInvoke still has the arguments as if we were triggered via the custom URL.
Even without the URL registration you can see this behavior. Just added the listener in the original code sample you can see it trigger each and every time you change orientation with the queuedEvents growing. And this only occurs when building against AIR 3.1 and above with the devices run-time remaining the same.
You are right in that I have some ignorance here. I don't really know what is happening in as much detail as I would like, hence the posting for aid. But I've done enough due diligence to show that there is significant behavior changes simply by compiling against a different SDK. Behavior that seems flawed to me. InvokeEvents shouldn't be dispatched each time you change orientation.
Now, maybe this is an intentional change and it is behaving the way it should and AIR 3.0 and previous was flawed. If that's the case, then it would be nice to hear the details and reasoning for the change as well as how to handle this new behavior. When I read through the InvokeEvent documentation I didn't get the impression that this was the case, however.
As for our server-side solution, I would rather resolve this on the client, but we do what we must to get things working. The only solution I can see to this problem is for us to add a unique identifier, such as a time stamp to the custom URL and then keep track of that when we hit on InvokeEvent handler. If future InvokeEvent calls have an identical identifier then we know it is an unintentional dupe and we can ignore it. This causes some usability issues and is less than ideal (e.g. we have to refresh the page/link after you click the link to make sure it isn't stale for the next time you want to click it).
Hopefully these details clear some things up. I should have gone into this level of detail from the start, but I thought the sample code and brief description replicated the issue quite easily and I figured if somebody had ran into this issue before it would be enough to start a productive conversation about it. I apoligize for the confusing and unproductive conversation my lack of details caused.
Thank you for the additional information. I think the best thing to do at this point is to add this to bugbase.adobe.com (if you haven't done so already.) A couple of things I'd recommend. First, please include a sample project so we can quickly verify the behavior. Second, I'd recommend stressing at the top of the bug that this is an injected issue with AIR 3.1, it does not occur with AIR 3.0. Finally, please post back with the bug URL so I can follow up internally.
Thanks for the response. I've created the bug, which can be found here: https://bugbase.adobe.com/index.cfm?event=bug&id=3144722. Let me know if it needs additional details. I tried to keep it straight to the point. I also included additional testing I did to narrow it down to Android 3.2.x devices. The ticket has an attached project to demonstrate the issue, which also includes 2 pre-built Android packages for AIR 3.0 and AIR 3.1.
I submitted a defect, but haven't heard any updates on it. You might want to comment on it and mention the mobile Android versions you've found it does or doesn't work on. My app was only for tablets, so that's what my test data focused on.
The only work around I can think of would be to add a GUID or timestamp to the URLs so the InvokeEvent handler can test to see if future invokes are duplicates or not. You just have to make sure that whatever generates the URLs will never legitimately re-send a stale GUID/stamp.
I have an another bug with Air 3.4 on Android on Galaxy nexus
Recently upgraded to the AIR 3.4 SDK and have run into a show stopping issue regarding InvokeEvent on mobile devices. The application is dispatching a new InvokeEvent each and every time you stop the application with NativeApplication.nativeApplication.exit() and launch application with the multitasking button, not with the application icon, it isn't clearing the "queuedEvents" array, the new event it dispatches each time.
In the case of our application, this would be parameters that tell the application to load certain data. So each time you change lauch application, the application re-triggers that load sequence, causing lots of undersirable behavior.
It isn't a bug, it's the default behavior for android.
<activity android:launchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.BROWSABLE"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="mycustomuri"/> </intent-filter> </activity>
the solution is to add android:launchMode="singleTop" in the application descriptor
How to remove the bug report at bugbase.adobe.com ?