2012年5月8日 星期二

讓 Ubuntu 12.04 的 ibus 倉頡五代輸入法預設使用繁體語系

日前安裝了 Ubuntu 12.04 後,在使用 ibus 裡的「倉頡五代輸入法」打字時發現似乎預設採用了簡體語系。於是爬文找了一下,原來這狀況在之前的版本裡已經存在了,便參考了這篇文章修改一下。

修改方法不難,使用任何一個編輯器開啟 /usr/share/ibus-table/engine/table.py 這個檔案,然後找到第 96 行到第 129 行這段:

  96         # self._chinese_mode: the candidate filter mode,
  97      #   0 is simplify Chinese
  98      #   1 is traditional Chinese
  99      #   2 is Big charset mode, but simplify Chinese first
 100      #   3 is Big charset mode, but traditional Chinese first
 101      #   4 is Big charset mode.
 102      # we use LC_CTYPE or LANG to determine which one to use
 103      self._chinese_mode = self._config.get_value (
 104              self._config_section,
 105              "ChineseMode",
 106              self.get_chinese_mode())
 107
 108  def get_chinese_mode (self):
 109      '''Use LC_CTYPE in your box to determine the _chinese_mode'''
 110      try:
 111          if os.environ.has_key('LC_CTYPE'):
 112              __lc = os.environ['LC_CTYPE'].split('.')[0].lower()
 113          else:
 114              __lc = os.environ['LANG'].split('.')[0].lower()
 115
 116          if __lc.find('_cn') != -1:
 117              return 0
 118          # hk and tw is should use tc as default
 119          elif __lc.find('_hk') != -1 or __lc.find('_tw') != -1\
 120                  or __lc.find('_mo') != -1:
 121              return 1
 122          else:
 123              if self.db._is_chinese:
 124                  # if IME declare as Chinese IME
 125                  return 1
 126              else:
 127                  return -1
 128      except:
 129          return -1 

get_chinese_mode 裡會依 locale 的 LC_CTYPE 來判斷,但由於我將 LC_CTYPE 設定成 en_US.UTF-8,原本在第 125 行就會返回 0 這個值,但依據第 96 行到第 101 行的註解,當返回 0 時則採用簡體中文語系。

所以,修改方式就是將第 125 行的返回值改成 1,這麼一來就可以直接使它使用繁體中文語系了。

2012年4月18日 星期三

Configuring USB Access under GNU/Linux

根據 http://source.android.com/source/initializing.html 這個網頁的說明,在 GNU/Linux 下只要設定好 /etc/udev/rules.d/51-android.rules 這個檔案,就可使用 ADB 工具連接 Android 手機了。同時,在網頁上也提供了一個範例:

# adb protocol on passion (Nexus One)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e12", MODE="0600", OWNER="<username>"
# fastboot protocol on passion (Nexus One)
SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", ATTR{idProduct}=="0fff", MODE="0600", OWNER="<username>"
# adb protocol on crespo/crespo4g (Nexus S)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e22", MODE="0600", OWNER="<username>"
# fastboot protocol on crespo/crespo4g (Nexus S)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e20", MODE="0600", OWNER="<username>"
# adb protocol on stingray/wingray (Xoom)
SUBSYSTEM=="usb", ATTR{idVendor}=="22b8", ATTR{idProduct}=="70a9", MODE="0600", OWNER="<username>"
# fastboot protocol on stingray/wingray (Xoom)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="708c", MODE="0600", OWNER="<username>"
# adb protocol on maguro/toro (Galaxy Nexus)
SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", ATTR{idProduct}=="6860", MODE="0600", OWNER="<username>"
# fastboot protocol on maguro/toro (Galaxy Nexus)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e30", MODE="0600", OWNER="<username>"
# adb protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d101", MODE="0600", OWNER="<username>"
# fastboot protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d022", MODE="0600", OWNER="<username>"
# usbboot protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d010", MODE="0600", OWNER="<username>" 

於是,我便拿自己的 Nexus One 來試了一下。

因為我將 Nexus One 接在筆電上,並啟用讓筆電透過 3G 上網,因此執行 lsusb 查看 Vendor ID 及 Product ID 時顯示如下:

Bus 001 Device 008: ID 18d1:4e14 Google Inc.  

所以,我將 cat /etc/udev/rules.d/51-android.rules 這個檔案改成如下:

# adb protocol on passion (Nexus One)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e12", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e14", MODE="0666"
# fastboot protocol on passion (Nexus One)
SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", ATTR{idProduct}=="0fff", MODE="0666"
# adb protocol on crespo/crespo4g (Nexus S)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e22", MODE="0666"
# fastboot protocol on crespo/crespo4g (Nexus S)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e20", MODE="0666"
# adb protocol on stingray/wingray (Xoom)
SUBSYSTEM=="usb", ATTR{idVendor}=="22b8", ATTR{idProduct}=="70a9", MODE="0666"
# fastboot protocol on stingray/wingray (Xoom)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="708c", MODE="0666"
# adb protocol on maguro/toro (Galaxy Nexus)
SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", ATTR{idProduct}=="6860", MODE="0666"
# fastboot protocol on maguro/toro (Galaxy Nexus)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e30", MODE="0666"
# adb protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d101", MODE="0666"
# fastboot protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d022", MODE="0666"
# usbboot protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d010", MODE="0666" 

存檔後,我將手機重新連接到筆電上,並重新載入 GNU/Linux 的 udev,也真的可以透過 ADB 工具連接到手機耶!

sudo service udev restart
sudo killall adb
adb devices 

以下是執行 adb devcies 後的訊息:

* daemon not running. starting it now on port 5037 *
* daemon started successfully *
List of devices attached 
HT02Rxxxxxxx device 

延伸閱讀:

2012年4月8日 星期日

Build Android Gingerbread with GCC 4.6

這兩天將 Debian 升級到 testing 版本後,沒想到編譯 Android 2.3 (Gingerbread) 時卻遇到了這樣的錯誤訊息:
host C++: libutils <= frameworks/base/libs/utils/RefBase.cpp
frameworks/base/libs/utils/RefBase.cpp: In member function ‘void android::RefBase::weakref_type::trackMe(bool, bool)’:
frameworks/base/libs/utils/RefBase.cpp:483:67: error: passing ‘const android::RefBase::weakref_impl’ as ‘this’ argument of ‘void android::RefBase::weakref_impl::trackMe(bool, bool)’ discards qualifiers [-fpermissive]
host C++: libutils <= frameworks/base/libs/utils/ResourceTypes.cpp
make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libutils_intermediates/RefBase.o] Error 1
make: *** Waiting for unfinished jobs....
frameworks/base/libs/utils/ResourceTypes.cpp: In member function ‘void android::ResTable::print(bool) const’:
frameworks/base/libs/utils/ResourceTypes.cpp:4369:84: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
frameworks/base/libs/utils/ResourceTypes.cpp:4375:43: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
這是由於 GCC 也一併升級為 4.6 版引起的,在用了下面這個 patch 後就搞定了:
diff -Naur old/frameworks/base/libs/utils/Android.mk new/frameworks/base/libs/utils/Android.mk
--- old/frameworks/base/libs/utils/Android.mk 2011-05-05 09:42:48.000000000 +0000
+++ new/frameworks/base/libs/utils/Android.mk 2012-04-07 15:45:40.738996228 +0000
@@ -57,7 +57,7 @@
 
 LOCAL_MODULE:= libutils
 
-LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS)
+LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS) -fpermissive
 LOCAL_C_INCLUDES += external/zlib
 
 ifeq ($(HOST_OS),windows)
延伸閱讀:

2011年6月27日 星期一

如此惡搞軟體市集,究竟是誰能得利呢?

這陣子鬧得最熱門的大概是台北市政府要求 Google 和 Apple 兩大軟體市集提供「七天鑑賞期」這回事吧!

先來看看台北市政府發出來的幾篇新聞稿吧!

而 Google 最新的回應則是「乾脆將台灣 Android Market 的付費軟體下架、停掉付費軟體下載服務」。(REF: 驚!GOOGLE全面停止台灣Android Market銷售App服務)

不過,各位網友可以仔細讀完以下這幾篇文章:

1. Google下架軟體、北市罰重金對槓,誰來回應消費者與開發者?

2. 消保法的過時與不完整 - App七天內可退錢,那電子書,音樂,電影也都可以看完再退囉

3. 問題在哪? 看蘋果、Google付費退費模式

在上述的文章裡提到,在 96 年 1 月提出來的消保法條文修正草案裡,已明確增列第十九條的「七天鑑賞期」排除了小額交易物品、報紙、期刊、雜誌和業經消費者啟封之影音產品或電腦軟體數項。而且在草案裡的說明也明確寫著:

「二、為適度平衡消費者與企業經營者之利益,並避免消費者濫用權力之道德風險產生,爰參酌歐盟遠距契約消費者保護指令,於第二項以負面表列之方式增列消費者就某些特定之交易客體無七日內不附理由解除契約之權利。」

但……現在已經是 100 年 6 月了,距草案提出來已經四年五個月了,它似乎還不知道被擱置在那個角落。台北市政府不去向有關單位反應為什麼這草案仍舊被攔置,卻反過來依據著過期的法條來惡搞軟體市集,確實是有點莫名其妙。

2011年1月21日 星期五

在 32 位元的 Ubuntu 編譯 Android 2.3 (Gingerbread)

前陣子 Google 公佈了 Android 2.3 (Gingerbread) 的原始碼後,相信也有不少人開始試著將它移植到自己手邊的一些板子上。

這幾天下載了 Gingerbread 的原始碼,也試著先在 Ubuntu 9.04 上編譯看看,但卻得到以下這個訊息:

Only 64-bit build environments are supported beyond froyo/2.2

呀!於是我裝了個 64 位元的 Ubuntu 10.10,並試著編譯確認下載的原始碼可以成功被編譯。這兩天試著翻找了一下,稍微修改了幾個地方,並且確認在 32 位元的 Ubuntu 10.04 可以編譯成功。

所以,如果要在 32 位元的 Ubuntu 編譯 Gingerbread,大概要修改的地方如下:

diff -Nur old/build/core/main.mk new/build/core/main.mk --- old/build/core/main.mk 2011-01-21 01:56:42.336200023 +0800
+++ new/build/core/main.mk 2011-01-21 02:00:23.515155033 +0800
@@ -72,10 +72,11 @@

ifeq ($(BUILD_OS),linux)
build_arch := $(shell uname -m)
-ifneq (64,$(findstring 64,$(build_arch)))
+ifneq (i686,$(findstring i686,$(build_arch)))
$(warning ************************************************************)
-$(warning You are attempting to build on a 32-bit system.)
+$(warning You are attempting to build on a 64-bit system.)
$(warning Only 64-bit build environments are supported beyond froyo/2.2.)
+$(warning But I still try to build on a 32-bit system.)
$(warning ************************************************************)
$(error stop)
endif
diff -Nur old/external/wpa_supplicant_6/wpa_supplicant/Android.mk new/external/wpa_supplicant_6/wpa_supplicant/Android.mk
--- old/external/wpa_supplicant_6/wpa_supplicant/Android.mk 2011-01-21 10:42:27.403764488 +0800
+++ new/external/wpa_supplicant_6/wpa_supplicant/Android.mk 2011-01-21 10:42:59.167242863 +0800
@@ -249,9 +249,9 @@
endif

ifdef CONFIG_DRIVER_PS3
-L_CFLAGS += -DCONFIG_DRIVER_PS3 -m64
+L_CFLAGS += -DCONFIG_DRIVER_PS3 -m32
OBJS_d += src/drivers/driver_ps3.c
-LDFLAGS += -m64
+LDFLAGS += -m32
endif

ifdef CONFIG_DRIVER_IPHONE
diff -Nur old/external/clearsilver/java-jni/Android.mk new/external/clearsilver/java-jni/Android.mk
--- old/external/clearsilver/java-jni/Android.mk 2011-01-21 10:43:06.469155531 +0800
+++ new/external/clearsilver/java-jni/Android.mk 2011-01-21 10:45:43.911803822 +0800
@@ -33,9 +33,9 @@

LOCAL_CFLAGS += -fPIC

-# This forces a 64-bit build for Java6
-LOCAL_CFLAGS += -m64
-LOCAL_LDFLAGS += -m64
+# This forces a 32-bit build for Java6
+LOCAL_CFLAGS += -m32
+LOCAL_LDFLAGS += -m32

LOCAL_NO_DEFAULT_COMPILER_FLAGS := true

diff -Nur old/external/clearsilver/cs/Android.mk new/external/clearsilver/cs/Android.mk
--- old/external/clearsilver/cs/Android.mk 2011-01-21 10:43:39.529054212 +0800
+++ new/external/clearsilver/cs/Android.mk 2011-01-21 10:45:55.135643624 +0800
@@ -8,9 +8,9 @@

LOCAL_CFLAGS := -fPIC

-# This forces a 64-bit build for Java6
-LOCAL_CFLAGS += -m64
-LOCAL_LDFLAGS += -m64
+# This forces a 32-bit build for Java6
+LOCAL_CFLAGS += -m32
+LOCAL_LDFLAGS += -m32

LOCAL_NO_DEFAULT_COMPILER_FLAGS := true

diff -Nur old/external/clearsilver/cgi/Android.mk new/external/clearsilver/cgi/Android.mk
--- old/external/clearsilver/cgi/Android.mk 2011-01-21 10:44:21.118879155 +0800
+++ new/external/clearsilver/cgi/Android.mk 2011-01-21 10:46:16.683115540 +0800
@@ -12,9 +12,9 @@

LOCAL_CFLAGS := -fPIC

-# This forces a 64-bit build for Java6
-LOCAL_CFLAGS += -m64
-LOCAL_LDFLAGS += -m64
+# This forces a 32-bit build for Java6
+LOCAL_CFLAGS += -m32
+LOCAL_LDFLAGS += -m32

LOCAL_NO_DEFAULT_COMPILER_FLAGS := true

diff -Nur old/external/clearsilver/util/Android.mk new/external/clearsilver/util/Android.mk
--- old/external/clearsilver/util/Android.mk 2011-01-21 10:44:55.704170280 +0800
+++ new/external/clearsilver/util/Android.mk 2011-01-21 10:46:28.487643813 +0800
@@ -17,9 +17,9 @@
LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
LOCAL_CFLAGS := -fPIC

-# This forces a 64-bit build for Java6
-LOCAL_CFLAGS += -m64
-LOCAL_LDFLAGS += -m64
+# This forces a 32-bit build for Java6
+LOCAL_CFLAGS += -m32
+LOCAL_LDFLAGS += -m32

LOCAL_NO_DEFAULT_COMPILER_FLAGS := true

2010年10月16日 星期六

How to Use ADB over TCP/IP?

對於 Android 的開發,Android Debug Bridge (ADB) 是一個相當實用的工具。再且多數的 ARM 開發板都具有乙太網路介面,若透過 TCP/IP 來使用 ADB 其實是相當容易的。

首先,假設將電腦和 ARM 開發板直接用網路線連接起來,將電腦的 IP 位址設定為 192.168.1.200,而 ARM 開發板則設為 192.168.1.202。

那麼,在 ARM 開發板這端需要指定 service.adb.tcp.port 這個變數,並重啟 adbd (ADB Daemon)。

stop adbd
setprop service.adb.tcp.port 5555
start adbd

在電腦端,確認 Android SDK 裡的 adb 版本至少為 1.0.25 或更新版本後,開啟一個 DOS 終端,然後利用 adb connect [IP]:[PORT] 連接 ADB Daemon。

adb kill-server
adb connect 192.168.1.202:5555

這樣就 OK 了。

所以,如果在移植 Android 時,加上這個 patch,在使用就稍微方便些了。

diff -Naur old/system/core/rootdir/etc/init.goldfish.sh new/system/core/rootdir/etc/init.goldfish.sh
--- old/system/core/rootdir/etc/init.goldfish.sh 2010-09-09 02:24:32.318070299 +0000
+++ new/system/core/rootdir/etc/init.goldfish.sh 2010-09-09 02:26:18.598160293 +0000
@@ -1,7 +1,10 @@
#!/system/bin/sh

-#ifconfig eth0 10.0.2.15 netmask 255.255.255.0 up
-#route add default gw 10.0.2.2 dev eth0
+ifconfig eth0 192.168.1.202 netmask 255.255.255.0 up
+route add default gw 192.168.1.1 dev eth0

diff -Naur old/system/core/rootdir/init.rc new/system/core/rootdir/init.rc
--- old/system/core/rootdir/init.rc 2010-09-09 02:22:45.189174370 +0000
+++ new/system/core/rootdir/init.rc 2010-09-09 02:23:15.899741002 +0000
@@ -270,9 +270,11 @@

# adbd on at boot in emulator
on property:ro.kernel.qemu=1
+ setprop service.adb.tcp.port 5555
start adbd

on property:persist.service.adb.enable=1
+ setprop service.adb.tcp.port 5555
start adbd

on property:persist.service.adb.enable=0

此外,若再從 system/core/adb/adb.c 這個檔案第 921 行處的程式碼來看,大約就更可以瞭解為什麼設定 service.adb.tcp.port 之後就可以由 TCP/IP 使用 ADB 了。

    /* for the device, start the usb transport if the
** android usb device exists and the "service.adb.tcp.port" and
** "persist.adb.tcp.port" properties are not set.
** Otherwise start the network transport.
*/
property_get("service.adb.tcp.port", value, "");
if (!value[0])
property_get("persist.adb.tcp.port", value, "");
if (sscanf(value, "%d", &port) == 1 && port > 0) {
// listen on TCP port specified by service.adb.tcp.port property
local_init(port);
} else if (access("/dev/android_adb", F_OK) == 0) {
// listen on USB
usb_init();
} else {
// listen on default port
local_init(ADB_LOCAL_TRANSPORT_PORT);
}

延伸閱讀: