From bb846060e9412f0ceea6cb61289941fcbf3b58bc Mon Sep 17 00:00:00 2001 From: Eric House Date: Mon, 14 Aug 2017 07:52:18 -0700 Subject: [PATCH 01/19] always add "self" choice to invite-by-relay-id list Poorly integrated: you can delete it only to have it come back, but send-to-self is just a debugging thing anyway. --- .../android/xw4/RelayInviteDelegate.java | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayInviteDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayInviteDelegate.java index 44d92c058..f8b043aba 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayInviteDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayInviteDelegate.java @@ -75,6 +75,7 @@ public class RelayInviteDelegate extends InviteDelegate { // private RelayDevsAdapter m_adapter; private boolean m_immobileConfirmed; private Activity m_activity; + private String m_devIDStr; public static void launchForResult( Activity activity, int nMissing, RequestCode requestCode ) @@ -101,6 +102,8 @@ public class RelayInviteDelegate extends InviteDelegate { super.init( msg, R.string.empty_relay_inviter ); addButtonBar( R.layout.relay_buttons, BUTTONIDS ); + m_devIDStr = String.format( "%d", DevID.getRelayDevIDInt(m_activity) ); + // getBundledData( savedInstanceState ); // m_addButton = (ImageButton)findViewById( R.id.manual_add_button ); @@ -437,6 +440,21 @@ public class RelayInviteDelegate extends InviteDelegate { // } // } // addPhoneNumbers + private void addSelf() + { + boolean hasSelf = false; + for ( DevIDRec rec : m_devIDRecs ) { + if ( rec.m_devID.equals( m_devIDStr ) ) { + hasSelf = true; + break; + } + } + if ( !hasSelf ) { + DevIDRec rec = new DevIDRec( "me", m_devIDStr ); + m_devIDRecs.add( rec ); + } + } + private void rebuildList( boolean checkIfAll ) { Collections.sort( m_devIDRecs, new Comparator() { @@ -444,15 +462,9 @@ public class RelayInviteDelegate extends InviteDelegate { return rec1.m_opponent.compareTo(rec2.m_opponent); } }); + + addSelf(); updateListAdapter( m_devIDRecs.toArray( new DevIDRec[m_devIDRecs.size()] ) ); - // m_adapter = new RelayDevsAdapter(); - // setListAdapter( m_adapter ); - // if ( checkIfAll && m_devIDRecs.size() <= m_nMissing ) { - // Iterator iter = m_devIDRecs.iterator(); - // while ( iter.hasNext() ) { - // iter.next().m_isChecked = true; - // } - // } tryEnable(); } From 19c7543eb319e25f97643b4bfd37209278d49168 Mon Sep 17 00:00:00 2001 From: Eric House Date: Mon, 14 Aug 2017 22:40:07 -0700 Subject: [PATCH 02/19] make finding most recent apk based on git revision Auto-update was based on my manually setting what the newest is. Better to use the git revision stored in the .apk, or failing that (later) in the file name, to determine "age". This is all based on forcing a linear order on git commits, but at least at the granularity of releases that should be ok. --- xwords4/android/scripts/info.py | 60 ++++++++++++++++++++++++++++---- xwords4/android/scripts/mygit.py | 18 ++++++++++ 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/xwords4/android/scripts/info.py b/xwords4/android/scripts/info.py index 6f98a8ea7..5ecf2ef8e 100755 --- a/xwords4/android/scripts/info.py +++ b/xwords4/android/scripts/info.py @@ -1,7 +1,8 @@ #!/usr/bin/python # Script meant to be installed on eehouse.org. -import logging, shelve, hashlib, sys, json, subprocess, glob, os, struct, random, string, psycopg2 +import logging, shelve, hashlib, sys, re, json, subprocess, glob, os +import struct, random, string, psycopg2, zipfile import mk_for_download, mygit import xwconfig @@ -54,6 +55,10 @@ k_LANGSVERS = 'lvers' # Version for those sticking with RELEASES k_REL_REV = 'android_beta_98' +# newer build-info.txt file contain lines like this: +# git: android_beta_123 +pat_git_tag = re.compile( 'git: (\S*)', re.DOTALL | re.MULTILINE ) + # Version for those getting intermediate builds k_suffix = '.xwd' @@ -164,18 +169,57 @@ def getDictSums(): openShelf() return s_shelf[k_SUMS] +def getGitRevFor(file, repo): + result = None + zip = zipfile.ZipFile(file); + + try: + result = zip.read('assets/gitvers.txt').split("\n")[0] + except KeyError, err: + result = None + + if not result: + try: + data = zip.read('assets/build-info.txt') + match = pat_git_tag.match(data) + if match: + tag = match.group(1) + if not 'dirty' in tag: + result = repo.tagToRev(tag) + except KeyError, err: + None + + # print "getGitRevFor(", file, "->", result + return result + def getOrderedApks( path, debug ): # logging.debug( "getOrderedApks(" + path + ")" ) apks = [] + fileToRev = {} pattern = path - if debug: pattern += "/XWords4-debug-android_*.apk" - else: pattern += "/XWords4-release_*android_beta_*.apk" + if debug: pattern += "/*debug*.apk" + else: pattern += "/*release*.apk" + + repo = mygit.GitRepo(xwconfig.k_REPOPATH) + refs = repo.getAllRevs() + revToOrder = {} + index = 0 + for ref in refs: + revToOrder[ref] = index + index = index + 1 files = ((os.stat(apk).st_mtime, apk) for apk in glob.glob(pattern)) for mtime, file in sorted(files, reverse=True): # logging.debug( file + ": " + str(mtime) ) - apks.append( file ) + gitRev = getGitRevFor(file, repo) + if gitRev: + if gitRev in revToOrder: + fileToRev[file] = gitRev + apks.append( file ) + + # now we can sort based on the ordering of git revisions + apks = sorted(apks, key=lambda apk: revToOrder[fileToRev[apk]]) return apks @@ -525,7 +569,7 @@ def usage(): print "usage:", sys.argv[0], '--get-sums [lang/dict]*' print ' | --test-get-app app avers gvers' print ' | --test-get-dicts name lang curSum' - print ' | --list-apks [path/to/apks]' + print ' | --list-apks [path/to/apks] [debug|release]' print ' | --list-dicts' print ' | --opponent-ids-for' print ' | --clear-shelf' @@ -564,10 +608,12 @@ def main(): print getDicts( [params] ) elif arg == '--list-apks': argc = len(sys.argv) - if argc >= 4: usage() + if argc >= 5: usage() path = "" if argc >= 3: path = sys.argv[2] - apks = getOrderedApks( path, False ) + debug = False + if argc >= 4: debug = sys.argv[3] == 'debug' + apks = getOrderedApks( path, debug ) if 0 == len(apks): print "No apks in", path for apk in apks: print apk diff --git a/xwords4/android/scripts/mygit.py b/xwords4/android/scripts/mygit.py index 98d745474..a6dc4c20f 100755 --- a/xwords4/android/scripts/mygit.py +++ b/xwords4/android/scripts/mygit.py @@ -80,6 +80,24 @@ class GitRepo: break return result; + def getAllRevs( self ): + result = [] + params = ['git', 'rev-list', '--reverse', 'HEAD'] + out, err = self.__doProcess( params ) + if err: self.__error('error from getRevsBetween') + result = None + if out: + result = out.splitlines() + return result + + def tagToRev(self, tag): + result = None + params = ['git', 'rev-list', '-n', '1', tag] + out, err = self.__doProcess( params ) + if err: self.__error('error from getRevsBetween') + if out: result = out.strip() + return result + def getHeadRev( self ): return self.getRevsBetween( 'HEAD', 'HEAD' )[0] From f7d4d6b637400330432cf09a03ed1e48b978e12b Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 16 Aug 2017 07:29:17 -0700 Subject: [PATCH 03/19] sort by versionCode, then by file age revert a bit, dropping use of git revision and repo to provide an order. Instead use aapt (which is an ubuntu package now) to pull the version code and appID from .apk files, order by versionCode, and secondarily by file mod time. --- xwords4/android/scripts/info.py | 102 ++++++++++++++++---------------- 1 file changed, 52 insertions(+), 50 deletions(-) diff --git a/xwords4/android/scripts/info.py b/xwords4/android/scripts/info.py index 5ecf2ef8e..df74bb667 100755 --- a/xwords4/android/scripts/info.py +++ b/xwords4/android/scripts/info.py @@ -192,36 +192,36 @@ def getGitRevFor(file, repo): # print "getGitRevFor(", file, "->", result return result -def getOrderedApks( path, debug ): - # logging.debug( "getOrderedApks(" + path + ")" ) - apks = [] - fileToRev = {} - pattern = path - if debug: pattern += "/*debug*.apk" - else: pattern += "/*release*.apk" +pat_badge_info = re.compile("package: name='([^']*)' versionCode='([^']*)' versionName='([^']*)'", re.DOTALL ) - repo = mygit.GitRepo(xwconfig.k_REPOPATH) - refs = repo.getAllRevs() - revToOrder = {} - index = 0 - for ref in refs: - revToOrder[ref] = index - index = index + 1 +def getAAPTInfo(file): + result = None + test = subprocess.Popen(["aapt", "dump", "badging", file], shell = False, stdout = subprocess.PIPE) + for line in test.communicate(): + if line: + match = pat_badge_info.match(line) + if match: + result = { 'appID' : match.group(1), + 'versionCode' : int(match.group(2)), + 'versionName' : match.group(3), + } + break + return result +def getOrderedApks( path, appID, debug ): + apkToCode = {} + apkToMtime = {} + if debug: pattern = path + "/*debug*.apk" + else: pattern = path + "/*release*.apk" files = ((os.stat(apk).st_mtime, apk) for apk in glob.glob(pattern)) for mtime, file in sorted(files, reverse=True): - # logging.debug( file + ": " + str(mtime) ) - gitRev = getGitRevFor(file, repo) - if gitRev: - if gitRev in revToOrder: - fileToRev[file] = gitRev - apks.append( file ) - - # now we can sort based on the ordering of git revisions - apks = sorted(apks, key=lambda apk: revToOrder[fileToRev[apk]]) - - return apks + info = getAAPTInfo(file) + if info['appID'] == appID: + apkToCode[file] = info['versionCode'] + apkToMtime[file] = mtime + result = sorted(apkToCode.keys(), reverse=True, key=lambda file: (apkToCode[file], apkToMtime[file])) + return result def getVariantDir( name ): result = '' @@ -280,7 +280,7 @@ def getApp( params, name ): # If we're a dev device, always push the latest if k_DEBUG in params and params[k_DEBUG]: dir = k_filebase + k_apkDir + variantDir - apks = getOrderedApks( dir, True ) + apks = getOrderedApks( dir, name, True ) if 0 < len(apks): apk = apks[0] curApk = params[k_GVERS] + '.apk' @@ -291,7 +291,7 @@ def getApp( params, name ): logging.debug("url: " + url) result = {k_URL: url} elif k_DEVOK in params and params[k_DEVOK]: - apks = getOrderedApks( k_filebase + k_apkDir, False ) + apks = getOrderedApks( k_filebase + k_apkDir, name, False ) if 0 < len(apks): apk = apks[0] # Does path NOT contain name of installed file @@ -303,19 +303,15 @@ def getApp( params, name ): result = {k_URL: url} logging.debug( result ) - elif k_AVERS in params and k_GVERS in params: - avers = params[k_AVERS] + elif k_GVERS in params: gvers = params[k_GVERS] if k_INSTALLER in params: installer = params[k_INSTALLER] else: installer = '' - logging.debug( "name: %s; avers: %s; installer: %s; gvers: %s" - % (name, avers, installer, gvers) ) + logging.debug( "name: %s; installer: %s; gvers: %s" + % (name, installer, gvers) ) if name in k_versions: - versForName = k_versions[name] - if versForName[k_AVERS] > int(avers): - result = {k_URL: k_urlbase + '/' + versForName[k_URL]} - elif k_GVERS in versForName and not gvers == versForName[k_GVERS]: + if k_GVERS in versForName and not gvers == versForName[k_GVERS]: result = {k_URL: k_urlbase + '/' + versForName[k_URL]} else: logging.debug(name + " is up-to-date") @@ -565,23 +561,25 @@ def clearShelf(): for key in shelf: del shelf[key] shelf.close() -def usage(): +def usage(msg=None): + if msg: print "ERROR:", msg print "usage:", sys.argv[0], '--get-sums [lang/dict]*' print ' | --test-get-app app avers gvers' print ' | --test-get-dicts name lang curSum' - print ' | --list-apks [path/to/apks] [debug|release]' + print ' | --list-apks [--path ] [--debug] --appID org.something' print ' | --list-dicts' print ' | --opponent-ids-for' print ' | --clear-shelf' sys.exit(-1) def main(): - if 1 >= len(sys.argv): usage(); + argc = len(sys.argv) + if 1 >= argc: usage(); arg = sys.argv[1] if arg == '--clear-shelf': clearShelf() elif arg == '--list-dicts': - if 2 < len(sys.argv): lc = sys.argv[2] + if 2 < argc: lc = sys.argv[2] else: lc = None dictsJson = listDicts( lc ) print json.dumps( dictsJson ) @@ -592,14 +590,13 @@ def main(): s_shelf[k_SUMS] = dictSums closeShelf() elif arg == '--test-get-app': - if not 5 == len(sys.argv): usage() + if not 4 == argc: usage() params = { k_NAME: sys.argv[2], - k_AVERS: int(sys.argv[3]), - k_GVERS: sys.argv[4], + k_GVERS: sys.argv[3], } - print getApp( params ) + print getApp( params, sys.argv[2] ) elif arg == '--test-get-dicts': - if not 5 == len(sys.argv): usage() + if not 5 == argc: usage() params = { k_NAME: sys.argv[2], k_LANG : sys.argv[3], k_MD5SUM : sys.argv[4], @@ -607,14 +604,19 @@ def main(): } print getDicts( [params] ) elif arg == '--list-apks': - argc = len(sys.argv) - if argc >= 5: usage() path = "" - if argc >= 3: path = sys.argv[2] debug = False - if argc >= 4: debug = sys.argv[3] == 'debug' - apks = getOrderedApks( path, debug ) - if 0 == len(apks): print "No apks in", path + appID = '' + args = sys.argv[2:] + while len(args): + arg = args.pop(0) + if arg == '--appID': appID = args.pop(0) + elif arg == '--debug': debug = True + elif arg == '--path': path = args.pop(0) + if not appID: usage('--appID not optional') + apks = getOrderedApks( path, appID, debug ) + if not len(apks): print "No apks in", path + else: print for apk in apks: print apk elif arg == '--opponent-ids-for': From 33f80fbefdb6f766880951a8f0f1372980289e97 Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 16 Aug 2017 07:34:03 -0700 Subject: [PATCH 04/19] up version strings for new release --- xwords4/android/app/build.gradle | 4 ++-- xwords4/android/app/src/main/assets/changes.html | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/xwords4/android/app/build.gradle b/xwords4/android/app/build.gradle index 5ffd333d6..2d1c6e313 100644 --- a/xwords4/android/app/build.gradle +++ b/xwords4/android/app/build.gradle @@ -1,6 +1,6 @@ def INITIAL_CLIENT_VERS = 8 -def VERSION_CODE_BASE = 119 -def VERSION_NAME = '4.4.123' +def VERSION_CODE_BASE = 120 +def VERSION_NAME = '4.4.124' def FABRIC_API_KEY = System.getenv("FABRIC_API_KEY") boolean forFDroid = hasProperty('forFDroid') diff --git a/xwords4/android/app/src/main/assets/changes.html b/xwords4/android/app/src/main/assets/changes.html index 9cc65c05a..b84d37f63 100644 --- a/xwords4/android/app/src/main/assets/changes.html +++ b/xwords4/android/app/src/main/assets/changes.html @@ -13,7 +13,7 @@ -

CrossWords 4.4.123 release

+

CrossWords 4.4.124 release

This is a quick bug-fix release.

@@ -25,8 +25,8 @@

New with this release

    -
  • Fix crash when invitation requires a wordlist you don't have
  • -
  • Include latest Portuguese translations
  • +
  • Fix failure to create game from invitation after downloading + missing wordlist

(The full changelog From 1a36f3286bb3c9628b2699b5a7f1da616f8b8dd2 Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 22 Aug 2017 07:52:15 -0700 Subject: [PATCH 05/19] ignore generated files --- xwords4/android/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xwords4/android/.gitignore b/xwords4/android/.gitignore index c2958256c..c3599faaa 100644 --- a/xwords4/android/.gitignore +++ b/xwords4/android/.gitignore @@ -3,3 +3,5 @@ local.properties .idea app/src/main/assets/build-info.txt +obj-* +libs-* From 24a38c8f46349c8267377aab805e0c3db38540f1 Mon Sep 17 00:00:00 2001 From: Eric House Date: Thu, 24 Aug 2017 06:58:53 -0700 Subject: [PATCH 06/19] cleanup connection status display text Get rid of treating 0 as a legit date (1970 being illegit). Tweak formatting. It's not perfect, but few people see it so we'll see how it goes during development. --- .../android/xw4/ConnStatusHandler.java | 40 ++++++++++++++----- .../java/org/eehouse/android/xw4/Utils.java | 3 +- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnStatusHandler.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnStatusHandler.java index bfcac0c2a..c2d0b9795 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnStatusHandler.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnStatusHandler.java @@ -84,14 +84,24 @@ public class ConnStatusHandler { public String newerStr( Context context ) { - s_time.set( successNewer? lastSuccess : lastFailure ); - return format( context, s_time ); + String result = null; + long time = successNewer? lastSuccess : lastFailure; + if ( time > 0 ) { + s_time.set( time ); + result = format( context, s_time ); + } + return result; } public String olderStr( Context context ) { - s_time.set( successNewer? lastFailure : lastSuccess ); - return format( context, s_time ); + String result = null; + long time = successNewer? lastFailure : lastSuccess; + if ( time > 0 ) { + s_time.set( time ); + result = format( context, s_time ); + } + return result; } public void update( boolean success ) @@ -175,13 +185,20 @@ public class ConnStatusHandler { String did = addDebugInfo( context, typ ); sb.append( String.format( "\n\n*** %s %s***\n", typ.longName( context ), did ) ); + + // For sends we list failures too. SuccessRecord record = recordFor( typ, false ); tmp = LocUtils.getString( context, record.successNewer? R.string.connstat_succ : R.string.connstat_unsucc ); - sb.append( LocUtils - .getString( context, R.string.connstat_lastsend_fmt, - tmp, record.newerStr( context ) ) ); + + String timeStr = record.newerStr( context ); + if ( null != timeStr ) { + sb.append( LocUtils + .getString( context, R.string.connstat_lastsend_fmt, + tmp, timeStr ) ) + .append( "\n" ); + } int fmtId = 0; if ( record.successNewer ) { @@ -193,11 +210,12 @@ public class ConnStatusHandler { fmtId = R.string.connstat_lastother_unsucc_fmt; } } - if ( 0 != fmtId ) { - sb.append( LocUtils.getString( context, fmtId, - record.olderStr( context ))); + timeStr = record.olderStr( context ); + if ( 0 != fmtId && null != timeStr ) { + sb.append( LocUtils.getString( context, fmtId, timeStr )) + .append( "\n" ); } - sb.append( "\n\n" ); + sb.append( "\n" ); record = recordFor( typ, true ); if ( record.haveSuccess() ) { diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/Utils.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/Utils.java index b4d98e644..e76107259 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/Utils.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/Utils.java @@ -511,8 +511,7 @@ public class Utils { new ObjectInputStream( new ByteArrayInputStream(bytes) ); result = ois.readObject(); } catch ( Exception ex ) { - Log.ex( TAG, ex ); - Assert.assertFalse( BuildConfig.DEBUG ); + Log.d( TAG, ex.getMessage() ); } return result; } From ff415640fde96cb9d6444931986de0785ec27312 Mon Sep 17 00:00:00 2001 From: Eric House Date: Sat, 26 Aug 2017 11:02:27 -0700 Subject: [PATCH 07/19] sync variants' AndroidManifest.xml files --- .../android/app/src/main/AndroidManifest.xml | 2 -- .../android/app/src/xw4d/AndroidManifest.xml | 26 ++++--------------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/xwords4/android/app/src/main/AndroidManifest.xml b/xwords4/android/app/src/main/AndroidManifest.xml index c198ca706..73519c956 100644 --- a/xwords4/android/app/src/main/AndroidManifest.xml +++ b/xwords4/android/app/src/main/AndroidManifest.xml @@ -6,8 +6,6 @@ - - - - @@ -76,32 +70,30 @@ + + @@ -112,17 +104,14 @@ @@ -132,6 +121,7 @@ + @@ -170,7 +160,6 @@ @@ -186,16 +175,12 @@ @@ -230,7 +215,6 @@ - Date: Sun, 27 Aug 2017 10:12:37 -0700 Subject: [PATCH 08/19] explicitly use Theme.Material as app theme Fixed Samsung having made a white actionbar default and so my menubar icons becoming invisible. --- xwords4/android/app/src/main/AndroidManifest.xml | 1 + xwords4/android/app/src/main/res/values/styles.xml | 2 ++ xwords4/android/app/src/xw4d/AndroidManifest.xml | 1 + 3 files changed, 4 insertions(+) diff --git a/xwords4/android/app/src/main/AndroidManifest.xml b/xwords4/android/app/src/main/AndroidManifest.xml index 73519c956..28b652169 100644 --- a/xwords4/android/app/src/main/AndroidManifest.xml +++ b/xwords4/android/app/src/main/AndroidManifest.xml @@ -46,6 +46,7 @@ + -

CrossWords 4.4.124 release

+

CrossWords 4.4.125 release

-

This is a quick bug-fix release.

+

This is a quick bug-fix release that may matter only for a few + Samsung devices

Please take @@ -25,8 +26,9 @@

New with this release

    -
  • Fix failure to create game from invitation after downloading - missing wordlist
  • +
  • Explicitly specify application "theme" to fix a Samsung + "upgrade" turning the titlebar white and so making menu icons + disappear

(The full changelog From 671d345377021763763925991f7c2a38b6b156d7 Mon Sep 17 00:00:00 2001 From: Eric House Date: Sun, 27 Aug 2017 15:55:31 -0700 Subject: [PATCH 12/19] remove most of xw4dbg's AndroidManifest.xml What's here is merged with the main one, so no point in duplicating and it's just a pain to maintain. Remove as much as possible that's not unique to the debug variant (crashlytics and wifidirect, basically.) --- .../android/app/src/main/AndroidManifest.xml | 3 - .../android/app/src/xw4d/AndroidManifest.xml | 204 ------------------ 2 files changed, 207 deletions(-) diff --git a/xwords4/android/app/src/main/AndroidManifest.xml b/xwords4/android/app/src/main/AndroidManifest.xml index 28b652169..bc49a4b99 100644 --- a/xwords4/android/app/src/main/AndroidManifest.xml +++ b/xwords4/android/app/src/main/AndroidManifest.xml @@ -83,9 +83,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -52,182 +16,14 @@ android:theme="@style/AppTheme" > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From db658edc67adfecb8075432ccd1bd2e956583fd6 Mon Sep 17 00:00:00 2001 From: Eric House Date: Mon, 28 Aug 2017 07:06:57 -0700 Subject: [PATCH 13/19] don't add to queue once it's stopped No point in adding something if we're not going to process it. --- .../src/main/java/org/eehouse/android/xw4/jni/JNIThread.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/JNIThread.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/JNIThread.java index 57cba9739..49a83d74d 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/JNIThread.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/JNIThread.java @@ -749,10 +749,11 @@ public class JNIThread extends Thread { public void handle( JNICmd cmd, Object... args ) { - m_queue.add( new QueueElem( cmd, true, args ) ); if ( m_stopped && ! JNICmd.CMD_NONE.equals(cmd) ) { - Log.w( TAG, "adding %s to stopped thread!!!", cmd.toString() ); + Log.w( TAG, "NOT adding %s to stopped thread!!!", cmd.toString() ); DbgUtils.printStack( TAG ); + } else { + m_queue.add( new QueueElem( cmd, true, args ) ); } } From 270df00692eeb256bc68770309a1c6179fbadf3e Mon Sep 17 00:00:00 2001 From: Eric House Date: Mon, 28 Aug 2017 07:12:10 -0700 Subject: [PATCH 14/19] use new API to offer to hide buttons When SDK >= 19 there's an API to tell if a listview is full enough to require scrolling. So use that, rather than the raw count of games, to decide whether to offer new users to hide the new game buttons. --- .../android/xw4/GamesListDelegate.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java index cd004bf1a..e98aecd9f 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java @@ -24,19 +24,20 @@ import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; -import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; +import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Handler; -import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; +import android.view.ContextMenu; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.widget.AdapterView; import android.widget.AdapterView.OnItemLongClickListener; +import android.widget.AdapterView; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; @@ -1926,8 +1927,19 @@ public class GamesListDelegate extends ListDelegateBase { m_mySIS.nextIsSolo = solo; - int count = m_adapter.getCount(); - boolean skipOffer = 6 > count || XWPrefs.getHideNewgameButtons( m_activity ); + boolean skipOffer = XWPrefs.getHideNewgameButtons( m_activity ); + if ( ! skipOffer ) { + // If the API's availble, offer to hide buttons as soon as there + // are enough games that the list is scrollable. Otherwise fall + // back to there being at least four games. + if ( Build.VERSION.SDK_INT >= 19 ) { + ListView list = getListView(); + skipOffer = !list.canScrollList( 1 ) && !list.canScrollList( -1 ); + } else { + skipOffer = 4 > m_adapter.getCount(); + } + } + if ( skipOffer ) { handleNewGame( solo ); } else { From bb4c5502c8be0fc6db0c81e2bdf9a4d58eff69c8 Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 29 Aug 2017 07:03:52 -0700 Subject: [PATCH 15/19] save commit id in fragment --- .../main/java/org/eehouse/android/xw4/MainActivity.java | 9 +++++---- .../main/java/org/eehouse/android/xw4/XWFragment.java | 4 ++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MainActivity.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MainActivity.java index ccd43ad95..f3b0e6382 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MainActivity.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MainActivity.java @@ -453,14 +453,14 @@ public class MainActivity extends XWActivity return frag; } - private void addFragmentImpl( Fragment fragment, Bundle bundle, + private void addFragmentImpl( XWFragment fragment, Bundle bundle, String parentName ) { fragment.setArguments( bundle ); addFragmentImpl( fragment, parentName ); } - private void addFragmentImpl( final Fragment fragment, + private void addFragmentImpl( final XWFragment fragment, final String parentName ) { if ( m_safeToCommit ) { @@ -497,7 +497,7 @@ public class MainActivity extends XWActivity } } - private void safeAddFragment( Fragment fragment, String parentName ) + private void safeAddFragment( XWFragment fragment, String parentName ) { Assert.assertTrue( m_safeToCommit ); String newName = fragment.getClass().getSimpleName(); @@ -505,10 +505,11 @@ public class MainActivity extends XWActivity popUnneeded( fm, newName, parentName ); - fm.beginTransaction() + int ID = fm.beginTransaction() .add( R.id.main_container, fragment, newName ) .addToBackStack( newName ) .commit(); + fragment.setCommitID( ID ); // Don't do this. It causes an exception if e.g. from fragment.start() // I wind up launching another fragment and calling into this code // again. If I need executePendingTransactions() I'm doing something diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWFragment.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWFragment.java index eeec3d7da..d13e724b1 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWFragment.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWFragment.java @@ -45,6 +45,7 @@ abstract class XWFragment extends Fragment implements Delegator { private DelegateBase m_dlgt; private String m_parentName; private boolean m_hasOptionsMenu = false; + private int m_commitID; private static Set sActiveFrags = new HashSet(); public static XWFragment findOwnsView( View view ) @@ -75,6 +76,9 @@ abstract class XWFragment extends Fragment implements Delegator { return m_parentName; } + public void setCommitID( int id ) { m_commitID = id; } + public int getCommitID() { return m_commitID; } + protected void onCreate( DelegateBase dlgt, Bundle sis, boolean hasOptionsMenu ) { m_hasOptionsMenu = hasOptionsMenu; From 741dbf2bedb85770070499d4fa9430f3b31559ac Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 29 Aug 2017 07:10:04 -0700 Subject: [PATCH 16/19] fix finish() to close a specific fragment Rather than just pop whatever's on top of the back stack, which might be the alert whose listener called finish(), use saved commit() ids to pop down to the fragment itself. This feels like a risky change, and it's tested only by back-button-dismissing the Wait alert in an unconnected game in BoardDelegate, so needs some bake time. --- .../src/main/java/org/eehouse/android/xw4/DelegateBase.java | 3 ++- .../src/main/java/org/eehouse/android/xw4/MainActivity.java | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java index f54ee142e..648896360 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java @@ -290,7 +290,8 @@ public class DelegateBase implements DlgClickNotify, if ( main.inDPMode() ) { if ( !m_finishCalled ) { m_finishCalled = true; - main.finishFragment(); + XWFragment fragment = (XWFragment)m_delegator; + main.finishFragment( fragment.getCommitID() ); } handled = true; } diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MainActivity.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MainActivity.java index f3b0e6382..72009ddcd 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MainActivity.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MainActivity.java @@ -298,11 +298,12 @@ public class MainActivity extends XWActivity resultCode, data ); } - protected void finishFragment() + protected void finishFragment( int commitID ) { // Assert.assertTrue( fragment instanceof XWFragment ); // Log.d( TAG, "finishFragment()" ); - getSupportFragmentManager().popBackStack/*Immediate*/(); + getSupportFragmentManager() + .popBackStack( commitID, FragmentManager.POP_BACK_STACK_INCLUSIVE ); } ////////////////////////////////////////////////////////////////////// From 077159b8c4e391db5db284ca4ecd8e7bd527862a Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 29 Aug 2017 07:31:37 -0700 Subject: [PATCH 17/19] save commitID in instanceState When the back stack is restored commit() is not called, so the fragment needs to save it. Without this 0 is passed to popBackStack() and everything's dismissed, not just the one fragment. --- .../src/main/java/org/eehouse/android/xw4/DelegateBase.java | 3 +-- .../src/main/java/org/eehouse/android/xw4/MainActivity.java | 6 +++--- .../src/main/java/org/eehouse/android/xw4/XWFragment.java | 3 +++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java index 648896360..5b9f4da1b 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java @@ -290,8 +290,7 @@ public class DelegateBase implements DlgClickNotify, if ( main.inDPMode() ) { if ( !m_finishCalled ) { m_finishCalled = true; - XWFragment fragment = (XWFragment)m_delegator; - main.finishFragment( fragment.getCommitID() ); + main.finishFragment( (XWFragment)m_delegator ); } handled = true; } diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MainActivity.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MainActivity.java index 72009ddcd..d4142fc47 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MainActivity.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MainActivity.java @@ -298,12 +298,12 @@ public class MainActivity extends XWActivity resultCode, data ); } - protected void finishFragment( int commitID ) + protected void finishFragment( XWFragment fragment ) { - // Assert.assertTrue( fragment instanceof XWFragment ); // Log.d( TAG, "finishFragment()" ); + int ID = fragment.getCommitID(); getSupportFragmentManager() - .popBackStack( commitID, FragmentManager.POP_BACK_STACK_INCLUSIVE ); + .popBackStack( ID, FragmentManager.POP_BACK_STACK_INCLUSIVE ); } ////////////////////////////////////////////////////////////////////// diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWFragment.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWFragment.java index d13e724b1..db4b076c7 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWFragment.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWFragment.java @@ -41,6 +41,7 @@ import junit.framework.Assert; abstract class XWFragment extends Fragment implements Delegator { private static final String TAG = XWFragment.class.getSimpleName(); private static final String PARENT_NAME = "PARENT_NAME"; + private static final String COMMIT_ID = "COMMIT_ID"; private DelegateBase m_dlgt; private String m_parentName; @@ -91,6 +92,7 @@ abstract class XWFragment extends Fragment implements Delegator { Log.d( TAG, "%s.onSaveInstanceState() called", getClass().getSimpleName() ); Assert.assertNotNull( m_parentName ); outState.putString( PARENT_NAME, m_parentName ); + outState.putInt( COMMIT_ID, m_commitID ); m_dlgt.onSaveInstanceState( outState ); super.onSaveInstanceState( outState ); } @@ -102,6 +104,7 @@ abstract class XWFragment extends Fragment implements Delegator { if ( null != sis ) { m_parentName = sis.getString( PARENT_NAME ); Assert.assertNotNull( m_parentName ); + m_commitID = sis.getInt( COMMIT_ID ); } Assert.assertNull( m_dlgt ); m_dlgt = dlgt; From 8489d1401f3514d15d3290567bc1abe83c173467 Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 29 Aug 2017 07:33:15 -0700 Subject: [PATCH 18/19] only try to put up Wait/Invite alert once Bring back the test for being null, and add an additional one via a new boolean iVar that we haven't tried posting it already. On some devices there's enough of a lag that the is-null test passes several times before the first makeDialog() call, leading to a cascade of attempts to create that hangs the UI. The test's needed, but only once should be start the process. --- .../java/org/eehouse/android/xw4/BoardDelegate.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java index d5460275f..78e963232 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java @@ -126,6 +126,7 @@ public class BoardDelegate extends DelegateBase private boolean m_overNotShown; private boolean m_dropOnDismiss; private DBAlert m_inviteAlert; + private boolean m_haveStartedShowing; public class TimerRunnable implements Runnable { private int m_why; @@ -2225,6 +2226,7 @@ public class BoardDelegate extends DelegateBase // Assert.assertFalse( BuildConfig.DEBUG ); } m_inviteAlert = null; + m_haveStartedShowing = false; } } @@ -2304,9 +2306,14 @@ public class BoardDelegate extends DelegateBase showDialogFragment( dlgID, dlgTitle, txt ); } + // This is failing sometimes, and so the null == m_inviteAlert test means + // we never post it. BUT on a lot of devices without the test we wind up + // trying over and over to put the thing up. private void showInviteAlertIf() { - if ( /* null == m_inviteAlert && */m_mySIS.nMissing > 0 && !isFinishing() ) { + DbgUtils.assertOnUIThread(); + if ( ! m_haveStartedShowing && null == m_inviteAlert + && m_mySIS.nMissing > 0 && !isFinishing() ) { InviteAlertState ias = new InviteAlertState(); ias.summary = m_summary; ias.gi = m_gi; @@ -2315,6 +2322,7 @@ public class BoardDelegate extends DelegateBase ias.rowid = m_rowid; ias.nMissing = m_mySIS.nMissing; showDialogFragment( DlgID.DLG_INVITE, ias ); + m_haveStartedShowing = true; } } From 79b0d38c0c7b99cb41a3bed3729dca208bcd5fb2 Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 30 Aug 2017 06:22:36 -0700 Subject: [PATCH 19/19] tweak changelog --- xwords4/android/app/src/main/assets/changes.html | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/xwords4/android/app/src/main/assets/changes.html b/xwords4/android/app/src/main/assets/changes.html index dc4d9ecbf..87690a560 100644 --- a/xwords4/android/app/src/main/assets/changes.html +++ b/xwords4/android/app/src/main/assets/changes.html @@ -15,8 +15,8 @@

CrossWords 4.4.125 release

-

This is a quick bug-fix release that may matter only for a few - Samsung devices

+

This release fixes a problem inviting to new networked games, and + with title bars on some Samsung devices.