最近做一个Android项目,利用Jsoup读取和解析网页数据,同样的程序在Android2.3上运行完全正常,而跑到Android4上面,bug出现了...
看了一下异常:android.os.NetworkOnMainThreadException
然后,上网搜索一下才发现,原来Android4默认情况下是不允许在主线程中访问网络的。
解决问题的思路有两种:
1、解除主线程网络访问限制,参见http://developer.android.com/reference/android/os/StrictMode.html
在onCreate中加入以下代码即可:
StrictMode.setThreadPolicy(newStrictMode.ThreadPolicy.Builder
() .detectDiskReads() .detectDiskWrites() .detectNetwork() // or .detectAll() for all detectable problems .penaltyLog() .build()); StrictMode.setVmPolicy(newStrictMode.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(); } }