星期六, 一月 21, 2012

Fedora 16 下換 GNOME3 Theme

一時無聊看到 ICS GNOME3 的 Theme 覺得很有趣想換一下,沒想到還有點麻煩。主要在於 Fedora 上面的 GNOME3 Theme Selector extension 有相容性問題沒辦法安裝。

解決的方法是只安裝 GNOME3 User Theme extension,然後再用 command line 修改 theme。

  1. 下載 GNOME3 的 Theme,並且放到 .themes 裡面,如果沒這個目錄就創建一個
  2. 安裝 user theme extension:
    # yum install gnome-shell-extension-user-theme.noarch
  3. 重開 gnome-shell,按下 alt + F2 輸入 r 按 enter
  4. 使用指令指定要使用的 theme:
    $ gsettings set org.gnome.shell.extensions.user-theme name "Ice Cream Sandwich"

這樣就可以切換到所指定的 theme 了。


這樣跟我的手機剛好搭成一套 :)

星期五, 十二月 30, 2011

客製化 ListView 產生 ScrollRunnable 互搶的問題解法

最近用了一個朋友寫的客製化的 ListView,主要的用途是作類似 iOS 上可以作 Pull down refresh 的功能。

但遇到了一個小問題困擾我很久。

因為 pull down 的 scrolling back to first item 的工作是由一個 ScrollRunnable 搭配 Scroller 實作的,這東西基本上平常運作都沒有問題,但是如果在 Scroll Fling 到最頂端的時候就會有 scroll 亂跳的問題。

深究 ListView/AbsListView 之後,發現其實 AbsListView 內有一個 mFlingRunnable 負責控制 Fling 動作發生時的捲動動作,而當使用另外一個  ScrollRunnable 去控制捲動的時候,會跟原本的 mFlingRunnable 的捲動互搶,造成捲動亂跳的問題。

知道原因了,要解決就很簡單吧?

錯了。

AbsListView 並沒有預留讓開發者存取 mFlingRunnable 的介面,拿不到 Runnable 就無法取消它。難道我要把整個 AbsListView, ListView 搬出來嗎 XDD

還好找到了一個不太好的 workaround。但是鑑於要把整個 AbsListView 移出來的成本太大,就將就著用了。答案是當使用 smoothScrollBy 系列的 method 的時候,AbsListView 將會自己移除 mFlingRunnable 的操作:


    public void smoothScrollBy(int distance, int duration) {
        if (mFlingRunnable == null) {
            mFlingRunnable = new FlingRunnable();
        } else {
            mFlingRunnable.endFling();
        }
        mFlingRunnable.startScroll(distance, duration);
    }

所以當你要操作自己的 ScrollRunnable 的時候,先執行 smoothScrollBy(0, 0) 就行了。因為參數都是 0 所以基本上 Fling 的動作就會取消了。

如果哪位看官有更好的解法請務必跟我說 :D

特別感謝 David Wu 跟我一起看了這個問題!

星期三, 十二月 14, 2011

Android 自製元件 - PrismFlipper

這幾天公司的 app 要作訂製的 notification bar,花了一點時間做出來,把他整理出來成一個小 view widget,這個 widget 主要是一個客製化的 notification bar,主要是想模擬三角稜柱翻動的樣子。跑起來大概像下面這樣:



使用方法也很簡單,用 flipper.showNext(text, reverse) 就可以使用了,下面附上比較完整的範例


final PrismFlipper flipper = (PrismFlipper)findViewById(R.id.viewFlipper1);
final String[] texts = new String[] { "Refresh", "go to last read position", "last read post" };
flipper.setFrontText(texts[0]);
flipper.setBackground(new ColorDrawable(0xff3465a4));
flipper.setTextColor(Color.WHITE);
Button btn = (Button)findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
   
 @Override
 public void onClick(View arg0) {
  flipper.showNext(texts[mPosition], false);
  mPosition = (mPosition + 1) % texts.length;
 }
});
        
btn = (Button)findViewById(R.id.button2);
btn.setOnClickListener(new OnClickListener() {
   
 @Override
 public void onClick(View arg0) {
  flipper.showNext(texts[mPosition], true);
  mPosition = (mPosition + 1) % texts.length;
 }
});

完整的範例可以在 github 上找到,授權是 BSD license。

星期一, 十月 17, 2011

Android 小技巧:找出未用的 Resource

記得好像有其他 Android 內建的方法可以哪些 resource 沒有被使用。一時找不到,Google 一下發現另外一套:Android Resource Tracker

使用方法也很簡單,在 project 目錄底下執行:
$ java -jar <PATH_TO_JAR>/AndroidUnusedResources1.4.jar

接著就會列出未被使用的資源:

Running in: /Users/yurenju/git/YOUR_PROJECT
242 resources found

44 unused resources were found:
array     : upload_photo_options
    /Users/yurenju/git/YOUR_PROJECT/res/values/arrays.xml
...

星期二, 十月 11, 2011

Eclipse 小技巧 - 同時設定多個 method breakpoint

有時候正在除錯剛寫好的 class 時,會需要針對 class 底下的所有 method 設定中斷點。不過一個一個設定實在太麻煩了,Eclipse 提供一個很貼心的功能,可以直接將多個 method 設定中斷點。

打開 Eclipse 找到列出所有 Method 的 Outline,用 Ctrl/Cmd 多選 Method 後,按右鍵選取 Toggle Method Breakpoint 即可。


星期四, 九月 22, 2011

Javascript client library 之 TDD

最近因緣際會在寫 web service 的 javascript client library,就趁著這個機會試試看 TDD (Test-Driven Development) 的方式來開發看看。

這次撰寫的 client library 因為是 javascript,所以就利用了 Javascript 常見的 event driven 的呼叫方式。原本打算用 jsunit 作為 unit test 的框架,但因為沒看到可以測試 callback 的 method,最後改用了 jquery 所使用的 qunit

qunit 在測試 callback 的方式大略如下:


test(
  'Login success test',

  function() {
    expect(1);
    stop();

    var service = new WebService();
    service.login(
      {
        username: 'user1@example.com',
        password: 'password'
      },
      function(res) {
        equal(res.response.status, "OK", 'expected login success');
        start();
      }
    );
  }
);
qunit 可以利用 stop() 停止整個 unit test 的進行,等到呼叫 start() 的時候再繼續執行。在這個測試中,qunit 會在 stop() 之後開始等待,等到呼叫到 callback method 裡面的 start() 之後才會繼續執行,這個時候就可以擷取到 equal() 所測試的結果。另外 expect() 可以指定預期會跑到的 assert 總共有幾個,在這個例子裡面只跑了一次 equal(),所以是 expect(1)。 當所有 test case 完成後,跑 qunit 的結果大略如下:


因為根本就還沒開始寫 client library,當然所有測試結果都是 failed。但在這個時候就已經得知 javascript client library 要如何使用以及有哪些回傳值了。這樣其實可以在早期的時候就可以看到整個 client library 的面貌。

而且看著 test case 一個一個的通過心中真是有莫名的快感阿。寫完之後就變成這樣:



使用 TDD 方法開發確實讓整個開發的過程踏實不少。不過這種開發方式還是比較適合實作函式庫,如果撰寫 UI 的話就沒有那麼適合了。

不過大家還是可以玩一下,蠻有收穫的 :)

星期六, 九月 10, 2011

Jenkins 系列 (1): 在終端機下設定 Android 模擬器

命題的有點怪,不過基本上這是篇為了在 Jenkins 進行 unit test 以及 daily build 的前置動作。當在建立 Continuous Integration 的測試系統時,我希望可以在一台獨立的機器進行測試。而在遠端的伺服器不一定有 X Window 的狀況,這個時候就會需要在終端機上設定 Android Eumlator 環境。

首先是下載並且解壓縮 Android SDK

$ wget http://dl.google.com/android/android-sdk_r12-linux_x86.tgz
$ tar zxvf android-sdk_r12-linux_x86.tgz

切換到 android-sdk-linux_x86/tools,並且用 --no-ui 選項來安裝 Android 3.2/2.3 或其他平台相關的 Platform SDK


$ cd android-sdk-linux_x86/tool
$ ./android update sdk --no-ui

這個時候會從最新的平台(如 Android 3.2)開始下載安裝,一路從最新的下載到最舊的 SDK。我是在下載完 Android 2.2 的 Platform SDK 就按 Ctrl + C 終止安裝。

編輯家目錄的 ~/.bash_profile,加入執行路徑:

PATH="$PATH:~/android-sdk-linux_x86/tools:~/android-sdk-linux_x86/platform-tools

安裝完 platform SDK 之後,可以利用下面的指令看到安裝了哪些 platform SDK:

$ android list target

輸出大略如下:

id: 4 or "android-8"
     Name: Android 2.2
     Type: Platform
     API level: 8
     Revision: 3
     Skins: QVGA, WVGA854, WQVGA432, HVGA, WVGA800 (default), WQVGA400
id: 5 or "android-9"
     Name: Android 2.3.1
     Type: Platform
     API level: 9
     Revision: 2
     Skins: QVGA, WVGA854, WQVGA432, HVGA, WVGA800 (default), WQVGA400
id: 6 or "android-10"
     Name: Android 2.3.3
     Type: Platform
     API level: 10
     Revision: 2
     Skins: QVGA, WVGA854, WQVGA432, HVGA, WVGA800 (default), WQVGA400


用下面的指令就可以建立新的 Android 2.3.3 模擬器環境

$ android create avd --name android-2.3 --target android-10

這個時候就可以用不跑模擬器畫面的方式啟動 Android 模擬環境:

$ emulator-arm -avd android-2.3 -no-window
想知道運行狀況,可以利用 adb logcat 瞭解。

星期六, 八月 27, 2011

jsmodem - 讓 jslinux 使用網路功能

前陣子有個很有趣的 project - jslinux,這個專案主要是在瀏覽器上面模擬 x86 電腦,再將 Linux 跑在瀏覽器上面。等於說這個專案簡單實作了 PC 模擬器,就如同 VMWare, VirtualBox 一樣,但是在瀏覽器上就可以跑模擬器上面的 OS 了。甚至在上面還包含了一個 C compiler,可以在上面編譯程式。


星期六, 八月 06, 2011

Mocking Bird - node.js REST API simulation (1)

當團隊決定開發一個使用 web service 的 mobile app 時,我們遇到了一個小問題:mobile app 跟 web service 是同時開發的,當 web service 還沒實作完畢前,mobile app developer 只能暫時先從規格中 implement 跟 web service 銜接的介面。

這聽起來有點瞎子摸象。

不過 Jamie Sa 提供了個有趣的點子:如果我們可以寫個模擬的 REST API service,並且透過 YAML 定義簡單的規格的話,我們就可以利用這個模擬 REST API 比較真實的跟 web service 銜接了 :)


星期六, 六月 25, 2011

Python and GObject-Introspection 簡報

2011/6/25 在 PycTW 2011 講了 Python and GObject-Introspection,主要講 GObject-Introspection 的原理還有簡單的介紹 python-gobject 如何實作 GObject-Introspection。投影片如下: