<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Haoxiqiang&#39;s Blog</title>
    <link>https://blog.substitute.tech/en/</link>
    <description>Recent content on Haoxiqiang&#39;s Blog</description>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Fri, 26 Jun 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://blog.substitute.tech/en/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Blog Migration: From Jekyll Chirpy to Hugo PaperMod</title>
      <link>https://blog.substitute.tech/en/posts/blog-migration-to-hugo/</link>
      <pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/blog-migration-to-hugo/</guid>
      <description>Documenting the migration from Jekyll &#43; Chirpy to Hugo &#43; PaperMod, including selection analysis and GitHub Pages best practices in 2026</description>
    </item>
    <item>
      <title>Build AOSP for Pixel 3 XL</title>
      <link>https://blog.substitute.tech/en/posts/aosp-build-for-pixel3/</link>
      <pubDate>Mon, 15 Aug 2022 20:53:06 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/aosp-build-for-pixel3/</guid>
      <description>&lt;p&gt;The AOSP build process is fairly well understood by now: sync the source code, add device-specific drivers and kernel, and build the target image. I had built AOSP before to debug certain issues, but official support for Pixel 3 XL only goes up to Android 12. Recently, while working on Chromium development, I needed to test WebView on a newer platform, so I used LineageOS 21 for the build instead.&lt;/p&gt;</description>
    </item>
    <item>
      <title>A Blind Spot in RSA Encryption with OpenSSL</title>
      <link>https://blog.substitute.tech/en/posts/openssl-rsa/</link>
      <pubDate>Mon, 08 Aug 2022 17:09:43 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/openssl-rsa/</guid>
      <description>&lt;p&gt;I thought I had a solid understanding of the differences between RSA encryption schemes and their use cases. But while implementing RSA encryption today, I noticed something puzzling: the ciphertext was different every time, even with the same plaintext and public key. This was a blind spot for me. After researching the internals, here is what I found.&lt;/p&gt;
&lt;h2 id=&#34;the-issue&#34;&gt;The Issue&lt;/h2&gt;
&lt;p&gt;The following code uses OpenSSL&amp;rsquo;s EVP API for RSA encryption. No random value is explicitly provided, yet the output differs on every call:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Jenkins Setup Notes</title>
      <link>https://blog.substitute.tech/en/posts/jenkins/</link>
      <pubDate>Mon, 06 Jun 2022 17:32:20 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/jenkins/</guid>
      <description>&lt;p&gt;I was working on an overseas application whose build server was originally located in Shanghai. Due to special circumstances, it needed to be migrated abroad. This post documents the Jenkins migration and configuration process.&lt;/p&gt;
&lt;h2 id=&#34;prerequisite-install-jdk-11&#34;&gt;Prerequisite: Install JDK 11&lt;/h2&gt;
&lt;p&gt;Using &lt;code&gt;jenv&lt;/code&gt; for multi-version Java management:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Install jenv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone https://github.com/jenv/jenv.git ~/.jenv
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;export PATH=&amp;#34;$HOME/.jenv/bin:$PATH&amp;#34;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;eval &amp;#34;$(jenv init -)&amp;#34;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;source&lt;/span&gt; ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Enable the export plugin and restart the session&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jenv enable-plugin &lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;exec&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$SHELL&lt;/span&gt; -l
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;installing-jenkins-on-centos&#34;&gt;Installing Jenkins on CentOS&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Add Jenkins repository and GPG key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Install&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;yum install jenkins
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;configuring-systemd-service&#34;&gt;Configuring systemd Service&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo vi /etc/systemd/system/jenkins.service
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo systemctl &lt;span class=&#34;nb&#34;&gt;enable&lt;/span&gt; /etc/systemd/system/jenkins.service
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo systemctl start jenkins
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;systemctl status jenkins
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;jenkins service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;network.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;simple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;LimitNOFILE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;65536&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/usr/bin/jenkins&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;work&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Environment&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;JENKINS_PORT=8082&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;WantedBy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;configuring-android-sdk&#34;&gt;Configuring Android SDK&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;wget https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;unzip commandlinetools-linux-8512546_latest.zip
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;chmod a+x cmdline-tools/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; cmdline-tools/bin
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Install required components via sdkmanager&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./sdkmanager --sdk_root&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/work/workspace/android_sdk --list
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./sdkmanager --install &lt;span class=&#34;s1&#34;&gt;&amp;#39;platforms;android-33&amp;#39;&lt;/span&gt; --sdk_root&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/work/workspace/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./sdkmanager --install &lt;span class=&#34;s1&#34;&gt;&amp;#39;build-tools;33.0.0&amp;#39;&lt;/span&gt; --sdk_root&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/work/workspace/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./sdkmanager --install &lt;span class=&#34;s1&#34;&gt;&amp;#39;cmdline-tools;7.0&amp;#39;&lt;/span&gt; --sdk_root&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/work/workspace/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./sdkmanager --install &lt;span class=&#34;s1&#34;&gt;&amp;#39;build-tools;32.0.0&amp;#39;&lt;/span&gt; --sdk_root&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/work/workspace/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./sdkmanager --install &lt;span class=&#34;s1&#34;&gt;&amp;#39;build-tools;31.0.0&amp;#39;&lt;/span&gt; --sdk_root&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/work/workspace/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./sdkmanager --install &lt;span class=&#34;s1&#34;&gt;&amp;#39;ndk;25.1.8937393&amp;#39;&lt;/span&gt; --sdk_root&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/work/workspace/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./sdkmanager --install &lt;span class=&#34;s1&#34;&gt;&amp;#39;platforms;android-28&amp;#39;&lt;/span&gt; --sdk_root&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/work/workspace/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./sdkmanager --install &lt;span class=&#34;s1&#34;&gt;&amp;#39;platforms;android-29&amp;#39;&lt;/span&gt; --sdk_root&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/work/workspace/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./sdkmanager --install &lt;span class=&#34;s1&#34;&gt;&amp;#39;platforms;android-30&amp;#39;&lt;/span&gt; --sdk_root&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/work/workspace/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./sdkmanager --install &lt;span class=&#34;s1&#34;&gt;&amp;#39;platforms;android-31&amp;#39;&lt;/span&gt; --sdk_root&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/work/workspace/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./sdkmanager --install &lt;span class=&#34;s1&#34;&gt;&amp;#39;cmake;3.22.1&amp;#39;&lt;/span&gt; --sdk_root&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/work/workspace/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./sdkmanager --install &lt;span class=&#34;s1&#34;&gt;&amp;#39;cmake;3.10.2.4988404&amp;#39;&lt;/span&gt; --sdk_root&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/work/workspace/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;fixing-ssh-key-permission-issues&#34;&gt;Fixing SSH Key Permission Issues&lt;/h2&gt;
&lt;p&gt;If you encounter &lt;code&gt;Permissions 0664 for &#39;/home/work/.ssh/jenkins_id_rsa&#39; are too open&lt;/code&gt;:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Configuring and Optimizing Shadowsocks Rust</title>
      <link>https://blog.substitute.tech/en/posts/shadowsocks-rust/</link>
      <pubDate>Fri, 06 May 2022 16:10:22 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/shadowsocks-rust/</guid>
      <description>&lt;p&gt;During the recent holiday, I reorganized the home network with the goal of streaming 4K content without buffering. Since I was rebuilding the server anyway, I decided to migrate from the old setup to the new shadowsocks-rust implementation.&lt;/p&gt;
&lt;h2 id=&#34;system-update&#34;&gt;System Update&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt update &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt upgrade
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;installing-and-configuring-ss&#34;&gt;Installing and Configuring SS&lt;/h2&gt;
&lt;h3 id=&#34;option-1-build-from-source-via-cargo&#34;&gt;Option 1: Build from Source via Cargo&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Install Rust toolchain&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl https://sh.rustup.rs -sSf &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sh
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Configure Cargo environment (add to .profile / .bash_profile)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# CARGO_HOME sets the installation path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# target-cpu=native lets rustc optimize for the current CPU&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CARGO_HOME&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/root/cargo
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;RUSTFLAGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;-C target-cpu=native&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;source&lt;/span&gt; .profile
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Install build dependencies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install build-essential
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Install shadowsocks-rust&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cargo install shadowsocks-rust
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;option-2-download-prebuilt-binary&#34;&gt;Option 2: Download Prebuilt Binary&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;wget https://github.com/shadowsocks/shadowsocks-rust/releases/download/v1.14.3/shadowsocks-v1.14.3.x86_64-unknown-linux-gnu.tar.xz
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tar -xf shadowsocks-v1.14.3.x86_64-unknown-linux-gnu.tar.xz
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cp ssserver /usr/local/bin
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;chmod a+x /usr/local/bin/ssserver
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;configuration&#34;&gt;Configuration&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mkdir /etc/shadowsocks
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;vi /etc/shadowsocks/config.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;server&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;::&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;server_port&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8888&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;method&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;aes-256-gcm&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;password&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;pw&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Test the server:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Optimizing Android Builds with Self-Hosted Nexus Repository</title>
      <link>https://blog.substitute.tech/en/posts/nexus/</link>
      <pubDate>Tue, 31 Dec 2019 21:29:27 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/nexus/</guid>
      <description>&lt;p&gt;In Android dependency management, it&amp;rsquo;s common to configure multiple remote repositories like &lt;code&gt;jcenter&lt;/code&gt;, &lt;code&gt;jitpack&lt;/code&gt;, &lt;code&gt;google()&lt;/code&gt;, and more. Some large projects, such as &amp;ldquo;Zuiyou&amp;rdquo;, depend on over 10 repositories. This becomes a significant problem during initial project setup, dependency changes, or network issues — troubleshooting builds becomes a nightmare.&lt;/p&gt;
&lt;p&gt;I had noticed this issue long ago but kept putting off addressing it. This post documents the Nexus setup process.&lt;/p&gt;
&lt;h2 id=&#34;installing-and-configuring-nexus&#34;&gt;Installing and Configuring Nexus&lt;/h2&gt;
&lt;p&gt;Prerequisite: JDK 8+.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Shadowsocks Setup and Optimization</title>
      <link>https://blog.substitute.tech/en/posts/shadowsocks/</link>
      <pubDate>Tue, 31 Dec 2019 20:29:27 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/shadowsocks/</guid>
      <description>&lt;p&gt;Network instability at the office was affecting work, so I set up a Shadowsocks server on my VPS for source code pulls. The steps below work on most Linux distributions and have been tested on Ubuntu 16.04 and 18.04.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;2024 Update:&lt;/strong&gt; The Python version of &lt;code&gt;shadowsocks&lt;/code&gt; used in this guide is no longer maintained. The actively maintained implementation is &lt;a href=&#34;https://github.com/shadowsocks/shadowsocks-rust&#34;&gt;shadowsocks-rust&lt;/a&gt;, which offers better performance and support for modern encryption protocols. For a fresh setup, refer to the &lt;a href=&#34;https://github.com/shadowsocks/shadowsocks-rust&#34;&gt;shadowsocks-rust documentation&lt;/a&gt;. The original Python-based steps are preserved below for reference.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android &amp; Linux Tips Collection #3</title>
      <link>https://blog.substitute.tech/en/posts/%E9%97%AE%E9%A2%98%E6%95%B4%E7%90%86%E4%B8%89/</link>
      <pubDate>Wed, 05 Apr 2017 11:00:06 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/%E9%97%AE%E9%A2%98%E6%95%B4%E7%90%86%E4%B8%89/</guid>
      <description>&lt;p&gt;Three quick tips: handling the back button in DialogFragment, chmod permission reference, and the underscore problem in SSL hostnames.&lt;/p&gt;
&lt;h2 id=&#34;dialogfragment-back-button-handling&#34;&gt;DialogFragment Back Button Handling&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;DialogFragment&lt;/code&gt; has no direct override for the back button. Two approaches were commonly used.&lt;/p&gt;
&lt;h3 id=&#34;approach-1-override-in-oncreatedialog&#34;&gt;Approach 1: Override in onCreateDialog&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Override&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Dialog&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;onCreateDialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Bundle&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;savedInstanceState&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Dialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getActivity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getTheme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()){&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Override&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;onBackPressed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Handle back press here&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;approach-2-via-onkeylistener&#34;&gt;Approach 2: Via onKeyListener&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Override&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;onResume&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;super&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;onResume&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Dialog&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dialog&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getDialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dialog&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;setOnKeyListener&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Override&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;onPause&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;super&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;onPause&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Dialog&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dialog&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getDialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dialog&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;setOnKeyListener&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;modern-approach-onbackpresseddispatcher-androidx&#34;&gt;Modern Approach: OnBackPressedDispatcher (AndroidX)&lt;/h3&gt;
&lt;p&gt;For newer versions, use AndroidX&amp;rsquo;s &lt;code&gt;OnBackPressedDispatcher&lt;/code&gt;. Since Fragment 1.6.1, &lt;code&gt;DialogFragment&lt;/code&gt; returns a &lt;code&gt;ComponentDialog&lt;/code&gt; by default, which has its own &lt;code&gt;OnBackPressedDispatcher&lt;/code&gt;:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android MediaStore: GROUP BY via ContentResolver</title>
      <link>https://blog.substitute.tech/en/posts/android%E7%9A%84mediastore/</link>
      <pubDate>Fri, 31 Mar 2017 11:19:26 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/android%E7%9A%84mediastore/</guid>
      <description>&lt;p&gt;When building a photo album feature similar to WeChat, I needed to read photos and videos with multi-folder switching — and it had to be faster than WeChat. After some research, the &lt;code&gt;MediaStore&lt;/code&gt; approach proved most suitable. Since I hadn&amp;rsquo;t used it much before, this post serves as a record.&lt;/p&gt;
&lt;h2 id=&#34;the-group-by-hack-in-contentresolver&#34;&gt;The GROUP BY Hack in ContentResolver&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ContentResolver.query()&lt;/code&gt; does not expose a &lt;code&gt;groupBy&lt;/code&gt; parameter (unlike &lt;code&gt;SQLiteQueryBuilder.query()&lt;/code&gt;), but you can achieve a similar effect by embedding &lt;code&gt;GROUP BY&lt;/code&gt; directly into the &lt;code&gt;selection&lt;/code&gt; argument.&lt;/p&gt;</description>
    </item>
    <item>
      <title>HTTPS Notes</title>
      <link>https://blog.substitute.tech/en/posts/https/</link>
      <pubDate>Wed, 20 Jan 2016 11:50:30 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/https/</guid>
      <description>&lt;p&gt;Before working with HTTPS, I recommend reading &lt;a href=&#34;https://developer.android.com/training/articles/security-ssl.html&#34;&gt;Android Training: Security with SSL&lt;/a&gt;. Many companies have adopted full-site HTTPS, but not all implementations are correct. This post records some issues I encountered.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android Issues Roundup (Part 2)</title>
      <link>https://blog.substitute.tech/en/posts/%E9%97%AE%E9%A2%98%E6%95%B4%E7%90%86%E4%BA%8C/</link>
      <pubDate>Tue, 19 Jan 2016 16:50:36 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/%E9%97%AE%E9%A2%98%E6%95%B4%E7%90%86%E4%BA%8C/</guid>
      <description>&lt;p&gt;Second batch of collected issues, mainly covering WebView memory management, cookie synchronization, and other development details.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building an App with RxJava</title>
      <link>https://blog.substitute.tech/en/posts/rxjava/</link>
      <pubDate>Thu, 07 Jan 2016 14:05:45 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/rxjava/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been working on a Zhihu Daily client to evaluate RxJava&amp;rsquo;s benefits and trade-offs in a real project. RxJava has gained significant traction abroad, with language bindings spanning Java, JavaScript, C#, Scala, Clojure, C++, Python, Ruby, Kotlin, Swift, and more.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android Development Issues and Solutions</title>
      <link>https://blog.substitute.tech/en/posts/%E9%97%AE%E9%A2%98%E6%95%B4%E7%90%86/</link>
      <pubDate>Tue, 29 Dec 2015 18:41:05 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/%E9%97%AE%E9%A2%98%E6%95%B4%E7%90%86/</guid>
      <description>&lt;p&gt;After reading some issue roundups on Xiaoke&amp;rsquo;s Blog, I realized I&amp;rsquo;ve encountered many of the same problems. Here&amp;rsquo;s a collected summary.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android Resource Shrinking</title>
      <link>https://blog.substitute.tech/en/posts/resourceshrinking%E8%B5%84%E6%BA%90%E6%B8%85%E7%90%86/</link>
      <pubDate>Wed, 23 Dec 2015 17:43:07 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/resourceshrinking%E8%B5%84%E6%BA%90%E6%B8%85%E7%90%86/</guid>
      <description>&lt;p&gt;While building a project, I discovered the &lt;code&gt;shrinkResources&lt;/code&gt; attribute, which removes unused resources from the APK. Here is how to configure it and what to watch out for.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tree View Menu with RecyclerView</title>
      <link>https://blog.substitute.tech/en/posts/treeview%E6%A0%91%E5%BD%A2%E8%8F%9C%E5%8D%95/</link>
      <pubDate>Wed, 16 Dec 2015 18:15:33 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/treeview%E6%A0%91%E5%BD%A2%E8%8F%9C%E5%8D%95/</guid>
      <description>&lt;p&gt;I had long wanted to write a tree view demo. Previously, I used &lt;code&gt;TreeViewList&lt;/code&gt; (a &lt;code&gt;ListView&lt;/code&gt; wrapper) or &lt;code&gt;ExpandableListView&lt;/code&gt; for multi-level menus. Eventually I realized there is no need for custom views &amp;ndash; just use &lt;code&gt;RecyclerView&lt;/code&gt; and manage the data flattening yourself.&lt;/p&gt;
&lt;p&gt;The core idea: recursively flatten a nested data structure into a linear list, then use &lt;code&gt;notifyItemRangeInserted&lt;/code&gt; / &lt;code&gt;notifyItemRangeRemoved&lt;/code&gt; to handle expand and collapse.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Lorem Ipsum — Placeholder Text</title>
      <link>https://blog.substitute.tech/en/posts/loremipsum%E4%B9%B1%E6%95%B0%E5%81%87%E6%96%87/</link>
      <pubDate>Fri, 04 Dec 2015 12:04:00 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/loremipsum%E4%B9%B1%E6%95%B0%E5%81%87%E6%96%87/</guid>
      <description>&lt;p&gt;A colleague asked me today what this text meant:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid veniam harum quas similique quis, quisquam tempore iste. Alias soluta dolorum ratione, dolorem quia corrupti, suscipit eveniet dolor dignissimos voluptas laborum debitis ea fugiat aliquam rem ullam minus a aliquid pariatur!&lt;/p&gt;
&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>Some Git Operations</title>
      <link>https://blog.substitute.tech/en/posts/git%E7%9A%84%E4%B8%80%E4%BA%9B%E6%93%8D%E4%BD%9C/</link>
      <pubDate>Thu, 10 Sep 2015 16:02:39 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/git%E7%9A%84%E4%B8%80%E4%BA%9B%E6%93%8D%E4%BD%9C/</guid>
      <description>&lt;p&gt;Basic commands are well documented elsewhere. Here are some operations I&amp;rsquo;ve found useful in real projects.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Solving Problems from Error Logs — Bugly Blog Collection</title>
      <link>https://blog.substitute.tech/en/posts/%E5%A6%82%E4%BD%95%E6%A0%B9%E6%8D%AE%E9%94%99%E8%AF%AF%E6%97%A5%E5%BF%97%E8%A7%A3%E5%86%B3%E9%97%AE%E9%A2%98/</link>
      <pubDate>Wed, 29 Jul 2015 12:00:39 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/%E5%A6%82%E4%BD%95%E6%A0%B9%E6%8D%AE%E9%94%99%E8%AF%AF%E6%97%A5%E5%BF%97%E8%A7%A3%E5%86%B3%E9%97%AE%E9%A2%98/</guid>
      <description>&lt;p&gt;We use Tencent Bugly for crash monitoring in our project. Most crash reporting tools are similar in functionality; Bugly was chosen for its clean statistics dashboard and reliable brand. Here is a curated collection of Bugly&amp;rsquo;s technical blog posts covering common crash scenarios and analysis approaches.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Java Reflection: Modifying Private Static Final Fields</title>
      <link>https://blog.substitute.tech/en/posts/javareflection/</link>
      <pubDate>Tue, 16 Jun 2015 11:09:06 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/javareflection/</guid>
      <description>&lt;p&gt;While debugging memory leaks, I often need to modify field values via reflection. I came across a great Stack Overflow answer worth documenting.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Common Issues When Customizing Volley</title>
      <link>https://blog.substitute.tech/en/posts/volley%E8%87%AA%E5%AE%9A%E4%B9%89%E4%B8%AD%E7%9A%84%E5%87%A0%E4%B8%AA%E9%97%AE%E9%A2%98%E7%9A%84%E5%8E%9F%E5%9B%A0/</link>
      <pubDate>Tue, 09 Jun 2015 17:30:15 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/volley%E8%87%AA%E5%AE%9A%E4%B9%89%E4%B8%AD%E7%9A%84%E5%87%A0%E4%B8%AA%E9%97%AE%E9%A2%98%E7%9A%84%E5%8E%9F%E5%9B%A0/</guid>
      <description>&lt;p&gt;While integrating Volley into a project, I encountered several common issues worth documenting. The following does not apply to Android 2.3 and below.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Gson User Guide</title>
      <link>https://blog.substitute.tech/en/posts/gsonexamples/</link>
      <pubDate>Mon, 08 Jun 2015 12:37:45 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/gsonexamples/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article is compiled from the official Gson User Guide. Gson&amp;rsquo;s performance is competitive with other JSON frameworks, and being Google-maintained makes it a solid choice for Java/Android JSON processing.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Gson is a Java library developed by Google for serializing Java objects to JSON and deserializing JSON strings back to Java objects.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Downloading Android Source Code</title>
      <link>https://blog.substitute.tech/en/posts/android%E6%BA%90%E7%A0%81%E4%B8%8B%E8%BD%BD/</link>
      <pubDate>Thu, 04 Jun 2015 15:45:04 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/android%E6%BA%90%E7%A0%81%E4%B8%8B%E8%BD%BD/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Timeliness note&lt;/strong&gt;: The mirror URLs in this article were valid for a specific period. Both TUNA (Tsinghua) and USTC (Hefei) AOSP mirror addresses have changed multiple times. Always consult each mirror&amp;rsquo;s official help page for current URLs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;AOSP source is enormous (~70GB), making downloads from Google&amp;rsquo;s official servers via VPN painfully slow. Chinese mirrors offer much faster speeds.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Make Your App the Default SMS App</title>
      <link>https://blog.substitute.tech/en/posts/defaultapp/</link>
      <pubDate>Mon, 18 May 2015 16:49:21 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/defaultapp/</guid>
      <description>&lt;p&gt;While using Google Messenger, I noticed it has a &amp;ldquo;set as default SMS app&amp;rdquo; feature. Here&amp;rsquo;s how it works.&lt;/p&gt;
&lt;p&gt;Starting from Android 4.4 KitKat, Google introduced the default SMS app mechanism. The official reasoning:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Some of you have built SMS apps using hidden APIs — a practice we discourage because hidden APIs may be changed or removed and new devices are not tested against them for compatibility. So, to provide you with a fully supported set of APIs for building SMS apps.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In short, if you build well and have enough users, Google takes notice and provides official support.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Notes from Reading Android Documentation</title>
      <link>https://blog.substitute.tech/en/posts/%E6%9C%80%E8%BF%91%E5%8F%91%E7%8E%B0%E7%9A%84%E5%87%A0%E4%B8%AA%E6%B3%A8%E6%84%8F%E7%82%B9/</link>
      <pubDate>Mon, 11 May 2015 11:18:26 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/%E6%9C%80%E8%BF%91%E5%8F%91%E7%8E%B0%E7%9A%84%E5%87%A0%E4%B8%AA%E6%B3%A8%E6%84%8F%E7%82%B9/</guid>
      <description>&lt;p&gt;A collection of subtle but important details I noticed while reading the Android developer documentation.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Dart Web Apps on Android</title>
      <link>https://blog.substitute.tech/en/posts/dart/</link>
      <pubDate>Tue, 05 May 2015 17:46:58 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/dart/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Historical note&lt;/strong&gt;: This article was written in 2015 based on the old Dart toolchain (Dart Editor + Dartium). Dart has since moved entirely to the Flutter ecosystem and the &lt;code&gt;dart&lt;/code&gt; CLI toolchain. Content is kept for reference only.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can launch and debug Android web applications built with Dart without pre-compiling to JavaScript. To do this, you need &lt;strong&gt;Dart Editor&lt;/strong&gt; and &lt;strong&gt;Dart Content Shell&lt;/strong&gt;. Dart Content Shell is automatically installed on the Android device.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Cache Algorithms</title>
      <link>https://blog.substitute.tech/en/posts/cachealgorithms/</link>
      <pubDate>Tue, 05 May 2015 16:31:28 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/cachealgorithms/</guid>
      <description>&lt;p&gt;Cache replacement policies determine which entries to evict when the cache is full. They have a direct impact on system performance. Here is an overview of common cache eviction algorithms.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Strange Problems I Encountered Recently</title>
      <link>https://blog.substitute.tech/en/posts/recent-strangeproblem/</link>
      <pubDate>Tue, 21 Apr 2015 14:41:34 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/recent-strangeproblem/</guid>
      <description>&lt;p&gt;A collection of obscure Android development issues and their solutions.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android Data Storage</title>
      <link>https://blog.substitute.tech/en/posts/androiddatastorage/</link>
      <pubDate>Wed, 08 Apr 2015 11:38:49 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/androiddatastorage/</guid>
      <description>&lt;p&gt;Android provides several options for persisting data, each suited to different use cases. Choosing the right storage method is critical for your app&amp;rsquo;s performance, security, and user experience.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android App Widgets</title>
      <link>https://blog.substitute.tech/en/posts/androidappwidgets/</link>
      <pubDate>Wed, 01 Apr 2015 10:37:26 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/androidappwidgets/</guid>
      <description>&lt;p&gt;An App Widget is a miniature application view that can be embedded into other applications (such as the Home screen) and receive periodic updates. Common examples include weather widgets and music player controls.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;appwidget&#34; loading=&#34;lazy&#34; src=&#34;https://blog.substitute.tech/images/appwidget.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android Developer Requirements</title>
      <link>https://blog.substitute.tech/en/posts/androiddeveloperrequirements/</link>
      <pubDate>Wed, 01 Apr 2015 09:50:52 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/androiddeveloperrequirements/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article was written in 2015. Some toolchain details and version numbers are outdated and provided for historical reference only. For current Android development, please refer to &lt;a href=&#34;https://developer.android.com/studio&#34;&gt;Android Studio&lt;/a&gt; and the &lt;a href=&#34;https://developer.android.com/&#34;&gt;official Android Developers documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>Design Patterns</title>
      <link>https://blog.substitute.tech/en/posts/designpatterns/</link>
      <pubDate>Mon, 30 Mar 2015 10:08:26 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/designpatterns/</guid>
      <description>&lt;p&gt;Design Patterns are reusable solutions to common problems in object-oriented design. The 23 classic patterns were systematized by the Gang of Four (GoF: Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides) in their 1994 book &lt;em&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This article is compiled from a blog post by &lt;a href=&#34;https://github.com/smallnest&#34;&gt;smallnest&lt;/a&gt; and a StackOverflow discussion on GoF design pattern implementations in the Java API.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;javagofdesignpatterns&#34; loading=&#34;lazy&#34; src=&#34;https://blog.substitute.tech/images/javagofdesignpatterns.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;../source/pdf/design-pattern-scard.pdf&#34;&gt;View PDF Overview&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Remote Debugging on Android with Chrome</title>
      <link>https://blog.substitute.tech/en/posts/remotedebuggingonandroidwithchrome/</link>
      <pubDate>Tue, 24 Mar 2015 14:54:02 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/remotedebuggingonandroidwithchrome/</guid>
      <description>&lt;p&gt;Chrome DevTools supports remote debugging of web pages and WebView applications on Android devices. This feature is invaluable for mobile front-end development and hybrid app development, allowing you to use the full suite of desktop Chrome DevTools to debug mobile pages.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Bezier Curve Practice</title>
      <link>https://blog.substitute.tech/en/posts/beziercurvepractice/</link>
      <pubDate>Wed, 04 Mar 2015 14:11:48 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/beziercurvepractice/</guid>
      <description>&lt;p&gt;Bézier curves are widely used in computer graphics to model smooth curves. They were independently developed by French engineers Pierre Bézier (Renault) and Paul de Casteljau (Citroën) in the 1960s.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;Bézier_3_big&#34; loading=&#34;lazy&#34; src=&#34;https://blog.substitute.tech/images/Be%CC%81zier_3_big.svg.png&#34;&gt;&lt;img alt=&#34;Bézier_3_big_gif&#34; loading=&#34;lazy&#34; src=&#34;https://blog.substitute.tech/images/Be%CC%81zier_3_big.gif&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android Property Animation</title>
      <link>https://blog.substitute.tech/en/posts/androidpropertyanimation/</link>
      <pubDate>Tue, 03 Mar 2015 10:31:21 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/androidpropertyanimation/</guid>
      <description>&lt;p&gt;&lt;code&gt;Property Animation&lt;/code&gt; is a powerful animation framework introduced in Android 3.0 (API 11). Unlike the older View Animation (tween animation) system, property animation actually changes the properties of the target object, not just its rendered appearance.&lt;/p&gt;</description>
    </item>
    <item>
      <title>SQLite Limits Explained: Tracing a SQLiteFullException</title>
      <link>https://blog.substitute.tech/en/posts/limitsinsqlite/</link>
      <pubDate>Sat, 28 Feb 2015 22:48:55 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/limitsinsqlite/</guid>
      <description>&lt;p&gt;While debugging a recent bug, I ran into a peculiar issue: &lt;code&gt;android.database.sqlite.SQLiteFullException: database or disk is full (code 13)&lt;/code&gt;. After extensive research without a definitive root cause, I am sharing my findings here in the hope that others with similar experiences can help shed light on this.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;limitsinsqlite01&#34; loading=&#34;lazy&#34; src=&#34;https://blog.substitute.tech/images/limitsinsqlite01.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Getting Started with Go: First Program and Basic Practices</title>
      <link>https://blog.substitute.tech/en/posts/go1/</link>
      <pubDate>Tue, 10 Feb 2015 22:48:55 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/go1/</guid>
      <description>&lt;p&gt;This article covers the four most fundamental steps in learning Go: writing your first program, creating a utility library, writing unit tests, and using remote packages. The content follows the original GOPATH workflow from the early Go 1.x era.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Go Modules were introduced in Go 1.11 and became the default in Go 1.16, effectively replacing GOPATH mode. For new projects, use &lt;code&gt;go mod init&lt;/code&gt; to create a module instead of manually setting up GOPATH. The examples below preserve the original style for reference.&lt;/p&gt;
&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>Android Notification Guide</title>
      <link>https://blog.substitute.tech/en/posts/androidnotification/</link>
      <pubDate>Thu, 29 Jan 2015 15:26:07 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/androidnotification/</guid>
      <description>&lt;p&gt;The notification system is a critical channel for user-app interaction on Android — it keeps users informed of important events even when the app is not in the foreground, such as incoming messages or calendar reminders. Notifications received a major overhaul in Android 4.1 (Jelly Bean) and continued to see refinements through Android 5.0 (Lollipop). Since 4.1, Android supports action buttons at the bottom of notifications, allowing users to perform common tasks directly without opening the app.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article was written for the Android 4.1–5.0 era APIs. Starting from Android 8.0 (API 26), all notifications must be assigned to a Notification Channel. Android 13 (API 33) introduced the &lt;code&gt;POST_NOTIFICATIONS&lt;/code&gt; runtime permission. The code examples below use &lt;code&gt;NotificationCompat&lt;/code&gt; for backward compatibility; visual results may vary across devices.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&#34;notification01&#34; loading=&#34;lazy&#34; src=&#34;https://blog.substitute.tech/images/notification01.jpg&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android Learning Resources Guide</title>
      <link>https://blog.substitute.tech/en/posts/android%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99%E6%8C%87%E5%8D%97/</link>
      <pubDate>Mon, 26 Jan 2015 16:35:07 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/android%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99%E6%8C%87%E5%8D%97/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Note: This post was written in 2015. Some links may no longer be valid. The recommendations reflect the ecosystem at that time, but the core learning path and methodology remain relevant.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;foreword&#34;&gt;Foreword&lt;/h2&gt;
&lt;p&gt;We all start somewhere. For any technology, everyone begins with Hello World. What puzzles me is why some people improve 100% in a year while others only 20% — or even stagnate. Is it IQ? In my opinion, it is more likely a matter of learning method.&lt;/p&gt;
&lt;p&gt;While on my wedding leave, I was writing blog posts and searching for learning materials. I found that relying solely on Baidu was terribly inefficient — at least half the time was wasted on useless pages. I decided to spend a few evenings organizing my bookmarks, making sure most resources are accessible from within China. The following is a curated list for beginner-to-intermediate Android developers. As for advanced-level topics — I&amp;rsquo;m not quite qualified to speak on those yet.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Setting Up Android Environment, Source Code, and Tools Using Chinese Mirrors</title>
      <link>https://blog.substitute.tech/en/posts/%E8%BD%BB%E6%9D%BE%E6%90%9E%E5%AE%9Aandroid%E7%9A%84%E7%8E%AF%E5%A2%83%E6%BA%90%E7%A0%81%E5%B7%A5%E5%85%B7/</link>
      <pubDate>Fri, 16 Jan 2015 08:35:07 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/%E8%BD%BB%E6%9D%BE%E6%90%9E%E5%AE%9Aandroid%E7%9A%84%E7%8E%AF%E5%A2%83%E6%BA%90%E7%A0%81%E5%B7%A5%E5%85%B7/</guid>
      <description>&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This post was written in 2015. Some mirror URLs may have changed or become unavailable. As of 2025, the recommended mirrors for Chinese developers are Tsinghua TUNA, USTC, and other university mirrors, or simply using Android Studio&amp;rsquo;s built-in SDK Manager.&lt;/p&gt;
&lt;p&gt;For developers behind the Great Firewall of China, accessing Google&amp;rsquo;s servers directly is slow or unreliable. This post covers mirror-based solutions for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Android SDK updates&lt;/li&gt;
&lt;li&gt;Android Studio downloads&lt;/li&gt;
&lt;li&gt;AOSP source code downloads&lt;/li&gt;
&lt;li&gt;Android NDK downloads&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Android Fragment$InstantiationException: Causes and Solutions</title>
      <link>https://blog.substitute.tech/en/posts/android-fragmentinstantiationexception/</link>
      <pubDate>Wed, 07 Jan 2015 08:35:07 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/android-fragmentinstantiationexception/</guid>
      <description>&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;android&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;support&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v4&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Fragment&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;InstantiationException&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Unable&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;instantiate&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fragment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;make&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sure&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exists&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;has&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;an&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;empty&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;constructor&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;that&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;public&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This error used to be rare, but recently it spiked. After investigation, here are the causes and solutions.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How Java HashMap Works Internally</title>
      <link>https://blog.substitute.tech/en/posts/javahashmap%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86/</link>
      <pubDate>Sat, 27 Dec 2014 08:35:07 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/javahashmap%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86/</guid>
      <description>&lt;p&gt;HashMap is one of the most frequently asked topics in Java interviews — it effectively tests a candidate&amp;rsquo;s understanding of data structures and engineering trade-offs. This article breaks down its core design and implementation details.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;hashmap01&#34; loading=&#34;lazy&#34; src=&#34;https://blog.substitute.tech/images/hashmap01.jpg&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>CSS Box Shadows Techniques</title>
      <link>https://blog.substitute.tech/en/posts/css-box-shadows/</link>
      <pubDate>Fri, 26 Dec 2014 23:35:07 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/css-box-shadows/</guid>
      <description>&lt;p&gt;The &lt;code&gt;box-shadow&lt;/code&gt; property in CSS3 is highly versatile. When used creatively, it can produce rich visual effects with pure CSS. Here are several practical techniques.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android EBUSY Exception</title>
      <link>https://blog.substitute.tech/en/posts/android-ebusy-exception/</link>
      <pubDate>Mon, 22 Dec 2014 15:35:07 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/android-ebusy-exception/</guid>
      <description>&lt;p&gt;While working on an image upload feature, I encountered a runtime exception on certain devices:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;java&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;io&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;FileNotFoundException&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mnt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sdcard&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Android&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;com&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;xxxxxx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;android&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;files&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xxxx&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;failed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EBUSY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Device&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;or&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resource&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;busy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;at&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;libcore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;io&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;IoBridge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IoBridge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;java&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;406&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;at&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;java&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;io&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;FileOutputStream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;init&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FileOutputStream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;java&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;88&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Caused&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;by&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;libcore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;io&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;ErrnoException&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;failed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EBUSY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Device&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;or&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resource&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;busy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;at&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;libcore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;io&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;Posix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Native&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Method&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;at&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;libcore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;io&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;BlockGuardOs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BlockGuardOs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;java&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;110&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>Tencent Interview</title>
      <link>https://blog.substitute.tech/en/posts/tencent-interview/</link>
      <pubDate>Mon, 08 Dec 2014 10:35:07 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/tencent-interview/</guid>
      <description>&lt;p&gt;I came across &lt;a href=&#34;http://stormzhang.com/android/other/2014/05/03/tencent-interview/&#34;&gt;stormzhang&amp;rsquo;s Tencent interview questions&lt;/a&gt; and decided to work through them, documenting my answers and thought process.&lt;/p&gt;
&lt;p&gt;Topics covered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Android fundamentals (processes, Activities, Handler)&lt;/li&gt;
&lt;li&gt;Screen density and resource qualifiers&lt;/li&gt;
&lt;li&gt;Thread synchronization in Java&lt;/li&gt;
&lt;li&gt;System design (resumable downloads, network architecture)&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Lambda Expressions in Java 8</title>
      <link>https://blog.substitute.tech/en/posts/java-8-%E7%9A%84-lambda/</link>
      <pubDate>Sun, 07 Dec 2014 15:35:07 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/java-8-%E7%9A%84-lambda/</guid>
      <description>&lt;h2 id=&#34;what-is-a-lambda-expression&#34;&gt;What is a Lambda Expression?&lt;/h2&gt;
&lt;p&gt;Lambda expressions are a core feature introduced in Java 8, enabling more concise code. Here is the most straightforward example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;Runnable&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;runnable1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Runnable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@Override&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;runnable1 start!!!&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;Runnable&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;runnable2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;runnable2 start!!!&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;runnable1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;runnable2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Both blocks are equivalent, but the lambda version is a single line. The basic form is &lt;code&gt;() -&amp;gt; expression&lt;/code&gt; or &lt;code&gt;() -&amp;gt; { statements; }&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Wireless Debugging on Android</title>
      <link>https://blog.substitute.tech/en/posts/android%E4%BD%BF%E7%94%A8wireless%E8%B0%83%E8%AF%95/</link>
      <pubDate>Fri, 05 Dec 2014 11:35:07 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/android%E4%BD%BF%E7%94%A8wireless%E8%B0%83%E8%AF%95/</guid>
      <description>&lt;p&gt;Ever since getting a Nexus device, I never wanted to plug in a USB cable again. Android supports ADB debugging over WiFi, making cable-free development a reality.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android&#39;s SQLite</title>
      <link>https://blog.substitute.tech/en/posts/androids-sqlite/</link>
      <pubDate>Mon, 01 Dec 2014 22:11:22 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/androids-sqlite/</guid>
      <description>&lt;p&gt;SQLite is a lightweight relational database engine built into Android, ideal for local data persistence. The &lt;code&gt;android.database.sqlite&lt;/code&gt; package provides everything you need without additional setup.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android&#39;s Palette</title>
      <link>https://blog.substitute.tech/en/posts/androids-palette/</link>
      <pubDate>Mon, 03 Nov 2014 10:01:22 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/androids-palette/</guid>
      <description>&lt;p&gt;The Palette library, part of Android Support Library (now migrated to AndroidX &lt;code&gt;palette&lt;/code&gt;), extracts representative colors from a Bitmap. In Material Design, deriving UI colors from imagery is a common pattern, and Palette makes this straightforward.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;palette01&#34; loading=&#34;lazy&#34; src=&#34;https://blog.substitute.tech/images/palette01.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android RecyclerView (Part 2): Parallax Scrolling</title>
      <link>https://blog.substitute.tech/en/posts/androids-recyclerview2-%E8%A7%86%E5%B7%AE%E6%BB%9A%E5%8A%A8/</link>
      <pubDate>Sun, 02 Nov 2014 14:01:22 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/androids-recyclerview2-%E8%A7%86%E5%B7%AE%E6%BB%9A%E5%8A%A8/</guid>
      <description>&lt;p&gt;Parallax scrolling is a common UI effect where different layers move at different speeds during scrolling, creating a sense of depth.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;parallaxrecycler&#34; loading=&#34;lazy&#34; src=&#34;https://blog.substitute.tech/images/parallaxrecycler.gif&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android RecyclerView</title>
      <link>https://blog.substitute.tech/en/posts/androids-recyclerview/</link>
      <pubDate>Sat, 01 Nov 2014 17:03:26 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/androids-recyclerview/</guid>
      <description>&lt;p&gt;RecyclerView is a more flexible replacement for ListView. According to the official documentation, it efficiently maintains a limited collection of scrolling data items, and is recommended when your Views need to interact with user gestures and network data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;RecyclerView01&#34; loading=&#34;lazy&#34; src=&#34;https://blog.substitute.tech/images/RecyclerView01.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android Canvas (Part 2): Clipping</title>
      <link>https://blog.substitute.tech/en/posts/android-canvas2/</link>
      <pubDate>Fri, 03 Oct 2014 14:19:06 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/android-canvas2/</guid>
      <description>&lt;p&gt;Canvas clipping limits the drawing region: only content within the clipped area is visible.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android Canvas (Part 1)</title>
      <link>https://blog.substitute.tech/en/posts/android-canvas1/</link>
      <pubDate>Thu, 02 Oct 2014 13:19:06 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/android-canvas1/</guid>
      <description>&lt;p&gt;A View renders its content by &amp;ldquo;drawing&amp;rdquo; — using a canvas (&lt;code&gt;Canvas&lt;/code&gt;) and a paintbrush (&lt;code&gt;Paint&lt;/code&gt;). The &lt;code&gt;Canvas&lt;/code&gt; obtained through the &lt;code&gt;onDraw&lt;/code&gt; method is directly composited onto the View.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;Canvas01&#34; loading=&#34;lazy&#34; src=&#34;https://blog.substitute.tech/images/android_canvas01.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Android Custom View (Part 2): Measurement Modes</title>
      <link>https://blog.substitute.tech/en/posts/customview2/</link>
      <pubDate>Wed, 01 Oct 2014 19:19:06 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/customview2/</guid>
      <description></description>
    </item>
    <item>
      <title>Android Custom View (Part 1)</title>
      <link>https://blog.substitute.tech/en/posts/customview1/</link>
      <pubDate>Wed, 01 Oct 2014 17:19:06 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/customview1/</guid>
      <description>&lt;p&gt;When you first start writing custom Views in Android, it&amp;rsquo;s common to feel unsure where to begin. Generally, there are two approaches:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;From scratch&lt;/strong&gt;: Extend &lt;code&gt;View&lt;/code&gt; and implement the appearance entirely through calculation and drawing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extend an existing View&lt;/strong&gt;: Add child views to an existing component, or override methods to change its behavior.&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    <item>
      <title>Building a Blog with Jekyll</title>
      <link>https://blog.substitute.tech/en/posts/welcome/</link>
      <pubDate>Sat, 21 Dec 2013 22:19:05 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/posts/welcome/</guid>
      <description>&lt;p&gt;This is the first post of this blog. I referenced many Jekyll templates at the time, adapted a custom theme inspired by &lt;code&gt;Pure&lt;/code&gt;, and hosted it on GitHub.&lt;/p&gt;
&lt;p&gt;Source code: &lt;a href=&#34;https://github.com/Haoxiqiang/haoxiqiang-template&#34;&gt;haoxiqiang-template&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;jekyll-overview&#34;&gt;Jekyll Overview&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://jekyllrb.com/&#34;&gt;Jekyll&lt;/a&gt; is a static site generator that converts plain text (Markdown, Liquid templates) into a complete static website without requiring a database. Combined with &lt;a href=&#34;https://pages.github.com/&#34;&gt;GitHub Pages&lt;/a&gt;, it provides free blog hosting.&lt;/p&gt;
&lt;h2 id=&#34;features&#34;&gt;Features&lt;/h2&gt;
&lt;h3 id=&#34;code-highlighting&#34;&gt;Code Highlighting&lt;/h3&gt;
&lt;p&gt;Jekyll has built-in syntax highlighting powered by Rouge:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;print_hi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nb&#34;&gt;puts&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Hi, &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;#{&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;print_hi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Tom&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;#=&amp;gt; prints &amp;#39;Hi, Tom&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;latex-math-rendering&#34;&gt;LaTeX Math Rendering&lt;/h3&gt;
&lt;p&gt;Set &lt;code&gt;latex: true&lt;/code&gt; in the page front matter to enable MathJax rendering:&lt;/p&gt;
&lt;p&gt;$$
\begin{aligned} \dot{x} &amp;amp;= \sigma(y-x) \
\dot{y} &amp;amp;= \rho x - y - xz \
\dot{z} &amp;amp;= -\beta z + xy \end{aligned}
$$&lt;/p&gt;
&lt;p&gt;$$
a^2 + b^2 = c^2
$$&lt;/p&gt;
&lt;p&gt;When $a \ne 0$, there are two solutions to $ax^2 + bx + c = 0$.&lt;/p&gt;
&lt;h3 id=&#34;excerpt-separator&#34;&gt;Excerpt Separator&lt;/h3&gt;
&lt;p&gt;Use `&lt;/p&gt;</description>
    </item>
    <item>
      <title>About</title>
      <link>https://blog.substitute.tech/en/about/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://blog.substitute.tech/en/about/</guid>
      <description>about</description>
    </item>
  </channel>
</rss>
