• Move to 'jekyll-redirect-from'

    Problems with jekyll_alias_generator

    I wrote “How to Add Redirects to Post URL on Octopress” few month ago. Now Octopress is compatible with Jekyll 2.0, and some plugins don’t seem to work. Current Octopress uses Jekyll 2.0.3 and when I run rake generate, I see an error:

    /path/to/jekyll/lib/jekyll/static_file.rb:40:in `stat': Not a directory @ rb_file_s_stat - /path/to/generated/alias/index.html/ (Errno::ENOTDIR)
    

    So I make this commit:

    diff --git a/_plugins/alias_generator.rb b/_plugins/alias_generator.rb
    index 1d24cd8..50e9404 100644
    --- a/_plugins/alias_generator.rb
    +++ b/_plugins/alias_generator.rb
    @@ -70,9 +70,10 @@ module Jekyll
               file.write(alias_template(destination_path))
             end
     
    -        (alias_index_path.split('/').size + 1).times do |sections|
    +        alias_index_path.split('/').size.times do |sections|
               @site.static_files << Jekyll::AliasFile.new(@site, @site.dest, alias_index_path.split('/')[0, sections].join('/'), '')
             end
    +        @site.static_files << Jekyll::AliasFile.new(@site, @site.dest, alias_dir, alias_file)
           end
         end
     
    

    But it seems that there is another problem with latest Jekyll, so I make another commit:

    diff --git a/_plugins/alias_generator.rb b/_plugins/alias_generator.rb
    index 50e9404..76102db 100644
    --- a/_plugins/alias_generator.rb
    +++ b/_plugins/alias_generator.rb
    @@ -56,13 +56,13 @@ module Jekyll
           alias_paths.compact!
     
           alias_paths.flatten.each do |alias_path|
    -        alias_path = alias_path.to_s
    +        alias_path = File.join('/', alias_path.to_s)
     
             alias_dir  = File.extname(alias_path).empty? ? alias_path : File.dirname(alias_path)
             alias_file = File.extname(alias_path).empty? ? "index.html" : File.basename(alias_path)
     
    -        fs_path_to_dir   = File.join(@site.dest, alias_dir)
    -        alias_index_path = File.join(alias_dir, alias_file)
    +        fs_path_to_dir = File.join(@site.dest, alias_dir)
    +        alias_sections = alias_dir.split('/')[1..-1]
     
             FileUtils.mkdir_p(fs_path_to_dir)
     
    @@ -70,8 +70,8 @@ module Jekyll
               file.write(alias_template(destination_path))
             end
     
    -        alias_index_path.split('/').size.times do |sections|
    -          @site.static_files << Jekyll::AliasFile.new(@site, @site.dest, alias_index_path.split('/')[0, sections].join('/'), '')
    +        alias_sections.size.times do |sections|
    +          @site.static_files << Jekyll::AliasFile.new(@site, @site.dest, alias_sections[0, sections + 1].join('/'), '')
             end
             @site.static_files << Jekyll::AliasFile.new(@site, @site.dest, alias_dir, alias_file)
           end
    

    To say the result first, I had no luck. The alias directories are generated, every index.html file under each directory won’t. By looking at diff of sitemap.xml, the plugin seems to generate wrong paths. I’m pretty newbie to Jekyll and how Octopress works with it. Also this is a plugin for Jekyll, not Octopress. So if you have any fix for this problem, please make pull requests to jekyll_alias_generator or just contact me.

    Read on →

  • How to Add Redirects to Post URL on Octopress

    When I write a new post on Octopress, I share the link of it to somewhere doesn’t support hyperlinks. Since people can’t click the link, they should copy and paste or just type it letter by letter. I wanted to make it easier, so I maded short url for every post.

    Alias Generator for Posts

    There is a Jekyll plugin that generates redirect pages for posts with aliases. Octopress is based on Jekyll and this plugin has no compatibility problem. Its source is on GitHub, so I just added it as submodule:

    $ git submodule add [email protected]:tsmango/jekyll_alias_generator plugins/jekyll_alias_generator
    

    In your _config.yml, you may have this line:

    plugins: plugins
    

    Then it reads plugins directory and alias_generator.rb in plugins/jekyll_alias_generator/_plugins/ directory is also loaded, so you can use and manage it!

    How to Use

    This plugin checks alias inside every post’s YAML Front Matter. Just place the path of the alias:

    ---
    layout: post
    title: "How to Add Redirects to Post URL on Octopress"
    alias: /p/20140523
    ---
    

    Multiple aliases are also available:

    ---
    layout: post
    title: "How to Add Redirects to Post URL on Octopress"
    alias: [/one-alias/index.html, /another-alias/index.html]
    ---
    

    When I rake generate, the plugin generates static html file at /p/20140523/index.html:

    <!DOCTYPE html>
    <html>
    <head>
    <link rel="canonical" href="/2014/05/23/how-to-add-redirects-to-post-url-on-octopress/"/>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <meta http-equiv="refresh" content="0;url=/2014/05/23/how-to-add-redirects-to-post-url-on-octopress/" />
    </head>
    </html>
    

    When you go to /p/20140523, it will redirect here. It also has canonical link, so it won’t affect search engine or web analysis services.

  • Gradle 환경에서 ProGuard 사용하기

    Gradle

    Gradle

    최근 Android Studio를 통해 개발을 진행하게 되면서, 자연스럽게 Gradle을 사용하게 되었다. .gradle 확장자를 가진 파일을 통해 빌드 설정을 자유롭게 조정할 수 있다. 이 글에서는 Gradle을 이용해 배포 APK를 생성하는 방법과 함께 ProGuard를 사용법을 공유하겠다.

    Gradle 환경에서 배포 APK 생성하기

    배포 APK에는 서명이 되어 있어야 하는데, 이를 위해서는 keystore 파일과 그 암호, 키 별칭, 키 암호가 필요하다. 디버그 APK에도 서명을 하지만, 알려진 keystore 암호와 키 별칭, 키 암호를 사용한다. 배포 APK의 서명을 위해 프로젝트의 build.gradle 파일에 다음 코드를 추가하면 된다.

    android {
        // ...
    
        signingConfigs {
            release {
                storeFile file("YOUR_KEYSTORE_PATH")
                storePassword "YOUR_KEYSTORE_PASSWORD"
                keyAlias "YOUR_KEY_ALIAS"
                keyPassword "YOUR_KEY_PASSWORD"
            }
        }
    
        buildTypes {
            release {
                signingConfig signingConfigs.release
            }
        }
    }
    

    이때 buildTypes 아래의 debug 항목은 굳이 명시하지 않아도 기본적으로 생성되며, 이 buildType디버그 keystore와 키를 사용하도록 설정되어 있다.

    다만 이때 build.gradle 파일에 keystore 암호와 키 암호가 평문으로 들어가게 되는데, 소스를 공개하고 있는 등의 이유로 이를 피하고 싶다면 각각의 항목을 쉘 프롬프트에서 입력받을 수 있다.

    signingConfigs {
        release {
            storeFile file(console.readLine("\n\$ Enter keystore path: "))
            storePassword new String(console.readPassword("\n\$ Enter keystore password: "))
            keyAlias console.readLine("\n\$ Enter key alias: ")
            keyPassword new String(console.readPassword("\n\$ Enter key password: "))
        }
    }
    

    그러나 이는 IDE를 통해 디버그 APK를 생성할 때 크래시를 내며, 이는 그때 코드의 consolenull이라서 발생하는 오류다. 이를 해결한 최종 코드는 다음과 같다.

    signingConfigs {
        release {
            final Console console = System.console();
            if (console != null) {
                storeFile file(console.readLine("\n\$ Enter keystore path: "))
                storePassword new String(console.readPassword("\n\$ Enter keystore password: "))
                keyAlias console.readLine("\n\$ Enter key alias: ")
                keyPassword new String(console.readPassword("\n\$ Enter key password: "))
            }
        }
    }
    

    디버그 APK와 배포 APK의 패키지 이름이 같으면 APK의 서명이 서로 달라 개발과 디버깅에 어려움이 있다. 이를 해결하기 위해서 buildTypes 아래에 debug 항목을 선언하여 디버그 APK의 패키지 이름을 바꿀 수 있고, 추가로 버전명도 바꿀 수 있다.

    buildTypes {
        debug {
            packageNameSuffix '.debug'
            versionNameSuffix '-debug'
        }
    }
    

    이제 터미널에서 다음 명령을 실행하면 디버그 APK와 배포 APK를 각각 얻을 수 있다. 물론 디버그 APK는 IDE로도 생성할 수 있다.

    $ ./gradlew assembleDebug
    $ ./gradlew assembleRelease
    

    Gradle은 캐멀케이스 단축키를 지원해서 aR에 해당하는 다른 명령이 없는 한 assembleRelease 대신 aR을 사용할 수 있다.

    Read on →

  • Layout Inflation as Intended →

    안드로이드 개발을 하다 보면 LayoutInflaterinflate(int, ViewGroup)inflate(int, ViewGroup, boolean)는 꽤 익숙하다. 하지만 다음 두 줄의 코드가 어떻게 다른지 아는 사람은 그리 많지 않을 것 같다. 실제로 Android Lint는 한쪽 코드는 피하도록 권하고 있다.

    inflater.inflate(R.layout.my_layout, null);
    inflater.inflate(R.layout.my_layout, parent, false);
    

    Dave Smith가 이 두 코드의 비교와 함께, 바른 Layout Inflation 방법에 대해 설명한 글이 있어 소개한다.

  • Fragment Transaction & Activity State Loss →

    FragmentTransactioncommit() 했을 때 Activity의 onSaveInstanceState(Bundle)이 실행된 후라면 다음과 같은 에러 메시지를 보게 된다.

    java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
    

    이 문제의 원인이 무엇인지, 어떻게 이 Exception을 피할지, 그리고 commitAllowingStateLoss()가 왜 마지막 수단이 되어야 하는지 잘 설명한 글이 있어 소개한다. Alex Lockwood가 쓴 Fragment Transaction과 Activity State Loss에 관한 글이다.