導航:首頁 > 操作系統 > android調試技巧

android調試技巧

發布時間:2022-08-12 21:42:56

⑴ 如何測試並調試基於 NDK 的 android 應用

《Android應用測試與調試實戰》Android應用測試與調試領域系統、深入且極具實踐指導意義著作由擁近10業經驗資深軟體發工程師調試技術專家撰寫旨廣程序員發高質量Android應用提供全位指導Android應用自化測試工程師發工程師需求發測試調試兩維度針採用java、HTML 5、C++&NDK三種Android應用發式所需要測試調試技術、進行細致深入講解Android應用自化測試調試提供原理性解決案
《Android應用測試與調試實戰》共16章兩部:第部自化測試篇(第1~11章)詳細講解進行Android自化測試需要掌握各種技術、工具包括Android自化測試基礎、Android應用白盒自化測試黑盒自化測試技術原理、Android服務組件內容組件測試、HTML 5應用NDK應用測試及Android應用兼容性測試持續集自化測試;第二部調試技術篇(第12~16章)詳細講解Android應用調試所需要各種工具使用、操作志析、內存志析及線程應用HTML 5 應用NDK 應用調試技巧

⑵ android studio怎麼運行調試

Android Studio目前已經成為開發Android的主要工具,用熟了可謂相當順手。作為開發者,調試並發現bug,進而解決,可是我們的看家本領。正所謂,工欲善其事必先利其器,和其他開發工具一樣,如Eclipse、Idea,Android Studio也為我們提供了強大的調試技巧,今天我們就來看看Android Studio中有關調試的技巧。

http://www.cnblogs.com/firstcsharp/p/4333264.html

⑶ 如何自學 Android 編程

1.明確目標

2.了解安卓開發中比較困難的地方

學習一個新平台,就要知道此平台開發要面臨的困難有哪些,不要做到最後,這些問題沒有考慮,那就比較糟糕了。在網上搜索了下,安卓開發困難總結如何:

1)安卓系統版本比較多,各版本之間的兼容性是個問題,此為系統碎片。

2)安卓設備千變萬化,設備難以統一,每個產品都成為獨立,分散的Android碎片。

3)解析度五花八門。一個產品,可能需要多個界面排版,人工消耗比較大。

看到這張圖,有沒有頭疼的感覺?

總結成一句話:Android的碎片化真是要來開發者的命。

3.搭建開發環境

"巧婦難為無米之炊",開發環境肯定是第一件要做的事情,這類的文章已經很多了,我也不多說了,多說也就比較無聊了。感謝吳秦,也是博客園里的一員,他寫的很詳細了,見這里。

4.查看網友總結的一些經驗。

不是什麼都查看,開發中遇到什麼問題,就去查看什麼問題,這樣你查到的知識,馬上就能深入的實踐,這樣知識就鞏固了。

1)首先當然要看Android的開發文檔,裡面其實大部分的知識都有了,還有就是SDK自帶的Samples。

2)博客園里搜索「Android開發」,會出來一大把,很多網友都是很系統的講解了。

3)eoe

android社區,裡面有很多網友上傳了現成的demo代碼,裡面很多都是模仿現在流行的產品的界面開發,很是不錯。

5.掌握調試方法

個人一直認為,調試技巧是開發中最重要的技能,如果調試技能比較差,不知道如何查找問題,那不會是個好的程序員,其技能也不會高到哪裡去。

Android做下來,感覺調試這塊做的很不錯了,這要感謝Eclipse

IDE做的比較不錯,但是Android的界面排版部分,真的不敢恭維,Eclipse時間用長了,佔用內存真是大。有哪位高手能否告訴我下,你們界面排版是用什麼的?

Android里,如果程序出了問題,有些是一下跟蹤不到的,這時就要用到Log類了,Log類使用很簡單,就不多說了。

自己一個很有感觸的經驗,如果你真的打算做Android開發,那就買一個設備,這樣能大大提高開發效率,模擬器有時用起來真是麻煩,而且開發的設備不要很好的,只要設備解析度是主流的,感測器的支持最好全點就夠了,國產的手機里,華為的還不錯,或者到淘寶上去買個二手的,投資不大。真的買了投資,可能也會增加你學習Android的決心。

6.程序框架

經過10多年的經歷,認識到程序的框架對開發產品真的是起到舉足輕重的作用。一個好的產品,如果有個好的程序框架,那真是事半功倍,可能開始所做的工作會比較多,很難看到令人激動的成果,但是相信我,絕對值得。一開始,我也是比較注重程序界面開發,很快就開發出界面來,而且著實比較激動,因為有東西出來了,但是後面的事情,真是令人發狂,想從頭再來,太遲了,離計劃的時間比較近了,時間不允許,只有硬著頭皮往上打補丁,硬著交付第一個版本,第二個版本或者後面的版本,遲早是要重來的。所以在後面帶領團隊開發的時候,在開發前,都是要討論程序框架,留出很大部分時間進行程序框架開發,及在開發中不斷的改進。

剛接觸Android,不知道用什麼程序框架,所以查了很多資料,一開始看到一個程序框架,感覺很不錯,所以一開始就使用了下面這個程序框架。

⑷ 如何自學Android

因為項目需要,8月中旬開始決定做安卓的程序,所以馬上就開始學習安卓方面的開發知識,把最近的學習實踐經歷和大家分享分享。不要一開始就下載一大堆資料,視頻,然後就不知道做什麼了,要給自己定個目標,我要做什麼?我怎麼達到目標?

我不懂java,但是懂C#和C++,所以我沒主張去單獨學習java語言,如果你是個最最初的新手,沒啥語言基礎,那你必須先看看java語言,不要很詳細看,因為學習Android中,你也是在學習java。

1. 明確目標

沒有目標的學習,會感覺到後面沒什麼成果,在1年前,我也打算學習android開發的,但是目的就是學習,到網上去下載很多學習的視頻,然後把開發環境搭建起來,能把Helloworld運行起來,能打些log,Activity之間也能互相切換了,但是後面也就不了了之了,因為不知道學了要干什麼。依葫蘆畫瓢的做了幾個例子,因為裡面的問題都是已經解決的,所以也沒能深入的系統學習。

這次因為產品的需要,要做Android版本,要做的東西一開始就已經設計好了,見搖搖2選1安卓版本,剛開始也不知道裡面有些什麼技術難度,但是要做的目標已經明確了,而且也沒有現成的,碰到問題就查資料,慢慢地解決,這樣有的放矢,學習的效果非常好。既有現成的技術可以使用,又有些技術,需要查比較多的資料,這樣記憶就比較深刻,所掌握的知識也比較系統。

接下來的一系列文章,我會把在開發搖搖2選1中遇到的問題,給大家詳細講講,程序雖然小,但是五臟俱全,做Demo和做產品的要求完全不是一個級別,如果Android大牛感覺知識講的比較淺,那可以繞道,畢竟我是從一個完全的新手開始的。

2. 了解安卓開發中比較困難的地方

學習一個新平台,就要知道此平台開發要面臨的困難有哪些,不要做到最後,這些問題沒有考慮,那就比較糟糕了。在網上搜索了下,安卓開發困難總結如何:

1)安卓系統版本比較多,各版本之間的兼容性是個問題,此為系統碎片。

2)安卓設備千變萬化,設備難以統一,每個產品都成為獨立,分散的Android碎片。

3)解析度五花八門。一個產品,可能需要多個界面排版,人工消耗比較大。

看到這張圖,有沒有頭疼的感覺?

總結成一句話:Android的碎片化真是要來開發者的命。

3. 搭建開發環境

"巧婦難為無米之炊",開發環境肯定是第一件要做的事情,這類的文章已經很多了,我也不多說了,多說也就比較無聊了。感謝吳秦,也是博客園里的一員,他寫的很詳細了,見這里。

4. 查看網友總結的一些經驗。

不是什麼都查看,開發中遇到什麼問題,就去查看什麼問題,這樣你查到的知識,馬上就能深入的實踐,這樣知識就鞏固了。

1)首先當然要看Android的開發文檔,裡面其實大部分的知識都有了,還有就是SDK自帶的Samples。

2)博客園里搜索「Android開發」,會出來一大把,很多網友都是很系統的講解了。

3)eoe
android社區,裡面有很多網友上傳了現成的demo代碼,裡面很多都是模仿現在流行的產品的界面開發,很是不錯。

5. 掌握調試方法

個人一直認為,調試技巧是開發中最重要的技能,如果調試技能比較差,不知道如何查找問題,那不會是個好的程序員,其技能也不會高到哪裡去。

Android做下來,感覺調試這塊做的很不錯了,這要感謝Eclipse
IDE做的比較不錯,但是Android的界面排版部分,真的不敢恭維,Eclipse時間用長了,佔用內存真是大。有哪位高手能否告訴我下,你們界面排版是用什麼的?

Android里,如果程序出了問題,有些是一下跟蹤不到的,這時就要用到Log類了,Log類使用很簡單,就不多說了。
自己一個很有感觸的經驗,如果你真的打算做Android開發,那就買一個設備,這樣能大大提高開發效率,模擬器有時用起來真是麻煩,而且開發的設備不要很好的,只要設備解析度是主流的,感測器的支持最好全點就夠了,國產的手機里,華為的還不錯,或者到淘寶上去買個二手的,投資不大。真的買了投資,可能也會增加你學習Android的決心。

6. 程序框架

經過10多年的經歷,認識到程序的框架對開發產品真的是起到舉足輕重的作用。一個好的產品,如果有個好的程序框架,那真是事半功倍,可能開始所做的工作會比較多,很難看到令人激動的成果,但是相信我,絕對值得。一開始,我也是比較注重程序界面開發,很快就開發出界面來,而且著實比較激動,因為有東西出來了,但是後面的事情,真是令人發狂,想從頭再來,太遲了,離計劃的時間比較近了,時間不允許,只有硬著頭皮往上打補丁,硬著交付第一個版本,第二個版本或者後面的版本,遲早是要重來的。所以在後面帶領團隊開發的時候,在開發前,都是要討論程序框架,留出很大部分時間進行程序框架開發,及在開發中不斷的改進。

剛接觸Android,不知道用什麼程序框架,所以查了很多資料,一開始看到一個程序框架,感覺很不錯,所以一開始就使用了下面這個程序框架。

⑸ jQuery Mobile + PhoneGap的Android應用怎麼調試

環境:eclipse3.6/adt18/sdk4.0/jqm1.2/phonegap2.1/jquery1.8/chrome/safari
我現在使用jqm+phonegap開發一個android應用
在本地用jqm寫好頁面代碼用瀏覽器調試好,然後用jsonp跨域請求數據,通過phonegap寫入sqlite。

我把寫好的代碼(建的android項目)放在4.0模擬器里運行,可以正常請求到數據、寫入、查詢,現在苦於phonegap代碼不好調試。
特來請教調試技巧。

我之前是調試嘗試:
1. 我看了下sina sae,在裡面創建應用然後把這個項目代碼發布上去也感覺不對,因為的index.html是放在android項目的assets/www/下面的,不知道怎麼在sae上引導項目進入index.html。

2. 我寫好的代碼在safari里運行,phonegap部分運行不了。

document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log("===>> deviceReady");
createTable();
$('#msg').text('deviceReady');
}

safari里不會執行onDeviceReady方法. 模擬器上面可以

我看了官網關於資料庫那塊的api,直接把代碼下來放在html中也是不能運行的。
這里我不確定瀏覽器是否直接phonegap對資料庫的操作。

不涉及系統API和phonegap特定api的可以直接在PC中的chrome下調試,比較方便,調試成功後使用phonegap打包再到Android環境下測試.涉及到chrome不提供的api的,建議編寫一些簡單的樁模塊來模擬,畢竟直接調試Android程序比調試html&js要麻煩很多.

⑹ 有哪些android開發技巧

1、android:clipToPadding

意思是控制項的繪制區域是否在padding裡面。默認為true。如果你設置了此屬性值為false,就能實現一個在布局上事半功陪的效果。先看一個效果圖。

上圖中的ListView頂部默認有一個間距,向上滑動後,間距消失,如下圖所示。

如果使用margin或padding,都不能實現這個效果。加一個headerView又顯得大材小用,而且過於麻煩。此處的clipToPadding配合paddingTop效果就剛剛好。

同樣,還有另外一個屬性也很神奇:android:clipChildren,具體請參考:【Android】神奇的android:clipChildren屬性

2、match_parent和wrap_content

按理說這兩個屬性一目瞭然,一個是填充布局空間適應父控制項,一個是適應自身內容大小。但如果在列表如ListView中,用錯了問題就大了。ListView中的getView方法需要計算列表條目,那就必然需要確定ListView的高度,onMesure才能做測量。如果指定了wrap_content,就等於告訴系統,如果我有一萬個條目,你都幫我計算顯示出來,然後系統按照你的要求就new了一萬個對象出來。那你不悲劇了?先看一個圖。

假設現在ListView有8條數據,match_parent需要new出7個對象,而wrap_content則需要8個。這里涉及到View的重用,就不多探討了。所以這兩個屬性的設置將決定getView的調用次數。

由此再延伸出另外一個問題:getView被多次調用。

什麼叫多次調用?比如position=0它可能調用了幾次。看似很詭異吧。GridView和ListView都有可能出現,說不定這個禍首就是wrap_content。說到底是View的布局出現了問題。如果嵌套的View過於復雜,解決方案可以是通過代碼測量列表所需要的高度,或者在getView中使用一個小技巧:parent.getChildCount == position

@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (parent.getChildCount() == position) {
// does things here
}

return convertView;
}

3、IllegalArgumentException: pointerIndex out of range

出現這個Bug的場景還是很無語的。一開始我用ViewPager + PhotoView(一個開源控制項)顯示圖片,在多點觸控放大縮小時就出現了這個問題。一開始我懷疑是PhotoView的bug,找了半天無果。要命的是不知如何try,老是crash。後來才知道是android遺留下來的bug,源碼里沒對pointer index做檢查。改源碼重新編譯不太可能吧。明知有exception,又不能從根本上解決,如果不讓它crash,那就只能try-catch了。解決辦法是:自定義一個ViewPager並繼承ViewPager。請看以下代碼:

/**
* 自定義封裝android.support.v4.view.ViewPager,重寫onInterceptTouchEvent事件,捕獲系統級別異常
*/
public class CustomViewPager extends ViewPager {

public CustomViewPager(Context context) {
this(context, null);
}

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

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
try {
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException e) {
LogUtil.e(e);
} catch ( e) {
LogUtil.e(e);
}
return false;
}
}

把用到ViewPager的布局文件,替換成CustomViewPager就OK了。

4、ListView中item點擊事件無響應

listView的Item點擊事件突然無響應,問題一般是在listView中加入了button、checkbox等控制項後出現的。這個問題是聚焦沖突造成的。在android裡面,點擊屏幕之後,點擊事件會根據你的布局來進行分配的,當你的listView裡面增加了button之後,點擊事件第一優先分配給你listView裡面的button。所以你的點擊Item就失效了,這個時候你就要根據你的需求,是給你的item的最外層layout設置點擊事件,還是給你的某個布局元素添加點擊事件了。

解決辦法:在ListView的根控制項中設置(若根控制項是LinearLayout, 則在LinearLayout中加入以下屬性設置)descendantFocusability屬性。

android:descendantFocusability="blocksDescendants"

官方文檔也是這樣說明。

5、getSupportFragmentManager()和getChildFragmentManager()

有一個需求,Fragment需要嵌套3個Fragment。基本上可以想到用ViewPager實現。開始代碼是這樣寫的:

mViewPager.setAdapter(new CustomizeFragmentPagerAdapter(getActivity().getSupportFragmentManager(), subFragmentList));

導致的問題是嵌套的Fragment有時會莫名其妙不顯示。開始根本不知道問題出現在哪,當你不知道問題的原因時,去解決這個問題顯然比較麻煩。經過一次又一次的尋尋覓覓,終於在stackoverflow上看到了同樣的提問。說是用getChildFragmentManager()就可以了。真是這么神奇!

mViewPager.setAdapter(new CustomizeFragmentPagerAdapter(getChildFragmentManager, subFragmentList));

讓我們看一下這兩個有什麼區別。首先是getSupportFragmentManager(或者getFragmentManager)的說明:

Return the FragmentManager for interacting with fragments associated with this fragment's activity.

然後是getChildFragmentManager:

Return a private FragmentManager for placing and managing Fragments inside of this Fragment.

Basically, the difference is that Fragment's now have their own internal FragmentManager that can handle Fragments. The child FragmentManager is the one that handles Fragments contained within only the Fragment that it was added to. The other FragmentManager is contained within the entire Activity.

已經說得比較明白了。

6、ScrollView嵌套ListView

這樣的設計是不是很奇怪?兩個同樣會滾動的View居然放到了一起,而且還是嵌套的關系。曾經有一個這樣的需求:界面一共有4個區域部分,分別是公司基本信息(logo、名稱、法人、地址)、公司簡介、公司榮譽、公司口碑列表。每部分內容都需要根據內容自適應高度,不能寫死。鄙人首先想到的也是外部用一個ScrollView包圍起來。然後把這4部分分別用4個自定義控制項封裝起來。基本信息和公司簡介比較簡單,榮譽需要用到RecyclerView和TextView的組合,RecyclerView(當然,用GridView也可以,3列多行的顯示)存放榮譽圖片,TextView顯示榮譽名稱。最後一部分口碑列表當然是ListView了。這時候,問題就出來了。需要解決ListView放到ScrollView中的滑動問題和RecyclerView的顯示問題(如果RecyclerView的高度沒法計算,你是看不到內容的)。

當然,網上已經有類似的提問和解決方案了。

給一個網址:

四種方案解決ScrollView嵌套ListView問題

ListView的情況還比較好解決,優雅的做法無非寫一個類繼承ListView,然後重寫onMeasure方法。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}

ListView可以重寫onMeasure解決,RecyclerView重寫這個方法是行不通的。

說到底其實計算高度嘛。有兩種方式,一種是動態計算RecycleView,然後設置setLayoutParams;另外一種跟ListView的解決方式類似,定義一個類繼承LinearLayoutManager或GridLayoutManager(注意:可不是繼承RecyclerView),重寫onMeasure方法(此方法比較麻煩,此處不表,下次寫一篇文章再作介紹)。

動態計算高度如下:

int heightPx = DensityUtil.dip2px(getActivity(), (imageHeight + imageRowHeight) * lines);
MarginLayoutParams mParams = new MarginLayoutParams(LayoutParams.MATCH_PARENT, heightPx);
mParams.setMargins(0, 0, 0, 0);
LinearLayout.LayoutParams lParams = new LinearLayout.LayoutParams(mParams);
honorImageRecyclerView.setLayoutParams(lParams);

思路是這樣的:服務端返回榮譽圖片後,由於是3列顯示的方式,只需要計算需要顯示幾行,然後給定行間距和圖片的高度,再設置setLayoutParams就行了。

int lines = (int) Math.ceil(totalImages / 3d);

至此,這個奇怪的需求得到了解決。

可是在滑動的時候,感覺出現卡頓的現象。聰明的你肯定想到是滑動沖突了。應該是ScrollView的滑動干擾到了ListView的滑動。怎麼辦呢?能不能禁掉ScrollView的滑動?

網路一下,你肯定能搜索到答案的。先上代碼:

/**
* @author Leo
*
* Created in 2015-9-12
* 攔截ScrollView滑動事件
*/
public class CustomScrollView extends ScrollView {

private int downY;
private int touchSlop;

public CustomScrollView(Context context) {
this(context, null);
}

public CustomScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}

@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
int action = e.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
downY = (int) e.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int moveY = (int) e.getRawY();
if (Math.abs(moveY - downY) > touchSlop) {
return true;
}
}
return super.onInterceptTouchEvent(e);
}
}

只要理解了getScaledTouchSlop()這個方法就好辦了。這個方法的注釋是:Distance in pixels a touch can wander before we think the user is scrolling。說這是一個距離,表示滑動的時候,手的移動要大於這個距離才開始移動控制項,如果小於此距離就不觸發移動。

看似很完美了。

但是還有另外一個問題:我每次載入這個界面花的時間太長了,每次由其它界面啟動這個界面時,都要卡上1~2秒,而且因手機性能時間不等。並不是由於網路請求,取數據由子線程做,跟UI線程毫無關系。這樣的體驗自己看了都很不爽。

幾天過去了,還是那樣。馬上要給老闆演示了。這樣的體驗要被罵十次呀。

難道跟ScrollView的嵌套有關?

好吧,那我重構代碼。不用ScrollView了。直接用一個ListView,然後add一個headerView存放其它內容。因為控制項封裝得還算好,沒改多少布局就OK了,一運行,流暢順滑,一切迎刃而解!

本來就是這么簡單的問題,為什麼非得用ScrollView嵌套呢?

stackoverflow早就告訴你了,不要這樣嵌套!不要這樣嵌套!不要這樣嵌套!重要的事情說三遍。

ListView inside ScrollView is not scrolling on Android

當然,從android 5.0 Lollipop開始提供了一種新的API支持嵌入滑動,此時,讓像這樣的需求也能很好實現。

此處給一個網址,大家有興趣自行了解,此處不再討論。

Android NestedScrolling 實戰

7、EmojiconTextView的setText(null)

這是開源表情庫com.rockerhieu.emojicon中的TextView加強版。相信很多人用到過這個開源工具包。TextView用setText(null)完全沒問題。但EmojiconTextView setText(null)後就悲劇了,直接crash,顯示的是null pointer。開始我懷疑時這個view沒初始化,但並不是。那就調試一下唄。

@Override
public void setText(CharSequence text, BufferType type) {
SpannableStringBuilder builder = new SpannableStringBuilder(text);
EmojiconHandler.addEmojis(getContext(), builder, mEmojiconSize);
super.setText(builder, type);
}

EmojiconTextView中的setText看來沒什麼問題。點SpannableStringBuilder進去看看,源碼原來是這樣的:

/**
* Create a new SpannableStringBuilder containing a of the
* specified text, including its spans if any.
*/
public SpannableStringBuilder(CharSequence text) {
this(text, 0, text.length());
}

好吧。問題已經找到了,text.length(),不空指針才怪。

text = text == null ? "" : text;
SpannableStringBuilder builder = new SpannableStringBuilder(text);

加一行判斷就行了。


先想到這么多,以後再補充。

⑺ 如何調試Android Framework

其實整個調試過程非常簡單:
在你要調試進程的合適位置打上斷點
跟蹤代碼(Step in/out/over等等)
在展開講述這兩方面之前,有必要先簡單了解下調試的基礎知識。Java平台的調試是有一個規范化的標準的,那就是JPDA(Java Platform Debugger Architecture);通過 JPDA 提供的 API,開發人員可以方便靈活的搭建 Java 調試應用程序。 JPDA 主要由三個部分組成:Java 虛擬機工具介面(JVMTI),Java 調試線協議(JDWP),以及 Java 調試介面(JDI)。
Java程序的調試無非就是通過一個調試器(debugger)獲取對應Java虛擬機的信息,上文所述的JDWP就是調試器與虛擬機通信的橋梁。在dalvik虛擬機內部有一個專門的jdwp線程,Android系統的adbd進程通過socket與各個虛擬機的jdwp線程進行通信,外部調試器通過adb工具與adbd通信進而完成與jdwp的通信。我們通常所說的「attach debugger」指的就是這個意思——連接到指定的需要調試的進程。

調試器工作原理
如何在正確的地方下斷點
「正確的地方」包含兩個含義:首先,調試是以進程為單位進行的,如果你需要調試運行在進程A 中的代碼,卻把debugger attach到了B進程,那麼這個斷點壓根兒就是牛頭不對馬嘴;另外呢,比如你想調試Android的多媒體框架,你得知道media相關的類在哪吧,也就是說需要在正確的函數裡面下斷點。
如何在合適的進程下斷點?
如果是調試我們自己寫的App,在Android Studio裡面非常簡單,在Run菜單de最後面有一個attach debugger to android process 的選項,點擊之後會出現一個菜單,選擇自己需要調試的進程即可;但是,如果需要調試Android Framework層的代碼,這樣做是達不到目的的——Framework層的代碼通常運行在別的進程(比如ActivityManagerService運行在system_server進程),而這些進程通常情況下是不可調試的,也就是說在attach debugger to android process 的那個菜單裡面不會有系統的進程,如下圖:

普通的無法調試的Android設備
為什麼不可調試呢?上文我們簡要講述了調試器的工作原理,我們知道每一個虛擬機有一個jdwp線程,如果這個線程拒絕連接到調試器,你也就沒辦法對這個進程進行調試了。Android的所有App進程都是通過Zygote進程fork出來的,我們在android.os.Process這個類裡面可以看到android進程的啟動過程有這么一句:
if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {

argsForZygote.add("--enable-debugger");

}

也就是說,一個進程是否可以調試是由進程啟動時候的參數決定的;普通的App進程如果是debug keystore默認是可以調試的,有或者你在AndroidManifest裡面指定debuggable為true也是可以調試的。對系統進程,我們只有採取系統級別的手段:讓整個系統可以調試——debug版或者編譯參數debuggable為1的系統。
解決這個辦法很簡單:使用模擬器(真機也行,限Nexus系列刷原生Android系統,把系統啟動的debuggable參數修改為1),我的Nexus 5 可以調試的進程如下:

可調試任意進程的設備
這樣,系統中所有的Android進程都可以調試了;這一點很重要,比如你要分析Activity的啟動流程,相當多一部分代碼是在ActivityManagerService所在的進程system_server執行的,如果你把斷點打在別的進程,就會產生跟丟了的情況。在比如,你要調試ActivityThread的main函數,在main函數裡面執行了一句attach,最終調用AMS的attachApplication的時候,代碼就通過Binder IPC調用到了AMS的system_server進程。
明白你要執行的代碼運行在哪一個進程相當重要,在Android中,由於Binder通信機制的存在,「進程遷移」使用的非常非常頻繁,因此需要對binder機制有一定的了解;詳細的話可以參考我的博客:Binder學習指南
如何在對應的代碼處下斷點?
假設我們現在把debugger attach到了正確的進程,那麼斷點應該下在哪裡呢?直觀來講,就是說我需要導入所有的Android源碼嗎?如果不是應該導入哪些代碼,怎麼導入?
首先,如果你需要調試的類在sdk裡面導出了,你壓根兒就不需要再導入源碼,Android Studio自動幫你關聯了這部分代碼(前提是你用SDK Manager下載了sdk的源碼,如下圖:

SDK manager下載源碼
比如你要調試ActivityManagerServce類的attachApplication方法,那麼很簡單;創建一個空的Android項目,SDK版本選擇與你要調試的模擬器/真機 的android相同(這很重要,下文會講述);然後attrach 到system_server進程,直接在attach_application上面打上斷點;隨便啟動一個app,可以看到我們熟悉的調試界面:

調試attachApplication
如果這部分類在sdk中沒有導入(比如@hide)的,又或者壓根兒不是SDK的類,(比如系統app的源碼)那應該怎麼辦呢?直接導入這部分代碼即可。不需要是Android項目,普通的Java項目即可;舉個例子,假設你想調試原生Android系統的「系統設置」這個程序,該如何做呢?
根據上面的分析,我們首先得知道「系統設置˜」運行在哪一個進程,通常情況下進程名字就是包名;我們查出設置的包名即可,而包名是在源碼的AndroidManifeist中聲明的,因此,我們找到「系統設置」這個程序的源碼即可;源碼在 https://android.googlesource.com/ ,系統App的源碼在/packages這個子目錄下面,我們一個個找,最終可以確定「系統設置」的源碼在https://android.googlesource.com/platform/packages/apps/Settings/ ;然後我們把這部分代碼git clone下來,導入Android Studio:

調試Settings
我們去AndroidManifest中查到,「系統設置」的包名為:com.android.settings,這樣我們attach到這個進程 :

attach setting進程
然後,我們隨便打個斷點玩一玩,比如進入設置主界面的時候,斷下來;我們在AndroidManifest中查到設置程序的入口界面為:Settings,我們在這個類的onCreate裡面打一個斷點,然後進入設置程序,發現完美滴斷下來了:

在setting中斷點成功
OK,到這里;應該學會如何在正確的位置打斷點了:正確的進程,正確的位置。接下來,要完成調試,還需要一些技巧。
如何跟蹤代碼?
或許你會說,跟蹤代碼不就是step in/out/over么,這有什麼難的?但其實事情並沒有你想像的那麼簡單,要優雅滴調試,還是需要一些姿勢的。
行號對應
跟蹤代碼一個首要的問題是行號對應。如果你在正確位置下了斷點,但是跟蹤的時候,單步調試,發現運行的代碼和Android Studio裡面的代碼對不上號,那麼就很蛋疼;要使得調試器的行號能夠對應,必須保證設備上的代碼和調試器的代碼是同一份;簡單來說,需要使用Android的原生系統(模擬器,Nexus系列真機),然後調試器裡面使用的SDK版本,必須和設備的系統版本一致。
行號不對應怎麼辦?
一定要注意行號對應這一點,這會使調試過程簡單很多;如果沒有辦法,行號對不上,那該如何調試呢?
行號不對應帶來的一個首要問題就是,下斷點的時候都有可能出現問題;比如你在TestClass的第100行下了一個斷點,但是由於行號不對應,有可能真正執行的代碼第100行是沒有意義的空行或者是在下一個函數裡面,這樣斷點就沒有起到應有的作用了。
要解決行好對應的問題,必須使用方法斷點;我們直接在某個函數的入口設置斷點,這樣即使行號對不上,也能在正確的入口出斷下來,這一點非常重要。
解決了如何下斷點的問題,那麼行號不對應,怎麼知道執行到哪了,怎麼查看局部變數?
觀察棧楨
在Android Studio的調試器的左邊,顯示了每一個線程執行的棧楨,棧楨裡麵包含了當前線程豐富的信息:

看到沒,真正運行的代碼在哪一行,當前運行的是什麼函數一目瞭然;接下來你在step into/out的時候,不能以源代碼的行數為准,而應該以這個棧楨所顯示的代碼行數為准。
熟練使用斷點
OK,現在不論行號是否能對應,我們都能正確滴下斷點調試了。斷點有很多種類型,方法斷點,watch point,條件斷點都能夠很好滴輔助我們調試;如果你連這幾個名詞都沒有聽說過,一定要惡補一下;可以參閱我的博客:Android Studio你不知道的調試技巧;我就不再復述了。望採納,謝謝。

閱讀全文

與android調試技巧相關的資料

熱點內容
進程序員公司能穿涼鞋嗎 瀏覽:245
PDF框大小 瀏覽:84
單片機產生鋸齒波 瀏覽:225
如何修改ie代理伺服器 瀏覽:417
折紙手工解壓玩具不用a4紙 瀏覽:485
怎麼雙向傳輸伺服器 瀏覽:286
電腦如何實現跨網段訪問伺服器 瀏覽:549
模塊化網頁源碼位元組跳動 瀏覽:485
梯度下降演算法中遇到的問題 瀏覽:605
伺服器連接電視怎麼接 瀏覽:323
phploop語句 瀏覽:502
交叉編譯工具鏈里的庫在哪 瀏覽:781
安卓手q換號怎麼改綁 瀏覽:399
nba球星加密貨幣 瀏覽:789
命令看網速 瀏覽:124
java堆分配 瀏覽:161
linuxbuiltin 瀏覽:560
cstpdf 瀏覽:941
texstudio編譯在哪 瀏覽:353
國家反詐中心app注冊登記表怎麼注冊 瀏覽:972