㈠ android輸入事件模擬
在一些自動化測試等情景下,輸入Android應用程序產生一些屏幕點擊等的輸入事件以實現特定需求。本文總結了幾種Android中模擬產生輸入事件的方式。
在Android中有兩個shell中運行的工具可以模擬培棚產生輸入事件 input 和 sendevent 。由於sendevent需要用到相應的設備,需要考慮許可權問題,因此一般不常用,這里只介紹input。
如點擊屏幕(200,300)處只需要如下命令即可:
Instrumentation是Android提供的一個測試工具,可以通過它監測系統與應用程序之間的交互。使用此方法需要如下的 system 許可權:
Instrumentation模擬點擊屏幕(200,300)事件的方法如下:
Android Inputmanager的 injectEvent() 方法配讓則也可以模擬產生輸入事件(API16以上版本)。不過此方法屬於隱藏方法,需要滑嫌反射調用,這里不作具體描述。
1 https://www.pocketmagic.net/injecting-events-programatically-on-android/#.VKn42M2UfCI
㈡ 如何讓所有 View 都可以帶上點擊的水波紋效果
V2EX›Android
如何讓所有 View 都可以帶上點擊的水波紋效果?
AtlantisZ· 2015-11-12 23:49:00 +08:00
這是一個創建於 483 天前的主題,其中的信息可能已經有所發展或是發生改變。
根據 G官方文檔
定製觸摸反饋
材料設計中的觸摸反饋可在用戶與 UI 元素互動時,在接觸點上提供即時視覺確認。適用於按鈕的默認觸摸動畫使用全新 RippleDrawable 類別,以波紋效果實現不同狀態間的轉換。
在大多數情況下,您應以下列方式指定視圖背景,在您的視圖 XML 中應用此功能:
?android:attr/selectableItemBackground 指定有界的波紋
?android:attr/ 指定越界的波紋
注意: 是 API 級別 21 中推出的新屬性。
此外,您可利用 ripple 元素將 RippleDrawable 定義為一個 XML 資源。
您可以為 RippleDrawable 對象指定一種顏色。如果要改變默認觸摸反饋顏色,請使用主題的 android:colorControlHighlight 屬性。
但是發現有時候一個 LinearLayout 設置 android:background="?android:attr/selectableItemBackground"
就帶上了水波紋效果,有的不行,,TextView 也是,設置 android:background="?android:attr/selectableItemBackground"有的帶上了,有的不行.
RecyclerView 的 Item layout 根布局加上了這個屬性也無效果.
後來輾轉反側,找到了 Stackflow 找到的回答,也不奏效.
FrameLayout view = (FrameLayout) View.inflate(context, R.layout.item_top_news, null);
RippleDrawable drawable = (RippleDrawable) mActivity.getResources()
.getDrawable(R.drawable.ripple_background);
view.setClickable(true);
view.setForeground(drawable);
求解如何實現 BiliBili MD 客戶端,幾乎每個 View 點擊都有的水波紋效果.
波紋
attr
Android
drawable
12 回復 |直到 2015-11-19 21:41:40 +08:00
1
little_cup 2015-11-13 00:04:55 +08:00
從設計的角度說,你不應該讓所有的 View 都帶上 Ripple 效果,只應該讓可點擊的元素帶上。
從程序的角度說,你無法讓所有的 View 都帶上 Ripple 效果,只能讓拿到點擊事件的元素帶上。
2
AtlantisZ 2015-11-13 00:15:38 +08:00
@little_cup額,我只是感覺很難有短文字敘述清楚問題,原來標題是如何讓 RecyclerView 的子 Item 帶上水波紋效果了.感覺太局限了.
請問現在 RecyclerView 的子 Item 已經可以響應點擊事件跳轉 Activity 了,請問如何才能帶上水波紋的點擊效果.我在 Item 的 layout 根布局修改 android:background="?android:attr/selectableItemBackground"沒有效果.
3
little_cup 2015-11-13 00:25:24 +08:00
@AtlantisZ哪個 view 綁定 click 就給哪個設 selectableItemBackground 。當然注意不要被其他 view 在視覺上覆蓋了。
4
AtlantisZ 2015-11-13 00:42:01 +08:00
在 onBindViewHolder 中
TypedValue typedValue = new TypedValue();
mActivity.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, typedValue, true);
Drawable background = getResources().getDrawable(typedValue.resourceId);
// Drawable background = getResources().getDrawable(R.drawable.ripple_background);
holder.rootView.setBackground(background);
holder.rootView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(getContext(), VideoDetailActivity.class));
// ToastUtils.showToast(mActivity, "av :: " + mRecommendList.get(position).av);
}
});
還是沒有用額.
5
AtlantisZ 2015-11-13 11:17:22 +08:00
@little_cup
在 onBindViewHolder 中
TypedValue typedValue = new TypedValue();
mActivity.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, typedValue, true);
Drawable background = getResources().getDrawable(typedValue.resourceId);
// Drawable background = getResources().getDrawable(R.drawable.ripple_background);
holder.rootView.setBackground(background);
holder.rootView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(getContext(), VideoDetailActivity.class));
}
});
還是沒有用額.
6
miao1007 2015-11-15 19:55:46 +08:00
這樣寫不會報錯?
ClassNoFound 這個錯誤在低 API 下會出現
7
ybjaychou 2015-11-17 20:53:35 +08:00
我也是在愁這個問題,同樣是在 RecyclerView 的 Item 裡面,不知道怎麼才能有點擊效果,就算不是水紋也可以啊。。
順便搭個車,就是怎麼在 RecyclerView 裡面做多選操作,然後 Toolbar 上面出現操作按鈕,不知道有人做過沒
8
ecma 2015-11-18 19:01:06 +08:00
同表示弄不出波紋點擊效果,不知道是不是 SDK 版本的原因。
目前暫時通過 github 上一個開源項目實現那個效果了。。
https://github.com/balysv/material-ripple
9
ecma 2015-11-18 19:05:55 +08:00
@ybjaychou
我自己是在 itemView 上加入了一個 checkBox ,平常處於隱藏狀態,需要批量刪除的適合,重新載入 RecyclerView 讓 checkBox 顯示。而 checkBox 的點擊事件則是往一個數組裡面扔 item 的 id ,那樣就知道選了那些。
toolbar 的改變的話可以通過 onPrepareOptionsMenu 和 invalidateOptionsMenu()來改變,當然也可以通過 ActionMode.Callback 來實現
通過這種方法來實現的話需要對 checkBox 的點擊進行標示優化,避免列表滑動的適合 checkBox 錯誤問題
10
ybjaychou 2015-11-19 12:52:08 +08:00 via Android
@ecma好,謝謝,我試試!
11
AtlantisZ 2015-11-19 16:49:47 +08:00
@ybjaychou
@ecma
參考http://stackoverflow.com/questions/26961147/touch-feedback-with-recyclerview-and-cardview/29033353解決了 RecyclerView 中 Item 無水波紋效果的問題額.
12
ecma 2015-11-19 21:41:40 +08:00
@AtlantisZ
THX!等下就去試試嘍
㈢ android系統開發要用哪些知識
android 技術內幕系統卷
第1章 准備工作 /1 1.1 深入認識android /2 1.1.1 android的系統構架 /2 1.1.2 android的初始化流程 /5 1.1.3 各個層次之間的相互關系 /8 1.1.4 android系統開發(移植)和應用開發 /11 1.2 獲取和編譯android的源碼 /13 1.2.1 環境配置 /13 1.2.2 獲取android源碼 /14 1.2.3 編譯android的源碼及其工具包 /16 1.2.4 運行android系統 /21 1.3 開發環境搭建 /23 1.3.1 應用開發環境搭建 /23 1.3.2 源碼開發環境搭建 /26 1.4 android源碼結構 /32 1.5 小結 /33 第2章 android的內核機制和結構剖析 /34 2.1 linux與android的關系 /35 .2.1.1 為什麼會選擇linux /35 2.1.2 android不是linux /35 2.2 android對linux內核的改動 /37 2.2.1 goldfish /37 2.2.2 yaffs2 /38 2.2.3 藍牙 /39 2.2.4 調度器(scheler)/39 2.2.5 android新增的驅動 /40 2.2.6 電源管理 /41 2.2.7 雜項 /41 2.3 android對linux內核的增強 /42 2.3.1 alarm(硬體時鍾)/43 2.3.2 ashmem(匿名內存共享)/46 2.3.3 low memory killer(低內存管理)/52 2.3.4 logger(日誌設備)/56 2.3.5 android pmem /65 2.3.6 switch /79 2.3.7 timed gpio /88 2.3.8 android ram console /94 2.4 小結 /99 第3章 android的ipc機制--binder /100 3.1 binder概述 /101 3.1.1 為什麼選擇binder /101 3.1.2 初識binder /102 3.2 binder驅動的原理和實現 /102 3.2.1 binder驅動的原理 /102 3.2.2 binder驅動的實現 /103 3.3 binder的構架與實現 /132 3.3.1 binder的系統構架 /132 3.3.2 binder的機制和原理 /133 3.4 小結 /150 第4章 電源管理 /151 4.1 電源管理概述 /152 4.2 電源管理結構 /152 4.3 android的電源管理機制 /153 4.4 android電源管理機制的實現 /154 4.5 小結 /187 第5章 驅動的工作原理及實現機制 /188 5.1 顯示驅動(framebuffer)/189 5.1.1 framebuffer的工作原理 /189 5.1.2 framebuffer的構架 /190 5.1.3 framebuffer驅動的實現機制 /190 5.2 視頻驅動(v4l和v4l2)/201 5.2.1 v4l2介紹 /201 5.2.2 v4l2的原理和構架 /201 5.2.3 v4l2的實現 /202 5.3 音頻驅動(oss和alsa)/208 5.3.1 oss與alsa介紹 /208 5.3.2 oss的構架與實現 /209 5.3.3 alsa的構架與實現 /213 5.4 mtd驅動 /214 5.4.1 mtd驅動的功能 /214 5.4.2 mtd驅動的構架 /215 5.4.3 mtd驅動的原理及實現 /215 5.5 event輸入設備驅動 /223 5.5.1 input的系統構架 /223 5.5.2 event輸入驅動的構架 /224 5.5.3 event輸入驅動的原理 /224 5.5.4 event輸入驅動的實現 /225 5.6 藍牙驅動(bluetooth)/235 5.6.1 bluetooth驅動的構架 /235 5.6.2 bluez的原理及實現 /237 5.7 wlan驅動(wi-fi)/244 5.7.1 wlan構架 /244 5.7.2 wi-fi驅動的實現原理 /245 5.8 小結 /245 第6章 原生庫的原理及實現 /246 6.1 系統c庫(bionic libc)/247 6.1.1 bionic libc功能概述 /247 6.1.2 bionic libc實現原理 /248 6.2 功能庫 /258 6.2.1 webkit構架與實現 /258 6.2.2 多媒體框架與實現 /275 6.2.3 android sqlite框架及原理 /285 6.3 擴展庫 /289 6.3.1 skia底層庫分析 /289 6.3.2 opengl底層庫分析 /299 6.3.3 android-openssl實現及運用 /306 6.3.4 freetype及font engine manager /317 6.3.5 freetype結構體系和渲染流程 /317 6.4 原生服務 /328 6.4.1 audioflinger實現 /328 6.4.2 surfaceflinger實現 /341 6.5 小結 /353 第7章 硬體抽象層的原理與實現 /354 7.1 硬體抽象層的實現原理 /355 7.1.1 android hal構架 /355 7.1.2 android hal的實現 /357 7.2 android overlay構架與實現 /361 7.2.1 android overlay系統構架 /361 7.2.2 overlay hal框架與實現 /362 7.2.3 overlay與surfacefinger /369 7.3 android camera 構架與實現 /375 7.3.1 android camera系統構架 /375 7.3.2 camera hal框架與實現 /377 7.3.3 camera本地實現 /385 7.4 android audio hal實現 /394 7.4.1 audio hal框架 /395 7.4.2 android默認的audio hal實現 /398 7.4.3 mp功能的audio hal實現 /400 7.4.4 基於a2dp的藍牙音頻設備hal實現 /402 7.4.5 模擬器上的audio hal實現 /403 7.5 android ril實現 /404 7.5.1 android ril構架 /404 7.5.2 radiooptiongs實現 /407 7.5.3 libril庫實現 /409 7.5.4 reference-ril庫實現 /415 7.5.5 rild守護進程實現 /418 7.5.6 request流程分析 /423 7.5.7 response流程分析 /427 7.6 android sensor hal實現 /434 7.6.1 android sensor構建 /434 7.6.2 sensor hal介面 /435 7.6.3 sensor hal實現 /438 7.7 android wifi hal實現 /441 7.7.1 android wifi系統構架 /441 7.7.2 wpa_supplicant框架 /442 7.7.3 wifi hal實現 /444 7.8 android藍牙本地實現 /447 7.8.1 android藍牙構架 /447 7.8.2 bluez結構體系 /448 7.8.3 bluez適配層 /452 7.9 android 定位實現 /453 7.9.1 定位系統構架 /453 7.9.2 gps hal實現 /454 7.10 android power hal實現 /459 7.11 android vibrator hal實現 /461 7.12 小結 /462 第8章 dalvik虛擬機的構架、原理與實現 /463 8.1 dalvik虛擬機概述 /464 8.1.1 什麼是dalvik虛擬機 /464 8.1.2 dalvik虛擬機的功能 /464 8.1.3 dalvik虛擬機與java虛擬機的區別 /465 8.2 dalvik構架與實現 /466 8.2.1 dalvik系統構架 /466 8.2.2 dx和dexmp工具 /468 8.2.3 .dex文件格式解析 /470 8.2.4 dalvik內部機制 /487 8.2.5 dalvik進程管理 /492 8.2.6 dalvik內存管理 /501 8.2.7 dalvik載入器 /509 8.2.8 dalvik解釋器 /517 8.2.9 dalvik jit /519 8.3 jni的構架與實現 /523 8.3.1 jni構架 /523 8.3.2 jni實現 /524 8.4 小結 /526 第9章 android 核心庫 /527 9.1 android核心庫簡介 /528 9.2 android系統api /529 9.2.1 android包 /529 9.2.2 android資源包 /529 9.2.3 apicheck機制 /529 9.3 小結 /532 後記 /533
㈣ 度十大游戲API
應用開發者利用內容,先抓眼球,引導下載,然後坐收新用戶,通過社交應用分享傳根據ESA(Entertainment Software Association)最近一項報告,美國有超過1億5千萬視頻 游戲 玩家,其中大約42%的人每周在視頻 游戲 上花費3小時以上。根據PwC的預測:到,全球視頻游戲收入將接近931.8億美元,而全球社交/休閑游戲市場則接近225.2億美元。如此驚人的數據擺在眼前,難怪游戲成為了ProgrammableWeb上最熱門API搜索項。最近傳出了很多游戲API的趣聞。9月,DMCA侵權通知(DMCA notice)發出,包括Bukkit,CraftBukkit,Spigot和Cauldron在內的一眾Minecraft游戲社區項目被關閉。DMCA侵權通知事件後不久,Minecraft的開發公司Mojang就被微軟公司以25億美元的價格收購。上個月343 Instries對外宣布,他們計劃專為Halo 5推出一個公共數據(public stats)API:Guardians視頻游戲最近為Xbox One推出了公共數據API。今年年初,ArenaNet為Guild Wars 2 API發布了一個額外的OAuth 2.0支持,2個月後又代之以API key system。此文推薦的Top 10精品游戲API涵蓋各種豐富內容,基於熱度(Popularity)、潛力(Potential)、文檔(Documentation)、便捷(Ease of Use)、功能(Functionality)進行對比,包括(但不僅限於)檢索視頻游戲數據,游戲貨幣化,視頻游戲串流和錄像,視頻游戲評論和模型等等。
1. EVE Online
科幻網游巨作EVE Online(星戰前夜)是最風靡的大型多人在線角色扮演游戲(MMORPG),曾獲獎無數,位列時代PC游戲排行榜前100第36位。Eve Online還永久入駐了紐約現代藝術博物館(MoMA)的應用設計(Applied Design)區,訪客可在4K超高清視頻前欣賞Eve Online中宏偉的宇宙景觀。
EVE Online CREST和XML APIs可用於對游戲中的角色、行業、市場、太陽系、聯盟和公司等數據進行編程。EVE Online開發者網站的資源頁面上能找到Eve Online API, API文檔,客戶端庫和論壇等內容。EVE Online CREST RESTful API的API文檔為簡單好上手的Wiki格式;Eve Online XML API的API文檔已遷移至第三方開發者文檔網站。
2. Riot Games
Riot Games(拳頭游戲公司)開發了炙手可熱的多人聯機在線競技游戲(MOBA)“英雄聯盟(LOL)”。根據該公司官網數據:每天在線人數約為2700萬,每月在線人數約為6700萬。今年7月份,由於版本更新後游戲內存在嚴重缺陷,Riot Games關閉了“英雄聯盟”排位賽,但游戲仍舊熱度不減, 位列時代PC游戲排行榜前100第35位。
Riot Games API用於對“英雄聯盟”中最近的游戲、玩家排名、符文、熟練度級別等信息進行編程。Riot Games的開發者網站設計精美,API狀態頁面、開發者論壇和API互動文檔等內容有序呈現。
3. Battle.net
在線視頻游戲網站Battle.net主要推廣Blizzard Entertainment公司開發的游戲:從動作角色扮演游戲(ARPG)“暗黑破壞神(Diablo)III”,到大型多人在線角色扮演游戲(MMORPG)“魔獸世界(WoW)”;從軍事科幻即時戰略游戲“星際爭霸(StarCraft)II”,到在線戰略紙牌游戲“爐石傳說(Hearthstone)”。“暗黑破壞神III”,“星際爭霸II”,“魔獸世界”分別位列時代PC游戲排行榜前100第79、29、31位。
最近經Blizzard Entertainment重新設計之後,開發者網站呈現開發者論壇、OAuth、游戲社區API指南和API互動文檔(I/O Docs)有機組合的新面貌。如今Battle.net API又多了暗黑破壞神III、魔獸世界、星際爭霸II、Community API以及游戲數據 API。而最近該公司又在Battle.net論壇上宣布“爐石傳說:魔獸英雄傳(Hearthstone: Heroes of Warcraft)API即將上線。
4. Facebook Game Services
當下Facebook游戲已破2000大關,其中不乏大熱門,例如“Candy Crush Saga(糖果粉碎傳奇)”、“Clash of Clans(部落戰爭)”,“Farm Heroes Saga(農場英雄傳奇)”,“Pet Rescue Saga(寵物大營救)”和“Words With Friends”。
Facebook用戶主要在智能手機和平板電腦上玩游戲,還有一些選擇了台式電腦。年初,Facebook開始推出一些台式電腦視頻應用廣告來增加游戲安裝量。
Facebook Games Developer Center為游戲開發者提供包括(但不僅限於)Achievements API、Scores API、應用通知、請求、游戲中心、Facebook Unity SDK等服務。在這里可以找到游戲概覽。API遷移(migration)指南、教程、清單、游戲貨幣化等有用信息。
5. Google Play Games Services
3月上線的Google Play集音樂、電子書、游戲、電影、期刊及其他Android應用於一身。今年3月,Google又宣布為Android游戲開發者新添游戲分析、AdMob原生廣告、AdMob應用內付費廣告及針對Android TV(安卓TV)的Nearby Connections第二屏API。
Google Developers:Games(谷歌開發者游戲網站)上很多API、SDK及包括(但不僅限於)game publishing API,Unity插件、Play Games Services(成就、排行榜、玩家級別等)和Google AdMob的各類服務唾手可得。Google Play Games Services網站內容雖多,但條理清晰,多而不雜。
6. Guild Wars 2
Guild Wars 2(激戰2)是風靡當下的一款大型多人在線角色扮演游戲(MMORPG),故事以虛幻的泰瑞亞大陸為背景,上演著波瀾壯闊的英雄史詩。上個月ArenaNet推出了首次對Guild War2的擴展版本——Guild Wars 2:Heart of Thorns(激戰2:瘋王)。
Guild War2的新建賬戶超700萬,游戲時間超14億小時,玩家互送禮物超223,484,104份,大大鼓勵ArenaNet擴展了Guild War 2。Guild War 2位列時代PC游戲排行榜前100第47位。
Guild War 2 API用於對游戲道具、地圖、交易站、World vs. World游戲模式及成就等游戲數據進行編程。Guild Wars 2的API文檔是簡單好上手的Wiki格式,使用廣泛。Guild Wars 2 API論壇也很活躍,可以找到API更新和API相關問題,還能與其他開發者討論錯誤和漏洞,參與API CDI線程等。
7. Steam
風靡當下的視頻游戲和娛樂平台Steam有超過6,000款游戲供玩家選擇,其游戲社區坐擁超過1億用戶。GameStop稱Steam從去年起就“蒸蒸日上”了,游戲數量從的3,700上升到8月的6,000。今年早些時候Valve公司宣布:內容創作者可通過Steam Workshop出售針對現有游戲的mods
Steam網頁API可以檢索應用新聞,搜索游戲全球數據、玩家評論、玩家成就、最近玩過的游戲等數據。Steam網頁API文檔為1頁,以Wiki模式呈現,還有很多現成的客戶端庫。API可以用JSON、XML、CSV和VDF(Valve Data Format)格式返回數據。
8. TwitchTV
炙手可熱的實時流媒體視頻平台和游戲社區Twitch當下的月均獨立訪客超過1億,直播用戶超過170萬。雖然該平台主攻游戲,但最近Twitch Interactive公司又宣布推出Twitch Creative社區,為藝術家、工匠、開發者等創意人士提供交流空間。Twitch還跟Battle.net、Google Play Games等流行視頻游戲平台進行合作,支持用Twitch賬戶登錄進行游戲串流錄像、在線直播游戲等
TwitchTV API可實現Twitch Connect、視頻、串流、搜索及其他內容與第三方應用的整合。GitHub上有完整的API文檔,另外Twitch網頁上還有開發者論壇。
9. Giant Bomb
Giant Bomb網站不僅提供視頻游戲信息,還有新聞(news)、評論(reviews)、網路(wiki)、視頻(videos)、播客(podcasts)、論壇(forums)等板塊。3月,Giant Bomb被CBS Interactive收購,該公司旗下還有與Giant Bomb相似的網站GameSpot。
Giant Bomb API可對Giant Bomb網頁上的游戲標題、評分、視頻、公司、主題、風格等內容進行編程。API文檔為1頁,以Wiki格式呈現;API開發者論壇上還有API快速入門指南,API改進日誌等豐富信息可供參考。
10. SpongeAPI
Sponge是Minecraft服務端支持的全新modding API,既可以充當伺服器,也可以用來作客戶端API,修改Minecraft游戲,伺服器擁有者也可以使用。Sponge這一項目是在9月份DMCA侵權通知引發CraftBukkit關閉不久後建立起來的。CraftBukkit作為Minecraft官方伺服器的有益補充,用Bukkit API來建立插件,為Minecraft伺服器增添新功能。
Sponge API更新很勤快,穩定的版本預計會在年末上線,但不少開發者已經開始使用和測試了,火熱程度可見一斑。Sponge Web網頁和GitHub上都能找到簡單好上手的完整API文檔。開發者還可以在官方網站上的論壇中了解更多關於Sponge項目開發和Sponge API的信息。
㈤ 如何在Android中使用OpenCV
如何在Android程序中使用OpenCV
有兩種方式(重點講後面一種):
1.使用OpenCV Java API。
OpenCV安裝路徑"F:OpenCV-2.3.1-android-bin"下有兩個文件夾,
將文件夾"OpenCV-2.3.1"拷貝到你的Eclipse工作空間所在的目錄,也就是在你的項目的上一級目錄中,然後導入到工作空間中,在Package Explorer中選擇你的項目,單機右鍵在彈出菜單中選擇Properties,然後在彈出的Properties窗口中左側選擇Android,然後點擊右下方的Add按鈕,選擇OpenCV-2.3.1並點擊OK,
此時,展開你的項目樹,你可以看到新加了一個OpenCV-2.3.1_src目錄,如下圖,那麼就是正確添加了OpenCV Java API,否則就是你放置OpenCV-2.3.1的目錄路徑不正確。
然後就可以在你的Java源文件中導入OpenCV的API包,並且使用OpenCV API了,OpenCV API的包的形式如下:
Org.opencv.(OpenCV模塊名).(OpenCV類名)
例如:
Org.opencv.core.Mat
2.利用JNI編寫C++ OpenCV代碼,通過Android NDK創建動態庫(.so)
新建一個工作空間,例如"TestOpenCV",在Window->Preferences中設置好Android SDK的路徑。
然後新建一個Android項目,Build Target選擇Android2.2,命名為"HaveImgFun",活動名改為HaveImgFun,Package name中填寫com.testopencv.haveimgfun,最後點擊finish。
如同使用OpenCV Java API那樣,將OpenCV-2.3.1文件夾拷貝到與工作空間同一級目錄中;另外,將"F:OpenCV-2.3.1-android-binsamples"下的includeOpenCV.mk文件拷貝到和項目HaveImgFun同一級目錄中:
(上面這個各個文件夾和文件的放置很重要,因為OpenCV-2.3.1下的OpenCV.mk中有很多相對路徑的指定,如果不是這樣放置,在NDK生成動態庫時可能會報文件或文件夾無法找到的錯誤)
選擇Package Explorer中你的項目,右鍵選擇new->folder,新建一個名為jni的文件夾,用來存放你的c/c++代碼。
然後把res->layout下的main.xml的內容改為下面所示:
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent"
6 >
7 <Button android:layout_height="wrap_content"
8 android:layout_width="fill_parent"
9 android:id="@+id/btnNDK"
10 android:text="使用C++ OpenCV進行處理" />
11 <Button android:layout_height="wrap_content"
12 android:layout_width="fill_parent"
13 android:id="@+id/btnRestore"
14 android:text="還原" />
15 <ImageView android:id="@+id/ImageView01"
16 android:layout_width="fill_parent"
17 android:layout_height="fill_parent" />
18 </LinearLayout>
上面的代碼就是一個線性布局裡麵包含2個按鈕加上一個顯示圖像的ImageView
在文件夾src下的com.testopencv.haveimgfun包中新建一個類用於包裝使用了opencv c++代碼的動態庫的導出函數,類名為LibImgFun。
Eclipse會為你創建一個新的文件LibImgFun.java,將裡面的內容改為:
1 package com.testopencv.haveimgfun;
2 public class LibImgFun {
3 static {
4 System.loadLibrary("ImgFun");
5 }
6 /**
7 * @param width the current view width
8 * @param height the current view height
9 */
10 public static native int[] ImgFun(int[] buf, int w, int h);
11 }
從上面的代碼可以得知,我們的動態庫名字應該為「libImgFun.so」,注意"public static native int[] ImgFun(int[] buf, int w, int h)"中的native關鍵字,表明這個函數來自native code。static表示這是一個靜態函數,這樣就可以直接用類名去調用。
在jni文件夾下建立一個"ImgFun.cpp"的文件,內容改為下面所示:
1 #include <jni.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <opencv2/opencv.hpp>
5 using namespace cv;
6
7 extern "C"
8 {
9 JNIEXPORT jintArray JNICALL Java_com_testopencv_haveimgfun_LibImgFun_ImgFun(JNIEnv* env, jobject obj, jintArray buf, int w, int h);
10 JNIEXPORT jintArray JNICALL Java_com_testopencv_haveimgfun_LibImgFun_ImgFun(JNIEnv* env, jobject obj, jintArray buf, int w, int h){
11
12 jint *cbuf;
13 cbuf = env->GetIntArrayElements(buf, false);
14 if(cbuf == NULL)
15 {
16 return 0;
17 }
18
19 Mat myimg(h, w, CV_8UC4, (unsigned char*)cbuf);
20 for(int j=0;j<myimg.rows/2;j++)
21 {
22 myimg.row(j).setTo(Scalar(0,0,0,0));
23 }
24
25 int size=w * h;
26 jintArray result = env->NewIntArray(size);
27 env->SetIntArrayRegion(result, 0, size, cbuf);
28 env->ReleaseIntArrayElements(buf, cbuf, 0);
29 return result;
30 }
31 }
上面的代碼中#include <jni.h>是必須要包含的頭文件,#include <opencv2/opencv.hpp>是opencv要包含的頭文件。
動態庫要導出的函數如下聲明:
JNIEXPORT jintArray JNICALL Java_com_testopencv_haveimgfun_LibImgFun_ImgFun(JNIEnv* env, jobject obj, jintArray buf, int w, int h);
JNIEXPORT 和JNICALL是必須要加的關鍵字
jintArray就是int[],這里返回類型要麼為空,要麼為jni中定義的類型,事實上就是CC++類型前面加上j,如果是數組,則在後面加上Array。
函數名的命名規則如下:
Java_(包路徑)_(類名)_(函數名) (JNIEnv *env, jobject obj, 自己定義的參數...)
包路徑中的"."用"_"(下劃線)代替,類名就是上麵包裝該動態庫函數的類的名字,最後一個才是真正的函數名;JNIEnv *env和jobject obj這兩個參數時必須的,用來調用JNI環境下的一些函數;後面就是你自己定義的參數。在這里,jintArray buf代表了傳進來的圖像的數據,int w是圖像的寬,int h是圖像的高。
這個函數的功能是將傳進來的圖像的上半部分塗成黑色。
然後再在jni下新建兩個文件"Android.mk"文件和"Application.mk"文件,這兩個文件事實上就是簡單的Makefile文件。
其中將Android.mk的內容改為如下所示:
LOCAL_PATH:=$(callmy-dir)
include$(CLEAR_VARS)
include../includeOpenCV.mk
ifeq("$(wildcard$(OPENCV_MK_PATH))","")
#trytoloadOpenCV.mkfromdefaultinstalllocation
include$(TOOLCHAIN_PREBUILT_ROOT)/user/share/OpenCV/OpenCV.mk
else
include$(OPENCV_MK_PATH)
endif
LOCAL_MODULE:=ImgFun
LOCAL_SRC_FILES:=ImgFun.cpp
include$(BUILD_SHARED_LIBRARY)
Application.mk的內容改為如下所示:
APP_STL:=gnustl_static
APP_CPPFLAGS:=-frtti-fexceptions
APP_ABI:=armeabiarmeabi-v7a
其中APP_ABI指定的是目標平台的CPU架構。(經過很多測試,android2.2必須指定為armeabi,android2.2以上的使用armeabi-v7a,如果沒有設置對,很有可能安裝到android虛擬機失敗,當然你同時如上面寫上也是可以的)
上面的步驟完成後,就可以使用NDK生成動態庫了,打開cygwin,cd到項目目錄下:
輸入$NDK/ndk-build命令,開始創建動態庫。
這時候刷新Eclipse的Package Explorer會出現兩個新的文件夾obj和libs。
現在,只剩最後一步完成這個測試程序。
將一張圖片,例如"lena.jpg"放到項目res->drawable-hdpi目錄中並刷新該目錄。
然後將HaveImgFun.java的內容改為下面所示:
1 package com.testopencv.haveimgfun;
2
3 import android.app.Activity;
4 import android.graphics.Bitmap;
5 import android.graphics.Bitmap.Config;
6 import android.graphics.drawable.BitmapDrawable;
7 import android.os.Bundle;
8 import android.widget.Button;
9 import android.view.View;
10 import android.widget.ImageView;
11
12 public class HaveImgFun extends Activity{
13 /** Called when the activity is first created. */
14 ImageView imgView;
15 Button btnNDK, btnRestore;
16
17 @Override
18 public void onCreate(Bundle savedInstanceState) {
19 super.onCreate(savedInstanceState);
20 setContentView(R.layout.main);
21
22 this.setTitle("使用NDK轉換灰度圖");
23 btnRestore=(Button)this.findViewById(R.id.btnRestore);
24 btnRestore.setOnClickListener(new ClickEvent());
25 btnNDK=(Button)this.findViewById(R.id.btnNDK);
26 btnNDK.setOnClickListener(new ClickEvent());
27 imgView=(ImageView)this.findViewById(R.id.ImageView01);
28 Bitmap img=((BitmapDrawable) getResources().getDrawable(R.drawable.lena)).getBitmap();
29 imgView.setImageBitmap(img);
30 }
31
32 class ClickEvent implements View.OnClickListener{
33 public void onClick(View v){
34 if(v == btnNDK){
35 long current=System.currentTimeMillis();
36 Bitmap img1=((BitmapDrawable) getResources().getDrawable(R.drawable.lena)).getBitmap();
37 int w=img1.getWidth(),h=img1.getHeight();
38 int[] pix = new int[w * h];
39 img1.getPixels(pix, 0, w, 0, 0, w, h);
40 int[] resultInt=LibImgFun.ImgFun(pix, w, h);
41 Bitmap resultImg=Bitmap.createBitmap(w, h, Config.RGB_565);
42 resultImg.setPixels(resultInt, 0, w, 0, 0,w, h);
43 long performance=System.currentTimeMillis()-current;
44 imgView.setImageBitmap(resultImg);
45 HaveImgFun.this.setTitle("w:"+String.valueOf(img1.getWidth())+",h:"+String.valueOf(img1.getHeight())+"NDK耗時"+String.valueOf(performance)+" 毫秒");
46 } else if(v == btnRestore){
47 Bitmap img2=((BitmapDrawable) getResources().getDrawable(R.drawable.lena)).getBitmap();
48 imgView.setImageBitmap(img2);
49 HaveImgFun.this.setTitle("使用OpenCV進行圖像處理");
50 }
51 }
52 }
53 }
點擊全部保存,OK,現在可以選擇一個Android虛擬機運行看一下效果,配置好Run Configuration然後點擊Run,得到下面的結果: