I'm seeing an assertion failure in cleanup that could be explained by
the cleanup happening when initGame() has been called but no subsequent
jni method that would have added the env to the map. So let's add it
immediately so that can't happen.
JNIThread is somehow sticking around sometimes and holding the lock for
a game so that that game can never be opened again. On the theory that
there's some place retain() was called but not release(), use the thing
in try-with-resources wherever possible. Which is pretty much
everywhere.
Also added age to the lock-holder report being uploaded.
I'm seeing something permanently lock a game so it can't be opened. So
add code to report the stack of the owner to Crashlytics when opening
fails 3 times in a row. It's stubbed out for non-debug builds.
I didn't like having to re-open a game to archive it after
rematching, so now there's a checkbox that lets you archive it after
either rematching OR just using OK to dismiss the alert. Also fixed
rematch of a solo game causing new game to be created in Archive
group if that's where the source game was.
squash me
Got tired of the space the forground-service notification icons were
taking. So now BT sends and receives are done via static threads and
onHandleWork(). The send thread times itself out quickly. The receive
thread doesn't yet. We'll see how long the OS lets it run and what
needs to be done to deal with that.
It's useful when testing to have the remote device play without human
interaction. So add an option, and UI to trigger it, for the players
created remotely in response to an invitation to be robots. There are
guards in place to catch the feature slipping into a release build.
Eliminate the writer thread, since onHandleWork() is already getting
called on a thread and can process the outbound queue itself. And get
rid of reader thread needing to wait for an instance of the RelayService
to be available to process a packet (which was taking 5-10 seconds all
the time): just post received packets via an enqueueWork() call using
the app context that's always available.
GameListItem was clearing its summary when kicking off a replacement
load. Instead keep the old around in case somebody wants it (e.g. to
figure out what menus to enable) until the reload finishes.
Also add logging of how long loading takes. I think a cache might be
called for.
Darned thing was dropping packets, failing to connect games built in
response to invitations, and otherwise misbehaving. First was due to not
resheduling when exited with outbound packets in queue; second to not
overriding relayNoConnProc() (due to signature change.) Though it still
happens occasionally.... Also added timestamps to track how long it
takes a packet to be sent and ACK'd.
Not sure why I was doing this, but it's not worth the
trouble (e.g. stopping updates of other data to fix an android bug
sending too many reregistration messages.) So now just use the first
element of arrays, replacing what's there instead of prepending. Ideally
those columns would not be arrays, but that's a harder change.
It's too useful to live without. So: tap into the static list of live
Delegates, and if any of them has an Activity available use it to run
Toast on UI thread. Otherwise there will be no display.
There's likely a bug in Android now where I'm registering over and
over though the fcm id hasn't been changed. That's wrong, but it's
also wrong (and filling up the db) to register a duplicate as if it
were new. So stop that.
My VSIZE is no longer legal, and apparently there's no workaround (no
way to safely figure the length of an array whose size is known at
compile time.) To avoid the risk of duplicating little constants, added
macros that define length in a way a new VSIZE can pick it up. Couldn't
make that work for struct field arrays, however, so there I'm using
constants.
Looks like certain launches that went through DispatchNotify could
create a second "instance" of the app. Giving that Activity a launchMode
of singleTask fixes this (singleTop does not.)
Launching a game in response to a wordlist it needing being downloaded
went through a different Intent-creation path from the rest, and
resulted in a second instance of the app showing in the launcher. This
shoudl fix that. I don't *think* it's the only way I'm getting second
instances or stacked GamesLists, but it should get fixed.
I modified existing translated strings, adding the new clause. Not doing
that would cause the existing strings to be stripped because they'd no
longer have the matching set of format specifiers.
Fix a race condition introduced by making initing jnithread be
asynchronous: all the layout that was supposed to happen after listeners
were added instead happened before, so that they weren't there to be
installed as part of layout. So now, after adding them, get them hooked
up to the UI. (The complexity of this is all historical: at some point
the listeners were getting added BEFORE there were views to attach them
to, so they were cached and added later. Probably now they could simply
be installed as part of adding them. But I'm not doing that now.)
Was seeing frequent failure to open games as JNIThread.getRetained() was
unable to get a lock without waiting. Which it can't do on UI thread. So
added a method to GameLock that takes a callback to be called when the
lock's obtained, with the actual waiting done on a local thread. Then
fixed BoardDelegate a bit to not crash while waiting for the callback.
Once built for SDK 26 the old GCM support code crashes as it's calling
startService() from background. Duh! Will have to bring in Firebase's
replacement at some point. For now if I'm to release it has to be
without GCM.
more dev-only code, likely: if the game that's sending the invitation is
open when the invitation arrives, should still check if it's a dupe or
should be accepted.
Was creating a second game in some cases in response to duplicated
invitations. Add a test for forceChannel: if there's already a game with
the same gameID *and* forceChannel assume the invitation is a dupe and
drop it.
So I don't have to open a game to see e.g. how it's connecting, refactor
the network status stuff so it can be called from both board and
gameslist views. Then add new context menuitem that calls it.
I'm seeing a rare case where a game connectes to relay specifying a room
and somehow gets both slots, having provided different gameSeeds the two
times. This means an opponent won't connect, the room being full in that
game. I can't reproduce, so am logging seed changes better and switching
linux client to leave seed generation to comms as Android does.