09网络技术-http协议访问网络
2018-03-28  本文已影响46人 
何惧l
WebView的用法
可以使用它在自己的程序中嵌入一个浏览器,用来展示各种各样的网页
- 新建一个WebVitwTest项目,修改activity中的代码
 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   >
    <WebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    
</LinearLayout>
- 这里使用了WebView控件,用来显示网页的,让它充满全屏
 
- 修改MainActivity中的代码
 
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        WebView webView = (WebView)findViewById(R.id.web_view);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebChromeClient(new WebChromeClient());
        webView.loadUrl("http://www.jianshu.com");
    }
}
- 首先获取到了WebVIew的实例,然后调用
getSettings()方法去设置一些浏览器的熟悉,这里只是调用了setJavaScriptEnabled(true)方法,让WebView支持javaAcript脚本 - 接下来就是调用
setWebChromeClient()方法,并传入一个WebViewClient的实例,就是当需要从一个网页跳到另一个网页时,目标网页仍然是在当前的WebView中显示,而不是打开系统的浏览器 - 最后就是调用
loadUrl()方法,并将网址出入就可以了 
- 由于使用到了网络功能,要访问网络是需要声明权限的,还的AndroidManifest中的代码
 
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.md.web">
    <uses-permission android:name="android.permission.INTERNET"/>
    ...
    </manifest>
- 
运行程序,这个时候要确保模拟器是联网的就可以了
WebView网页.png
当然了,这只是一种简单的实现方式,下面就是利用Http协议做真正的网络开发工作了
 
使用HTTP协议访问网络
上面使用WebView访问网页,因为是封装好的,不能直观的看出来HTTP协议到底是如何工作的,下面通过手动方法HTTP请求的方法,深入的了解一下这个过程
使用HttpURLConnection
- 首先获取到HttpURLConnection的实例,只需new出一个URL对象,并传入目标的网络地址中,然后调用一下openConnection()方法即可
 
URL url = new URL("http://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
- 获取到实例后,设置一下HTTP请求所使用的方法,常用的就是POST和GEE请求,GET就是从服务器那获取数据,POST请求就是提交数据给服务器
 
connection.setRequestMethod("GET")
- 下面就是自由的定制了,比如设置连接超时,读取超时的毫秒数,以及服务器希望得到的一些消息头等
 
connection.setConnecTimeout(8000);
connection.setReadTImeout(8000);
- 之后调用getInputStream()方法读取到服务器返回的输入流就可以,
InputStream in = connection.getInputStream(); - 最后调用disconnect()方法将这个HTTP连接关闭就可以了
 - 新建一个NetworkTest项目,进行实际操作一下,修改activity中的代码
 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   >
    <Button
        android:id="@+id/send_request"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        />
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <TextView
            android:id="@+id/request_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </ScrollView>
    
</LinearLayout>
- 这里使用了新的控件ScrollView,就是可以借助滚动的形式查看屏幕以外的部分内容,Button用于发送HTTP请求,TextView用于将服务器返回的数据显示
 
- 修改MainActivity中的代码
 
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private TextView responseText;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button sendRequst = (Button)findViewById(R.id.send_request);
        responseText = (TextView)findViewById(R.id.request_text);
        // 按钮添加绑定事件
        sendRequst.setOnClickListener(this);
    }
    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.send_request){
            sendRequestWithHttpURLConnection();
        }
    }
    private void sendRequestWithHttpURLConnection(){
        //开启线程来发送网络请求
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                BufferedReader reader = null;
                try {
                    // 获取到实例
                    URL url = new URL("https://www.jianshu.com/");
                    connection = (HttpURLConnection)url.openConnection();
                    // 设置一些属性
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    InputStream in = connection.getInputStream();
                    //对获取到的输入流进行读取
                    reader = new BufferedReader(new InputStreamReader(in));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null){
                        response.append(line);
                    }
                    // 把获取的数据传入到这个方法中
                    showResponse(response.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    if(reader != null){
                        try {
                            reader.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (connection != null){
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }
    private void showResponse(final String response){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // 这里拿数据显示到界面上
                responseText.setText(response);
            }
        });
    }
}
- 首先在按钮的点击事件中调用了sendRequestWithHttpURLConnection()方法
 - 这个方法中先是开启了一个子线程,在子线程中使用了HttpURLConnection发送了一个HTTP请求,请求的是简书首页,利用BufferedReader对服务器返回的流进行读取,然后把数据传入到showResponse()方法中
 - 在这个方法中,使用了runOnUiThread()方法,把数据设置到textView中,为什么使用这个runOnUiThread()方法,是因为Android是不允许在子线程中进行UI操作的,通过这个方法将线程切换到主线程
 
- 当然了,最后还得声明一下网络权限,在AndroidManifest中
 
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.md.web">
    <uses-permission android:name="android.permission.INTERNET"/>
    ...
    </manifest>
- 
运行程序,点击按钮就可以了
返回的数据.png
返回的是源码,
 - 如果是想要给服务器提交数据怎么办,这个时候把请求方式改成GET请求就可以了,并在获取输入流之前把要提交的数据写入就可以了,注意每条数据都要用键值对的形式,数据之间使用&号区分就可以了,比如提交用户名和密码
 
    connection.setRequestMethod("POST");
    DataOutputStream out = new DataOutputStream(connection.getOutputStream());
    out.writeBytes("username=pony007&&password=123456");
使用OkHttp
- 添加OkHttp库的依赖,编辑app/build.gradle文件,在dependencies闭包中
 
dependencies {
    ...
    compile 'com.squareup.okhttp3:okhttp:3.4.1'
}
- OkHttp的基本用法
- 创建一个OkHttpClient的实例
OkHttpClient client = new OkHttpClient() - 接下来如果想要发送一条HTTP请求,就需要创建一个Request对象
Request request = new Request.Builder().build(); - 当然了,这只是一个空的Rerquest对象,没有实际的作用,在最终的build()方法之前连缀很多其他方法来丰富这个Request对象,比如可以通过url()方法来设置目标网络地址
 
.url("https://www.jianshu.com/") .build();- 之后调用OkHttpClient的newCall()方法来创建一个Call对象,并调用它的execute()方法来发送请求并获得服务器返回的数据
Response response = client.newCall(request).execute(); - 其中的Request对象就是服务器返回的数据,可以使用下面的写法来得到返回的具体内容
String responseData = response.body().string(); - 如果是POST请求会比GET请求稍微复杂一点,首先构建一个RequestBody对象用来存放待提交的数据,如下
 
RequestBody requestBody = new FormBody.Builder() .add("username","pony007") .add("password","123456") .build();- 然后在Request.Builder中调用post()方法并将RequestBody对象传入
 
.url("https://www.jianshu.com/") .post(requestBody) .build();- 接下来就是和GET请求一样了,调用execute()方法获取返回的数据就可以了
 
 - 创建一个OkHttpClient的实例
 - 继续改上面的程序,布局的就不用改动了,直接该MainActivity中的,添加一个sendRequestWithOkHttp()方法就可以了
 
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private TextView responseText;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button sendRequst = (Button)findViewById(R.id.send_request);
        responseText = (TextView)findViewById(R.id.request_text);
        // 按钮添加绑定事件
        sendRequst.setOnClickListener(this);
    }
    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.send_request){
            sendRequestWithOkHttp();
        }
    }
    private void sendRequestWithOkHttp(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
                            .url("https://www.jianshu.com/")
                            .build();
                    Response response = client.newCall(request).execute();
                    // 获取到了从服务器返回的数据
                    String responseData = response.body().string();
                    // 把获取的数据传入到这个方法中
                    showResponse(responseData);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
    private void showResponse(final String response){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // 这里拿数据显示到界面上
                responseText.setText(response);
            }
        });
    }
}
- 在这个方法中还是开启了一个子线程,使用OkHttp发出一条HTTP请求,最后还是使用showResponse()方法将服务器返回的数据显示在界面上了
 - 
可以看到这个非常的简便,实现的功能是一样的
OkHttp返回的数据.png