diff --git a/README.md b/README.md
index 517674815f535f1db85bd3584e3cb0dbc9c71dae..385b543d69ac63d2915d1e81630785645097b661 100644
--- a/README.md
+++ b/README.md
@@ -883,7 +883,7 @@ Options:
 
 `--android-audio=ANDROID_AUDIO
 `
- : When generating an Android browser, include an option to convert the selection to audio using this URL as a prefix, e.g. http://example.org/speak.cgi?text= (use for languages not likely to be supported by the device itself)
+ : When generating an Android browser, include an option to convert the selection to audio using this URL as a prefix, e.g. https://example.org/speak.cgi?text= (use for languages not likely to be supported by the device itself)
 
 `--android-urls=ANDROID_URLS
 `
diff --git a/annogen.py b/annogen.py
index 87a54f97e427539b946b27f052fcef5653ee7f16..27965acd6eff715c6d17f8f2447b73fa689d6df7 100644
--- a/annogen.py
+++ b/annogen.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python2
 
-program_name = "Annotator Generator v0.6831 (c) 2012-19 Silas S. Brown"
+program_name = "Annotator Generator v0.6832 (c) 2012-19 Silas S. Brown"
 
 # See http://people.ds.cam.ac.uk/ssb22/adjuster/annogen.html
 
@@ -245,7 +245,7 @@ parser.add_option("--android-print",
                   action="store_true",default=False,
                   help="When generating an Android browser, include code to provide a Print option (usually print to PDF) and a simple highlight-selection option. The Print option will require Android 4.4, but the app should still run without it on earlier versions of Android.")
 cancelOpt("android-print")
-parser.add_option("--android-audio",help="When generating an Android browser, include an option to convert the selection to audio using this URL as a prefix, e.g. http://example.org/speak.cgi?text= (use for languages not likely to be supported by the device itself)")
+parser.add_option("--android-audio",help="When generating an Android browser, include an option to convert the selection to audio using this URL as a prefix, e.g. https://example.org/speak.cgi?text= (use for languages not likely to be supported by the device itself)") # do need https if we're Android 5+ and will be viewing HTTPS pages, or Chrome will block (OK if using EPUB-etc or http-only pages)
 parser.add_option("--android-urls",
                   help="Whitespace-separated list of URL prefixes to offer to be a browser for, when a matching URL is opened by another Android application")
 parser.add_option("--extra-js",help="Extra Javascript to inject into sites to fix things in the Android or iOS browser app. The snippet will be run before each scan for new text to annotate. You may also specify a file to read: --extra-js=@file.js (do not use // comments, only /* ... */ because newlines will be replaced)")
@@ -1372,7 +1372,7 @@ def bookmarkJS():
   # Highlighting function, currently depending on android_print (calls canPrint, and currently no other way to save highlights, TODO: figure out how we can save the highlights in a manner that's stable against document changes and annotation changes with newer app versions)
   if android_print:
     p = r""";ssb_local_annotator_highlightSel=function(colour){var r=window.getSelection().getRangeAt(0);var s=document.getElementsByTagName('ruby'),i,d=0;for(i=0;i < s.length && !r.intersectsNode(s[i]); i++);for(;i < s.length && r.intersectsNode(s[i]); i++){d=1;s[i].setAttribute('style','background:'+colour+'!important');if(!window.doneWarnHighl){window.doneWarnHighl=true;ssb_local_annotator.alert('','This app cannot yet SAVE your highlights. They may be lost when you leave.'+(ssb_local_annotator.canPrint()?' Save as PDF to keep them.':''))}}if(!d)ssb_local_annotator.alert('','This tool can highlight only annotated words. Select at least one annotated word and try again.')};if(!document.gotSelChg){document.gotSelChg=true;document.addEventListener('selectionchange',function(){var i=document.getElementById('ssb_local_annotator_HL');if(window.getSelection().isCollapsed || document.getElementsByTagName('ruby').length < 9) i.style.display='none'; else i.style.display='block'})}function doColour(c){return '<span style=\"background:'+c+' !important\" onclick=\"ssb_local_annotator_highlightSel(&quot;'+c+'&quot;)\">'+(ssb_local_annotator_toolE?'\u270f':'M')+'</span>'}return """+sort20px(r"""'<button id=\"ssb_local_annotator_HL\" style=\"display: none; position: fixed !important; background: white !important; border: red solid !important; color: black !important; right: 0px; top: 3em; position: fixed !important; font-size: 20px !important; z-index:2147483647; -moz-opacity: 1 !important; filter: none !important; opacity: 1 !important; overflow: auto !important;\">'""")+r"""+doColour('yellow')+doColour('cyan')+doColour('pink')+doColour('inherit')+'</button>'"""
-    if android_audio: p=p.replace("ssb_local_annotator_highlightSel=",r"""ssb_local_annotator_playSel=function(){if(!window.doneWarnAudio && !confirm('Send selected words to third-party server for audio?')) return;window.doneWarnAudio=true;var r=window.getSelection().getRangeAt(0);var s=document.getElementsByTagName('ruby'),i,d=0;for(i=0;i < s.length && !r.intersectsNode(s[i]); i++);var t=new Array();for(;i < s.length && r.intersectsNode(s[i]); i++) t.push(s[i].getElementsByTagName('rb')[0].innerText); var ae=document.createElement('audio');ae.setAttribute('src','"""+android_audio+r"""'+t.join(''));ae.play();};ssb_local_annotator_highlightSel=""").replace("+'</button>'",r"""+'<span onclick=\"ssb_local_annotator_playSel()\">'+(ssb_local_annotator_toolE?'\ud83d\udd0a':'S')+'</span></button>'""") # TODO: this 'confirm' will say "The page at (URL) says" which is inaccurate; need our own dialog w. some kind of exec-JS callback
+    if android_audio: p=p.replace("ssb_local_annotator_highlightSel=",r"""ssb_local_annotator_playSel=function(){if(!window.doneWarnAudio && !confirm('Send selected words to third-party server for audio?')) return;window.doneWarnAudio=true;var r=window.getSelection().getRangeAt(0);var s=document.getElementsByTagName('ruby'),i,d=0;for(i=0;i < s.length && !r.intersectsNode(s[i]); i++);var t=new Array();for(;i < s.length && r.intersectsNode(s[i]); i++) t.push(s[i].getElementsByTagName('rb')[0].innerText); var ae=document.createElement('audio');ae.setAttribute('src','"""+android_audio+r"""'+t.join(''));ae.play();};ssb_local_annotator_highlightSel=""").replace("+'</button>'",r"""+'<span onclick=\"ssb_local_annotator_playSel()\">'+(ssb_local_annotator_toolE?'\ud83d\udd0a':'S')+'</span></button>'""")
     unconditional_inject += p
   unconditional_inject = "(function(){"+unconditional_inject+"})()"
   return unconditional_inject+"+("+should_show_bookmarks+"?("+show_bookmarks_string+"):("+toolset_string+"))", "var a=e.getElementsByTagName('*'),i;for(i=0;i < a.length; i++){var c=a[i].getAttribute('onclick');if(c){a[i].removeAttribute('onclick');a[i].addEventListener('click',Function('ev',c+';ev.preventDefault()'))}else{c=a[i].getAttribute('href');if(c&&c.slice(0,11)=='javascript:'){a[i].addEventListener('click',Function('ev',c.slice(11)+';ev.preventDefault()'))}}}"
@@ -1380,8 +1380,9 @@ if bookmarks: jsAddRubyCss += "+("+bookmarkJS()[0]+")"
 jsAddRubyCss += ";d.body.insertBefore(e,d.body.firstChild)"
 if bookmarks: jsAddRubyCss += ";"+bookmarkJS()[1]
 jsAddRubyCss += ";d.rubyScriptAdded=1 })" # end of all_frames_docs call for add-ruby
-jsAddRubyCss += ";tw0()" # perform the first annotation scan after adding the ruby (calls all_frames_docs w.annotWalk)
-jsAddRubyCss += ";if(!window.doneHash){window.doneHash=1;setTimeout(function(){var h=window.location.hash.slice(1);if(h&&document.getElementById(h)) document.getElementById(h).scrollIntoView()},500)}" # and redo jump-to-ID if necessary (e.g. Android 4.4 Chrome 33 on EPUBs; TODO: is this really necessary on iOS?), but don't redo this every time doc length changes on Android
+jsAddRubyCss += ";if(!window.doneHash){var h=window.location.hash.slice(1);if(h&&document.getElementById(h)) window.hash0=document.getElementById(h).offsetTop}" # see below
+jsAddRubyCss += "tw0()" # perform the first annotation scan after adding the ruby (calls all_frames_docs w.annotWalk)
+jsAddRubyCss += ";if(!window.doneHash && window.hash0){window.hCount=10*2;window.doneHash=function(){var e=document.getElementById(window.location.hash.slice(1)); if(e.offsetTop==window.hash0 && --window.hCount) setTimeout(window.doneHash,500); e.scrollIntoView()};window.doneHash()}" # and redo jump-to-ID if necessary (e.g. Android 4.4 Chrome 33 on EPUBs; TODO: is this really necessary on iOS?), but don't redo this every time doc length changes on Android. setTimeout loop because rendering might take a while with large documents on slow devices.
 
 def jsAnnot(alertStr,xtraDecls,textWalkInit,annotScan,case3,postFixCond=""):
   #