Sky2023-07-08T01:40:00Ztag:www.timelesssky.com,2023-07-08:atom.xmlCopyright (c) 2023
Bloggart 1.0
Fixing Samsung smart TV problems with the security certificatetag:www.timelesssky.com,2023-07-08:post:62064073008742402023-07-08T01:40:21Z2023-07-08T01:40:21Zskyhttp://www.timelesssky.com/
<p>One day, my 2016 Samsung smart TV can no longer access any apps like youtube. A popup message indicates problem with the security certificate for this site.</p>
<p>A Google search result: <a href="https://eu.community.samsung.com/t5/tv/message-on-smart-tv/td-p/262551">message on smart tv</a> does not have a solution.</p>
<p>The problem could be due to <a href="https://www.bleepingcomputer.com/news/security/expiring-ssl-certs-expected-to-break-smart-tvs-fridges-and-iots/">Expiring root SSL certs expected to break smart TVs, fridges, and IoTs</a>. This means that a TV software update is required to fix it.</p>
<p>The TV web browser can still access http site, but it cannot access https site. Neither can smart hub apps access Samsung server.</p>
<hr />
<p>I have noted down the steps I have taken to eventually fix this issue. Though, I am uncertain whether all the steps are necessary.</p>
<p>After each step, I check whether I can access youtube (or smart hub apps). If I can access, then the issue is fixed, otherwise I turn off the power for the TV to shut it down. After some time has passed or whenever I watch the TV again, then I test the next step.</p>
<ol>
<li><a href="#Download">Download and install latest Samsung software update</a></li>
<li><a href="#Reset">Reset smart hub</a></li>
<li><a href="#Unplug">Unplug the TV cable</a></li>
<li><a href="#Install">Install smart hub apps</a></li>
</ol>
<hr />
<h4><a id="Download"></a>1. Download and install latest Samsung software update</h4>
<p>On the Official <a href="https://www.samsung.com/sg/support/">Samsung online support</a> site, enter the model code number of your TV in the Product Support box. On the TV product page, download the "Upgrade File" for installation if the version is later than the TV current software version. My TV auto update is set to On, so I must have missed the latest update released last year.</p>
<p>The downloaded zip file T-JZMUABC_USB.zip contents has to be extracted, and the files under the extracted image folder needs to be copied to a usb disk (windows/fat32 formatted).</p>
<p>Below Linux commands are to format a usb disk. (eg. mine is /dev/sdc ) fdisk is used to create a partition in the usb disk. See <a href="https://www.digitalocean.com/community/tutorials/create-a-partition-in-linux">Create a Partition in Linux - A Step-by-Step Guide</a>.
</p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="go"> sudo fdisk /dev/sdc</span><br /><span class="go"> sudo mkfs.vfat -F 32 /dev/sdc1</span><br /><span class="go"> </span><br /></pre></div><br /></div></p>
<p>Below, is to copy the zip file contents over to the usb disk. There are 2 files: info.txt & upgrade.msd in the image folder.
</p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="go"> unzip T-JZMUABC_USB.zip</span><br /><span class="go"> mkdir d </span><br /><span class="go"> sudo mount /dev/sdc1 d</span><br /><span class="go"> sudo cp -a T-JZMUABC_USB/image/* d/</span><br /><span class="go"> sudo umount d</span><br /><span class="go"> </span><br /></pre></div><br /></div></p>
<p>Unmounting the usb disk in Linux may take quite a long time.</p>
<p>Insert the usb disk into the TV usb port.</p>
<p>Goto the TV Settings > Support > Software Update > Update now<br />
Select "Update now" to install the Upgrade software.</p>
<p>After the installation is completed, the security certificate issue still remains.</p>
<hr />
<h4><a id="Reset"></a>2. Reset smart hub</h4>
<p>Refer to <a href="https://www.samsung.com/sg/support/tv-audio-video/how-to-troubleshoot-apps-that-are-not-working-on-the-samsung-smart-tv/">How to troubleshoot apps that are not working on the Samsung Smart TV</a></p>
<p>Reset Smart Hub settings will reset it to their factory defaults and deletes all Smart Hub service agreements, and Smart Hub applications. The default PIN is 0000.</p>
<p>Goto the TV Settings > Support > Self Diagnosis > Reset Smart Hub<br />
Select "Reset Smart Hub" to reset/delete all Smart Hub service agreements and apps. </p>
<p>After the reset is done, I still cannot connect to Samsung Smart Hub server to reinstall.</p>
<hr />
<h4><a id="Unplug"></a>3. Unplug the TV cable</h4>
<p>According to the above Samsung How to troubleshoot apps, unplug TV cable from the power socket for 30 seconds, and then plug it back in; will shut the TV down completely and reboots it.</p>
<p>I unplug the TV cable for a few minutes. In the meantime, I also reboot my wifi router.</p>
<hr />
<h4><a id="Install"></a>4. Install smart hub apps</h4>
<p>Finally, the TV can access the Smart Hub apps. The youtube is working properly again.</p>
Booting multiple Linux with rEFIndtag:www.timelesssky.com,2023-06-19:post:62644845197393922023-06-19T12:30:00Z2023-06-19T12:27:42Zskyhttp://www.timelesssky.com/
<p>When I install a Linux OS with an existing Windows OS, I always install the grub bootloader. Now, when I install a second Linux OS and the grub bootloader, this second grub bootloader will become the default bootloader. There is not too much difference between the two grub bootloaders, its only the order of the Linux boot entries and look and feel.</p>
<p>When the Linux grub bootloader is installed/updated , it becomes the default. Because I have added some custom boot entries to my primary Linux, Debian, I would rather keep its bootloader as default. At some point in time, with the Debian grub bootloader as default, I cannot boot into the second Linux.</p>
<p>After the recent Debian upgrade to bookworm, I happen to know <a href="https://www.rodsbooks.com/refind/index.html">rEFInd boot manager</a> and after reading <a href="https://askubuntu.com/questions/760875/any-downside-to-using-refind-instead-of-grub/760971#760971">Any downside to using rEFInd instead of GRUB?</a>, I hope rEFInd will be able to solve my boot issues.</p>
<p>It does!</p>
<hr />
<p>I have a EFI partition on /dev/sda1 .</p>
<p>To install rEFInd on Debian, sudo apt install refind</p>
<p>By default, it will copy/install to /boot/efi/EFI/refind</p>
<p>sudo cp -a /usr/share/refind/fonts/liberation-mono-regular-28.png /boot/efi/EFI/refind/</p>
<p>sudo vi /boot/efi/EFI/refind/refind.conf</p>
<p>I make 3 changes to /boot/efi/EFI/refind/refind.conf </p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="go">font liberation-mono-regular-28.png</span><br /><span class="go">fold_linux_kernels false</span><br /><span class="go"> </span><br /></pre></div><br /></div></p>
<p>Append "include android.cfg" to the end of /boot/efi/EFI/refind/refind.conf
</p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="go">include android.cfg</span><br /><span class="go"> </span><br /></pre></div><br /></div></p>
<p>The rEFInd default font text is too tiny for my eyes, so the font setting use liberation-mono-regular-28.png which comes with the refind package, but the file needs to be copied to /boot/efi/EFI/refind/</p>
<p>By default, fold_linux_kernels setting is true, rEFInd will only show a single boot entry for each partition with a Linux OS. On Debian, there are 2 Linux kernels and rEFInd may not boot the newest one. If fold_linux_kernels setting is false, rEFInd will show 2 Debian boot entries, one for each kernel.</p>
<p>Lastly, I add a custom boot entry (in android.cfg) for Android x86.</p>
<hr />
<p>sudo vi /boot/efi/EFI/refind/android.cfg</p>
<p>/boot/efi/EFI/refind/android.cfg </p>
<p><div class="code"><div class="highlight"><pre><span></span>menuentry <span class="s2">"Android-x86 9.0-r2"</span> <span class="o">{</span><br /> icon EFI/refind/icons/os_artful.png<br /> volume ALinux<br /> loader /android-9.0-r2/kernel<br /> initrd /android-9.0-r2/initrd.img<br /> options <span class="s2">"root=/dev/ram0 androidboot.selinux=permissive SRC=/android-9.0-r2"</span> <br /><span class="o">}</span><br /> <br /></pre></div><br /></div></p>
<p>I have <a href="/blog/android-x86-desktop">Android x86 desktop</a> on partition /dev/sda8 .<br />
To give the partition file system the label ALinux, sudo e2label /dev/sda8 ALinux</p>
<p>The volume can be either filesystem label, partition label, or partition GUID number.</p>
<hr />
<p>After booting successfully the various OS, I decides to remove the Debian grub bootloader.
</p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="go">sudo dpkg --purge shim-signed</span><br /><span class="go">sudo dpkg --purge grub-efi-amd64-bin grub-efi-amd64</span><br /><span class="go">sudo dpkg --purge grub2-common</span><br /> <br /><span class="go">sudo mv /boot/efi/EFI/debian/grubx64.efi /boot/efi/EFI/debian/grubx64.efi.0</span><br /><span class="go"> </span><br /></pre></div><br /></div></p>
<p>The grubx64.efi is renamed, so that the grub bootloader entry will not appear in rEFInd boot screen.</p>
<p>For reference, see <a href="https://www.rodsbooks.com/refind/installing.html">Installing and Uninstalling rEFInd</a> .</p>
Migrated Blog to AppEngine Python 3tag:www.timelesssky.com,2023-03-29:post:61982131743621122023-03-29T02:16:42Z2023-03-29T02:16:42Zskyhttp://www.timelesssky.com/
<p>This site is now running on AppEngine Python 3 runtime.</p>
<p>For reference, see AppEngine <a href="https://cloud.google.com/appengine/docs/standard/python3/python-differences">Migrating to Python 3 runtime</a>.</p>
<p>Thankfully, AppEngine standard environment allows us to access many of <a href="https://cloud.google.com/appengine/docs/standard/python3/services/access">legacy bundled services and APIs in the Python 3 runtime</a>.</p>
<p>Since I am lazy, I try to make as little change as possible. That includes using back the old <a href="https://github.com/GoogleCloudPlatform/webapp2">webapp2</a> framework even though Google documentation says it is not supported in Python 3. The only issue I encounter is that webapp2.Response cannot write a binary bytes object, it will raise an error. There is a <a href="https://github.com/GoogleCloudPlatform/webapp2/issues/146#issuecomment-678915592">solution for this issue</a>.</p>
<p>The requirements.txt file has 2 library dependencies, they are <a href="https://github.com/GoogleCloudPlatform/appengine-python-standard">appengine-python-standard</a> and webapp2. The AppEngine runtime will automatically install those listed in requirements.txt</p>
<p>requirements.txt </p>
<p><div class="code"><div class="highlight"><pre><span></span>appengine-python-standard><span class="o">=</span>1.0.0<br /><span class="nv">webapp2</span><span class="o">==</span>3.0.0b1<br /> <br /></pre></div><br /></div></p>
<p>To use legacy services, add "app_engine_apis: true" to the app.yaml config file. Other app.yaml changes includes script handlers.</p>
<p>In main.py , we need to call wrap_wsgi_app to use AppEngine WSGI middleware so as to access legacy bundled services and APIs. In my case, the code also use the deferred API. </p>
<p>main.py </p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">google.appengine.api</span> <span class="kn">import</span> <span class="n">wrap_wsgi_app</span><br /><span class="n">app</span> <span class="o">=</span> <span class="n">wrap_wsgi_app</span><span class="p">(</span><span class="n">webapp2</span><span class="o">.</span><span class="n">WSGIApplication</span><span class="p">(</span><span class="n">routes</span><span class="p">),</span> <span class="n">use_deferred</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span><br /> <br /></pre></div><br /></div></p>
<hr />
<p>I run into the following error when deploying the app. It appears there is some issue with the default service account.
</p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="go">gcloud app deploy --version 5 --no-promote</span><br /> <br /><span class="go">ERROR: (gcloud.app.deploy) PERMISSION_DENIED: The version cannot run because </span><br /><span class="go">it is unable to generate an access token for the target service account timeless-sky@appspot.gserviceaccount.com. </span><br /><span class="go">Please check that your project has the App Engine Standard Service Agent role </span><br /><span class="go">following https://cloud.google.com/appengine/docs/standard/go/service-agent.</span><br /><span class="go"> </span><br /></pre></div><br /></div></p>
<p>After I create a new service account with the Editor role. It deploys successfully with the new service account.
</p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="go">gcloud app deploy --version 5 --service-account xxxx@timeless--sky.iam.gserviceaccount.com --no-promote</span><br /><span class="go"> </span><br /></pre></div><br /></div></p>
Amazing Spidertag:www.timelesssky.com,2021-12-12:post:62014854025707522021-12-12T02:35:11Z2021-12-12T02:35:11Zskyhttp://www.timelesssky.com/
<p>Once, in my home, I saw a spider climbing up to the ceiling hanging in midspace. I cannot see the spider thread, so its as if it is walking in space. It had a fall after it climbs up some distance. Somehow, it manages to hang in midspace. It then continue to climb up to the ceiling and eventually reaching its destination successfully.</p>
Android x86 desktoptag:www.timelesssky.com,2020-06-27:post:56315271362641922020-06-27T01:59:00Z2020-06-27T01:59:00Zskyhttp://www.timelesssky.com/
<p>I have installed <a href="https://www.android-x86.org/">Android x86</a> on a Dell laptop under its own partition.</p>
<p>The standard navigation bar takes up quite a chunk of space at the bottom. It will be good to remove it.</p>
<p>Pressing the Windows key will make Android go to the home screen. Unfortunately, the keyboard does not has a Back key. The keyboard does has a number of redundant keys, like, it has a normal Enter key and another numpad Enter key. We can convert the numpad Enter key to be the Android Back key. By doing so, we can remove the standard navigation bar permanently to free up more screen space.</p>
<p>To modify the keyboard numpad Enter key to be the Back key, one can modify the system file /system/usr/keylayout/Generic.kl</p>
<p>Change the following line in Generic.kl , replace the NUMPAD_ENTER by BACK</p>
<p>key 96 NUMPAD_ENTER</p>
<p>so it becomes</p>
<p>key 96 BACK</p>
<p>Assuming now that both Android home and back buttons can be handled via the keyboard Windows and numpad Enter key, (yet to be tested) the navigation bar can be removed by adding the following line to /system/build.prop .
</p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="go"> qemu.hw.mainkeys=1</span><br /><span class="go"> </span><br /></pre></div><br /></div></p>
<p>Files under /system is mounted read-only from Android x86 system.sfs . We have to unpack system.sfs to modify files within it using Linux utility. (My android partition is /dev/sda8 )</p>
<p>Steps to unpack and mount android /system under Linux with root user:
</p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="go"> cd /mnt</span><br /><span class="go"> mount /dev/sda8 d</span><br /><span class="go"> cd d/android-9.0-r2/</span><br /><span class="go"> mkdir system</span><br /><span class="go"> unsquashfs system.sfs </span><br /><span class="go"> mount squashfs-root/system.img system</span><br /><span class="go"> </span><br /></pre></div><br /></div></p>
<p>Next, to change NUMPAD_ENTER to BACK in Generic.kl and adding a line to /system/build.prop
</p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="go"> vi system/usr/keylayout/Generic.kl</span><br /><span class="go"> echo "qemu.hw.mainkeys=1" >> system/build.prop</span><br /><span class="go"> </span><br /></pre></div><br /></div></p>
<p>Last, to repack the modified system.sfs:
</p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="go"> umount system</span><br /><span class="go"> rm system.sfs</span><br /><span class="go"> mksquashfs squashfs-root/system.img system.sfs</span><br /><span class="go"> rm squashfs-root/system.img && rmdir squashfs-root && rmdir system</span><br /><span class="go"> </span><br /></pre></div><br /></div></p>
<p>Now, we can reboot back to Android to test the changes to system.sfs, and all should be ok.</p>
<hr />
<p>Android x86 comes with a pre-installed taskbar <a href="https://github.com/farmerbb/Taskbar">com.farmerbb.taskbar</a>
located in /system/priv-app/Taskbar/Taskbar.apk</p>
<p>The taskbar version is 5.0.1</p>
<p>Taskbar lets you launch apps in <a href="https://developer.android.com/guide/topics/ui/multi-window">freeform</a> floating windows on Android 7.0+ devices. Taskbar puts a start menu and recent apps tray on your screen that's accessible at any time. These features make the Android system more like a desktop.</p>
<p>Braden Farmer, the developer of Taskbar, had written an article on xda-developers.com -
https://www.xda-developers.com/android-nougats-freeform-window-mode-what-it-is-and-how-developers-can-utilize-it/</p>
<p>The Taskbar has released a newer version 6.0 on Google Play. One can install this new version alongside the system version. (The system Taskbar uses a different package name: com.farmerbb.taskbar.androidx86) I need to launch the Taskbar in maximized window (right-click icon -> new window )</p>
<p>Since the newer Taskbar is working, we can delete the pre-installed /system/priv-app/Taskbar/Taskbar.apk from the Android x86 system.sfs in Linux.</p>
<p>The only issue I have with the newer version is that it's recent apps does not allow showing running apps only. (which is the default in the pre-installed taskbar and it works)</p>
<p>Even if I put the newer Taskbar.apk into the /system/app path, as a system app, it can now set running_apps_only option, but it will not display any apps on the recent bar. This issue can be traced to taskbar is using the API ActivityManager.getRecentTasks for running_apps_only option. getRecentTasks was deprecated in API level 21 and does not work for a user app. (due to the app signature?) </p>
<p>I have also discussed about getRecentTasks in <a href="/blog/technical-details-of-app-gatekeeper-version-1-1">Technical details of App Gatekeeper version 1.1</a></p>
Customizing surftag:www.timelesssky.com,2019-09-29:post:56463450418708482019-09-29T06:52:37Z2019-09-29T06:52:37Zskyhttp://www.timelesssky.com/
<p><a href="https://surf.suckless.org">surf</a> is a simple minimalist web browser based on webkit2gtk by <a href="https://suckless.org">suckless</a> community.</p>
<p>Its user interface does not have any graphical controls like menus and icons. The Ctrl+G shortcut invokes the <a href="https://tools.suckless.org/dmenu/">dmenu</a> program to allow user to enter URL.</p>
<p>In Debian, to install surf,</p>
<p>sudo apt install surf curl suckless-tools</p>
<p>curl is required for downloading files, and suckless-tools contains the dmenu program.</p>
<p>I make some enhancements to surf:</p>
<ol>
<li><a href="#customizing-zoomlevel">Customizing zoomlevel behavior</a> </li>
<li><a href="#default-download">Configure a default download location</a></li>
<li><a href="#enhance-navigation">Enhance the navigation</a></li>
</ol>
<hr />
<h4><a id="customizing-zoomlevel"></a> 1. Customizing zoomlevel behavior</h4>
<p>To start surf with zoomlevel 2 ,<br />
surf -z 2</p>
<p>One issue I find is that when surf launched a new surf window after clicking a URL, the new surf defaults to zoomlevel 1.</p>
<p><a href="https://github.com/skyleecm/surf/blob/surf-webkit2/surf.c">surf.c</a> code is modified to make surf defaults to the zoomlevel it is started with.</p>
<hr />
<h4><a id="default-download"></a> 2. Configure a default download location</h4>
<p>By default, surf downloads file to your home directory. There is no option to change this, and surf does not provide any prompt for user to save the file somewhere else.</p>
<p>The DOWNLOAD(u, r) code in <a href="https://github.com/skyleecm/surf/blob/surf-webkit2/config.def.h">config.def.h</a> is modified to use the variable download as the default download location if it is defined in the user config file ~/.surf/config , otherwise it defaults to the user's home directory.</p>
<p>For example, if ~/.surf/config file contains a line:<br />
download=~/Downloads</p>
<p>surf will now download file to ~/Downloads directory.</p>
<p>Note:<br />
the Debian surf works with any x-terminal-emulator, but the compiled surf from suckless works only with st (a terminal emulator from suckless), which can be installed in Debian with: apt install stterm</p>
<hr />
<h4><a id="enhance-navigation"></a> 3. Enhance the navigation</h4>
<p>By default, surf does not have history or bookmarks.</p>
<p>I replace dmenu with my script <a href="https://github.com/skyleecm/surf/blob/surf-webkit2/bin/dmenu-url">dmenu-url</a> in config.def.h . The dmenu-url script uses <a href="https://github.com/davatorium/rofi">rofi</a> instead of dmenu to provide input/selection of URL.</p>
<p>The script keeps track of user's URL input/selection in a file ~/.local/share/recent_url , where the most recent input is inserted at beginning of file and removed from rest of file. Similarly, it keeps track of find text input/selection in a file ~/.local/share/recent_sfind .</p>
<p>The script then presents this history list so that user can just select a URL when entering a URL.</p>
<p>The location of the history files can be configured by the variable recent_dir in ~/.surf/config file.</p>
<p>Additionally, if the script detects the URL entered is not really a URL, it will perform a search query instead with the condition that the variable search_q is defined in ~/.surf/config file.</p>
<p>For example, to use Google search, set<br />
search_q=http://www.google.com/search?q=</p>
<hr />
<p>Under Debian, before compiling, required header files have to be installed first:<br />
apt install libwebkit2gtk-4.0-dev libgcr-3-dev</p>
<p>To compile and then install under /usr/local/ with<br />
make clean install</p>
<p>I have the customized surf code @ https://github.com/skyleecm/surf.git</p>
<hr />
<p>Related:<br />
<a href="https://ultra-technology.org/internet_browsing/surf-browser-by-suckless-on-debian-ubuntu/">Building surf browser by suckless on Debian/Ubuntu. Add media streaming support and fix some problems</a></p>
<p>Git help:</p>
<ul>
<li><a href="https://paazmaya.fi/forking-a-repository-from-github-to-bitbucket">Forking a repository from GitHub to Bitbucket</a></li>
<li><a href="http://matthew-brett.github.io/pydagogue/gh_delete_master.html">Deleting your git master branch</a></li>
</ul>
DNS Hosting changed to Cloudflaretag:www.timelesssky.com,2019-06-30:post:56365004399575042019-06-30T06:54:43Z2019-06-30T06:54:43Zskyhttp://www.timelesssky.com/
<p><a href="http://timelesssky.com/">timelesssky.com</a> domain is previously hosted by <a href="https://dyn.com">Dyn</a>. Oracle (acquired Dyn in 2016) has announced the end-of-life for the free Standard DNS service in May 31, 2020.</p>
<p><em>timelesssky</em>.com domain is now hosted by <a href="https://www.cloudflare.com">Cloudflare</a>.</p>
<p>Cloudflare has made it easy to migrate existing dns records by automatically retrieving your domain DNS records. The whole process is explained in their article <a href="https://support.cloudflare.com/hc/en-us/articles/201720164">Creating a Cloudflare account and adding a website</a>.</p>
<hr />
<p>Most of timelesssky dns records are pointing to Google Apps domain. Except for the http redirecting of <em>timelesssky</em>.com to www.<em>timelesssky</em>.com .</p>
<p>Previously, I believe Google Apps does not have this feature yet. Now, it has.</p>
<p>In Google Admin, the feature is located at Account > Domains : Redirect the naked domain.</p>
<p>In Changing the A-record for your domain, it will ask you to add some ip records for the naked domain. Once, these A-records are added in the Cloudflare page, you can click on the "I have completed the steps" button.</p>
<hr />
<p>After first <a href="https://dash.cloudflare.com/">sign-in to Cloudflare</a>, it prompts you to add a site. (site is the domain name)</p>
<p>I select the free plan.</p>
<p>Cloudflare will present all your existing domain DNS records. Then, I add the A-records required by Google http redirecting, and remove the previous A-record used by Dyn webhop feature.</p>
<p>Final step is to change the domain nameservers to Cloudflare nameservers. This is done at the domain registrar of the domain name.</p>
<hr />
<p>The Cloudflare domain nameservers are:</p>
<ol>
<li>lia.<em>ns.cloudflare</em>.com</li>
<li>terin.<em>ns.cloudflare</em>.com</li>
</ol>
<p>Under Linux, we can check if the nameserver is serving the updated dns records (eg.):</p>
<p>host -t ns <em>timelesssky</em>.com lia.<em>ns.cloudflare</em>.com</p>
AppGatekeeper updated for latest Androidtag:www.timelesssky.com,2018-10-06:post:56419067552071682018-10-06T02:57:46Z2018-10-06T02:57:46Zskyhttp://www.timelesssky.com/
<p>This new version 1.6.0 has targetSdkVersion of 26 (Android Oreo). Partly, this is due to Google sending developers a reminder that after November 1, 2018, the Play Console will prevent you from submitting new APKs with a targetSdkVersion less than 26.</p>
<p>Below is the list of changes group by:</p>
<ul>
<li><a href="#ui-or-behavior-changes">UI or behavior changes</a></li>
<li><a href="#code-only-changes">Code only changes</a></li>
<li><a href="#bug-fix">Bug fix</a></li>
<li><a href="#android-9-dark-greylist-non-SDK-changes">Android 9 dark greylist non SDK changes</a></li>
</ul>
<hr />
<h4><a id="ui-or-behavior-changes"></a> UI or behavior changes:</h4>
<p>In prior versions, the app uses Theme.Holo . Now, it will use Theme.Material for Android 5 & above, otherwise it use back Theme.Holo . There are some minor adjustments due to using the material theme.</p>
<p>The app now checks for <a href="https://developer.android.com/guide/topics/permissions/overview">runtime permission</a> for read/write external storage for Android 6 & above. Basically, just before the app needs to read or write to external storage, it checks with the Android system whether user has granted the required permission. If permission has already been granted, it proceeds as usual; otherwise it asks Android to prompt the user to either approve or deny the requested permission. If user approves, the read/write will proceed; otherwise the operation is aborted.</p>
<p>The free app does not perform any read/write. The upgraded app performs read only for Restore, read/write for Backup, write only for Export All Usage and Export Usage, and it will request for read/write permissions when user taps on the Export to directory path setting in Settings screen. Regardless, the Android system request permission dialog will only ask the user to approve storage permission. (Currently, both read and write external storage are grouped by Android system into storage permission)</p>
<p>On restoring the app from Android system recents, if Android system creates a new app process, then instead of allowing Android system to launch the last recently used activity, the app will always launch the main activity. This change fix dependencies issue for some of the activities that rely on the main activity.</p>
<p>Slightly related to above, if user leaves the app such that it is not visible, the app will now close or cancel any alert message dialog.</p>
<p>There is a particular issue when using material theme for Android 5 system. The maximum date of DatePickerDialog although shown visually to be selectable, cannot be selected. Thus, to solve this, the app checks if it is Android 5.X , and it explicitly creates the DatePickerDialog with Theme.Holo . It compensates this by making a slight change to the dialog title and the buttons color via using material theme colors. The DatePickerDialog in material theme will set the dialog title to the selected date, but this is not done if using holo theme. The new code implements showing the selected date in the title as well for holo theme.</p>
<p>The app uses a default Export to directory path, which is now not created, until the first write operation is executed or when user first taps on the Export to directory path setting in Settings screen and has approved the Android storage permission. This default Export path is not displayed in the Settings until user changes it.</p>
<hr />
<h4><a id="code-only-changes"></a> Code only changes:</h4>
<p>Certain <a href="https://developer.android.com/guide/components/broadcasts">broadcast</a> receiver in the manifest is now handled/registered via the activity or service.</p>
<ul>
<li>main activity register CONNECTIVITY_ACTION system broadcast</li>
<li>service register shutdown, time and timezone change system broadcasts</li>
</ul>
<p>On receiving boot completed broadcast (or others that require restarting service), the receiver starts the service via startForegroundService method on Android 8 & above. The reason is that in that instance, the app is in the background, and <a href="https://developer.android.com/about/versions/oreo/background#services">Android 8 system doesn't allow a background app to create a background service</a>.</p>
<p>Code changes to cater for <a href="https://developer.android.com/guide/topics/ui/notifiers/notifications#ManageChannels">notification channels</a>. Starting in Android 8 (API level 26), all notifications must be assigned to a channel or it will not appear. A channel of default importance is created for the foreground service notification.</p>
<p>Simplify certain codes related to the service execution when it is started from the receiver. (only apply to Android 8 & above)</p>
<p>Adjustment of codes related to UsageStatsManager.queryUsageStats. On testing the service in Android 9 emulator, this method can return UsageStats from the previous day, and also can have multiple UsageStats per app. The new code handles this possibility.</p>
<p>The app will query billing service within the Application.onCreate method, which is too early. For example, the after boot receiver will also query billing service, which is unintentional. This querying is shifted until the first app activity is created.</p>
<p>Various changes to make the actionBar work like before, due to the use of material theme.</p>
<p>Internal code changes to cancel any modification in "Allowed Access" screen by rotating the device.</p>
<p>The app now uses ACRA 4.8.5 , a slight change is made to make it not send any crash reports when the app starts.</p>
<p>The app internal crash logger previously log stack trace to the default Export path. (It is enabled only if the Application Crash Report setting is enabled) Given that this default Export path may not exist, it now logs to the path provided by getExternalFilesDir(null)</p>
<hr />
<h4><a id="bug-fix"></a> Bug fix:</h4>
<p>Android 7.1 makes a change in the internal system interface used by Toast. This causes the service's warning toast to crash the service. The fix handles the new interface and comply with its expected behavior.</p>
<p>When the app draws the labels used in the apps usage graph, an exception may be thrown possibly when the labels are very close. This bug is fixed.</p>
<p>In some cases of Android system/device, when the app draws Chinese chars for the category icon, an exception may be thrown. The fix catches the exception, and draws only the first character instead.</p>
<hr />
<h4><a id="android-9-dark-greylist-non-SDK-changes"></a> Android 9 dark greylist non SDK changes:</h4>
<p>Android 9 (API level 28) introduces new <a href="https://developer.android.com/about/versions/pie/restrictions-non-sdk-interfaces">restrictions on the use of non-SDK interfaces</a>, whether directly, via reflection, or via JNI.</p>
<p>The app target SDK is below API level 28, so the use of dark greylist interface is permitted. But, considering Google is requiring developers to update to the latest API. The dark greylist interface usage may eventually be denied.</p>
<p>The app access Spinner.SavedState field showDropdown. In case if an exception is caught, it checks if API level >= 28, and access the whitelist hidden method Spinner.isPopupShowing .</p>
<p>The app "Restrict days to" spinner access superclass non-SDK interface. In case of exception, it is using a work-around solution. Certain codes are simplified as well.</p>
<p>The app service toast access non-SDK light greylist interface. It is not in immediate danger. Just in case the use of light greylist interface is disallowed in future, the service code is modified to disable the display of warning toast message if the interface is inaccessible. However, the "app has been stopped" message toast will still be displayed.</p>
<p>Testing is done on the Android emulator with Android 9 image.</p>
<p>To disallow usage of dark grey and black listed APIs, change the below settings to 2.
</p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="go"> adb shell settings put global hidden_api_policy_pre_p_apps 2</span><br /><span class="go"> adb shell settings put global hidden_api_policy_p_apps 2</span><br /><span class="go"> </span><br /></pre></div><br /></div></p>
<hr />
<p>This is the first release built using gradle, all previous versions are built using ant.</p>
<p>Testing is done on alps A9, Amazon Fire 7 & 8, LG Q6 (Android 7.1 & after upgrade 8.1), Android emulator with Android 6, 8, 9.</p>
<p>Thanks to Google and especially <a href="http://stackoverflow.com">stackoverflow</a>!</p>
<hr />
<p>Google is introducing digital wellbeing features for <a href="https://blog.google/products/android/introducing-android-9-pie/">Android 9</a>, <strong>including a new Dashboard that helps you understand how you’re spending time on your device; an App Timer that lets you set time limits on apps and grays out the icon on your home screen when the time is up;</strong> the new Do Not Disturb, which silences all the visual interruptions that pop up on your screen; and Wind Down, which switches on Night Light and Do Not Disturb and fades the screen to grayscale before bedtime.</p>
<hr />
<p>Given Google may request developers to update their apps targetSdkVersion in the future, and it is possible that I do now want to do so if it causes too much trouble, and I may still want to update the app to fix bugs; I will provide the app binary release on my website. <a href="https://drive.google.com/open?id=13x6AeWhHa5GSF5lXUHMlbnHK8RJA6eNa">Download AppGatekeeper-release.v1.6.0.apk</a> </p>
<hr />
<p><a href="https://play.google.com/store/apps/details?id=com.timelesssky.appgatekeeper">App Gatekeeper</a> (version 1.6.0) is released.</p>
<p>Past release:</p>
<ul>
<li><a href="/blog/appgatekeeper-without-google-play">AppGatekeeper without Google Play</a></li>
<li><a href="/blog/enhance-appgatekeeper-service">Enhance AppGatekeeper service</a></li>
<li><a href="/blog/fix-scroll-recursion-on-showing-edit-limit">Fix scroll recursion on showing edit limit</a></li>
<li><a href="/blog/custom-number-keyboard-to-edit-limit">Custom keyboard to edit limit</a></li>
<li><a href="/blog/app-gatekeeper-updated-to-version-1-1">App Gatekeeper updated to version 1.1</a></li>
</ul>
AppGatekeeper without Google Playtag:www.timelesssky.com,2017-09-22:post:56313836826787842017-09-22T06:22:15Z2017-09-22T06:22:15Zskyhttp://www.timelesssky.com/
<p>In this update, AppGatekeeper now runs without requiring Google Play, and is able to show the Settings "Apps with usage access" screen even if the device hides it from user.</p>
<p>Other changes:</p>
<ul>
<li>ACRA crash report backend is changed to <a href="https://github.com/skyleecm/android_crash_reports.git">android_crash_reports</a></li>
<li>fix / catch getCalendarView exception for Android >= 7</li>
<li>move the "save to database" code (when the service is stopped), to the end of the service thread</li>
<li>minor fix</li>
</ul>
<hr />
<p>Codes to show the "Apps with usage access" Settings screen by specifying the activity name:
</p>
<p><div class="code"><div class="highlight"><pre><span></span> <span class="n">intent</span><span class="o">.</span><span class="na">setFlags</span><span class="o">(</span><span class="n">Intent</span><span class="o">.</span><span class="na">FLAG_ACTIVITY_NEW_TASK</span><span class="o">);</span><br /> <span class="n">intent</span><span class="o">.</span><span class="na">setComponent</span><span class="o">(</span><span class="k">new</span> <span class="n">ComponentName</span><span class="o">(</span><br /> <span class="s">"com.android.settings"</span><span class="o">,</span><br /> <span class="s">"com.android.settings.Settings$UsageAccessSettingsActivity"</span><span class="o">));</span><br /> <span class="n">startActivity</span><span class="o">(</span><span class="n">intent</span><span class="o">);</span><br /> <br /></pre></div><br /></div></p>
<hr />
<p>Testing is done on Samsung Galaxy S3 and Nexus 7 and Amazon Fire.</p>
<p>For devices that originally does not come with Google Play (like Amazon Fire), users will still have to install Google Play first, at least to download and install apps that are only released on Google Play. For reference, see <a href="/blog/appgatekeeper-on-amazon-fire">AppGatekeeper on Amazon fire</a>.</p>
<p>AppGatekeeper dependency on Google Play is due to using Google Play billing service to allow user to purchase the upgrade.</p>
<p>If user has purchased the upgrade on another device, then user should used the same user account to install AppGatekeeper. When user runs AppGatekeeper with the internet connected, the app will query billing service whether the user has purchased the upgrade. If the answer is positive, the app will be updated to premium version automatically. (The Upgrade menu in navigation dropdown will not be shown thereafter)</p>
<p>Subsequently, if the user wishes, Google Play and its dependencies can be uninstalled from the device. Internally, the app does not change its status if the billing service is not available.</p>
<p>This release fix a bug which crashes the app when the billing service is being set up without Google Play.</p>
<p>Tested on Amazon Fire 7 (with account that has upgraded), Fire HD 8.</p>
<hr />
<p><a href="https://play.google.com/store/apps/details?id=com.timelesssky.appgatekeeper">App Gatekeeper</a> (version 1.4.0) is released. </p>
<p>Past release:</p>
<ul>
<li><a href="/blog/enhance-appgatekeeper-service">Enhance AppGatekeeper service</a></li>
<li><a href="/blog/fix-scroll-recursion-on-showing-edit-limit">Fix scroll recursion on showing edit limit</a></li>
<li><a href="/blog/custom-number-keyboard-to-edit-limit">Custom keyboard to edit limit</a></li>
<li><a href="/blog/app-gatekeeper-updated-to-version-1-1">App Gatekeeper updated to version 1.1</a> (refer to it for explanation of usage access.)</li>
</ul>
AppGatekeeper on Amazon firetag:www.timelesssky.com,2017-08-23:post:57102398191042562017-08-23T07:07:25Z2017-08-23T07:07:25Zskyhttp://www.timelesssky.com/
<p>Recent <a href="https://en.wikipedia.org/wiki/Fire_OS">Amazon fire</a> tablets are based on Android 5.0 . So, AppGatekeeper should be able to run on them.</p>
<p>There are however two issues hindering:</p>
<ul>
<li>Amazon fire does not come with Google Play</li>
<li>Amazon fire Settings ui hide the "Apps with usage access" screen. For explanation of usage access, see <a href="/blog/app-gatekeeper-updated-to-version-1-1">App Gatekeeper updated to version 1.1</a></li>
</ul>
<hr />
<p>There are already a lot of articles covering how to install Google Play on devices without it.</p>
<p>For reference, refer to <a href="https://forum.xda-developers.com/amazon-fire/general/how-to-install-google-play-store-fire-t3486603">How to install Google Play Store on Fire OS 5.X</a>
and <a href="https://forum.xda-developers.com/amazon-fire/general/installing-google-framework-playstore-t3216122">Installing Google Framework Playstore 5th Gen Amazon Fire</a></p>
<p>There are basically 4 apk to install including Google Play:</p>
<ul>
<li>GoogleLoginService.apk (Google Account Manager)</li>
<li>GoogleServicesFramework.apk</li>
<li>com.google.android.gms-1.apk (Google Play Services)</li>
<li>com.android.vending-1.apk (Google Play Store)</li>
</ul>
<p>Given that I have nexus 7 2012 and I have upgraded to Android 5.1 , I decide to obtain the apk files from nexus 7.</p>
<p>With root access to nexus 7, one can use adb pull as follow,
</p>
<p><div class="code"><div class="highlight"><pre><span></span><span class="go"> adb pull /system/priv-app/GoogleLoginService/GoogleLoginService.apk .</span><br /><span class="go"> adb pull /system/priv-app/GoogleServicesFramework/GoogleServicesFramework.apk .</span><br /><span class="go"> adb pull /data/app/com.google.android.gms-1/base.apk .</span><br /><span class="go"> mv base.apk com.google.android.gms-1.apk</span><br /><span class="go"> adb pull /data/app/com.android.vending-1/base.apk .</span><br /><span class="go"> mv base.apk com.android.vending-1.apk</span><br /><span class="go"> </span><br /></pre></div><br /></div></p>
<p>The version of GoogleLoginService.apk and GoogleServicesFramework.apk on my nexus 7 matches the version listed on the above 1st reference page.</p>
<p>Version of Google Play services is 10.0.84<br />
Version of Google Play is 7.8.16.P-all</p>
<p>Easiest way to install on fire tablets is to use: adb install</p>
<p>As I remember now, my initial installation does not work, as the Google Play app cannot be launched. However, when I install again on a later date, it suceeds, that is Google Play can run. (I have no idea what is the difference, could it be that I turn on wifi ??)</p>
<hr />
<p>Download <a href="https://play.google.com/store/apps/details?id=com.timelesssky.appgatekeeper">App Gatekeeper</a> from Google Play and install.</p>
<p>From Amazon fire Settings ui, the "Apps with usage access" screen cannot be accessed. There is a normal app that can be used to access this screen. Refer to <a href="https://forum.xda-developers.com/hd8-hd10/general/root-activity-launcher-to-remove-t3615276">Use Activity Launcher to remove accounts, to grant, revoke usage access</a> by xda user DragonFire1024 (Thanks!)</p>
<p>Download and install <a href="https://play.google.com/store/apps/details?id=de.szalkowski.activitylauncher">Activity Launcher</a> from Google Play.</p>
<p>To enable usage access for AppGatekeeper (or any other apps that require the permission):</p>
<ol>
<li>Run Activity Launcher</li>
<li>Select All activities (in navigation dropdown)</li>
<li>Click on Settings activity to show all of its activities</li>
<li>Click on Apps with usage access to access it</li>
<li>Enable AppGatekeeper to access usage</li>
</ol>
<p>Now, run AppGatekeeper and it will not prompt for user to enable usage access any more.</p>
<p>Tested on Fire 7, Fire HD 8 (7th gen).</p>