2015年4月7日火曜日

[日本旅遊]2014-12-27 秋葉原

有看過2014年8月的遊記的人,就會知道這次的行程是在那個時間點就已經買好機票了。
來回總共7K台幣含40kg行李。 LCC真的太讚了。 沒出狀況的話...

殺頭機場的洗手間廣告螢幕當機了www


這次搭機的時候發現香草有主題曲了! 輕快的吉他主奏曲,給人出國到海灘渡假的感覺。
非常適合的曲子。


照慣例香爆機上旅客。





白色富士!

八丈島。


45mm的極限就這樣了。



隔4個月又回家了。

這次的住宿地點是膠囊旅館,直接搭京成本線到終站上野。


還是比較喜歡「全部雪のせいだ。」的台詞。都是雪害的啦~~~ XD


膠囊旅館離上野站很近...安頓花不了多少時間,之後就直接衝到秋葉原。


坦克世界跟少女戰車合作,之後初的船艦世界也充滿了艦娘梗,大勝利的一家公司。



好久沒看到等身大的模型了。


冬天的秋葉原街頭:真是好冷...

這次的賽馬梗請出了鹹蛋超人,所以座騎是鹹蛋超馬?


背後位來一張。這隻馬的肌肉感做得還不錯。



齊聚一堂殊死戰。

上次好像忘記拍了,補個幾張。


故意斜拍才看得出來這張看板其實別有玄機。


新上市的景品:自動關開關的盒子。


好痛的外套。


接著去sofmap4號店拍拍新作pvc。



儀裝25。

吃城加賀...這艦隊的食料存量令人擔心。


秋山澪


銀湯匙合作作品。


沒想到有一般販售。


歐拜手機殼。


QB業績又大增了,恭喜。


凜抱著sonic的感覺真的很有趣。


晚餐是麵屋武藏武骨相傳(上野站旁,旅館附近)。味道還ok。不過店看起來快關門了才進去點餐,還好還可以點。看來存貨還沒用完... 就這樣邊吃邊看店員整理廚房也蠻有趣的。

圖上的是紅沾麵,麵量中,$830。這家的麵從並到特大到隨你裝(據說是1kg以內)都免加價。大食王的優良店。不知道沾麵湯會不會也跟著多給就是了。
味道算是中辣。我還可以接受。可能是比較辣,除了辣跟麻之外,其他的味道比較沒那麼明顯,下次還是試試白沾麵吧。整體來說還可以。叉燒有塗特製的烤肉醬,還是被辣味蓋掉了所以沒印象是啥味道。



這次住的是這間:サウナ カプセルホテル オリエンタル
會選擇這間的原因是原本愛用的地點竟然沒得租,接下來開始找才發覺事態不妙,
每一家都在漲價。丸忠漲到3800左右,從秋葉原還得搭車的話我乾脆住上野。
但是在上野找旅館的時候發現便宜的接近全滅... 不想讓旅費爆增的情況下,只剩下膠囊有空房。所以總之先訂了參戰的這幾天,之後的再想辦法。頂多每天住溫泉旅館!

大致上的狀況:
女性使用不可,在櫃台前就可以看到館內的人跑來跑去,當然也包含衣衫不整的人。
有悶騷屬性的,連入館都別想了吧XD

設施的狀況都有點年紀了。老舊有點生鏽,關不太起來還外帶鑰匙很難轉的櫃子,沒有免治CPP,膠囊內的電視櫃是之前的CRT時代的。裡面是改成LCD了啦...
看起來比較新的設施...自販機?

館內一定要換上質料有點糟的浴袍。
行李放在受付櫃台旁邊加上tag,只靠監視器錄影。
個人使用的櫃子只有半高,對於我這個還要放背包的人,放進去之後其他的東西就只能用擠的。貴重物品有另一個比較好的保險櫃,不過大小只能放放手錶皮夾飾品鈔票等等東西,還是免了。電梯只能用到2300,之後只能靠樓梯走,這個對腳不太好的人來說不太方便。

大浴場還算夠大(周圍一次可以容納20人左右的大小),0點過後基本上是一人獨占狀態。
可以好好泡澡是很重要的。尤其是對腳不好的人來說...

不能在膠囊內吃東西(正常),每一層樓都有個沙發區可以聊天休息吃東西。
室溫偏高,我想吹電風扇... 讓我最不爽的是有一群K國人半夜還在給我聊天。
參戰的這三天都沒睡好。相當痛苦...

這幾天晚上回旅館之後都在查其他旅館的資訊。
最後總算讓我找到了之後的住宿點。就留待之後再提吧。

2015年3月26日木曜日

[安藤]android studio的新專案架構:Gradle build system

當把手上的Android開發用潮到出水機升級成Yosemite之後,第一件事情就是發現ADT不能在native的環境下跑了。得裝jdk 的舊版本。
心想將近一年沒升級ADT,也該升級一下了。

上google官方的開發者首頁之後才想起來google在去年底推出Android Studio。
(這個時間點是1.1版)於是下載來更新。 應該會跟之前Eclipse改到ADT那樣的無痛吧?
但是把Project匯入之後,才發現事情完全不是如想像的那樣...

有一大堆東西要重新設定。好不容易整理完(光是這個整理的流程就又可以寫一篇)之後,視窗一直跳出提醒:

...Gradle? What!?
點了「More information...」出現了Gradle的user guide:
http://tools.android.com/tech-docs/new-build-system/user-guide

看了一下(英文不好,花了快近8小時看完),似乎是為了解決之前的舊系統要讓同一份code可以產生不同版本(免費跟付費版)可以比較方便。對於正在用同一份程式碼開發多版本的人來說還蠻方便的。
決定花一些時間來了解,順便轉移程式碼到此架構。不想一直被吵
就算是失敗了也還有之前已經轉移到Android studio的基礎可以繼續用。

花了時間啃完硬到不行的user guide,還是一知半解。
還是從空的project來了解最快。
總之開了一個空的計畫:

從檔案總管看到的檔案結構:

文件裡面提到,所有的操作描述全部都放在build.gradle這個檔案裡面。
總之打開project根目錄的build.gradle瞧瞧。

...哇靠,這是啥?一些文件裡面沒提到的指令,看不懂。
有個檔案:settings.gradle也蠻可疑的。總之打開來看看:
include ':app'
看來這檔案是拿來include 「app」用的。


這時又想起文件內的一句話:project設定的操作都可以使用Android studio的「Project structure」來做修改。意下就是不要自己手改檔案...

好吧。繼續從Android studio裡面觀察。
發現還有另一個build.gradle:「Module: app」裡面的。
旁邊寫著「Module:app」,所以「app」就是指Module嘍。
總之打開來看看:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 19
    buildToolsVersion "21.1.1"

    defaultConfig {
        applicationId "com.akazukin.chacha"
        minSdkVersion 15
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}


總算有不少文件裡面有提到的指令了。
先來找找要怎麼增加Module吧? 總之在Module「app」上面按右鍵:
喔,有指令可用。
總之加了一個Module 「chachalibrary」:
看來「Module」比較像舊系統的的「Project」。有自己的res/manifest。
那要怎麼設定Module 的關聯,讓Module可以include進來?
打開「Project Structure」:

選擇「Module depedency」:

然後會自動列出可以import的模組:

就加好了。也太簡單XD
順道一提,「Scope」的「Complie」是指這個project在make project的階段會被compile。provided的話聽說還沒有完整實作,建議不要用。

這時再回來看「app」的build.gradle,發現多了一行
「compile project(':chachalibrary')」

apply plugin: 'com.android.application'

android {
    compileSdkVersion 19
    buildToolsVersion "21.1.1"

    defaultConfig {
        applicationId "com.akazukin.chacha"
        minSdkVersion 15
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile project(':chachalibrary')
}


看來加模組的方式就是如法泡製,加在depedencies裡面就好。
假如要import的是已經編成jar的project的話,請直接copy jar檔擺在
app/libs 目錄裡面再加在depedencies裡面。
直接使用import project的方法,可能主程式碼會無法參照內部的class跟function。

import eclipse project成module的流程:

  • android studio的視窗menu->File->Import Module,選擇要import的模組(會自動copy所需檔案,不需要先copy進project裡面),一步步照系統給你的流程做完。
  • 修改project根目錄的settings.gradle,加上
    「include ':< module名稱>'」
  • 重啓android studio(因為不會refresh...)
  • 修改project root/< module名稱>/build.gradle(這個時候會因為buildToolsVersion指定的19版沒有安裝而沒出現在project裡面,請直接使用文字編輯程式編輯),調整compileSdkVersion/buildToolsVersion兩個參數,讓它跟app Module裡面的build.gradle參數相同。dependencies若是沒有「compile fileTree(dir: 'libs', include: ['*.jar'])」這一行的話就加上去。
  • 一樣在build.gradle裡面,defaultConfig至少要加這兩個參數,要不然可能無法被其他模組參照:
        {
            minSdkVersion 15
            targetSdkVersion 15
        }
  • AndroidManifest.xml若是有參數衝突的話,拿掉import進來的module裡面的AndroidManifest.xml的參數。
  • 在lib路徑有擺android support library的話,請刪除,改用系統提供的。(在project structure的dependencies裡面可以add library depedency,有android support library可以選。記住,每個有include的都要選一樣的版本,否則之後執行的時候會出「multiple dex files define landroid/support/annotation/AnimRes」的錯誤。)

注意這幾點應該就可以compile了。





繼續測試文件裡面還有提到的三個重要觀念:
sourceSet / buildtype / flavor。

buildtype:通常是debug/release兩種。
flavor:通常是拿來設定package name,package sign,切換resources目錄的設定用。
這樣就可以達到同一份程式碼只要更換package name跟簽名,連各個java檔的package class name都可以不用換就可以上google play。
sourceSet:從檔案結構的角度來看,就是src目錄下面的「main」「androidTest」這兩個目錄。但是打開目前所有的build.gradle檔案都沒提到這幾個關鍵字。
看來得自己做了。

依照Stackoverflow的高手的建議,先宣告flavor再宣告sourceSet。

sourceSets {
        main {
            manifest.srcFile 'src/main/AndroidManifest.xml'
            java.srcDirs = ['src/main/java']
            aidl.srcDirs = ['src/main/java']
            renderscript.srcDirs = ['src/main/java']
            res.srcDirs = ['src/main/res']
            assets.srcDirs = ['src/main/assets']
        }
    }


結果按下debug,發現跳出視窗警告「Error:AndroidManifest.xml doesn't exist or has incorrect root tag」... 暈了...Orz
強行點選Debug,點選「Continue Anyway」,
發現build完之後可以正常執行。看來是Android Studio的bug。看了這篇之後你就不會被嚇到了。XD

這時出現了一個疑問:那可不可以導入其他sourceSet目錄的檔案? 答案是可以的。
直接在MainActivity裡面直接宣告ApplicationTest class看看,以這時的狀態是會找不到class的。
但是把build.gradle做如下的修改:

sourceSets {
        main {
            manifest.srcFile 'src/main/AndroidManifest.xml'
            java.srcDirs = ['src/main/java', 'src/androidTest/java']
            aidl.srcDirs = ['src/main/java']
            renderscript.srcDirs = ['src/main/java']
            res.srcDirs = ['src/main/res']
            assets.srcDirs = ['src/main/assets']
        }
    }


會發現剛剛找不到class的問題不再發生了。這樣看起來sourceset是可以互相導入,而且只要有同樣的目錄結構的話,class也會擺在一起,成為連集。

那接下來就只剩一個問題:假如兩個sourceSet有相同檔案存在的時候,gradle會怎麼處理?
繼續做實驗:把MainActivity.java copy到src/androidTest/java/com/akazukin/chacha目錄,馬上被抱怨Duplicate class...
看來soruceset的宣告,使用逗號加目錄的話,會成為連集。不能重複檔案。
要讓gradle自動選檔看來是行不通。

有趣的是,直接做一個strings.xml在src/flavor1/res/values裡面,執行之後發現app會使用該stings.xml裡面的資源。看來sourceset的設計會自動apply?
所以又做了很多實驗,希望可以搞清楚檔案的使用規則。



總結關於sourceSets / buildType / flavor的結論:連集。是的。就這兩個字...
應用的方式跟流程:
main裡面放的是最基本的設定跟必須的程式碼。
若是有設定flavor的需求,也就是根據不同的flavor給不同的設定的話,以下為flavor的使用方式:
  • 不需要編輯build.gradle去增加sourceSet的設定區塊。照flavor的設定名稱,在src/main同一層增加同名的目錄即可。
  • 要在同樣的資源檔案(AndroidManifest/string/values等等)上面增加設定的話,檔案擺放的目錄結構必須跟main一模一樣。如圖:
  • AndroidManifest.xml:要是有兩個設定值同時存在,值卻不相同的時候,此檔案的處理結果會給error。
    因此若是有針對不同flavor而必須給不一樣的數值的時候(例如googleplay api key),必須參數化,從strings或是values裡面取。無法參數化的設定(例如gcm的permission)就放在各個flavor裡面,main裡面不要放。
  • res/values下面的資料是以resource name為單位,flavor的目錄裡面有定義的話就優先取用。例:flavor1 跟main同時有兩個相同的string name的話,會先取用flavor1所指定的值。
  • 其他的res是以resource file為單位,flavor的目錄裡面有定義的話優先取用。例:flavor1 跟main同時有兩個相同的layout file/drawable file的話,會取用flavor1裡面的layout file/drawable file。
到此總算是對這個系統有初步的認識了。
最後,要在不同的flavor之間切換編輯的對象的話,android studio主視窗的左下角的邊條有一個「build variants」,點擊之後會出現一個小框框,試著操作一下就知道該怎麼切換了。

其他一些遇到的狀況:

  • 若是有getMethod()等等reflect的使用需求的話,可能會需要跳過型態檢查。
    請在project根目錄的build.gradle裡面加上:
    allprojects {
        gradle.projectsEvaluated {
            tasks.withType(JavaCompile) {
                options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
            }
        }
    }
  • 執行時遇到com.android.dex.DexIndexOverflowException:在主project的build.gradle的defaultConfig裡面加上「multiDexEnabled true」。