瞭解JSON格式

這篇…我想就是給初次看JSON格式的人看的吧
如果懂了它的格式,不會太難

JSON全名叫做JavaScript Object Notation
就是在JavaScript之中,表示物件的一種格式

既然是格式,為何這麼多人愛用
可以好好瞭解一下

 

 

JSON格式簡單來說,就是這二句重點:


物件(object)用大括號 { }

陣列(array)用中括號 [ ]

先記住這概念


如果你看不懂JSON,可以用類似這種線上JSON格式化的網站

http://www.jsoneditoronline.org

幫助你瞭解

google搜尋一下:json format

就會有很多,這個網站我覺得做得不錯
我不是故意要打它的廣告,但這網站應該有助於JSON的學習


 

物件(object)

這裡說的object,不管你曾經在哪裡聽過這個名詞

他就是用key-value的方式儲存

來個範例吧!

{"subject":"Math","score":80}

這就是json裡的object

Screen Shot 2012-12-24 at 11.40.23 AM  

key-value就是指一個鍵值(key)對應一個值(value),跟變數很像

像是subject這個key有個值叫Math

score它的值為80

 

官方網站有個迷宮圖,有助於理解

object  

 


陣列(array)

陣列可能就比較熟悉些

例如

[0,4,5,2,7,8,3]

Screen Shot 2012-12-24 at 12.12.01 PM  

不難理解,就像是之前寫陣列一類似
這裡的範例是使用數字,但也可以是文字布林或者是陣列物件null。當然,混合就不用說了,絕對OK。

value  

 

文字(text)的例子

["Tom", "John", "Amy", "Ivy"]

Screen Shot 2012-12-24 at 12.32.54 PM  

布林(Boolean)

[true, true, false, false, true, true]

Screen Shot 2012-12-24 at 12.34.43 PM  

硬要用key-value的方式解釋的話
就是0,1,2,3的照順序的數字

array  

 

所以物件和陣列,某方面來說(不考慮資料損失),是可以互相轉換

若 物件 -> 陣列

就會損失鍵值(key)的資料,留下值(value)
或是程式到時候指定說,要鍵值陣列(key array),就會把所有的鍵值(key)合併一起成陣列

若 陣列 -> 物件

就可以將每個值編上數字

 

這裡注意一點
json object的鍵值(key),一定要用文字做鍵值

以下是錯誤的

{0:"Tom", 1:"John", 2:"Amy", 3:"Ivy"}  // error syntax

Screen Shot 2012-12-24 at 12.45.37 PM  

正確應改為

{"0":"Tom", "1":"John", "2":"Amy", "3":"Ivy"}

而整個JSON格式文件之中,是不能使用註解的

 

最後用這二個範例結束吧

成績單

[{"name":"Tom","lastname":"Chen","report":[{"subject":"Math","score":80},{"subject":"English","score":90}]},{"name":"Amy","lastname":"Lin","report":[{"subject":"Math","score":86},{"subject":"English","score":88}]}]

Untitled_Panorama1  

看起來很複雜,對吧?
其實不難

我們做成大家看得懂的表格

成績單1

姓名  Tom Chen 
數學 80 
英文  90 

成績單2

姓名  Amy Lin 
數學 86
英文 88 

 

剛剛也有提到這是個成績單
一開始用一個陣列 [] 包起來,然後是二個物件 {}

[{ …學生1… },{ …學生2… }]

學生資料內有姓名和成績

{"name":"Tom","lastname":"Chen","report": …成績資料… }

成績的部份,因為有很多成績資料,所以有用陣列 [] 包起來

{"name":"Tom","lastname":"Chen","report":[{ …成績1… },{ …成績2… }]} 

一個成績資料,也是個物件

{"subject":"Math","score":80}

全部拼起來就成那樣

 

如果用XML的格式寫就長這樣

<data>

    <student>
        <name>Tom</name>
        <lastname>Chen</lastname>

        <report>

            <subject>
                <name>Math</name>
                <score>80</score>
            </subject>
            <subject>
                <name>English</name>
                <score>90</score>
            </subject>

        </report>
    </student>

    <student>
        <name>Amy</name>
        <lastname>Lin</lastname>

        <report>

            <subject>
                <name>Math</name>
                <score>86</score>
            </subject>
            <subject>
                <name>English</name>
                <score>88</score>
            </subject>

        </report>
    </student>

</data>

應該不會太難

 

最後是網站上一開始附的範例

{"name":"John Smith","age":32,"employed":true,"address":{"street":"701 First Ave.","city":"Sunnyvale, CA 95125","country":"United States"},"children":[{"name":"Richard","age":7},{"name":"Susan","age":4},{"name":"James","age":3}]}

Screen Shot 2012-12-24 at 1.57.08 PM  

用XML可能會這麼寫:

<person>

    <name>John Smith</name>
    <age>32</age>
    <employed>true</employed>

    <address>
        <street>701 First Ave.</street>
        <city>Sunnyvale, CA 95125</city>
        <country>United States</country>
    </address>

    <childrens>

        <child>
            <name>Richard</name>
            <age>7</age>
        </child>

        <child>
            <name>Susan</name>
            <score>4</score>
        </child>

        <child>
            <name>Susan</name>
            <score>4</score>
        </child>

    </childrens>

</person>

比起XML,JSON的格式看起來是不是簡潔許多呢?

 


備註

在JSON的格式中,關於中文或其他非英文的部份

一定要用Unicode encode過

通常這個一般處理JSON的函式庫都會做掉

除非你自己print,自己兜出JSON格式

像是

我是中文  就會變成  u6211u662fu4e2du6587

類似這種 u開頭,接一串數字的東西

可以用這個工具做轉換(不過一般程式的library會做掉啦,這不用擔心)

http://www.htmlescape.net/stringescape_tool.html

 

另外有些字元在JSON不能直接打,需要做跳脫的(escape character) 在這
有些大家都很熟悉,就不細講了

"
\
/
b
f
n
r
t

這裡有些字碼表供參考

http://en.wikipedia.org/wiki/List_of_Unicode_characters

 

最後,練練英文,去JSON官方網站去看看吧

http://www.json.org

可以看到不同語言對於這個資料格式的實作
接下來也會提到實作的部分

 

參考資料:

http://zh.wikipedia.org/zh-tw/JSON

[HTTP相關] 解析HTTP封包,瞭解Session ID和3-way handshake(三向交握)

這就是我們一直在用,不管是手機還是瀏覽器
在這虛擬化技術,雲端科技,Web 2.0等等蓬勃發展的年代
只要是上網,一定完全脫離不了Http的關係

對於網路,這是很基底的概念
想要讓技術層面更進一步
可以從日常接觸到的概念開始
讀通了,就很有用

—————————————————————–(以上都是廢話)—————————————————————

好吧,說真的我不大會教網路這種東西
可能有修過網路相關課程的人,可能會比較懂一點

我盡量從觀察到實際結果,配合網路概念解釋一遍 

 

HTTP封包

我先放這次抓HTTP封包的截圖,再來解釋可能會比較有概念一點

2011-10-21 00 09 30.png  

 

這次所使用的軟體是Wireshark,是個抓封包的軟體

http://www.wireshark.org/download.html

裝好之後選擇網路介面然後就可以看到類似像上圖的東西了喔
我想你一定是在看我的文章,你看你的視窗上面有pixnet耶

 


 

講起網路,不免還是從OSI七層開始講起

這個部份我覺得wiki分類的真好  http://en.wikipedia.org/wiki/OSI_model

2011-10-21 00 17 37.png    

有興趣可以點開wiki的連結看,裡面有對應的文章

天音:這時候要像老師一樣諄諄教誨 (雖然我很不想~>"<)

 

OSI七層協定從下到上分別為

實體層(Physical Layer),資料鏈結層(Data Link Layer),網路層(Network Layer),傳輸層(Transport Layer),會談層(Session Layer),展現層(Presentation Layer),應用層(Application Layer)

裡面藍字的內容都是現有協定名字

wiki的目錄,一堆藍字都沒看過沒關係,在這裡,我們只要管  TCP  HTTP  在哪一層就行了


 

對應到我們抓到的HTTP封包

Screen Shot 2012-03-13 at 下午5.36.47  

第一行,是個概覽,這個封包總共收到幾個Frame(訊框)等等

第二行,就是我們收到的Frame(訊框),可以看到我們用Ethernet協定傳送,裡面記錄著最後傳和目標傳到的Mac位址….等等

第三行,就是TCP/IP中的IP協定(Internet Protocol),紀錄著來源和目標的IP等等資訊

第四行,Transmission Control Protocol縮寫就是TCP協定啦,HTTP連線也是基於TCP協定的,可以看到來源和目的的port(連接埠)號

第五行,就是HTTP協定(Hypertext Transfer Protocol)啦

這裡有展開,可以看到完整的HTTP標頭,一個HTTP連線原來附著這麼多的資訊,也是等下要講的重點

第六行,沒甚麼特別的,就只是網頁原始碼

 


封包和傳送原理

封包大概是這樣子的

osi1  

從程式的眼光來看好了,軟體要送個資料到另一台電腦

除了  實體層(Physical Layer) 之外  

會依序從上往下包

你可以想成要送人家禮物要包裝

或想成郵局要送郵務,要在包裹上貼很多標籤

或是辦公室的便利貼,貼一些備註訊息

 

每往下一層就加一些東西上去,到別人的電腦也是這樣,一層層拿掉標籤

最後得到資料

 

HTTP(應用層)也是如此,HTTP是基於TCP(傳輸層)的

在連線的時候也是如此

要先有TCP先連線才會可以跑HTTP的協定

 

 

不要問我為什麼要分那麼多層,網路這東西是有歷史的

很多東西到現今也還在變化 (但這個概念短時間已經是不會變了)

 


先解釋TCP

看到一堆紅線了嗎

分成前三組和後三組

前三組,就是出名的三向交握 (3-way handshake 也有人翻譯三次握手)

(天音:甚麼三向交握都看攏無)

 

看英文比中文意思比較準,意思就是 握手寒暄 啦

 

 

請設想一個情況,想你打skype給朋友
剛接起來網路電話的時候有沒有遇到這樣的情況

[SYN]              我: 哈嚕, 有沒有聽到聲音?

[SYN, ACK]      A: 有聽到,那我呢?有沒有聽到聲音

[ACK]              我: 有滴~

(…….然後開始聊天,喔不是,是傳資料=  =")

 

沒錯,三向交握就這麼簡單

標籤看起來很複雜而已

 

另外這組

[FIN, ACK]

[ACK]

是四向交握協定Four-way Handshake,用來關閉連線的

引用一下文章的內容

1. (B) –> ACK/FIN –> (A)

2. (B) <–     ACK    <– (A)

3. (B) <– ACK/FIN <– (A)

4. (B) –>    ACK     –> (A)

理當要有四個,為何只有二個?我想是Keep-Alive的關係

所以連線沒有斷,保持連線,若有其他的要求就可以馬上繼續連線
而不用重新建立連線


HTTP標頭

HTTP標頭裡面有很多資訊,像是Server的資訊,很明顯是跟Apache做連線

這裡也很清楚看到中間有Set-Coookie: 和PHPSESSID就是Session的ID啦

當Server使用Session時

雖然Session的資料是放在Server上沒錯〈Client看不到〉

為了分辨這個是那個Client連來的
所以會放一個Session ID給Client

(像是你去寄放物品的櫃台寄放東西,櫃台會交給你一把鑰匙一樣)
用鑰匙認顧客

而且這個Session ID會隨著你的連線,在下次要求的時候,放在標頭裡面
一起發送給Server

 

而在網頁設計當中,Session往往都被當成會員登入等依據

當你在清理Cookie的時候,Session ID也一起被你清掉了
也理所當然的被登出了

 

但Session使用上有些限制

  1.  他只能在同一個網域名字下使用,不能跨網域

  2.  Client端要開啟Cookie (當然這項,一般的瀏覽器通常都是開啟的)

  3.  通常Session和Cookie一樣,有Expires(失效時間)的

所以Facebook的認證上考慮到這些限制,才會採用OAuth 2.0

就是模擬Session的原理,只是把Session ID變成token的方式,用HTTP最簡單的GET方式

掛在網址串上面,以做身分的識別

(有關OAuth2.0相關的東西下次再講)


所以Hsuan網友在Android建立HTTP連線裡面

http://j796160836.pixnet.net/blog/post/28994669

問的問題:

 

我在1.php 寫 session 
在2.php echo出session的值
這是沒問題的

但是如果用android端做測試的話
會抓不到session的值
請問這個跟android端有關係嗎??

所以在程式中,Session ID並沒有存下來

 


參考資料:

TCP: SYN ACK FIN RST PSH URG 詳解

https://sites.google.com/site/cimpleteam/articles/tcpsynackfinrstpshurgxiangjie

TCP/IP 概論

http://www2.meps.tp.edu.tw/documents/memo/TCP%EF%BC%8FIP%E6%A6%82%E8%AB%96/index.htm

[iOS] 利用NSURLConnection建立HTTP連線 (GET篇)

最近在研究iOS開發,對於Http連線的好處
在這裡就不再贅述

之前寫過Android版本的,請見:

http://j796160836.pixnet.net/blog/post/28994669

 

雖然我也在學習中,我盡量解釋其方法
如果有誤,還煩請大大們指正

——————————————————————————————————————-

 

開一個新的專案

在Interface Builder版面設計中,拉出一個Button和一個Label

——————————————————————————————————————-

其中 Button Touch Up Instide 中綁定  – (IBAction)request_btn_onclick:(id)sender   方法

LabelReferencing Outlets 綁定  @property (retain, nonatomic) IBOutletUILabel *label;     變數

——————————————————————————————————————-

 

ViewController.h 放入以下宣告

@interface ViewController : UIViewController

{

    NSMutableData *responseData;

}

 

// 開始接收資料,會呼叫此方法

– (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;

// 接收新的資料時,會呼叫此方法

– (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;

// 下載完畢時,會呼叫此方法

– (void)connectionDidFinishLoading:(NSURLConnection *)connection;

// 連線錯誤時,會呼叫此方法

– (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;

——————————————————————————————————————-

ViewController.m 加入以下程式片段

 

#pragma mark – Connection delegate

– (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

{

    // 開始下載,重置responseData資料

    NSLog(@”didReceiveResponse”);

    [responseDatasetLength:0];

}

– (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

{

    // 下載中,附加資料

    [responseDataappendData:data];

}

– (void)connectionDidFinishLoading:(NSURLConnection *)connection

{

    // 下載完成,釋放responseData

    [connection release];

    NSLog (@”succeeded  %d byte received”, [responseDatalength]);

    // 轉譯編碼文字

    NSString *responseString = [[NSStringalloc] initWithData:responseDataencoding:NSUTF8StringEncoding];

   

    [responseDatarelease];

   

    label.text =  responseString;

    [responseString release];

}

– (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

{

    // 下載錯誤

    label.text = [NSStringstringWithFormat:@”Connection failed: %@”,[error description]];

    NSLog(@”Connection failed! Error – %@ %@”,

          [error localizedDescription],

          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);

}

——————————————————————————————————————-

這段就是按鈕按下去會執行的語法

#pragma mark – Button onClick

 

– (IBAction)request_btn_onclick:(id)sender {

   

    responseData = [[NSMutableDatadata] retain];

    NSString *url = [NSString stringWithFormat:@”http://127.0.0.1/httptest/t.php”];

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURLURLWithString:url ]];

    [[NSURLConnection alloc] initWithRequest:request delegate:self];

   

}

——————————————————————————————————————-

我簡單解釋一下

剛剛在ViewController之中新增一個 NSMutableDatadata 變數 (Mutable代表可變動的)

然後在 – (IBAction)request_btn_onclick:(id)sender 這裡

指定一個 url 就是我們要瀏覽的位置,GET要上傳的內容就串在後面

再來建立一個 NSURLRequest 和 NSURLConnection 把連線建立起來

回應的部分傳進delegate (委派)之中

 

而delegate (委派)有四個

 

// 開始接收資料,會呼叫此方法

– (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;

當系統開始要接收資料的時候這個方法會被呼叫到
要把這 responseData 給清空,如果UI上有ProgressBar的話要將之歸零

// 接收新的資料時,會呼叫此方法

– (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;

每次資料在下載的時候,會不停的呼叫這個方法
可以看到這個data傳入的參數,就是每一小塊一小塊的資料
我們只要把它累加起來即可,如果UI上有ProgressBar的話就可以慢慢累加1

// 下載完畢時,會呼叫此方法

– (void)connectionDidFinishLoading:(NSURLConnection *)connection;

最後跑完會呼叫這個方法,就是你需要做處理的部分
例如顯示到畫面上,存入SQLite….等等


// 連線錯誤時,會呼叫此方法

– (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;

最後就是這個,中間若有網路錯誤等因素就會呼叫這個方法
你可以跳一個提示框或是印Log

 

這個範例的url是指到本機的Apache Server的其中的一隻php網頁
你也可以換成yahoo等網站,只是會跑出一堆網頁原始碼而已

可以玩看看 

——————————————————————————————————————-

以下是我不負責任的把語法翻成大家熟悉的Java
對於像我一樣,對Objective-C有閱讀障礙的

可以看一下(當然,底下的程式完全不能跑,就不用複製了….XD)

 

public  class  ViewController  implements  NSURLConnectionDelegate  {

 

   public  static  UILabel  label;

 

   private  NSMutableData  responseData;

 

   public  void  viewDidLoad()  {

 

      responseData  =  new  NSMutableData();

 

      NSString  url  =  “http://127.0.0.1/httptest/t.php”;

 

      NSURLRequest  request  =  new  NSURLRequest(url);

 

      new  NSURLConnection(request,  this);

 

   }

 

 

 

   @Override

 

   public  void  didReceiveResponse(NSURLConnection  connection, NSURLResponse  response)  {

 

      //  開始下載,重置responseData資料

 

      NSLog(“didReceiveResponse”);

 

      responseData.setLength(0);

 

   }

 

 

 

   @Override

 

   public  void  didReceiveData(NSURLConnection  connection,  NSData  data)  {

 

      //  下載中,附加資料

 

      responseData.appendData(data);

 

   }

 

 

 

   @Override

 

   public  void  connectionDidFinishLoading(NSURLConnection  connection)  {

 

      //  下載完成,釋放responseData

 

      connection  =  null;

 

      NSLog(NSString.format(“succeeded    %d  byte  received”responseData.length));

 

      //  轉譯編碼文字

 

      NSString  responseNSString  =  responseData.toNSStringWithEncoding(NSUTF8NSStringEncoding);

 

      responseData  =  null;

 

 

 

      label.text  =  responseNSString;

 

      responseNSString  =  null;

 

   }

 

 

 

   @Override

 

   public  void  didFailWithError(NSURLConnection  connection,  NSError  error)  {

 

      //  下載錯誤

 

      label.text  =  NSString.format(“Connection  failed:  %s”,  error.description());

 

      NSLog(NSString.format(“Connection  failed!  Error  –  %s”,

 

             error.localizedDescription()));

 

   }

 

}

——————————————————————————————————————-

參考資料

http://www.01-labor.com/2011/07/nsurlconnectionhttp.html

http://stm237.iteye.com/blog/1005752

NSURLConnection官方文件

https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html

[iOS開發] 讓JB後的iPhone/iPad能夠從xcode安裝發佈自己開發的程式 (免付費開發者帳號)

注意:這只是拿來做程式開發測試用途,越獄(Jailbreak)後所產生的後果和問題要自行負責

 

首先,先感謝綠毒團隊 讓A5晶片(iPhone 4s / iPad2) 在iOS 5.01也成功越獄了
這下能夠釋放iDevices的全功能,讓iDevices更強大


好吧,這次的重點
是要讓自己寫的iOS程式能夠在實機底下執行做測試
畢竟有些功能模擬器還是無法達到的

若程式的規模不及到要上架的程度
可以使用這個方法來做測試

 

當然,有付費版的開發者帳號最佳 (USD$99/年),就別看此篇了
在開始之前,你需要先JB你的裝置
這可能需要你自行去Google,假設你已經完成越獄了
會有個Cydia的程式安裝在你的裝置上 

 

筆者的環境

Mac OSX 10.7.2 (Lion)

Xcode 4.2.1

iPad2 16G Wifi (iOS 5.01 Jailbreaken)

 

 

等下將會以iOS 5.01 做示範


Step1  到cydia安裝AppSync

 

打開Cydia,使用底下的搜尋框尋找Appsync

100APPLE_IMG_0049.PNG  

就會有很多的名稱叫AppSync for iOS5.0+,擇一安裝即可 (這需符合你裝置的iOS版本)

這裡只是以此為範例 


Step2  編輯SDKSettings.plist

 

打開Finder,找到左側欄的應用程式 > 工具程式 > 終端機

 

鍵入指令

sudo vi /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/SDKSettings.plist

 

若是xcode 4.3版請修改

vi /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/SDKSettings.plist

(感謝Chiakie大大的幫忙)

Screen Shot 2012-01-23 at 下午1.52.00.png

輸入自己帳戶的密碼之後

會打開vim的介面
(vim共有三種模式 一般介面,編輯模式,指令列模式)

詳細vim操作可參照 鳥哥的文章
http://linux.vbird.org/linux_basic/0310vi.php

按下鍵盤的 i 可以編輯,編輯完畢按下鍵盤的 Esc

Screen Shot 2012-01-23 at 下午1.54.04.png

尋找CODE_SIGNING_REQUIRED,這個Key
將其底下的String從YES改成NO

 

編輯完畢按下鍵盤的Esc鍵,直接鍵入 :wq  在按鍵盤的 Enter (或return鍵)

Screen Shot 2012-01-23 at 下午2.39.06.png  

即可退出


Step3  修改Xcode專案的設定

 

打開你的Xcode,開啟你需要編輯的專案

Screen Shot 2012-01-21 at 下午5.14.25.png

依照圖片按到專案名稱,按下Info頁籤

找到Deployment Target,確認iOS Deployment Target是否是為 5.0  (這需符合你裝置的iOS版本)

 

再來相同的地方,找到Build Settings的頁籤

Screen Shot 2012-01-21 at 下午5.13.29.png

找到Code Signing

將以下全部改成Don’t Code Sign

(預設值是Debug > Any iOS SDK和Release >  Any iOS SDK的值為iPhone Developer)

 

 


Step4  連接你的iDevice (iPhone/iPad)

 

連接你的iPhone或iPad

按下專案視窗的右邊Organizer,找到Devices頁籤

Screen Shot 2012-01-23 at 下午12.39.36.png

可以找到你的裝置並且是亮綠燈的,且符合專案使用的iOS版本

 

 

回到專案視窗

  

按Scheme下拉框選擇你剛剛連接的裝置,按下Run

複製 -Screen Shot 2012-01-23 at 下午12.53.46.png  

就會開始編譯

 Screen Shot 2012-01-23 at 下午12.52.47.png

 


Step5  實機測試

 

編譯成功後

Screen Shot 2012-01-23 at 下午12.53.46.png  

會出現這樣

Error launching remote program: fail to get the task for process ……

的錯誤沒有關係

 

查看一下iPhone或iPad

100APPLE_IMG_0048.PNG  

你會發現他已經成功裝到你的機器上摟

 

 


參考資料

http://www.minwt.com/?p=2825

http://happyjc1106.blogspot.com/2011/12/xcode43.html

http://linux.vbird.org/linux_basic/0310vi.php

 

 

 

Macbook pro 13″使用至今的心得

我沒有品牌忠誠度,盡量中立的寫
主要注重在Mac & Windows差異的部分 

==散熱和電源方面==
Unibody用整塊鋁合金片製造,散熱還不錯,只會底下熱而已,鍵盤區不燙,也很有質感
風扇平時很少轉,除非跑即時聲音運算(EX: fl studio)或是圖形運算(EX: 星海II)的時候
風扇全開的時候會嚇到~哈哈,還好是轉一下就會降下來

 

 

i5處理器對我來說蠻夠用的,但好像是插著電源才會跑全速

Macbook pro的電池還蠻能撐的,號稱有6hr啦
實際一直玩它玩3hr不是問題
磁鐵接頭,接上去嚇一跳,Wow~

整體來說比我之前的12.5″的筆電(Acer TM3000)還要輕巧
但裝備一項都沒缺 (除了VGA頭之外啦,那外接線盒有點雞肋) 

 

==使用習慣==
control鍵,option(alt)鍵,command鍵 常常還是處於混亂狀態

在Mac底下:
control鍵還是control鍵
option鍵 = alt鍵
command鍵 = ctrl鍵

在Windows (跑Boot camp)底下:
control鍵 = ctrl鍵
option鍵 = alt鍵
command鍵 = window key……..=口=”

常常按錯不打緊,旁邊還有fn鍵來攪局,按錯頗正常
————————–
再來就是又愛又恨的Muti-touch
很多人搞不清楚,這跟Windows差異也最大
Lion這點做進控制台的觸控版設定頁面裡面,選項旁邊就是影片教學

雙指雙點 = 滑鼠右鍵 (這我最不能苟同,還好可以改成右下角)
雙指滑動 = 滑鼠滾輪 (這還蠻不錯的,不需局限筆電的右側邊)
三指按住窗框可移動視窗位置
四指向左右滑 = 切換不同的桌面 (還OK的項目)
四指向上滑 = 所有視窗和桌面的一覽
四指向下滑 = 相同類型的視窗(EX:瀏覽器) Expose打散
以上二個動作就是沒事做做手指運動XDD
找視窗還蠻順的,不致於說找不到,對於Dock上的工作列表的依賴性就降低了

四指抓取動作 = 打開啟動器,會有所有程式一覽 (類似iphone上的程式icon的放大版)
四指釋放動作(抓取的相反) = 關閉啟動器 or 顯示桌面 (這超難做到的,乾脆改成隱藏點比較快)

雙指縮放 & 雙指旋轉 (這支援的軟體真的不多,只有Apple出了才有效用)

Mac 雖然講求人性化,但還是需強記這些手勢和動作
看看apple要不要傳播給更多人知道這些小玩意兒
————————–
Vmware fusion和Boot camp實在絕配
Boot camp允許你在Mac上安裝Windows (我是裝Win7 x64啦)
而Vmware fusion又可以簡單的詢問你要不要設定Boot Camp虛擬機
轉換一下直接完成
打開虛擬機後就可以輕鬆的在Mac和Windows裡面切換了
當然剛剛的Muti-touch手勢,大部分都有幫你帶進來

沒事簡單的文書處理的時候可以開虛擬機
真正需要效能的時候開Boot Camp
虛擬機不慢,用起來像在用雙核電腦的感覺
這點我還蠻喜歡的

反倒是Boot Camp這就變成了一個缺點
他對於Windows的支援度整體就是失敗

剛剛的Muti-touch手勢全部廢掉
只剩最簡單的觸控版左鍵和右鍵
當然就沒有所謂的滾輪了,請慢慢拖曳Scroll bar吧

 

指令方面因為都是Unix-like所以一些Linux指令是通用的
還沒有用它寫過Windows程式,聽說會和其他的Windows不相容

可能是我對Mac軟體不熟吧,有沒有方便的文字編輯器? (EX: Notepad++或是Emeditor)
 

 

————————–
最後就是長時間在Mac筆電鍵盤打字,手腕和框邊一直磨擦,頗不舒服的 (可能大一點尺寸會改善吧)

delete鍵在哪裡…..原來是fn鍵+delete呀
沒有出名的Ctrl + alt + delete

到Mac底下要被改成  fn鍵 + control + option + delete
XDDD

Sony Ericsson Xperia X10 刷 2.3.3 + Root + xRecovery教學

Sony Ericsson Xperia™ X10 刷機教學整理

==================================================

 

Step1. 請於x10進入OS(操作系統) 做

設定->應用程式->開發->USB偵錯->打勾
設定->應用程式->開發->螢幕保持開啟->打勾
設定->應用程式->未知的來源->打勾

Step2. 下載並安裝Update Service
選擇X10

依照畫面指示 關閉你的手機

USB線接上手機,按住Back鍵不放並同時將USB線接上PC
進入刷機模式

Update Service抓到手機後會自動進行網路下載版本和更新的動作
然後最後會提示你拔除USB線,然後開機
這樣2.3.3就升級成功了

Step3. 進入OS(操作系統)之後確認為2.3.3
接下來,打開FlashTool

按下flash
點選X10_aZuZu_Kernel_Downgrade_Generic按下OK
依照畫面指示進入刷機模式 (請參考Step2)
刷機的Log直到出現turn on your usb debug就OK!!!

Step4. 拔除USB線,按電源鍵開機,當感到開機的時候的些微震動就可以接回USB線

在pc的FlashTool root鍵的位置會變成可按的,按下root。直到Root should be available after reboot!

Step5. 完成root時,手機不管有沒有自動reboot,把電池拔掉數分鐘。pc端USB拔除。

Step6. 刷入X10_aZuZu_Kernel_UpGrade_Generic,步驟相同請參考Step3

Step7. 點選 Ask Root Perms 之後請注意你的手機,他會問你是否接受root程序,請按「接受」

之後手機端會出現「Unknown已經獲得最高權限」的字樣
這時候FlashTool上的 xRecovery按鈕應該成為可點選了,然後按下xRecovery
並等待其安裝成功

==================如何進入X10的刷機模式==================
1. 關閉你的手機

(註:在還沒按住Back鍵之前,畫面上不能有Sony Ericsson字樣或者電池充電中的圖示。若有,可以拔電池約一分鐘再接回去,接上電池後等待約30秒左右,讓系統偵測完畢。也確定他為黑螢幕)

2. USB線接上手機,按住Back鍵不放並同時將USB線接上PC
進入刷機模式

3. 成功進入刷機模式的話,手機的右上角會亮綠燈
(綠燈亮了之後就可以放掉Back鍵,不用再按住Back鍵不放了)

而且PC上會多出一個叫SEMC USB Flash driver的不明裝置
那個驅動在FlashTool_0.2.9.1\drivers\X10_ADB_drivers.zip
解壓縮後的資料夾內

4. SEMC USB Flash driver的不明裝置,安裝完驅動會變成
Sony Ericsson sa0102 ADB Interface

================如何進入刷入後的xRecovery================
重新開機,看到Sony Ericsson的白字的時候,連續按返回鍵,不是按住喔,是一直連續0.5-1秒按放按放,之後會跑出Xrecovery模式
按音量的上下鍵選擇,右方的Back鍵就是返回,中間的Home按鍵則是進入,這時候電源鍵會變成無用

 

 =================================================

這次刷機有用到的文章

[教學] x10 2.3.3 root+Recovery完全教學
http://gphonefans.net/thread-59094-1-1.html

[教學] X10新手ROOT+安裝busybox,xRecovery刷2.2+變磚救機術
http://gphonefans.net/thread-34157-1-1.html

Flashtool軟體網站 (目前版本 Flashtool v0.5.3.0)
http://androxyde.github.com/Flashtool/

====================找到的一些教學====================

X10一鍵 解鎖/上鎖
http://www.mobile01.com/topicdetail.php?f=569&t=2062214

[RECOVERY image] {v2} X10 GB 3.0.1.G.0.75 [Prerooted + Fixed xRecovery]
http://forum.xda-developers.com/showthread.php?t=1192152&fb_source=message

===========自訂的ROM (朋友推薦的,不過沒用到就是了)===========

X10 Wolfs V7(Test V3)/ThGo2_v9.3 (畫面很順) (11/5)X10台灣版2.3.3官方版可一鍵root
http://www.mobile01.com/topicdetail.php?f=569&t=2288956&last=32340524

[Android] ViewFlipper “Receiver not registered” 的 bug

又抓到一個bug了,真開心

這次是Android自己本身控件的問題

有使用到ViewFlipper的朋友注意了

 

如果最近有遇到這個bug

java.lang.IllegalArgumentException: Receiver not registered: android.widget.ViewFlipper$1@464946a0

at android.app.ActivityThread$PackageInfo.forgetReceiverDispatcher(ActivityThread.java:793)
at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:814)
at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:331)
at android.widget.ViewFlipper.onDetachedFromWindow(ViewFlipper.java:104)
at android.view.View.dispatchDetachedFromWindow(View.java:6033)
…….(略刪)

網友看過source code 發現是google本身控件的Bug

可以用以下,最簡單的方式可以這樣解決

—————————————————————————-

解決方式

建立一個package名字叫做com.J_Test.temp

建立一個class名稱叫做myViewFlipper 

貼上其程式碼

 

package
com.J_Test.temp;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ViewFlipper;

public class myViewFlipper extends ViewFlipper

{
     // 建立預設的建構子
     public myViewFlipper(Context context)
     {
           super(context);
     }

     public myViewFlipper(Context context,
AttributeSet attrs)
     {
           super(context, attrs);
     }

 
     @Override
     protected void onDetachedFromWindow()
     {
           // Android 2.1~2.3.4bug ()
           // 解決ViewFlipper “Receiver not
registered” Error
           try
           {
                super.onDetachedFromWindow();
           } catch (IllegalArgumentException e)
           {
                stopFlipping();
           }
     }
}

 

 

使用方式

將舊有的程式碼

   <ViewFlipper
        android:id=“@+id/flipper”
        android:layout_width=“match_parent”
        android:layout_height=“wrap_content”
        android:flipInterval=“5000”
        android:inAnimation=“@anim/push_up_in”
        android:outAnimation=“@anim/push_up_out” >

 ………….

    </ViewFlipper>

替換掉成我們的控件

   <com.J_Test.temp.myViewFlipper
        android:id=“@+id/flipper”
        android:layout_width=“match_parent”
        android:layout_height=“wrap_content”
        android:flipInterval=“5000”
        android:inAnimation=“@anim/push_up_in”
        android:outAnimation=“@anim/push_up_out” >

 ………….

    </com.J_Test.v1.temp.myViewFlipper>

 

這樣就OK了

 

原理就是上述藍色字處有bug

我們繼承它,把super()用try-catch把他接起來

然後呼叫stopFlipping()會讓所有程序停止

 

 

—————————————————————————-

測試方式如下:

在XML做一個ViewFlipper

JAVA程式對應尋找其View

ViewFlipper mFlipper = (ViewFlipper) findViewById(R.id.flipper);

還沒有呼叫

mFlipper.startFlipping();

之前就把螢幕轉向

網友測試好像從Android 2.1就出現此bug

測試從Android 2.3.4都還仍然依舊

—————————————————————————-

 

 

參考資料

http://daniel-codes.blogspot.com/2010/05/viewflipper-receiver-not-registered.html
http://code.google.com/p/android/issues/detail?id=6191


[Android] 多執行緒-Handler和Thread的關係 (2)

之前寫過一個多執行緒,發現還是寫太亂了,不夠簡單

http://j796160836.pixnet.net/blog/post/28766165

 

我重新敘述一下

 

多執行緒的部分,有幾個名詞

  • Runnable 工作包 (要做的事情)
  • Thread 執行緒
  • Handler
  • Message

 

————————————————————————–

Runnable

就是像是專案管理裡的工作包,說穿了就是要做的事情啦,像是這樣

   private Runnable r1=new Runnable () {

        public void run() {

            //………………………..

            //做了很多事

        }

    };

這裡的 r1 就是一個runnable

————————————————————————–

Thread

在Android的世界裡,Thread分成二種

1.  單次型 (Java原有的)

2.  常駐型 (Android特有的)

 

 

————————————————————————–

1.  單次型

意指就是給他一件艱巨的任務

他做完就會關閉了

 

寫法實在有夠簡單

   
   Thread t1=
new Thread(r1);

   t1.start();


這裡的 r1 是一個runnable

————————————————————————–

 

2.  常駐型

就是做完事情他不會自動關閉,而是變成一個idle (閒置) 的狀態

閒置意思就是他沒事幹啦~  要給他事情做

 

        mThread = new HandlerThread(“name”);

        //Worker待命,等待其工作 (開啟Thread)

        mThread.start();

這樣子就可以建立且執行Thread了

連Runnable也不想打的話可以合併起來

 

     Thread XXX = new Thread(new Runnable()

     {

           publicvoid run()

           {

                // ……工作

           }

     }).start();

 

要給他事情做要這樣寫

 mThreadHandler.post(r1);

 

 

有沒有發現,單次型的Thread就是把事情定義下來然後呼叫start()

開始跑,跑完關閉

 

而常駐型的話,反而是讓你先start()

然後post(r1)   給他事情做,做完就閒置

 

請務必記得不用這個Thread的時候要把他關閉


        if (mThread != null)
            mThread.quit();

大部分的情況,常駐型的Thread

在onCreate()裡面建立Thread

在onDestory()裡面關閉Thread



————————————————————————–

Handler

那甚麼是Handler呢?

你可以想成是一個服務的窗口

給他事情做的地方


寫法有二種


1.  mUI_Handler.post(r2);
2.  mUI_Handler.sendEmptyMessage(MSG_UPLOAD_OK);

第一種就是直接給他一個Runnable,讓他去執行

第二種就是傳一個Message給他



Handler的建立

 private Handler mUI_Handler = new Handler();

這樣會建立一個基於Main Thread (UI Thread)的Handler


————————————————————————–

Message


這東西不複雜,剛剛不是還在講Runnable嘛?

Message就是要一言以蔽之,用一個值  (一句話)
代表一堆事情(Runnable)


先看看Handler的變形吧


Handler的建立

 private Handler mUI_Handler = new Handler();

這樣會建立一個基於Main Thread (UI Thread)的Handler

以下是他的變形

     private Handler mUI_Handler new Handler()

     {

           @Override

           public void handleMessage(Message msg)

           {

                switch (msg.what)

                {

                     case MSG_UPLOAD_OK:

                           // …………..

                           break;

                }

           }

     };

這樣會建立一個基於Main Thread (UI Thread)的Handler

有一個窗口,有一個地方可以處理Message的地方  ( 就是handleMessage() )

這裡用一個switch case的格式表示

msg.what  就是你訊息的內容

MSG_UPLOAD_OK  這就是你的訊息了(自己自訂)

像這樣

privatestaticfinalint MSG_UPLOAD_OK= 0x00000001;

說穿了就是個int而已


要使用的時候就這樣

 mUI_Handler.sendEmptyMessage(MSG_UPLOAD_OK);

可以使用帶參數的寫法

 mUI_Handler.obtainMessage(MSG_UPLOAD_OK, arg1, arg2).sendToTarget();

或是

 mUI_Handler.obtainMessage(MSG_UPLOAD_OK, obj1).sendToTarget();

這樣可以帶二個int去,或是直接帶object給他(收到了之後再去轉型…)









[Android] 如何Debug 含有Bundle (has Extra) 的Intent

2012-12-24 02 15 06  

不知道在Android做Intent除錯時
和我有類似的經驗

自己寫的APP,明明看到LogCat上面寫著

 

Starting activity: Intent { cmp=<你的Package名稱>/.<你的Activity名稱> (has extras) }

 

對呀,我的Activity被Intent喚起來了

但那個has extras又是啥鬼?
阿我就是想知道那些Extras是啥呀(怒吼~

 


 

如果用Log直接把Intent直接toString

Log.v("Test Intent", intent.toString());

對不起他只會跟你說是個物件,ID為何
這訊息根本不是我們想要的

 


 

沒關係,有解的。

 

你需要

intent.getExtras()

會回傳Bundle

 

利用Bundle的

bundle.keySet()  來達成

它會回傳一個只有Key名字的hash

那你可以使用.toArray()轉換成普通的陣列

 

組合起來成為一長串

Log.v("Test Intent", intent.getExtras().keySet().toArray().toString())

 

 就是它了。

 

 

參考文章
http://groups.google.com/group/android-developers/browse_thread/thread/00828fe418964285

[SQL] 多個各自count之後還要join成一張表 (在多個表格裡count資料)

我這個標題我還想了一下要怎麼下

下太複雜我怕大家又看不太懂,還有搜尋引擎關鍵字的問題

(題外話……)

 

這個用看的不會懂,做過才知道其中的奧妙

————————————————————————–

問題

問題是這樣的

 

假設說,我有個資料庫,分別存了A表格 B表格 C表格 ……

都是主鍵(Primary Key)+外鍵(Foreign Key)的格式

這幾張表都有外來鍵只向同一張表格的主鍵

也就是

A表格

A_id(主鍵)  A_name  data ……

B表格

B_id(主鍵)   A_id(外來鍵)   data ……

C表格

C_id(主鍵)   A_id(外來鍵)   data ……

 

如今

 

我想要個別統計一下資料的狀況

 

最後呈現的欄位是這樣
A_id    A_name   B_count  C_count

 

這對我們來說不是難事

所以我們在資料庫下了這些SQL  (以下使用MySQL的格式表示)

 

對表格B做統計
SELECT `A_id`, COUNT(`B_id`) as `B_count` FROM `tableB` GROUP BY `A_id`;

 

得到
A_id    B_count  的欄位

 

對表格B做統計
SELECT `A_id`, COUNT(`C_id`) as `C_count` FROM `tableC` GROUP BY `A_id`;

 

得到
A_id    C_count  的欄位

 

問題來了

我們有學過JOIN,他們都有A_id
我們如何把他們另外統計的二張表格合起來

還要顯示A表格的其他內容

 

你要如何做?

 

————————————————————————–

第一,我可能會想到在JOIN的過程中

不能直接JOIN起來的話

好歹列數也要一致相同吧

所以我改這樣下

SELECT `A_id`, `A_name`, COUNT(`tableB`.`A_id`) as `B_count` FROM `tableA` LEFT JOIN `tableB` ON `tableA`.`A_id`=`tableB`.`A_id` GROUP BY `tableA`.`A_id`;

SELECT `A_id`, `A_name`, COUNT(`tableC`.`A_id`) as `C_count` FROM `tableA` LEFT JOIN `tableC` ON `tableA`.`A_id`=`tableC`.`A_id` GROUP BY `tableA`.`A_id`;

 

 

使用LEFT JOIN是因為INNER JOIN是有對到資料才會出現

而LEFT JOIN才會顯示Count是零的狀況

 

這樣也不盡人意……

 

 

————————————————————————–

解答

找好久才找到這個解答

我個人認為其重要性接近死背這個架構

 

SELECT `A_id`, `A_name`,

(SELECT COUNT(*) FROM `tableB` WHERE  `tableB`.`A_id`=`tableA`.`A_id`) AS `B_count`,  

(SELECT COUNT(*) FROM `tableC` WHERE  `tableC`.`A_id`=`tableA`.`A_id`) AS `C_count`,  

FROM `tableA`;

 

這個架構叫做

關聯子查詢

SQL語句裡面跟外面有產生關聯的

但是光看問題不會馬上想到這個架構

 

 

解釋

簡單來說一句SQL語法做了三個動作

 

從刮號裡面先看好了

裡面有二句SQL語法,看起來像是獨立的但不能跑

會有這個錯誤

#1054 – Unknown column ‘tableA.A_id’ in ‘where clause’

因為他找不到tableA在哪裡

 

 

SELECT COUNT(*) FROM `tableB` WHERE  `tableB`.`A_id`=`tableA`.`A_id`

這句的意思是計算tableB總共有幾筆

我們有學到在WHERE裡面打上

`tableB`.`A_id`=`tableA`.`A_id`

意思就是要讓表格合併起來 (像是INNER JOIN)

 

—————————————————-

*TIPS:

 

WHERE id=id能獨立跑的是這個

SELECT `tableA`.*, `tableB`.* FROM `tableA`, `tableB` WHERE `tableB`.`A_id`=`tableA`.`A_id`

用INNER JOIN 改寫變成

SELECT `tableA`.*, `tableB`.* FROM `tableA`INNER JOIN `tableB` ON `tableB`.`A_id`=`tableA`.`A_id`

 

—————————————————-

在來就是外面那層

SELECT `A_id`, `A_name`, (……) AS `B_count`,  (……) AS `C_count`,  FROM `tableA`;

就只有簡單的撈整張表格出來而已

 

AS就是做欄位別名

整個SQL語句要做為一個欄位賦予別名

那該SQL語句必須資料輸出一個欄位而已

這裡輸出COUNT(*)剛好只有一欄,符合規定

 

—————————————————-

其它範例

 

有個問卷的系統,表格長這樣

這個學生詢問了向各種對象,問各種不同的問題,放在不同的表格

而如今他想要把他的問題做統計

 

欄位名稱如下

Student(id,name,mykad,…)
Customer Service(id, Q1,Q2,Q3,date)
Instructor(id, Q1,Q2,Q3,date)
Runner(id, Q1,Q2,Q3,date)

SQL語法如下:

SELECT A.name, A.mykad, 

(select count(*) from customerservice B where B.id = A.id and B.Q1=’Excellent’) AS E, 
(select count(*) from customerservice C where C.id = A.id and C.Q1=’Satisfaction’) AS S,
(select count(*) from customerservice D where D.id = A.id and D.Q1=’Poor’) AS P
FROM student A

就會輸出欄位

name   mykad  E  S  P

 

這裡的參考資料一定要看,他寫的比我還要詳細

http://stackoverflow.com/questions/1279569/sql-combine-select-count-from-multiple-tables
http://www.daniweb.com/software-development/legacy-and-other-languages/threads/352342