Sean's Note: 2013

2013年12月6日 星期五

Using Prototype in JavaScript

用 JavaScript 所建立的物件都繼承了 Object 這個最頂層的物件,

而 Object 物件含有 prototype 這個屬性(Property) 。
 
var myObject = {} // 等同於 var myObject = new Object()
 
沒用到 prototype 時,每個實體(killerRabbit 和 cuteRabbit) 都擁有各自的 name 屬性,

卻沒有共同的屬性:

    
function Rabbit(name) {
  this.name = name
}

var killerRabbit = new Rabbit("killer");
var cuteRabbit = new Rabbit("cute");

所以如果這兩隻兔子想要共用屬性時,prototype 就可以派上用場:

function Rabbit(name) {
  this.name = name
}
Rabbit.prototype.printName = function(){
    print('My name is: ', this.name)
};

由於 Rabbit 有 prototype,Object 又有 prototype,那尋訪的順序是? 看看下面的例子:
Object.prototype.teeth = "normal";
function Rabbit() {
  this.teeth = 'big'
}
Rabbit.prototype.teeth = "small";
var killerRabbit = new Rabbit("killer");
print(Rabbit.prototype.teeth)        // small
print(Rabbit.teeth)                  // normal
print(killerRabbit.teeth)            // big
print(killerRabbit.prototype.teeth)  // Exception: TypeError: Cannot read property 'teeth' of undefined

當查看一個物件的屬性時,JavaScript 會:
  1. 先看該物件實體(this) 有無該屬性。
  2. 在看該物件的 prototype 物件有無該屬性。
  3. 最後看 Object 物件的 prototype 物件有無該屬性,沒有的話則給予 undefined。

參考資料:http://eloquentjavascript.net/chapter8.html

2013年12月5日 星期四

Set ADB in TCP/IP mode

今天又多學了一招用網路而不是 USB 來對 Android 的裝置 debug,

網路的部分可以使用 WiFi 或 Ethernet,只要對 ADB 下幾行指令即可:

Step1: 指定 ADB 要聆聽哪個 port
(得先接上 USB,否則會有 error: device not found 的訊息)

> adb tcpip 5555
restarting in TCP mode port: 5555

Step2: 指定 ADB 連接到哪個 IP 位址,從裝置的 Setting 裡可以查到
> adb connect 192.168.x.x:5555
connected to 192.168.x.x:5555

Step3: 想改回 USB 時
> adb usb
restarting in USB mode

2013年11月20日 星期三

[Python] 前綴字 _ 和 __ 的差別

一個底線 _

def _getName(self):
    ...

name = property(_getName)

代表 _getName 是 private function,不應該被外部呼叫,常常應用於 property 中

,然而在 Python 中,並沒有真的 private function,所以應該說是撰寫上的慣例。

兩個底線 __

class A():

    def __getName(self):
        ....

a = A()
a.__getName # Wrong!!
a._A__getName # OK, but not doing this!

代表 __getName 不允許被 override,而且也不能被外部呼叫。

Python 的實作方式其實就是在方法前加上類別名稱 -> _A__getName。

Ref: http://igorsobreira.com/2010/09/16/difference-between-one-underline-and-two-underlines-in-python.html

2013年10月24日 星期四

The Performance of Sony MicroVault Click USB3.0

最近續約中華電信,獲得了一萬點歡樂點,換算成台幣約六百塊,

所以就在網站上挑了個市價約 NT.590 的 Sony USB 3.0。

Sony MicroVault Click USB3.0
拿到後馬上格式化成 NTFS 16K,再用 CrystalDiskMark 3.0.2f 來跑跑看效能,

先接上 USB2.0 的孔,看看和一般的 USB 有何不同:

沒有特別驚人,但還算是個還不錯的 USB2.0

再換 USB3.0 的孔試試,應該會很威吧?

...

結果跑到一半就給我跳出了這樣的訊息...

0x00000003EE

該不會拿到了有問題的 USB 吧!!

趕緊用 Flash Drive Tester v1.14 測試,結果也顯示隨身碟狀況良好。

再換 ATTO 試試看,也可以正常測完,不曉得到底是 CrystalDiskMark 的問題

還是 USB 的問題 @@

不過實際寫檔讀檔也沒啥問題,所以就不管了。 

ATTO Disk Benchmark

結論是 Sony MicroVault Click USB3.0 的 Read 還算是中上的水準,

而 Write 算是頗爛的,跟 USB 2.0 根本沒差多少!! (不是太推薦)

2013年10月18日 星期五

Windows Messsage: Clicking mouse button will also trigger mouse down event.

用 Microsoft Spy++ 攔了一下滑鼠相關的 messages,

發現原來只按滑鼠左鍵一樣也會觸發 WM_MOUSEMOVE 。

WM_SETCURSOR
WM_SETCURSOR
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_SETCURSOR
WM_SETCURSOR
WM_MOUSEMOVE

2013年10月3日 星期四

Symbols and Symbol Files

當程式做完連結 (link) 後,連結器 (Linker) 除了產生 .exe 和 .dll 檔之外,也會額外產生

symbol 檔。symbol 檔包含了執行程式時所不需要的資料,但在除錯上就極為有用:

  • 全域變數
  • 區域變數
  • 函式的名稱還有進入點的位址
  • Frame pointer omission (FPO) 的紀錄
  • 原始碼的行號

這些每一個項目都稱為 symbol,所以一個 symbol 檔會包含有很多 symbols,

symbol 檔的副檔名為 .pdb 或 .dbg,Visual C++ 6.0 Linker 之後只會產生 .pdb。


Ref: http://msdn.microsoft.com/en-us/library/windows/hardware/ff558825(v=vs.85).aspx

2013年10月2日 星期三

Debug Android source code in Eclipse

在 Attach 時選擇 source 的資料夾:

C:\Program Files\Android\android-sdk\sources\android-14

此外,會發現不能用滑鼠右鍵的方式對 Android 原始碼的 private function 下斷點(Break point),

到 Run -> Toggle Line Breakpoint,即可強制下斷點。

Ref: https://www.assembla.com/spaces/scala-ide/tickets/3271#/activity/ticket:

2013年9月30日 星期一

Symbol path for Windows debuggers

一般指定本地端的 symbol 檔路徑的指令如下,
.sympath c:\MySymbols
而 Debugger 查詢 symbol 檔的順序為:
  1. c:\MySymbols\symbols\dll
  2. c:\MySymbols\dll
  3. c:\MySymbols
  4. Current Directory
  5. Current Directory\dll

如果電腦有連接網路最有效率的方法就是直接連 Symbol Server,

srv*symbolstore

Microsoft's symbol store:

.sympath srv*http://msdl.microsoft.com/download/symbols

建議加上 Cahce:

.sympath cache*;srv*http://msdl.microsoft.com/download/symbols

cache* 是指把 symbol 檔存到 default 的本地端,下次就不用載一次。

2013年9月16日 星期一

About AsyncTask

AsyncTask 隨著 Android SDK 的更新,也改變了幾次設定。在 Android 1.5(CUPCAKE) 中,
AsyncTask 是 Single Thread,一個 task 接著一個 task 執行;從 Android 1.6(DONUT) 一直到
Android 2.3(GINGERBREAD),AsyncTask 變成了 Multi-Thread,當 tasks 剛好等於 5 個時,
最多就可以同時執行 5 個 threads (CORE_POOL_SIZE=5) 來完成 tasks,如果又多 1 個 task,
就會放到 queue 裡,這個 queue 的大小為 10,直到 queue 放不下時,才會在建立一個 thread
來處理新進的 task,最多可有 128 (MAXIMUM_POOL_SIZE) 個 threads 同時處理 tasks,而
tasks 最多可有 128+10=138 個,超過時會發生 java.util.concurrent.RejectedExecutionException
以上所提到的定義值,可在 AsyncTask.java 的原始碼中看到:
    // Source code of Android 4.2.1 r.1.2
    public abstract class AsyncTask <Params, Progress, Result> {
    private static final String LOG_TAG = "AsyncTask";

    private static final int CORE_POOL_SIZE = 5;
    private static final int MAXIMUM_POOL_SIZE = 128;
    private static final int KEEP_ALIVE = 1;
    ...

    private static final BlockingQueue<runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<runnable>(10);

    ...
Android 4.4 之後,CORE_POOL_SIZE 改為 CPU_COUNT+1,MAXIMUM_POOL_SIZE 改為 CPU_COUNT*2+1,queue 的大小改為 128,所以 threads 變少了(猜想應該是為了效能的關係),queue 變大了。
    // Source code of Android 4.4 r1 
    // http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/android/os/AsyncTask.java#AsyncTask 
    public abstract class AsyncTask <Params, Progress, Result> {
    private static final String LOG_TAG = "AsyncTask";

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE = 1;
    ...

    private static final BlockingQueue<runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<runnable>(128);

    ...

從 Android 3.0(HONEYCOMB) 之後又改回了 Single Thread。Single Thread 版本的 tasks 最多
大小則取決於記憶體,因為是使用 ArrayDeque 來存放 tasks:

private static class SerialExecutor implements Executor {
    final ArrayDeque<runnable> mTasks = new ArrayDeque<runnable>();
    Runnable mActive;

    public synchronized void execute(final Runnable r) {
        mTasks.offer(new Runnable() {
        ...

另外,想要使用之前 Multi-Thread 的版本就要呼叫
executeOnExecutor(THREAD_POOL_EXECUTOR, Object []),而不是原本的 execute。

參考資料:
  1. http://developer.android.com/reference/android/os/AsyncTask.html
  2. http://blog.csdn.net/hitlion2008/article/details/7983449
  3. http://stackoverflow.com/questions/4068984/running-multiple-asynctasks-at-the-same-time-not-possible
  4. http://stackoverflow.com/questions/10480599/how-asynctask-works-in-android

2013年8月29日 星期四

Something about Fonts

  1. 不是所有的 Font 都支援所有的 Languages,所以在 Windows 的 Registry:
    HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink
    便定義了對照表,譬如在打中文字時若套用 MS UI Gothic 字型,便會選擇 MINGLIU.TTC 也就是常見的
    新細明體來顯示。
  2. FontLink\SystemLink\MS UI Gothic
  3. 欲查詢某個 Language 有哪些 Font 有支援,可參考下列網站:
    http://www.alanwood.net/unicode/fontsbyrange.html
  4. 更多有關 Font Linking 的說明,可參考 MSDN 網站:
    http://msdn.microsoft.com/en-us/goglobal/bb688134.aspx

2013年8月16日 星期五

About BitmapFactory.Option.inSampleSize

本以為這個數字可以隨便設,後來看了一下官方寫的文件後才發現,

這個設定只有 2 的冪次方效果, 也就是圖片 down-sapling 完不會有 1/3 或 1/5

的效果。 因為設其他數值,底下也是會取接近 2 的冪次方來做運算。 

例如: 設 3,底層實際取 2 做運算;設 4, 5, 6, 7 ,實際皆取 4 做運算。

If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory. 
The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded bitmap. 
For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16 the number of pixels. 
Any value <= 1 is treated the same as 1. 
Note: the decoder uses a final value based on powers of 2, any other value will be rounded down to the nearest power of 2.
資料來源: 官方網站

仔細看了一下 skia library 的原始檔 SkImageDecoder_libjpeg.cpp,發現 Android 也是

用 IJG 的 JPEG Lib 去做 down-sapling:

bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, SkBitmap::Config prefConfig, Mode mode)
{
    ...
    jpeg_decompress_struct cinfo;
    cinfo.scale_denom = sampleSize;
    ...
}

Google 了一下 scale_denom 的說明,文件上也說明的相當清楚了。

unsigned int scale_num, scale_denom Scale the image by the fraction scale_num/scale_denom. Default is 1/1, or no scaling. 
Currently, the only supported scaling ratios are 1/1, 1/2, 1/4, and 1/8. (The library design allows for arbitrary scaling ratios but 
this is not likely to be implemented any time soon.) Smaller scaling ratios permit significantly faster decoding since fewer 
pixels need be processed and a simpler IDCT method can be used.
資料來源: 網站

2013年8月14日 星期三

"Java SE7 技術手冊" 讀後筆記

CH3 基礎與法

  1. 如果運算式中包括不同型態數值,則運算時以長度最長的型態為主,其他數值自動提昇 (Promote) 型態。
  2. 如果運算元都是不大於 int 的整數,則自動提升為 int 型態進行運算。
    所以下方的例子將編譯失敗 (Type mismatch: cannot convert from int to short) :
    short a = 2;
    short b = 3;
    short c = a + b; // Sol: short c = (short)a + b;
    

CH4 認識物件

  1. Integer 實際上是使用 Integer.valueof() 來建立 Integer 實例,所以看看 Integer.java (可在 JDK 資料夾 src.zip 中的 java/lang
    底下找到) ,會發現其在 -128 ~ 127 間有 cache 的機制。
    public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
    }
  2. 使用 + 串接字串會產生新的 String 實例,所以不要將 + 用在重複性的串接場合,可用 StringBuilder (Note: 適用於 single thread,multithread 則用 StringBuffer) 來改善效能。

CH5 物件封裝

  1. 如果沒有宣告權限修飾的成員,只有在相同套件的類別中,才可以直接存取,也就是"套件範圍權限"。

CH7 介面與多型

  1. interface 的方法只能宣告為 public abstract (也可省略不寫),無須且不能有實作。
  2. Listener 常用 interface 來實作。

CH11 執行緒與並行 API

  1. 執行緒有可能在未經 notify()、interrupt() 或逾時情況下私自甦醒 (Spurious wakeup),
    所以 wait() 一定要在條件成立的迴圈中執行。

2013年7月31日 星期三

Using ProGuard to remove Log

在開發 app 的過程中,我們常會用 Log.d 或 Log.v 印一些訊息,
這多多少少會影響應用程式的執行效能,所以在要 release apk 時,就可以
用上 ProGuard 的設定,來自動移除 Log。

ProGuard is a free Java class file shrinker, optimizer, obfuscator, and preverifier.

要啟用 ProGuard 的設定,要修改在專案路徑下的 project.properties 檔案內容,
加上一行 proguard.config=proguard-project.txt,指定 ProGuard 設定檔的路徑。
之後在 proguard-project.txt (ProGuard 設定檔) 裡,加上以下的敘述即可。

-dontwarn android.support.**
-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
}

Releasing and signing an Android Application

使用 Eclipse 時,對著 project 按右鍵 -> Android Tools
可以選擇把我們的專案 export 成 signed/unsigned 的 apk 檔 :
-> Export Signed Application Package...
-> Export Unsigned Application Package...
而沒有 sign 過的 apk,只能安裝在 Emulator 上。


手動 sign 的方法可參考這篇:
http://www.androiddevelopment.org/tag/apk/

2013年7月25日 星期四

將 dip 轉換成 pixel

在 Android 手機裡,我們大都用 DIP(Density Independent Pixel unit) 來設計 UI 而非 pixel 值,
這時想將 DIP 轉換為 pixel,可直接套用下列的函式。
 
public int convertDIPtoPixel(int dp)
{
  final float scale = getResources().getDisplayMetrics().density;
  int pixels = (int) (dp * scale + 0.5f);
  return pixels;
}

公式: density = dpi/160, px = dp * density
density 是指每 dpi 代表多少 pixel,在 160 dpi 的裝置上,1 dpi = 1 pixel,density 為 1;
在 320 dpi 的裝置上,1 dpi = 2 pixel,所以 density 為 2。

詳見: http://developer.android.com/reference/android/util/DisplayMetrics.html#density

Layout 常遇見的問題

  1. alignParentBottom/alignParentTop/alignParentLeft/alignParentRight 這些屬性,如果在 parent 有設 padding 的屬性時,該 view 不會完全的與 parent 貼齊,而會留下 padding 的間距。
  2. layout_marginBottom 有時候會沒效果。
    http://stackoverflow.com/questions/10386036/why-is-layout-marginbottom-ignored-when-using-wrap-content

2013年7月9日 星期二

android.util.AndroidRuntimeException: You cannot combine custom titles with other title features

想要加入自訂義的 title bar 時,
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.main);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title_bar);

卻跑出了這樣的錯誤訊息:

android.util.AndroidRuntimeException: You cannot combine custom titles with other title features

結果看到官網發現:

Beginning with Android 3.0 (API level 11), the action bar is included in all activities that use the Theme.Holo theme (or one of its descendants), which is the default theme when either thetargetSdkVersion or minSdkVersion attribute is set to "11" or greater.

也就是如果沒有特別指定 Theme,預設是用 Theme.Holo 這個主題,而這樣就已經包含了

Action Bar,Title Bar 和 Action Bar 兩者不能並存,所以只好在 title bar 的 style 裡加上 parent 

沒有 actionbar 的樣式 "android:Theme"

<style name="TitleBarTheme" parent="android:Theme">。

系統定義一些 theme 的詳細屬性,可以參考 themes.xml

2013年6月26日 星期三

ASCII、ANSI、Unicode、UTF-8 的差別

SBCS (Single Byte Character Set)

  • ASCII
    ASCII 是美國於 1967 年發表的一套電腦編碼系統,主要將 26 個英文字母用 1 個 byte 來表示。加上數字與其他的字元符號,總共有 128 個字元,後來又衍生了有 256 個字元的 extended ASCII  (詳見: ASCII Table)。
  • ANSI
    ANSI 是 American National Standards Institute 的縮寫。內容就是 ISO 8859/x 加上額外的字元,也是用 1 個 byte 來表示,比起 ASCII 少了一些控制字元,卻多了一些重音字元 (accented characters) (詳見: ANSI Table)。

MBCS (Multi-Bytes Character Set)

  • 在 Window 系統裡,根據不同語言的系統有不同的預設值,可到 "控制台" -> "地區及語言" -> "系統管理" -> "非 Unicode 程式的語言" -> "變更系統地區設定..." 做更改。例如選擇 "中文 (繁體,台灣)" 時,使用的是 Big5 編碼; "中文 (簡體,中國)" 是用 GB2312 編碼;"日文 (日本)" 則是 Shift-JIS 編碼。

    (詳見: Code Page Identifiers)

    為什麼會有這些額外的編碼? 當然是因為早先的 ASCII 只定義了英文字母,可是其他國家也 想要用電腦啊! 而且每個國家有各自的文字,於是各自發展了以 ASCII 衍伸的編碼,用 128 之後來開始定義自己的文字。

    附註:在程式語言裡的 ANSI String 、ATL 的 macro A2W 和 W2A 指的是 ANSI/MBCS 兩者的集合。 

Wide Character 

  • Unicode
    原全名為 Universal Multiple-Octet Coded Character Set,又稱我們熟知的 Unicode 萬國碼。原先一個國家一套編碼,會造成用日文編碼的程式無法正確在中文系統上顯示,為了解決這樣的問題,Unicode 就自然的誕生了。Unicode 用 2 個 bytes 來表示所有國家的字母及字元  (可表示 65535 個字), 而原先的 ASCII 碼與 Unicode 的表示仍然相同,只是 Unicode 多用了一倍的記憶體空間。
  • UTF-8 (8-bit Unicode Transformation Format)
    是一種針對 Unicode 的可變長度字元編碼,以 1~3 個 bytes 來表示一個字元,如此大大的減少了記憶體空間的使用量,便於在網路上更有效率的傳輸。
    這是一個 Unicode 與 UTF-8 的轉換表:

UnicodeUTF-8
0000 - 007F0xxxxxxx
0080 - 07FF110xxxxx 10xxxxxx 
0800 - FFFF
1110xxxx 10xxxxxx 10xxxxxx

用一個簡單的例子來說明如何轉換,"我" 的 Unicode 是 6211,座落於表中的第三列,以二 進位表示即 0110 0010 0001 0001,依序從後面補置表中的 x 處,得到
11100110 10001000 10010001,再轉成十六進位, E6 88 91 即是 "我" 的 UTF-8 編碼。

2013年6月21日 星期五

[CSS] 將 div 水平置中

我們可以用兩個 div 來達成,c2 是我們要置中的 div, 先將要置中的 c2 用 c1 包起來,

並將 c1 的 width 和 left 都設為 50% (即頁面的一半寬度),再將 c2 左推 50% 的寬,

若是使用絕對位置 absolute ,記得將 width 設為 100%,此時就達成置中了的效果了。

.c1
{
    position:absolute;
    width:50%;
    left:50%;
    border:2px solid blue;
}

.c2 /* relative */
{
    position:relative;
    left:-50%;
    border:2px solid red;
    text-align: center;
}

.c2 /* absolute*/
{
    position:absolute;
    left:-50%;
    width:100%;
    border:2px solid red;
    text-align: center;
}

[CSS] position 和 width 的關係

.class1
{
    position: absolute;
}

當 position 設為 absolute 時,width 的預設值為內容的寬。

.class1
{
    position: relative;
}

當 position 設為 relative時,width 的預設值為父容器的寬。




2013年6月20日 星期四

[TortoiseSVN] Revert Changes From This Revision

在使用版本控制時,有時我們會想要 roll back 某一個 revision,譬如說想要

 roll back revision 12001:

12010
12007
12001
12000

這時只要 Show log 將 Log Messages 的 Dialog 給叫出來, 選取該 revision 按滑鼠右鍵,

選擇 Revert changes from this revision,就可將該 revision 的 code 或檔案給移除或復原,

要注意的是這改變的是 Local 端的程式,想要更新 Server 端就得在 Commit 一次。

2013年5月23日 星期四

Resolution getting from android device is different from spec.

今天在玩 Toshiba AT500 時,發現規格上寫的解析度是 1280x800,

寫程式時卻要到了 1280x752。

( EX: getWindowManager().getDefaultDisplay().getMetrics(metrics); )

不過實際上 AP 能顯示的的確是 Height: 752 沒錯,因為下面還有一條 Status Bar!

但在使用 WebView(fillparent) 時,

JavaScript 是把解析度當成 1280x800 來看,

(window.screen.availWidth = 1280, window.screen.availHeight = 800)

CSS 則是把解析度當成 1280x752。

除此之外,背景圖像若設的跟 WebView 一樣大,影像將會超過 WebView 幾個 pixel,

若要貼得漂亮,就只能在減掉這些 pixel。

2013年5月22日 星期三

[Samsung Galaxy R] 移除客製 ROM 中的 Hmai 或其他客製軟體

1. 切換到撥號器下,輸入*#06#,出現一串數字,把 IMEI 抄下來2. 一樣在撥號器下,輸入

     *#272*IMEI#,就會出現:

  •  TWM 台灣大哥大 客製版
  •  CWT 中華電信 客製版
  •  BRI 台灣通路版
  • TGY 香港版本
  • KOR 韓國版本等選項

3.  點選 BRI 並安裝,安裝完後重開機就不會出現通路商客製化的軟體了。

資料來源: 網路、論壇

2013年5月13日 星期一

Be cautious with strncpy_s

strncpy_s 的宣告如下:


注意 numberOfElements 一定要大於 count,

Ex:

char dst[6]; 

strncpy_s(dst, 6, "a long string", 5);

dst 必須保留一位置給結束字元(null terminator)。 

否則有機會 crash。

2013年5月2日 星期四

Show device images on WebView.

先取得圖片的 Uri 路徑 (Ex: uri = "content://media/external/images/media/5103"),

前面的路徑是 Lib 已定義的 Uri MediaStore.Images.Media.EXTERNAL_CONTENT_URI,

後面的數字即是 query 欄位 MediaStore.MediaColumns._ID 時所得。

利用 Uri.withAppendedPath(Uri, String) 將兩者串接得到 uri,

在將 uri 字串往 JavaScript 層丟,創建一個 html 的 "img" 元件,將其屬性 "src" 設為該 uri 即可。

2013年4月16日 星期二

使用 Animation 的簡單步驟

要讓 Android 的元件產生動畫效果,幾個步驟如下:
  1. 宣告一個 Animation animation 物件並設定動畫相關屬性。
  2. animation.setDuration(200) : 必要,動畫時間長度。
  3. animation.setFillAfter(true): 非必要,預設為 false,是否停留在動畫結束後的畫面。
  4. animation.setInterpolation(new Interpolator()): 非必要,預設為 LinearInterpolator,也可設
    定成 AccelerateInterpolater(加速) 或 CycleInterpolator(轉圈)。設定動畫的效果。
  5. animation.setAnimationListener(): 設定一個監聽者,可控制動畫前後要做什麼事。
  6. 最後,呼叫 View.startAnimation(animation),動畫即開始。
詳細可參考 Android 的 Example -> ApiDemo -> Transition3d.java

2013年4月11日 星期四

Eclipse useful hotkeys

Most Used:

F3 尋找定義

ctrl + shift + G References in workspace

ctrl + G Declaration in workspace

ctrl + M 將目前 focus 的視窗放大最大

ctrl + / 註解 (取消註解)

ctrl + shift + O 自動匯入所欠缺的類別

alt + ← 移至上一次游標所在位置

alt + → 移至下一次游標所在位置

ctrl + shift + X 大寫字母  (在寫 constant 的時候頗實用)

ctrl+shift+R Open Resource (找 file 用它就對了)

Sometimes Used:

ctrl + shift + P 移至匹配的括號

ctrl + shift + L 列出所有快速鍵

ctrl + D 刪除單一行

ctrl + shift + F 程式碼自動排版

ctrl + shift + Y 小寫字母

alt + shift + J 加入Java doc說明

ctrl + shift + T search (用來找類別)

ctrl+F11 快速執行

F11 快速執行(Debug模式)

ctrl+K 快速搜尋選取的字(有點像瀏覽器搜尋的 F3)

SVN IDE for Eclipse

提供 Eclipse 的 SVN IDE 套件主要有 Subclipse 和 Subversive,而兩者有何不同呢?

從網路上搜尋的結果看來,功能都差不多強大,只是 Subclipse 由 SVN 官方所推出,

Subversive 由 Eclipse 官方所推出,愛用哪個就自己選囉。

這邊以 Subclipse 為例,其目前更新到 1.8.19 版,使用方法就和平常安裝 Plugging 一樣,

Help -> Install New Software... > Add

Location: http://subclipse.tigris.org/update_1.8.x

安裝完後,在 Navigator 視窗裡的空白處按下滑鼠右鍵 -> Team 即可看到常用的 SVN

功能。

2013年4月10日 星期三

Advanced Uses of Enum

常見的 Enum 用法大多如下:
public enum EnumMenu{
   APPLE,
   BANANNA,
   CHEESE
}

其實 Enum 可以更好用,假如我們今天有個菜單分別有名稱和價錢兩個屬性,我們便可以建立

Enum 的 Constructor 使其可以輸入名稱和價錢。之後,還可以拿名稱和價錢來做一些運算,例

如格式化文字的輸出,只要 Override toString() 即可。

public enum EnumMenu{
   APPLE("Apple", 10),
   BANANNA("Bananna", 20),
   CHEESE("Cheese", 30);

   private String name;       
   private int price;   
 
   private EnumMenu(String name, int price) {
      this.name = name;
      this.price = price;
   }
 
   public String toString(){
      return "Name: " + name + ", Price: " + price; 
   }
}

// System.out.println(EnumMenu.APPLE); // Name: apple, Price: 10

2013年4月9日 星期二

Enable Intellisense for Eclipse

Intellisense 可以讓使用者在敲首字時即開始提示,Eclipse 預設雖然有開啟這項功能,
但只有當按下 . 的時候才有作用,否則必須要按 Alt + / 才會出現選單以供選擇。
想要開啟如同 VS 首字開始自動提示的功能的話,步驟如下:
1. 工具列 Windows -> Preferences
2. 開啟對話視窗後 Java -> Editor -> Content Assist
3. 勾選 "Enable auto-activation" 的選項
Auto activation delay 為提示出現的延遲時間。
Auto activation triggers for Java 為 IDE 遇到何種字元會自動啟動提示,預設只有 dot,改成 .abcdefghijklmnopqrstuvwxyz(,
Auto activation triggers for Javadoc 在註解區塊中遇到何種字元會啟動提示,預設是 @ 及 #
改完後 Apply  -> OK

2013年4月8日 星期一

About Service

  1. Service 是個背景程序,當 App 和使用者已經沒有互動時,它還能夠在背後
    繼續運算。
  2. Service 本身並不是一個 thread,它作運用於 main thread 之中。

ServiceConnectionLeaked

離開 Acitivy 的時候,Eclipse 跑出 ServiceConnectionLeaked 這個錯誤訊息,

後來發現是結束 Acitivy 時,需要在呼叫 unbindService(myService)。

2013年4月2日 星期二

使用 Socket 前要注意的二三事

  1. 不應該在 UI thread 建立 Socket。(For Android)
  2. socket.isClosed() 只能判斷 local 端的 socket 是否被關閉了,無法判斷 remote 端的,
    例如即使 Client 已關閉 socket,在 Server 端呼叫 isClosed() 還是會拿到 FALSE。
    想判斷是否還可正常連線,就只能直接 read/write 看看,如果 read() 回傳 -1,就代
    表連線可能已經中斷導致 Stream 也被關閉,再也拿不到資料 (EOF)。
  3. 當兩邊 Stream 建立時,一方的 read() 通常會被 block 住,但如果另一方的 Stream
    突然被關閉,此時的 read() 再也不會被 block,而是不斷的回傳 -1 (EOF)。

2013年3月29日 星期五

Measure the display width of a string

我們常常會用 Graphics2D.drawString("Hello", 100, 100); 在元件上畫出字串,

若想要依字串畫出來的大小來決定其位置,可以先取得 FontMetrics 物件,

FontMetrics fm = getFontMetrics(font);

再透過 FontMetrics.getHeight() 和  fm.stringWidth(String) 即可拿到該字串的高和寬。

Static variables are not resetting when the application is destroyed

當 APP 觸發 OnDestory() 而結束時,所宣告的 static variables 並不會因此而重設,

必須手動重設,這是因為當 class 被載入時,靜態變數就會一直存在直到 class

被卸載,像是 Remove 整個 APP 時或系統記憶體不足的時候。

Do not use Socket with DataInputStream

今天在寫的 socket 程式時,使用 DataInputStream/DataOutputStream 來傳遞資料,

發現用 DataInputStream 時,能夠一次讀到的 bytes 很少,每次都是 1448 bytes

(不知道怎麼算出來的?),讀的也很慢。試著改用 BufferedInputStream/BufferedOutputStream

來傳遞資料發現變快許多,而且每次能讀的的 bytes 也比較多,都是 1448 的整數倍,

1448, 2896(2x1448), 4344(3), 8688(6), 30408(21), 33304(23), 36200(25)... 等。

2013年3月28日 星期四

new Socket 時發生 Exception

今天想寫一個 Android 的 Client 端將資料傳輸到 PC 的 Server 端。

我在 onCreate() 時去 new Socket(strIP, 27015) 卻發生 NullPointerException

strIP 明明就不是 null pointer,傳進去後卻莫名變成 null 了。

在網路上也找不到相關的資料,索性試著將 new Socket 一行移至 OnClick(),

這時跑出了另一個 NetworkOnMainThreadException,於是讓我找到了相關的文章。

根據 Why Ice Cream Sandwich Crashes Your App 這篇文章的說明,Android 3.0 以上

不允許在 UI thread 裡做以下的運算:
  • Opening a Socket connection (i.e. new Socket()).
  • HTTP requests (i.e. HTTPClient and HTTPUrlConnection).
  • Attempting to connect to a remote MySQL database.
  • Downloading a file (i.e. Downloader.downloadFile()).
解決方法: AsyncTask, Thread, Service(Android)

Debugging with Android SDK source code

之前已提過 [Eclipse] 對 Java SDK source code debug

對於 Android SDK source code debug 也是一樣,問題是要如何取得 Android SDK

的 source code 呢? 對於 Android 4.0 之前需要用 Repro 和 Git 這類的工具將 source

抓下來,到了 4.0 之後不需要在這麼麻煩,直接在 Android SDK Manager 就可以

下載,下載完後在 Debug perspective 對該 process 按下滑鼠右鍵選擇

Edit Lookup Path... 設置對應路徑即可。

▲ Android SDK Manager

[Eclipse] 對 Java SDK source code debug

我們可以安裝 JRE 或 JDK 來開發 Java 程式,但若要看到 Java SDK 的 source code,

並針對其 Debug,我們就只能安裝 JDK 了。

只要在 Window → Preferences → Java → Installed JREs → Search.... 設置 JDK 所安裝的

路徑即可。如此一來便可透過 F3Ctrl + 滑鼠左鍵看到定義 String 的 class 檔,而不會

有 "Source not found" 的訊息頁跑出來。

2013年3月26日 星期二

Cursor 在 OnStop 完之後被 Reset 了?

今天在使用 Cursor 時發現,使用開發的 App 到一半關螢幕,

使其觸發 OnStop() 事件,在當下 c.getPosition() 的值還是對的,

OnRestart() 回來後,c.getPosition() 卻變成 -1,也就是被重新指回頭了。

不知道是預期的行為還是怎樣,只好用個變數在 OnStop() 時記下,

OnRestart() 回來後,在把 cursor 指向原來的位置。

Macro # 和 ## 的用法

使用 # 可以把巨集引數變為一個字串,而 ## 則把兩個巨集引數串接在一起。

例如:
#define STR(s) #s
#define EXP(a,b) int(a##e##b)

printf ("Number %s\n", STR(655.3)); // Number 655.3
printf ("Number %s\n", EXP(5, 2));  // int(5e2), Number 500

2013年3月25日 星期一

讀取外部記憶體的圖片並秀在 ImageView 上

Step 1: 宣告外部記憶體 URI 位置
Uri uriMedia = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

Step 2: Query URI 的資料,利用 c.moveToNext() 取得繞行所有圖片的資料。
Cursor c = managedQuery(uriMedia, null, null, null, null);

Step 3: 取得 _id 後,建立該圖片完整的 URI。
uriSource = Uri.withAppendedPath(uirMedia, c.getString(0));

取得完整的 URI 後,有兩種方法可以秀出圖片:

Step 4.1: 利用 URI 的 stream data 建立 Bitmap 物件。
ContentResolver resolver = getContentResolver();
resolver.openInputStream(uriSource)
imageView.setImageBitmap(bitmap); 

Step 4.2: 直接將 URI 當參數設給 imageView
imageView.setImageURI(uriSource);

在這邊要注意的是,Android 單一程式的記憶體空間只能使用到 16~128MB,所以當

圖片太大不管是 setImageBitmap 或 setImageURI,都有可能造成 Out of Memory 的

錯誤訊息。解決方法可見 Loading Large Bitmaps Efficiently

Runtime.getRuntime().totalMemory() 可以查看應用程式目前的記憶體(Heap Size)大小,

Heap Size 是動態增長的。

Runtime.getRuntime().maxMemory() 可以查看應用程式的記憶體(Heap Size)能增長到多大。

2013年3月5日 星期二

把常用的 TortoiseSVN 功能整合進 Visual Studio

我們可以將 TortoiseSVN 常用的功能,如 Log 和 Blame 整合進 Visual Studio,

步驟如下:

開啟 VS -> Tools -> External Tools...

[External Tools]






















Command: C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe

Arguments(Log): /command:log /path:"$(ItemPath)"

Arguments(Blame): /command:blame /path:"$(ItemPath)" /line:$(CurLine)

如此一來,就可以在 VS 上對某一段 code 做 Log 和 Blame 啦! 相當好用!

2013年3月4日 星期一

利用指令透過 Visual Studio 開啟指定檔案


我們可以在執行檔 C:/Program Files/Microsoft Visual Studio 8/Common7/IDE/devenv.exe

後面加上:

A.cpp /command "Edit.Goto 200"

或是

/edit A.cpp

兩者的差異是,前者會開啟新的 VS 並可指定行號,後者會用已開啟的 VS 做為編輯器,

但無法指定行號。

[Notepad++] 開啟某文件並留在某一行

這對開啟程式碼文件頗實用,指令如下:

C:\Program Files\Notepad++\notepad++.exe C:\a.cpp -n200

即可開啟 a.cpp 這個檔案,並停留在 200 行的位置。

更多的 Command Line 可參考:
1. http://npp-community.tuxfamily.org/documentation/notepad-user-manual/command-line
2. http://sourceforge.net/apps/mediawiki/notepad-plus/index.php?title=Command_Line_Switches

2013年2月18日 星期一

今天遇到了一個跟 namespace 有關的蠢問題

// A.cpp
namespace SEAN
{
    static int num;
}

// B.cpp
#include "A.h"

int num = SEAN::num; // 這行一直跑出 error C2589: '(' : illegal token on right side of '::'

搞了很久才注意到 SEAN::num 是定義在 A.cpp 而非 A.h,

想要用就要定義在 A.h 裡。




2013年1月18日 星期五

[Eclise] 執行 64bits 的 Eclipse 出現錯誤

最近抓了 64 位元的 Eclipse 4.2.1 來用,執行時卻跳出這樣的錯誤訊息。



原來我 Java 裝的 32 位元版,所以兩者不相容。

只要再安裝一次 64 位元的 Java  就行了。

2013年1月10日 星期四

Using Pyro to talk to remote object

如同 Java 中的 RMI,Python 也有 Pyro 可以用,

Pyro 是一套程式庫,使我們可以讓物件在網路上互相溝通。

Python 2.5 的使用者,可以安裝 Pyro3 (文件);

Python 2.6 以上的使用者,可以安裝 Pyro4 (文件)。

安裝方法: 可以用 easy_install 來快速安裝 Pyro。

2013年1月7日 星期一

Visual Studio 專案設定檔的存放路徑

C:\Users\[UserName]\AppData\Local\Microsoft\VisualStudio\8.0\VCComponents.dat

裡面存放著 Include Dirs, Lib Dirs 等等的路徑,我們常常對於不同的專案會有

不同的設定,此時只要備份並覆蓋該檔即可。