2011年8月30日 星期二

[Android 精華文章] 生成 .keystore 並導出 .apk 檔案後安裝到 Android 平台


前言 :
因為目前寫的 Android app 為個人使用且未打算發佈到 Market, 因此下面介紹如何透過生成 .keystore 與 導出 .apk (其實就是 jar 檔) 後, 再安裝到 Android 的手持裝置.

生成 .keystore :
因為導出 .apk 有兩種, 一種是 signed 過的, 另一種是 unsigned (後面會提到). 在導出 unsigned 的 .apk 後, 我發現無法安裝在 Android 手持裝置上, 因此只好試試 signed 的方法. 首先我們要透過 Java 的 keytool 來產生 .keystore 的檔案, 而該檔案將用來後續產生 signed .apk 使用, 底下是 keytool 的簡單說明 :
Keytool 是一個JAVA環境下的安全鑰匙與憑證的管理工具.它管理一個存儲了私有鑰匙和驗證相應公共鑰匙的與它們相關聯的X.509 憑證鏈的keystore(相當一個資料庫,裏面可存放多個X.509標準的憑證). 它能夠使用戶使用數位簽名來管理他們自己的私有/公共鑰匙對,管理用來作自我鑒定的相關的憑證,管理資料完整性和鑒定服務.它還能使用戶在通信時緩存它們的公共鑰匙.

接著請參考命令如下 : keytool -genkey -keystore john.keystore -alias johnalias <john 與 johnalias 為自己決定>

完成導出後, 接著請把它複製(搬移)到你的專案目錄下, 方便等下導出 signed 的 .apk.

導出 signed .apk 檔 :
接著我們要透過 IDE Eclipse 來導出一個已存在的 Android 開發專案 (這裡以 NTUHReport 為範例). 首先請在專案上點擊滑鼠右鍵, 在出現 Menu 上選擇 :
Android Tools > Export Signed Application Package (如下圖)


在出現視窗中選擇與導出專案並點擊下一步 :


接著選擇 .keystore 並輸入該 .keystore 的密碼, 最後選擇下一步 :


根據剛剛選擇的 .keystore, 選擇對應的 alias 與輸入密碼後, 選擇下一步 :


最後便是選擇導出 .apk 路徑, 並點擊 "Finish" 完成導出 :


安裝 .apk 到手持裝置 :
最後一個階段便是安裝剛剛導出的 .apk 到手持裝置上. 第一步便是將該 .apk 透過 SD 卡或是 usb 傳輸到 Android 手持裝置上.
1. 關閉USB儲存裝置,按設定>應用程式>未知來源打勾 :


2. 利用ASTRO檔案總管讀取放在SD那中的APK檔,選擇Open App Manager 並點擊 "Install" :

(選擇 "Open App Manager")


(點擊 "Install")

3. 出現下面視窗代表 APK的安裝完成了 :


補充說明 :
android googlemap 應用生成keystore 申請Map key 並註冊簡明教程
Android 手機安裝、解除安裝APK 教學
發佈 App 到 Android Market
「Android Market (市集)」是一個「Android」官方(Google)提供的「Android」應用程式下載網站,同時也內建於所有的「Android」手機中。透過手機上的「Market」程式,使用者可以直接在「Android」手機上瀏覽「Android Market」網站,查看各種可供使用的應用程式。看到喜歡的程式可以直接下載安裝。也可以透過「Android Market」為這些軟體打分、或是交換對這些軟體的意見...
This message was edited 12 times. Last update was at 31/08/2011 10:50:18

2011年8月27日 星期六

[Android 範例代碼] 使用 XML SAX Parser


轉載自 這裡
前言 :
這篇文章使用 SAX 來解析 XML 格式文件. 在 Android SDK 開發環境跟 XML 有關的方法有 SAX 與 DOM 兩種. 使用 DOM 解析器在開始工作前會先載進整個文件到記億體, 而在手機或終端裝置記億體比較嚴苛環境下往往會造成拖慢速度或記憶體不足的元凶. 使用 DOM 的好處是相對於 SAX 來講, 在解析文件時可以寫相對少的代碼. 但這裡我們的範例將使用 SAX, 原因是我們的開發環境對記億體較講究, 且使用 SAX 我們可以客制需要解析文件的部分並過濾不需要的相關訊息來加快處理的速度.

使用 XML SAX Parser :
考慮我們有 XML 檔案內容如下 :

接著我們要在 Activity 中處理該 xml 檔案, 首先我們要定義一個類別 Data 來存放我們解析出 XML 檔中有興趣的欄位或訊息 :
- Data.java :
  1. public class Data {   
  2.   // I know this could be an int, but this is just to show you how it works   
  3.   public String sectionId;   
  4.   public String section;   
  5.   public String area;   
  6.   
  7.   public Data() {   
  8.   
  9.   }   
  10. }  

接著 SAX (參考 XMLReader) 支援從 URI 直接 Streaming 動態解析 XML 或是從檔案讀取 XML 內容進行解析. 這裡我們因為將 xml 存放與檔案中, 故使用第二種方法. 在解析之前我們還必須定義一個類別或 Handler (DataHandler). 用來當作 XMLReader 的回呼函式. 在回呼函式中每當 Parser 解析完一個 Document 或 Element 便會透過對應的回呼函式 ( startElement() , endElement() etc ) 通知我們進行處理, 這時我們便可以取出有興趣的 Element 並過濾掉不需要的 Element. 而該類別或 Handler 需繼承 DefaultHandler 類別. 相關代碼如下 :
- DataHandler.java :
  1. public class DataHandler extends DefaultHandler {   
  2.   
  3.   // booleans that check whether it's in a specific tag or not   
  4.   private boolean _inSection, _inArea;   
  5.   
  6.   // this holds the data   
  7.   private Data _data;   
  8.   
  9.   /**  
  10.    * Returns the data object  
  11.    *  
  12.    * @return  
  13.    */   
  14.   public Data getData() {   
  15.     return _data;   
  16.   }   
  17.   
  18.   /**  
  19.    * This gets called when the xml document is first opened  
  20.    *  
  21.    * @throws SAXException  
  22.    */   
  23.   @Override   
  24.   public void startDocument() throws SAXException {   
  25.     _data = new Data();   
  26.   }   
  27.   
  28.   /**  
  29.    * Called when it's finished handling the document  
  30.    *  
  31.    * @throws SAXException  
  32.    */   
  33.   @Override   
  34.   public void endDocument() throws SAXException {   
  35.   
  36.   }   
  37.   
  38.   /**  
  39.    * This gets called at the start of an element. Here we're also setting the booleans to true if it's at that specific tag. (so we  
  40.    * know where we are)  
  41.    *  
  42.    * @param namespaceURI  
  43.    * @param localName  
  44.    * @param qName  
  45.    * @param atts  
  46.    * @throws SAXException  
  47.    */   
  48.   @Override   
  49.   public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {   
  50.   
  51.     if(localName.equals("section")) {   
  52.       _inSection = true;   
  53.   
  54.       _data.sectionId = atts.getValue("id");   
  55.     } else if(localName.equals("area")) {   
  56.       _inArea = true;   
  57.     }   
  58.   }   
  59.   
  60.   /**  
  61.    * Called at the end of the element. Setting the booleans to false, so we know that we've just left that tag.  
  62.    *  
  63.    * @param namespaceURI  
  64.    * @param localName  
  65.    * @param qName  
  66.    * @throws SAXException  
  67.    */   
  68.   @Override   
  69.   public void endElement(String namespaceURI, String localName, String qName) throws SAXException {   
  70.     Log.v("endElement", localName);   
  71.   
  72.     if(localName.equals("section")) {   
  73.       _inSection = false;   
  74.     } else if(localName.equals("area")) {   
  75.       _inArea = false;   
  76.     }   
  77.   }   
  78.   
  79.   /**  
  80.    * Calling when we're within an element. Here we're checking to see if there is any content in the tags that we're interested in  
  81.    * and populating it in the Config object.  
  82.    *  
  83.    * @param ch  
  84.    * @param start  
  85.    * @param length  
  86.    */   
  87.   @Override   
  88.   public void characters(char ch[], int start, int length) {   
  89.     String chars = new String(ch, start, length);   
  90.     chars = chars.trim();   
  91.   
  92.     if(_inSection) {   
  93.       _data.section = chars;   
  94.     } else if(_inArea) {   
  95.       _data.area = chars;   
  96.     }   
  97.   }   
  98. }  

最後要做的就是在 Activity 類別使用上述客製化過的類別與 SAX 套件來處理 XML 解析, 部分代碼如下 :
- Activity 部分代碼 :
  1. @Override   
  2. public void onCreate(Bundle icicle) {   
  3.   super.onCreate(icicle);   
  4.   setContentView(R.layout.main);   
  5.   
  6.   
  7.   // start the parser and get back the Data object, which you can do whatever you want with   
  8.   Data data = _parseXml();   
  9. }   
  10.   
  11. private Data _parseXml() {   
  12.   Data data = null;   
  13.   
  14.   // sax stuff   
  15.   try {   
  16.     SAXParserFactory spf = SAXParserFactory.newInstance();   
  17.     SAXParser sp = spf.newSAXParser();   
  18.   
  19.     XMLReader xr = sp.getXMLReader();   
  20.   
  21.     DataHandler dataHandler = new DataHandler();   
  22.     xr.setContentHandler(dataHandler);   
  23.   
  24.     xr.parse(new InputSource(new FileInputStream("/path/to/data.xml")));   
  25.   
  26.     data = dataHandler.getData();   
  27.   
  28.   } catch(ParserConfigurationException pce) {   
  29.     Log.e("SAX XML""sax parse error", pce);   
  30.   } catch(SAXException se) {   
  31.     Log.e("SAX XML""sax error", se);   
  32.   } catch(IOException ioe) {   
  33.     Log.e("SAX XML""sax parse io error", ioe);   
  34.   }   
  35.   
  36.   return data;   
  37. }  

上面代碼首先透過Singleton模式 SAXParserFactory.newInstance() 取的 SAX Parser 的工廠並接著取得 XMLReader. 接著將剛剛我們撰寫的 Handle/回呼函式 傳進去當作解析過程中抽取我們有興趣的訊息. 解析完畢後, 我們並透過 Handler (DataHandler) 的函式 getData() 取回剛剛我們用來存放有興趣資訊的類別, 最後一步便是根據需求來處理這些資訊. (例如如果有 GUI, 便可以使用 TextView.setText() 將之顯示出來).

補充說明 :
android xml parser 如何從網路下載XML並解析
Android XML Parsing Tutorial – Using DOMParser
Moving ahead from Android XML Parsing using SAXParser, here we are going to see about how to parse a XML using DOM Parser...
This message was edited 8 times. Last update was at 27/08/2011 22:59:45

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...