Android語音識別技術、訊息推送機制、二維碼掃描技術、NDK、JNI
一、常用資料結構:陣列,堆,棧,佇列,連結串列,樹,圖,散列表
陣列:把具有相同型別的若干變數按有序的形式組織起來。
堆:是一個特殊的樹形資料結構,每個結點都有一個值。一般說的堆是指二叉堆。他的最大特點就是根節點的值最小或最大,並且根節點的兩個子樹也是一個堆。
棧:只能在某一端插入和刪除的特殊線性表。按照先進後出的原則儲存資料,先進入的資料被壓入棧底,最後的資料在棧頂,需要讀資料的時候從棧頂開始彈出資料。
佇列:一種特殊的線性表,只允許在表的前端進行刪除操作,而在表的後端進行插入操作。插入端叫隊尾,刪除端叫隊頭。佇列是按照先進先出或後進先出的原則組織資料。佇列中沒有元素的時候,
成為空對列。
連結串列
樹:包含n(n>0)個結點的有窮集合K,在K中定義了一個關係N,N滿足以下條件。(1)有且僅有一個結點K0,對於關係N來說沒有前驅,稱K0為根節點。
(2)除K0外,K中的每個結點,對於關係N來說有且僅有一個前驅。
(3)K中各個結點,對於關係N來說可以有m個
後繼。
圖:是由結點的有窮集合V和邊的集合E組成。在圖結構中,結點稱為頂點,邊是頂點的有序偶對,若兩個頂點之間存在一條邊,就表示這兩個頂點的是相鄰關係。
散列表:如果結構中存在關鍵字和K相等的記錄,則必定在f的儲存位置上。不需比較便可直接取得查詢記錄,稱這個關係為雜湊函式。
二、排序思想
快速排序:它的基本思想是通過一趟掃描後,使得排序序列的長度能大幅度地減少。在氣泡排序中,一次掃描只能確保最大數值的數移到正確位置,而待排序序列的長度可能只減少1。快速排序通過一趟掃描,就能確保某個數(以它為基準點吧)的左邊各數都比它小,右邊各數都比它大。然後又用同樣的方法處理它左右兩邊的數,直到基準點的左右只有一個元素為止。
選擇排序是常用內部排序的一種,常見的實現演算法有直接選擇排序演算法和堆排序演算法,選擇排序的基本思想是每次從待排資料中選擇第n小的資料放到排序列表的第n個位置,假如共有N個數據待排,那麼經過N-1次排序後,待排資料就已經按照從小到大的順序排列了。
直接選擇排序演算法的思想比較簡單:(假設資料放在一個數組a中,且陣列的長度是N)
1:從a[0]-a[N-1]中選出最小的資料,然後與a[0]交換位置
2:從a[1]-a[N-1]中選出最小的資料,然後與a[1]交換位置(第1步結束後a[0]就是N個數的最小值)
氣泡排序的基本思想是相鄰兩個元素進行比較,然後交換。第一趟後最後一個數組元素是最大或最小元素,然後對前n-1個數重複如此n-1趟。
3:從a[2]-a[N-1]中選出最小的資料,然後與a[2]交換位置(第2步結束後a[1]就是N-1個數的最小值)
以此類推,N-1次排序後,待排資料就已經按照從小到大的順序排列了。
插入排序:基本思想,每次將一個待排序的資料元素,插入到前面已經排好序的數列中的適當位置,是數列依然有序;直到待排序列元素插入完為止。
堆排序:是一種樹形選擇排序,在排序過程中,將數列看成是一顆完全二叉樹的順序儲存結構,利用完全二叉樹中雙親結點和孩子結點之間的呢在關係來選擇最小的元素。
三、二維條碼
什麼是二維條碼?
二維條碼能夠在橫向和縱向兩個方位同時表達資訊,因此能在很小的面積內表達大量的資訊。
二維條碼可以分為堆疊式二維條碼和矩陣式二維條碼。堆疊式二維條碼形態上是由多行短截的一維條碼堆疊而成;矩陣式二維條碼以矩陣的形式組成,在矩陣相應元素位置上用“點”表示二進位制“1”,用“空”表示二進位制“0”,由“點”和“空”的排列組成程式碼。
堆疊式二維條碼,有代表性的包括PDF417、Code 49、Code 16K等。矩陣式二維條碼有代表性的是Code one、Aztec、Date Matrix、QR碼等。
二維條碼的特點:
1.高密度編碼,資訊容量大:可容納多達1850個大寫字母或2710個數字或1108個位元組,或500多個漢字,比普通條碼資訊容量約高几十倍。
2.編碼範圍廣:該條碼可以把圖片、聲音、文字、簽字、指紋等可以數字化的資訊進行編碼,用條碼錶示出來;可以表示多種語言文字;可表示影象資料。
3.容錯能力強,具有糾錯功能:這使得二維條碼因穿孔、汙損等引起區域性損壞時,照樣可以正確得到識讀,損毀面積達50%仍可恢復資訊。
4.譯碼可靠性高:它比普通條碼譯碼錯誤率百萬分之二要低得多,誤位元速率不超過千萬分之一。
5.可引入加密措施:保密性、防偽性好
6.成本低,易製作,持久耐用。
7.條碼符號形狀、尺寸大小比例可變
8.二維條碼可以使用鐳射或CCD閱讀器識讀。
Android上使用Zxing識別條形碼和二維碼。ZXing是個很經典的條碼/二維碼識別的開源類庫。也可以採用Barcode Scanner。
四、訊息推送:
要獲取伺服器上不定時更新的資訊一般來說有兩種方法,第一種是客戶端使用Pull(拉)的方式,隔一段時間就去伺服器上獲取資訊,看是否有更新的資訊出現。第二種就是伺服器使用Push(推送)的方式,當伺服器端有新資訊了,則把最新的資訊Push到客戶端上。
雖然Pull和Push兩種方式都能實現獲取伺服器端更新資訊的功能,但是明顯來說Push is better than pull。因為Pull方式更費客戶端的網路流量,更主要的是費電量。
Android Cloud to Device Messaging (C2DM)是一個用來幫助開發者從伺服器向Android應用程式傳送資料的服務。該服務提供了一個簡單的、輕量級的機制,允許伺服器可以通知移動應用程式直接與伺服器進行通訊,以便於從伺服器獲取應用程式更新和使用者資料。C2DM服務負責處理諸如訊息排隊等事務並向運行於目標裝置上的應用程式分發這些訊息。即後來的GCM,在國內難以使用。
在Android下最有的方式應該採取XMPP協議推送Android資訊:
首先介紹一下XMPP基於可擴充套件標記語言(XML)的協議,它用於即時訊息(IM)以及線上探測。這個協議可能最終允許因特網使用者向因特網上的其他任何人傳送即時訊息。
Google官方的C2DM伺服器底層也是採用XMPP協議進行的封裝。
androidpn是一個基於XMPP協議的java開源Androidpush notification實現。它包含了完整的客戶端和伺服器端。該伺服器端基本是在另外一個開源工程openfire基礎上修改實現的。它的實現示意圖如下:
androidpn(韓國開發)客戶端需要用到一個基於java的開源XMPP協議包asmack,這個包同樣也是基於openfire下的另外一個開源專案smack,不過我們不需要自己編譯,可以直接把androidpn客戶端裡面的asmack.jar拿來使用。客戶端利用asmack中提供的XMPPConnection類與伺服器建立持久連線,並通過該連線進行使用者註冊和登入認證,同樣也是通過這條連線,接收伺服器傳送的通知。
androidpn伺服器端也是java語言實現的,基於openfire開源工程,不過它的Web部分採用的是spring框架,這一點與openfire是不同的。Androidpn伺服器包含兩個部分,一個是偵聽在5222埠上的XMPP服務,負責與客戶端的XMPPConnection類進行通訊,作用是使用者註冊和身份認證,併發送推送通知訊息。另外一部分是Web伺服器,採用一個輕量級的HTTP伺服器,負責接收使用者的Web請求。伺服器架構如下:
最上層包含四個組成部分,分別是SessionManager,Auth Manager,PresenceManager以及Notification Manager。SessionManager負責管理客戶端與伺服器之間的會話,Auth Manager負責客戶端使用者認證管理,Presence Manager負責管理客戶端使用者的登入狀態,NotificationManager負責實現伺服器向客戶端推送訊息功能。
伺服器端介面如下,分別對應了上述的幾個功能模組:
傳送以後,我們可以在手機端看到接收的訊息:
這個解決方案的最大優勢就是簡單,我們不需要象C2DM那樣依賴作業系統版本,也不會擔心某一天Google伺服器不可用。利用XMPP協議我們還可以進一步的對協議進行擴充套件,實現更為完善的功能。
採用這個方案,目前只能傳送文字訊息,不過對於推送來說一般足夠了,因為我們不能指望通過推送得到所有的資料,一般情況下,利用推送只是告訴手機端伺服器發生了某些改變,當客戶端收到通知以後,應該主動到伺服器獲取最新的資料,這樣才是推送服務的完整實現。
國內的推送服務商:
個推:個推與新浪微博之間實現合作。這大大加強了其知名度。個推通過IP通道實現使用者間免費實時通訊服務,支援文字,圖片,語音,視訊及檔案的傳輸。個推注重的是整體策略的佈局,對於企業型APP來說較為實用!
極光:極光推送在推送方面表現出的是短平快,極光推送可以傳送訊息,效果分析圖表等。與此同時,極光推送開通了定製化服務,可以推送時間、使用者群、位置等。極光推送更偏重於個人或小團體的APP,靈活、迅速是其優勢所在。
蝴蝶:蝴蝶雲推送將發展的核心定位在了雲端系統,制約蝴蝶雲推送發展的,一是雲端技術的發展能力;二是地面部隊的推廣,蝴蝶雲推送能否讓APP開發者所採用,需要蝴蝶推送團隊仔細考量。
智遊:針對APP開發,穩定維護長連線是推送平臺的一個基礎,當運營商在2G,2.5G的條件下,出現了網路超齡超負荷,造成信令風暴,以至於刻意縮短空閒連線的釋放超時,以起到節省通道資源的目的。智遊推送團隊為了維護長連線的穩定性,避免在信令風暴出現的時候,保持連線的穩定性,使用了多項核心技術,由於涉及到公司核心業務,需要保密。
個推,1. 第三方客戶端整合個推SDK。
2. 第三方客戶端啟動的時候,呼叫SDK介面,啟動推送服務,SDK後臺執行並維護和個推服務端的長連線,實現SDK註冊和登入。
3. 第三方服務端呼叫個推伺服器的介面,將要傳送的資料通過個推伺服器傳送到指定身份的個推SDK當中。
4. 個推SDK解析定製資料,並且把第三方伺服器透傳的資料傳送給第三方客戶端,第三方客戶端根據伺服器的資料做出相應的動作或者展現。
五、google語音識別技術
原理
在Android 4.1中,Google加入了被稱為“神經網路”的技術,這種技術將語音識別錯誤率降低了25%以上。當你對你的Android手機說出一個要搜尋的關鍵字時,你的聲音會轉變成聲譜圖,被分成8段然後傳送到不同的伺服器上。Google通過分析以前記錄過的無數聲譜圖,來推測你究竟說了什麼。
在這個處理過程中,Google做了兩件事:
1,從聲譜圖中分辨出母音和子音;
2,從母音和子音的組合中推測出單詞,然後再做進一步處理。這就和你在看見一張圖片的時候是一樣的:你的大腦總會先尋找這張圖片的邊緣再看內容。
語音識別,藉助於雲端技術可以識別使用者的語音輸入,包括語音控制等技術,使用前需要安裝語音識別服務。
Android開發實現:
啟動,RecognizerIntent。
設定語言模式
開始語音識別
把語音傳至google伺服器,雲端搜尋
搜尋完畢,傳回資料,得到語音字元
六、JNI
JNI是java NativeInterface,java本地介面。與硬體或作業系統進行互動,提高程式效能會使用C/C++編寫的程式碼,Java程式碼與其他語言編寫的程式碼進行互動,於是產生了JNI。
書寫步驟:
(1)編寫帶有native宣告的方法的類。
(2)javac編譯該java類,javah+java類名生成副檔名為h的標頭檔案。
(3)C/C++實現本地方法。(native宣告的方法)
(4)將C/C++編寫的檔案生成動態連結庫。
編寫java程式:
Public class HelloWorld{
Publicnative void dispalyHelloWorld();
Static{
System.LoadLibrary(“hello”);
}
Public staticvoid main(String[] args){
New HelloWorld().displayHelloWorld();
}
}
編譯:Javac HelloWorld.java
生成標頭檔案:Javah HelloWorld
編寫本地方法:本地方法名和標頭檔案本地方法名相同。
linux下何謂.so檔案:1. 用過windows的同學應該都知道 .dll檔案吧, 這二者有什麼共通之處呢,其實 .so檔案就跟.dll檔案差不多.
2.一般來說.so檔案就是常說的動態連結庫,都是C或C++編譯出來的。與Java比較就是:它通常是用的Class檔案(位元組碼).
3.Linux下的.so檔案時不能直接執行的,一般來講,.so檔案稱為共享庫.
4.dll也是由C/C++編寫,由VC工具編譯。
GDB是GNU開源組織釋出的一個強大的UNIX下的程式除錯工具。
NDK全稱:NativeDevelopment Kit。
1、NDK是一系列工具的集合。
NDK提供了一系列的工具,幫助開發者快速開發C(或C++)的動態庫,並能自動將so和java應用一起打包成apk。這些工具對開發者的幫助是巨大的。[1]
NDK集成了交叉編譯器,並提供了相應的mk檔案隔離平臺、CPU、API等差異,開發人員只需要簡單修改mk檔案(指出“哪些檔案需要編譯”、“編譯特性要求”等),就可以創建出so。
NDK可以自動地將so和Java應用一起打包,極大地減輕了開發人員的打包工作。
2、NDK提供了一份穩定、功能有限的API標頭檔案宣告。
NDK產生so動態連結庫供JNI呼叫。
顯示大量圖片時,如何管理記憶體?
儘量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource來設定 一張大圖,因為這些函式在完成decode後,最終都是通過java層的createBitmap來完成的,需要消耗更多記憶體。
因此,改用先通過BitmapFactory.decodeStream方法,創建出一個bitmap,再將其設為ImageView的 source,decodeStream最大的祕密在於其直接呼叫JNI>>nativeDecodeAsset()來完成decode,無需再使用java層的createBitmap,從而節省了java層的空間。
如果在讀取時加上圖片的Config引數,可以跟有效減少載入的記憶體,從而跟有效阻止拋out of Memory異常
記憶體溢位解決辦法:
(1) 壓縮圖片
(2) 優化Dalvik虛擬機器的堆記憶體分配,在oncreate方法裡面呼叫下列方法;VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);
(3)及時回收Bitmap物件
(4)HandlerThread(非同步載入)+LruCache(記憶體快取)+DiskLruCache(硬碟快取).