【0032】Android基础-21-网络源码查看器
【1】网络源码查看器-【功能】类似于下面的浏览器的功能,发出一个http网络请求,将服务器中的数据返回显示(并没有解析的功能)



【2】界面布局

1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" 6 android:paddingBottom="@dimen/activity_vertical_margin" 7 android:paddingLeft="@dimen/activity_horizontal_margin" 8 android:paddingRight="@dimen/activity_horizontal_margin" 9 android:paddingTop="@dimen/activity_vertical_margin" 10 tools:context=".MainActivity" > 11 12 <EditText 13 android:id="@+id/et_url" 14 android:layout_width="fill_parent" 15 android:layout_height="wrap_content" 16 android:text="http://www.baidu.com" /> 17 18 <Button 19 android:id="@+id/bt_looksource" 20 android:layout_width="fill_parent" 21 android:layout_height="wrap_content" 22 android:text="查看源码" /> 23 24 <ScrollView 25 android:layout_width="wrap_content" 26 android:layout_height="wrap_content" > 27 28 <TextView 29 android:id="@+id/tv_source" 30 android:layout_width="match_parent" 31 android:layout_height="match_parent" /> 32 </ScrollView> 33 34 </LinearLayout>
【3】逻辑

【4】请求url地址的逻辑

获得url地址中的数据使用到的类:获取使用的协议是标准的http协议
在HttpURLConnection类中有实例,可以通过其中的方法进行状态的判断;


【源码】
1 package layoutdemo.com.example.a1netsourcecodeinsight; 2 3 import android.content.Context; 4 import android.support.v7.app.AppCompatActivity; 5 import android.os.Bundle; 6 import android.view.View; 7 import android.widget.Button; 8 import android.widget.EditText; 9 import android.widget.TextView; 10 import android.widget.Toast; 11 12 import java.io.InputStream; 13 import java.net.HttpURLConnection; 14 import java.net.MalformedURLException; 15 import java.net.URL; 16 import java.net.URLConnection; 17 18 import layoutdemo.com.example.StreamUtil.StreamUtil; 19 20 public class MainActivity extends AppCompatActivity implements View.OnClickListener { 21 private EditText et_url; 22 private TextView tv_performCode; 23 private Context mContext; 24 @Override 25 protected void onCreate(Bundle savedInstanceState) { 26 super.onCreate(savedInstanceState); 27 setContentView(R.layout.activity_main); 28 29 //1.找到控件 30 Button bt_searchURL = (Button) findViewById(R.id.bt_searchURL); 31 et_url = (EditText) findViewById(R.id.et_url); 32 tv_performCode = (TextView) findViewById(R.id.tv_performCode); 33 //2.设置点击事件 34 bt_searchURL.setOnClickListener(this); 35 36 } 37 38 @Override 39 public void onClick(View view) { 40 //3.获取输入的地址 41 String urlString = et_url.getText().toString().trim(); 42 //4.查询获取的地址的内容 43 /* 44 * 需要使用到UrlConnetion类; 45 * */ 46 try { 47 //4.1创建一个url对象 48 URL url = new URL(urlString); 49 //4.2获取一个urlConnection对象 50 HttpURLConnection connection = (HttpURLConnection)url.openConnection(); 51 //4.3 为HttpURLConnection对象设置一些参数,请求方式,连接的超时时间 52 connection.setRequestMethod("GET"); 53 System.out.println("11111111"); 54 connection.setReadTimeout(1000); 55 //4.4 获取响应码 56 int code = connection.getResponseCode(); 57 if (code == 200){ 58 //5.获取有效的数据,并将数据解析成为String 59 InputStream stream = connection.getInputStream(); 60 String result = StreamUtil.streamToString(stream); 61 tv_performCode.setText(result); 62 } 63 } catch (Exception e) { 64 e.printStackTrace(); 65 } 66 67 68 } 69 }
【5】封装专门的streamToString方法
【源码】
1 package layoutdemo.com.example.StreamUtil; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 7 /** 8 * Created by Administrator on 2017-10-23. 9 */ 10 11 public class StreamUtil { 12 public static String streamToString(InputStream in) { 13 String result = ""; 14 15 try { 16 //创建一个字节数组的写入流 17 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 18 19 byte[] buffer = new byte[1024]; 20 int lenght = 0; 21 while ((lenght = in.read(buffer)) != -1){ 22 outputStream.write(buffer,0,lenght); 23 outputStream.flush(); 24 } 25 result = outputStream.toString(); 26 outputStream.close(); 27 } catch (IOException e) { 28 e.printStackTrace(); 29 } 30 31 return result; 32 } 33 }
【6】访问网络需要增加权限

【7】运行结果

【8】改进-实际的内容没有显示完整,改进:


【9】出现的异常-在Android7.1上出现的BUG
1 10-23 03:16:01.925 12883-12883/layoutdemo.com.example.a1netsourcecodeinsight W/System.err: 2 10-23 03:16:01.926 12883-12883/layoutdemo.com.example.a1netsourcecodeinsight W/System.err: at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303) 3 10-23 03:16:01.926 12883-12883/layoutdemo.com.example.a1netsourcecodeinsight W/System.err: at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:86) 4 10-23 03:16:01.926 12883-12883/layoutdemo.com.example.a1netsourcecodeinsight W/System.err: at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:74) 5 10-23 03:16:01.926 12883-12883/layoutdemo.com.example.a1netsourcecodeinsight W/System.err: at java.net.InetAddress.getAllByName(InetAddress.java:752) 6 10-23 03:16:01.926 12883-12883/layoutdemo.com.example.a1netsourcecodeinsight W/System.err: at com.android.okhttp.internal.Network$1.resolveInetAddresses(Network.java:29) 7 10-23 03:16:01.926 12883-12883/layoutdemo.com.example.a1netsourcecodeinsight W/System.err: at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:187) 8 10-23 03:16:01.926 12883-12883/layoutdemo.com.example.a1netsourcecodeinsight W/System.err: at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:156) 9 10-23 03:16:01.926 12883-12883/layoutdemo.com.example.a1netsourcecodeinsight W/System.err: at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:98) 10 10-23 03:16:01.926 12883-12883/layoutdemo.com.example.a1netsourcecodeinsight W/System.err: at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:345)
【出现异常的原因】
看名字就应该知道,是网络请求在MainThread中产生的异常
先来看一下官网的解释:
Class Overview
The exception that is thrown when an application attempts to perform a networking operation on its main thread.
This is only thrown for applications targeting the Honeycomb SDK or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged. See the document Designing for Responsiveness.
Also see StrictMode.
http://developer.android.com/intl/zh-cn/reference/android/os/NetworkOnMainThreadException.html
解释一下,从Honeycomb SDK(3.0)开始,google不再允许网络请求(HTTP、Socket)等相关操作直接在Main Thread类中,其实本来就不应该这样做,直接在UI线程进行网络操作,会阻塞UI、用户体验相当bad!即便google不禁止,一般情况下我们也不会这么做吧~
所以,也就是说,在Honeycomb SDK(3.0)以下的版本,你还可以继续在Main Thread里这样做,在3.0以上,就不行了,建议
【10】异常的解决


【源码】增加新的线程,在线程中做网络请求的操作
1 package layoutdemo.com.example.a1netsourcecodeinsight; 2 3 import android.content.Context; 4 import android.support.v7.app.AppCompatActivity; 5 import android.os.Bundle; 6 import android.view.View; 7 import android.widget.Button; 8 import android.widget.EditText; 9 import android.widget.TextView; 10 import android.widget.Toast; 11 12 import java.io.IOException; 13 import java.io.InputStream; 14 import java.net.HttpURLConnection; 15 import java.net.MalformedURLException; 16 import java.net.URL; 17 import java.net.URLConnection; 18 19 import layoutdemo.com.example.StreamUtil.StreamUtil; 20 21 public class MainActivity extends AppCompatActivity implements View.OnClickListener { 22 private EditText et_url; 23 private TextView tv_performCode; 24 private Context mContext; 25 @Override 26 protected void onCreate(Bundle savedInstanceState) { 27 super.onCreate(savedInstanceState); 28 setContentView(R.layout.activity_main); 29 30 //1.找到控件 31 Button bt_searchURL = (Button) findViewById(R.id.bt_searchURL); 32 et_url = (EditText) findViewById(R.id.et_url); 33 tv_performCode = (TextView) findViewById(R.id.tv_performCode); 34 //2.设置点击事件 35 bt_searchURL.setOnClickListener(this); 36 System.out.println("onCreate:"+Thread.currentThread().toString()); 37 38 } 39 40 @Override 41 public void onClick(View view) { 42 //3.获取输入的地址 43 final String urlString = et_url.getText().toString().trim(); 44 System.out.println("onClick:"+Thread.currentThread().toString()); 45 //4.查询获取的地址的内容 46 /* 47 * 需要使用到UrlConnetion类; 48 * */ 49 try { 50 new Thread(new Runnable() { 51 @Override 52 public void run() { 53 54 System.out.println("onClick:run()"+Thread.currentThread().toString()); 55 try { 56 //4.1创建一个url对象 57 URL url = new URL(urlString); 58 //4.2获取一个urlConnection对象 59 HttpURLConnection connection = (HttpURLConnection)url.openConnection(); 60 //4.3 为HttpURLConnection对象设置一些参数,请求方式,连接的超时时间 61 connection.setRequestMethod("GET"); 62 System.out.println("11111111"); 63 connection.setReadTimeout(1000); 64 //4.4 获取响应码 65 int code = connection.getResponseCode(); 66 if (code == 200){ 67 //5.获取有效的数据,并将数据解析成为String 68 InputStream stream = connection.getInputStream(); 69 String result = StreamUtil.streamToString(stream); 70 tv_performCode.setText(result); 71 } 72 } catch (Exception e) { 73 e.printStackTrace(); 74 } 75 76 } 77 }).start(); 78 79 } catch (Exception e) { 80 e.printStackTrace(); 81 } 82 83 84 } 85 }

【11】出现新的异常-转到handler节

浙公网安备 33010602011771号