【Android】安卓原生态发起网络GET请求 && Post请求

发布于:2025-09-02 ⋅ 阅读:(17) ⋅ 点赞:(0)

在这里插入图片描述

三三要成为安卓糕手

引入:在Android中发起网络请求

在Android中可以使用HttpURLConnection、OkHttp、Retrofit等常见的请求方式:

  1. HttpURLConnection:Android自带的网络请求方式,使用起来较为复杂,但自由度更高,适合尽量减少外部依赖的项目;
  2. OkHttp:适合绝大多数Android项目,特别是在需要高效处理网络请求的场景中;
  3. Retrofit:在OkHttp的基础上做了封装,代码更加简洁明了;
  4. Volley:Google推出的网络请求库,目前不经常被用到。

一:需求

查询用户4,点击发起Get请求,形成http数据传输,接收从后端返回的用户数据

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预期结果如下

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

二:http传输三个问题

要想进行http明文传输,需要解决三个问题

  • 清单文件中声明网络访问权限
  • 设置可以明文传输
  • 不要在主线程中进行http连接访问
public class HttpUrlConnectionActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "HttpUrlConnectionActivity";
    private EditText etUserId;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_http_url_connection);


        findViewById(R.id.btn_get).setOnClickListener(HttpUrlConnectionActivity.this);
        etUserId = findViewById(R.id.et_user_id);

    }

    @Override
    public void onClick(View v) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (v.getId() == R.id.btn_get) {
                    //这个过程真的非常的惊艳
                    String id = etUserId.getText().toString();
                    String urlAddress = "http://titok.fzqq.fun/addons/cms/api.user/userInfo?user_id=" + id + "&type=archives";

                    Log.i(TAG, "urlAddress:"+urlAddress);

                    try {
                        //创建URL对象,传入服务器地址
                        URL url = new URL(urlAddress);
                        //打开连接,HttpURLConnection对象中设置一些连接的属性:比如请求方法和连接时间,读取数据的时间
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        //连接方法
                        connection.setRequestMethod("GET");
                        //连接超时时间
                        connection.setConnectTimeout(8000);
                        //读取超时时间
                        connection.setReadTimeout(80000);

                        //读取服务器的输入流,从这里面可以读取服务器返回的数据
                        InputStream inputStream = connection.getInputStream();
                        //输入流包装成BufferReader,方便读取数据
                        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));


                        //不断读取数据,append到builder中,最后将结果转化为String
                        String line;
                        StringBuilder builder = new StringBuilder();
                        while ((line = reader.readLine()) != null) {
                            builder.append(line);
                        }
                        String string = builder.toString();

                        Log.i(TAG, "网络访问的结果:" + string);
                        //关闭连接
                        connection.disconnect();


                    } catch (MalformedURLException e) {
                        throw new RuntimeException(e);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }

            }
        }).start();
    }
}

1:声明网络访问权限

<uses-permission android:name="android.permission.INTERNET"/> //网络访问

2:Http明文请求属性设置

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从 Android 9.0 (Pie) 开始,默认情况下,应用只能进行 HTTPS 请求。要允许 HTTP 请求,需要在AndroidManifest.xml 中配置网络安全策略

(1)方式一

<application
    ....
    android:networkSecurityConfig="@xml/network_security_config">
    ....
</application>

然后,创建 res/xml/network_security_config.xml 文件,并定义允许 HTTP 请求的配置:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <!-- 允许应用使用明文流量(HTTP) -->
    <domain-config cleartextTrafficPermitted="true">
        <--表示允许某个域名-->
        <domain includeSubdomains="true">titok.fzqq.fun</domain>
    </domain-config>
</network-security-config>

(2)方式二:usesCleartextTraffic

或者直接添加全局设置,快速支持HTTP,但这种做法有可能存在安全隐患

usesCleartextTraffic 使用明文网络流量 “cleartext” 指未加密的文本(明文) “traffic” 是网络流量

<application
    ....
    android:usesCleartextTraffic="true">
    ....
</application>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3:不要在主线程中进行http连接访问

因为http连接是有连接时间和响应时间的,虽然1~2秒(网络不好会更久)对于人的感官来说很短暂,但是对于机器来说度秒如年;所以我们不能再主线程中进行http连接,而要选择去new Thread在子线程做这个事情

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

总结一下:主线程主要负责 UI 渲染和交互,若在主线程执行耗时操作(如网络请求、文件读写等),会阻塞 UI 刷新,导致界面卡顿甚至 ANR(应用无响应)

三:代码中涉及到的写法

访问地址:用的是字符串拼接的方式

archive 英 [ˈɑːkaɪv] 档案 记录

String urlAddress = "http://titok.fzqq.fun/addons/cms/api.user/userInfo?user_id=" + id + "&type=archives";

1:子线程处理http请求

把http代码放到Runnable中,并且用.start()方法启动

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2:设置连接属性

涉及到:创建url对象,打开连接,设置连接方法,连接超时时间,读取超时时间

						//创建URL对象,传入服务器地址
                        URL url = new URL(urlAddress);
                        //打开连接,HttpURLConnection对象中设置一些连接的属性:比如请求方法和连接时间,读取数据的时间
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        //连接方法
                        connection.setRequestMethod("GET");
                        //连接超时时间
                        connection.setConnectTimeout(8000);
                        //读取超时时间
                        connection.setReadTimeout(80000);

3:如何读取数据

						//不断读取数据,append到builder中,最后将结果转化为String
                        String line;
                        StringBuilder builder = new StringBuilder();
                        while ((line = reader.readLine()) != null) {
                            builder.append(line);
                        }
                        String string = builder.toString();

                        Log.i(TAG, "网络访问的结果:" + string);
                        //关闭连接
                        connection.disconnect();

这里的while循环括号中条件代码的写法非常奇妙,好好体会

四:如何发起Http-Post请求

1:总体代码

引子:写完下面这段代码,对客户端和服务器之间怎么进行http连接,能有非常直观的感受;还有一些方法需要熟练,代码中的注释写的非常详细了,下面的说明就简略展开了

    /**
     * 发起一个post请求
     */
    private void SendPostRequest() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //先进行字符串拼接
                String loginUrl = "http://titok.fzqq.fun/addons/cms/api.login/login";
                try {
                    /**
                     * 第一步:构造请求头,包括url,请求方法,发送报文格式,接受数据格式,(可以加连接超时时间,读取数据超时时间)
                     */
                    URL url = new URL(loginUrl);
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    //设置请求方法
                    connection.setRequestMethod("POST");
                    //允许服务器输出数据
                    connection.setDoOutput(true);
                    //设置请求头,比如:请求报文格式,要接收的数据格式
                    connection.setRequestProperty("Content-Type","application/json;charset=uft-8");
                    connection.setRequestProperty("Accept","application/json");

                    /**
                     * 第二步:构造json请求体,用输出流把数据输出
                     */

                    //构造json请求体
                    String account = edUserName.getText().toString();
                    String password = edPassword.getText().toString();
                    String jsonBody = "{ \"account\": \"" + account + "\",\"password\": \"" + password + "\" }";


                    //搞成输出流,把这段字符串化为json格式
                    OutputStream os = connection.getOutputStream();
                    //设置为字节数组方便底层处理
                    byte[] bytes = jsonBody.getBytes("utf-8");
                    os.write(bytes,0,jsonBody.length());


                    /**
                     * 读取响应
                     */
                    int responseCode = connection.getResponseCode();
                    if(responseCode == HttpURLConnection.HTTP_OK){
                        //200表示访问成功,开始接收返回的数据
                        InputStream is = connection.getInputStream();
                        //理解:定义一种读取的方式——带缓冲的字符流读取方式
                        BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8"));

                        //把不断读取的相应数据,拼接汇总
                        String line;
                        StringBuilder builder = new StringBuilder();
                        while((line = br.readLine()) != null){
                            builder.append(line);
                        }

                        //得到最终的响应数据了,我们在主线程去使用响应的数据
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                String loginResult = builder.toString();
                                Log.i(TAG, "run: 返回响应的数据是:" + loginResult);
                            }
                        });

                    }else{
                        Log.i(TAG, "run: 网络请求失败");
                    }


                } catch (MalformedURLException e) {
                    throw new RuntimeException(e);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }

            }
        }).start();
    }

2:构造http请求头

(1)new URL(loginUrl)

注意new URL()这个对象的时候要大写

(2)url.openConnection

通过url打开http连接

(3)setDoOutput

设置参数true;设置允许服务器输出数据

(4)setRequestProperty

设置请求属性;比如说明客户端发送出去的请求的报文格式,要求服务器返回回来的报文格式

property 英 [ˈprɒpəti] 属性

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3:构造json请求体,用输出流把数据输出

这里发送的json请求体格式要按照开发文档上的标准来,用参数拼接的方式来整,会轻松很多

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(1)getBytes(“utf-8”)

将字符串 jsonBody 按照 UTF-8 字符编码转换为字节数组,再把字节数组输出出去

4:读取响应

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(1)getResponseCode

获取响应码,安卓HttpURLConnection中提供了相应的响应码常量,这里的HTTP_OK状态描述就是状态码200

(2)缓冲读取字符

 BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8"));

这行代码非常精髓,这是一种读取方式,输入流读取数据进来(以utf-8的编码格式)

buffer 英 [ˈbʌfə®] 缓冲区

(3)runOnUiThread

在主线程中处理接收到的响应数据

五:结果

登录成功

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


网站公告

今日签到

点亮在社区的每一天
去签到