【原創】對於一些Android開發過程中坑爹、細小,但又重要的錯誤的總結


對於一些Android開發過程中總有些很坑爹的錯誤,繞了很大一圈,最后發現是一行代碼放錯位置,或者少了幾句聲明等等。

在此,我就分享下個人在android開發過程中遇到的一些問題,也是作為一份備忘~

調試Android程序的方法(我都是用真機調試,模擬器太慢了,不爽):

  1. 我會用System.out.println();作為信息打印,類似與單片機調試中的串口打印,可以直觀的看到程序執行到哪里
  2. 我會查看運行過程中的error,幫助自己定位錯誤和網上搜資料(雖然有很多錯誤考看這個還是摸不着頭腦,但對有些簡單的錯誤還是很有幫助的)
  3. 在調一些網絡通信的程序時,我會在PC端寫一個服務端java程序,有時還會用到wireshark這個網絡數據包分析軟件,這個工具可以清楚地看到網絡中實際的數據,很方便
  4. 在調試多進程、有關SD等方面的程序時,我偶爾會用DDMS來對程序進行監測

以上4點中,我一般用前三種就夠了,第4種網上很多人說是什么開發Android必備的,不過我用的很少,可能是我水平還不到家吧

問題匯總:

1、使用UDP來進行網絡通信時,由於其receive方法是阻塞的,對於由發送轉為接收模式的應用程序,如果發送請求丟包,則該程序會一直阻塞,而不再發送請求,一個實用的方法是UDP套接字的setSoTimeout();方法,可以設定其接收等待時間,以便超時后再次發送請求,保證其可靠性。

2、使用Google的Map-API來進行開發時,<uses-library android:name="com.google.android.maps" />的聲明要放在<application></>標簽對中,這個是對調用的lib庫的聲明,不像對授權的聲明可以放在<application></>的外面,我就說這里搞錯了,然后搞了一天,程序還是打開錯誤

 1 <application android:icon="@drawable/icon" android:label="@string/app_name">
 2         <activity android:name=".ParkingWorld"
 3                   android:label="@string/app_name">
 4             <intent-filter>
 5                 <action android:name="android.intent.action.MAIN" />
 6                 <category android:name="android.intent.category.LAUNCHER" />
 7             </intent-filter>
 8         </activity>
 9         <activity
10             android:name=".HomeActivity"
11             android:label="@string/location">
12         </activity>
13         <activity
14             android:name=".LocationMap"
15             android:label="@string/location">
16         </activity>
21         <!-- 聲明需要使用Google Map API -->
22         <uses-library android:name="com.google.android.maps" />
23     </application>

3、使用Google的Map-API來進行開發時,遇到地圖MapView組件顯示網格,並且有“MapActivity:Couldn't get connection factory client”的error,這可能是由於一下幾個原因造成:(類似文章可參考http://our2848884.blog.163.com/blog/static/1468548342011625102639660/)

a.Google API Key申請。試着用錯誤的Google API Key運行程序,地圖得到的只是空格。

key的申請可以參考http://choha.iteye.com/blog/1132841

這里為了得到正確的密匙有一點要注意,那就是產生key的方式不同會影響key是否能用,下面的方法我用着可以:

在cmd中執行keytool -list -alias androiddebugkey -keystore “你的debug keystore位置” -storepass android -keypass android

b.“INTERNET”使用權限(允許應用程序訪問網絡)正確添加了如下語句:<uses-permission android:name="android.permission.INTERNET"/>

c.使用Google地圖的函數庫語句正確添加了。 <uses-library android:name="com.google.android.maps"/>,且置於</application>標簽前。

4、使用DatagramSocket類創建UDP的套接字,使用Socket、SeverSocket進行TCP的套接字通信時,使用完后要記得調用其close方法,否則端口會被一直占用,導致錯誤;而且close語句的位置也很重要,我在一個activity中要多次使用套接字來發數據,本想使用一個套接字解決問題,在最后的Stop();或者Destory();方法中將其close,但結果行不通,而我創建一個進程,進程每次執行開始創建一個,進程執行結束時套接字close,這樣程序就不會報錯,且穩定性也不錯,對於那些時常需要刷新數據的應用來說很實用。

5、使用TabHost時,要注意在TabActivity中不能有setContentView(R.layout.main);這樣的設置布局的語句,因為TabHost其本身就是用來設置布局的,否則會產生以下錯誤:Caused by: java.lang.RuntimeException: Your content must have a TabHost whose id attribute is 'android.R.id.tabhost'

6、當你在A工程中調試X.java時,如果你同時在eclipse中有另一個B工程中也有同名文件X.java,則在雙擊打印出來的錯誤信息時,eclipse可能會幫你定位到B工程的X.java中,讓你看了半天也沒找到哪里有錯誤,這時你可以先把B工程從eclipse刪去,再重新雙擊打印出來的錯誤信息,eclipse就會幫你正確定位啦。

7、java中的乘方運算用Math.pow(底數, 指數);方法,而不使用"^"符號,"^"在java中表示異或。

8、在使用TextView的setText方法時,注意其重載性,若要要將int整型作為參數時,編譯器認為你的參數是個資源ID,找不到對應的ID時,會出現類似以下的報錯:android.content.res.Resources$NotFoundException: String resource ID #0xfe                                       而如果你是要顯示這個int型數據,我通常會用  “”+數據  的方法利用“+"符號的重載性,將int數據直接轉為String類型。當然,也可以用Integer.valueOf(int i).toString將其轉為String類型。

9、使用套接字傳數據使用以下方法時,雖然String類型中是用char型來存儲數據的,但在使用getBytes()方法后,有的數據,比如char型0x0001會變為一個字節的byte型0x01,而不是兩個字節0x00和0x01,但很多時候其還是會變為兩個字節,比如中文編碼。這可以用wireshark抓包來看,當然也可以直接調用類的length()方法,再打印查看。

1 byte dataSend[] = str.getBytes();  //把傳輸內容分解成字節*/3 //創建一個DatagramPacket對象,並指定要講這個數據包發送到網絡當中的哪個、地址,以及端口號
4 DatagramPacket packetSend = new     DatagramPacket(dataSend,dataSend.length,serverAddress,dstPort);
5 //調用socket對象的send方法,發送數據
6 socket.send(packetSend);

因此在用一個字節表達數據時,為防止String轉byte[]時的不確定性,我就直接用byte[]賦給dataSend[],也可以使用String的getBytes(String charsetName)方法

Returns a new byte array containing the characters of this string encoded using the named charset.
 1 byte by[] = new byte[4];
 2 by[0] = ledNum;
 3 by[1] = (byte)(Integer.parseInt(strR1));
 4 by[2] = (byte)(Integer.parseInt(strG1));
 5 by[3] = (byte)(Integer.parseInt(strB1));
 6 byte dataSend[] = by;
 7 //創建一個DatagramPacket對象,並指定要講這個數據包發送到網絡當中的哪個、地址,以及端口號
 8 DatagramPacket packetSend = new     DatagramPacket(dataSend,dataSend.length,serverAddress,dstPort);
 9 //調用socket對象的send方法,發送數據
10 socket.send(packetSend);

 

10、在使用TabHost時應注意其Activity的生命周期,如果不加 Intent.FLAG_ACTIVITY_CLEAR_TOP 這個flag,則Tab之間切換時,Activity只是0nPause();而不執行onStop();和onDestroy(); 並且在設置 addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) 之后,切換到另一個Activity會調用另一個Activity的OnCreat方法

1 tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator(getString(R.string.park),
2                 getResources().getDrawable(android.R.drawable.star_on))
3                         .setContent(new Intent(this, ParkActivity.class)
4                                 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)));  //這句用來清空之前所有的activity

 11、從XML文件中獲取字符串的方法 getString(R.string.my_str);

 12、在 handlerSocket.post(update); 之后又在update中遞歸調用 handlerSocket.postDelayed(this, 2000); 則可能會導致跳轉到另一個Activity時,update仍會一次又一次地執行,這時可以在跳出Activity的觸發函數,如onPause,onStop函數中加入 handlerSocket.removeCallbacks(update); 如果還是不行的話可以使用全局開關變量,runFlag(自己取的名字)。在跳入Activity的觸發函數,如onCreat,onResume函數中runFlag=1,而在跳出Activity的觸發函數runFlag=0。並且使用runFlag來控制 handlerSocket.postDelayed(this, 2000);  如下列代碼

 1 @Override   
 2 protected void onCreate(Bundle savedInstanceState)
 3 {
 4     ......
 5     runFlag = 1;
 6     ......
 7     ......
 8     update =new Runnable(){    
 9     @Override
10     public void run() {
11         ......
12         if(runFlag == 1){
13             handlerSocket.postDelayed(this, 2000);
14         }
15     }
16     handlerSocket.post(update);
17 }
18 @Override
19 protected void onPause() {
20     // TODO Auto-generated method stub
21     super.onPause();
22     //handlerSocket.removeCallbacks(update);
23     runFlag = 0;
24 }

 

 

 

未完待續。。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM