Android項目訪問webservice,同樣的程序在Android2.3上運行完全正常,而跑到Android4上面,bug出現了...
看了一下異常:android.os.NetworkOnMainThreadException
然後,上網搜索一下才發現,原來Android4默認情況下是不允許在主線程中訪問網絡的。
解決問題的思路有兩種:
1、解除主線程網絡訪問限制,參見http://developer.android.com/reference/android/os/StrictMode.html
在onCreate中加入以下代碼即可:
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
不過如果要求至少是API-9纔可以,否則會編譯器提示錯誤,所以在適配一些低版本系統時候不太給力。
2、多線程中訪問網絡-既然系統默認不允許在主線程中訪問,那麼再開一個線程好了,這樣在處理複雜流程的時候也不會影響界面的流暢,用戶體驗也好。
以下是一段測試代碼:
public class MainActivity extends Activity {
private Button btnTest;
private Button btnClear;
private TextView txtResult;
private Handler handler = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
// StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
// .detectDiskReads()
// .detectDiskWrites()
// .detectNetwork() // or .detectAll() for all detectable problems
// .penaltyLog()
// .build());
// StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
// .detectLeakedSqlLiteObjects()
// .detectLeakedClosableObjects()
// .penaltyLog()
// .penaltyDeath()
// .build());
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnTest = (Button) findViewById(R.id.btnTest);
btnClear = (Button) findViewById(R.id.btnClear);
txtResult = (TextView) findViewById(R.id.txtResult);
//
handler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 0) {
txtResult.append("\nBegin test >>\n");
} else if (msg.what == 1) {
txtResult.append(msg.obj.toString());
} else if (msg.what == 2) {
txtResult.append("\n<<End test\n");
}
}
};
//
txtResult.setText("");
txtResult.setMovementMethod(ScrollingMovementMethod.getInstance());
btnTest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// doTest();
doTestOnAndroid4();
}
});
btnClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doClear();
}
});
}
protected void doClear() {
txtResult.setText("");
}
protected void doTest() {
String url = "http://www.baidu.com/";
txtResult.append("\nBegin test >>\n");
String text = "";
try {
text = Jsoup.connect(url).get().toString();
} catch (Exception e) {
e.printStackTrace();
// text = e.getMessage();
}
txtResult.append(text);
txtResult.append("\n<<End test\n");
}
protected void doTestOnAndroid4() {
new Thread(new Runnable() {
@Override
public void run() {
Message m = new Message();
m.what = 0;
handler.sendMessage(m);
//
m = new Message();
m.what = 1;
String url = "http://www.baidu.com/";
try {
m.obj = Jsoup.connect(url).get().toString();
} catch (Exception e) {
e.printStackTrace();
// m.obj = e.getMessage();
}
handler.sendMessage(m);
//
m = new Message();
m.what = 2;
handler.sendMessage(m);
}
}).start();
}
}