Android开发

Android开发HTTP协议请求
贵鬼2024-10-16发布
78 0

Android 9开始默认只能访问以HTTPS开头的安全地址,不能直接访问以HTTP开头的网络地址。如果应用仍想访问以HTTP开头的普通地址,就得修改AndroidManifest.xml,给application节点添加如下属性,表示继续使用HTTP明文地址。


使用HttpURLConnection对象

Get方法

public static  T get(String url,Class responseClass){
    HttpURLConnection connection = null;    
    try{
        URL _url = new URL(url);        
        connection = (HttpURLConnection)_url.openConnection();
        connection.setDoOutput(false);        
        connection.setDoInput(true);        
        connection.setRequestMethod("GET");        
        connection.setUseCaches(false);        
        connection.setInstanceFollowRedirects(true);        //是否自动处理重定向        
        connection.setConnectTimeout(3000);        
        connection.connect();       //连接  
      
        int code = connection.getResponseCode();        
        if(code == 200){
            String content = StringTools.getStr(connection.getInputStream());            
            Log.i(TAG,"GET返回:" + content);           
        }else{
            Log.e(TAG,"HTTP错误码:" + code);            
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();            
            BufferedInputStream bufferedInputStream = new BufferedInputStream(connection.getErrorStream());            
            byte[] data = new byte[255];            
            int length = -1;            
            while ((length = bufferedInputStream.read(data)) != -1){
                buffer.write(data,0,length);            
            }
            String errorMsg = new String(buffer.toByteArray(),StandardCharsets.UTF_8);
            Log.e(TAG,errorMsg);        
        }
    }catch (Exception e){
        Log.e(TAG,e.getMessage(),e);    
    }finally {
        if(connection != null){
            connection.disconnect();        
        }
    }
    return null;
}

Post方法

public static  T post(String url,Object requestObj,Class responseClass){
    HttpURLConnection connection = null;    
    try{
        URL _url = new URL(url);        
        connection = (HttpURLConnection)_url.openConnection();        
        connection.setDoOutput(true);        
        connection.setDoInput(true);        
        connection.setRequestMethod("POST");        
        connection.setUseCaches(false);        
        connection.setInstanceFollowRedirects(true);        //是否自动处理重定向        
        connection.setRequestProperty("Content-Type","application/json;charset:utf-8");        
        connection.setConnectTimeout(3000);        
        connection.connect();       //连接        
        
        OutputStream out = connection.getOutputStream();        
        out.write(JsonTools.toJSONBytes(requestObj));        
        out.flush();        
        out.close();        
        int code = connection.getResponseCode();        
        if(code == 200){
            String content = StringTools.getStr(connection.getInputStream());            
            Log.i(TAG,"POST返回:" + content);          
        }else{
            Log.e(TAG,"HTTP错误码:" + code);            
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();            
            BufferedInputStream bufferedInputStream = new BufferedInputStream(connection.getErrorStream());            
            byte[] data = new byte[255];            
            int length = -1;            
            while ((length = bufferedInputStream.read(data)) != -1){
                buffer.write(data,0,length);            
            }
            String errorMsg = new String(buffer.toByteArray(),StandardCharsets.UTF_8);            
            Log.e(TAG,errorMsg);        
        }
    }catch (Exception e){
        Log.e(TAG,e.getMessage(),e);    
    }finally {
        if(connection != null){
            connection.disconnect();        
        }
    }
    return null;
}

通过okhttp调用HTTP接口

添加okhttp包

implementation 'com.squareup.okhttp3:okhttp:4.9.2'

Get方法

// 发起GET方式的HTTP请求
public void doGet() {
    OkHttpClient client = new OkHttpClient(); // 创建一个okhttp客户端对象
    // 创建一个GET方式的请求结构
    Request request = new Request.Builder()
            //.get() // 因为OkHttp默认采用get方式,所以这里可以不调get方法
            .header("Accept-Language", "zh-CN") // 给http请求添加头部信息
            .url(URL_STOCK) // 指定http请求的调用地址
            .build();
    Call call = client.newCall(request); // 根据请求结构创建调用对象
    // 加入HTTP请求队列。异步调用,并设置接口应答的回调方法
    call.enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) { // 请求失败
            // 回到主线程操纵界面
            runOnUiThread(() -> tv_result.setText("调用股指接口报错:"+e.getMessage()));
        }

        @Override
        public void onResponse(Call call, final Response response) throws IOException { // 请求成功
            String resp = response.body().string();
            // 回到主线程操纵界面
            runOnUiThread(() -> tv_result.setText("调用股指接口返回:\n"+resp));
        }
    });
}

Post方法

// 发起POST方式的HTTP请求(报文为JSON格式)
public void postJson() {
    String username = et_username.getText().toString();
    String password = et_password.getText().toString();
    String jsonString ="";
    try {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("username",username);
        jsonObject.put("password",password);
        jsonString = jsonObject.toString();
    } catch (JSONException e) {
        e.printStackTrace();
    }
    // 创建一个POST方式的请求结构
    RequestBody body = RequestBody.create(jsonString, MediaType.parse("text/plain;charset=utf-8"));
    OkHttpClient client = new OkHttpClient(); // 创建一个okhttp客户端对象
    Request request = new Request.Builder().post(body).url(URL_LOGIN).build();
    Call call = client.newCall(request);
    // 加入HTTP请求队列。异步调用,并设置接口应答的回调方法
    call.enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) { // 请求失败
            // 回到主线程操纵界面
            runOnUiThread(() -> tv_result.setText("调用登录接口报错:"+e.getMessage()));
        }

        @Override
        public void onResponse(Call call, final Response response) throws IOException { // 请求成功
            String resp = response.body().string();
            // 回到主线程操纵界面
            runOnUiThread(() -> tv_result.setText("调用登录接口返回:\n"+resp));
        }
    });
}

下载图片方法

public void downloadImage() {
    // 创建一个okhttp客户端对象
    OkHttpClient client = new OkHttpClient();
    // 创建一个GET方式的请求结构
    Request request = new Request.Builder().url(URL_IMAGE).build();
    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(@NonNull Call call, @NonNull IOException e) { // 请求失败
            // 回到主线程操纵界面
            runOnUiThread(() -> tv_result.setText("下载网络图片报错:" + e.getMessage()));

        }

        @Override // 请求成功
        public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
            InputStream is = response.body().byteStream();
            // 从返回的输入流中解码获得位图数据
            Bitmap bitmap = BitmapFactory.decodeStream(is);
            String mediaType = response.body().contentType().toString();
            long length = response.body().contentLength();
            String desc = String.format("文件类型:%s,文件大小:%d", mediaType, length);
            // 回到主线程操纵界面
            runOnUiThread(() -> {
                tv_result.setText("下载网络图片返回:"+desc);
                iv_result.setImageBitmap(bitmap);
            });
        }
    });
}

下载文件方法

public void downloadFile() {
    OkHttpClient client = new OkHttpClient(); // 创建一个okhttp客户端对象
    // 创建一个GET方式的请求结构
    Request request = new Request.Builder().url(URL_APK).build();
    Call call = client.newCall(request); // 根据请求结构创建调用对象
    // 加入HTTP请求队列。异步调用,并设置接口应答的回调方法
    call.enqueue(new Callback() {
        @Override
        public void onFailure(@NonNull Call call, @NonNull IOException e) { // 请求失败
            // 回到主线程操纵界面
            runOnUiThread(() -> tv_result.setText("下载网络文件报错:" + e.getMessage()));
        }

        @Override
        public void onResponse(@NonNull Call call, @NonNull Response response) { // 请求成功
            String mediaType = response.body().contentType().toString();
            long length = response.body().contentLength();
            String desc = String.format("文件类型为%s,文件大小为%d", mediaType, length);
            // 回到主线程操纵界面
            runOnUiThread(() -> tv_result.setText("下载网络文件返回:" + desc));
            String path = String.format("%s/%s.apk",
                    getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(),
                    DateUtil.getNowDateTime());
            // 下面从返回的输入流中读取字节数据并保存为本地文件
            try {
                InputStream is = response.body().byteStream();
                FileOutputStream fos = new FileOutputStream(path);
                byte[] buf = new byte[100 * 1024];
                int sum = 0, len = 0;
                while ((len = is.read(buf)) !=-1){
                    fos.write(buf,0,len);
                    sum += len;
                    int progress = (int)(sum * 1.0f/length *100);
                    String detail = String.format("文件保存在%s。已下载%d%%",path,progress);
                    // 回到主线程操纵界面
                    runOnUiThread(() -> tv_progress.setText(detail));
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    });
}

上传文件方法

private void uploadFile() {
    // 创建分段内容的建造器对象
    MultipartBody.Builder builder = new MultipartBody.Builder();
    String username = et_username.getText().toString();
    String password = et_password.getText().toString();
    if (!TextUtils.isEmpty(username)) {
        // 往建造器对象添加文本格式的分段数据
        builder.addFormDataPart("username", username);
        builder.addFormDataPart("password", password);
    }
    for (String path : mPathList) { // 添加多个附件
        File file = new File(path); // 根据文件路径创建文件对象
        // 往建造器对象添加图像格式的分段数据
        builder.addFormDataPart("image", file.getName(),
                RequestBody.create(file, MediaType.parse("image/*")));
    }
    RequestBody body = builder.build(); // 根据建造器生成请求结构
    OkHttpClient client = new OkHttpClient(); // 创建一个okhttp客户端对象
    // 创建一个POST方式的请求结构
    Request request = new Request.Builder().post(body).url(URL_REGISTER).build();
    Call call = client.newCall(request); // 根据请求结构创建调用对象
    // 加入HTTP请求队列。异步调用,并设置接口应答的回调方法
    call.enqueue(new Callback() {
        @Override
        public void onFailure(@NonNull Call call, @NonNull IOException e) { // 请求失败
            // 回到主线程操纵界面
            runOnUiThread(() -> tv_result.setText("调用注册接口报错:\n" + e.getMessage()));
        }

        @Override
        public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { // 请求成功
            String resp = response.body().string();
            // 回到主线程操纵界面
            runOnUiThread(() -> tv_result.setText("调用注册接口返回:\n" + resp));
        }
    });

}