暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

HarmonyOS网络请求使用示例

鸿蒙技术社区 2022-02-25
1749

在应用开发的过程中,网络请求是很常见的场景,其中常见是加载网络图片、访问后台接口等。在安卓系统中实现这些相信大家已经很熟悉了,那么在鸿蒙系统中又有哪些相似与不同呢?


今天给大家带来的是在鸿蒙系统中发起网络请求的使用示例,示例中包含了使用鸿蒙 API 完成 get、post 请求,加载网络图片等。


功能展示如下图:

开发概述


首先,使用网络模块的相关功能时,需要请求相应的权限。
添加在 entry 模块的 config.json 中:

权限相关配置好后,接下来看一下鸿蒙开发官网上对于网络模块开发的接口说明。


鸿蒙官网网络开发文档:
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/connectivity-net-url-0000000000045542


文档中给出了网络开发的关键接口说明及网络开发的一般步骤:

  • 调用 NetManager.getInstance(Context) 获取网络管理的实例对象。

  • 调用 NetManager.getDefaultNet() 获取默认的数据网络。

  • 调用 NetHandle.openConnection() 打开一个 URL。

  • 通过 URL 链接实例访问网站。


并且提供了网络状态的监听接口:
addDefaultNetStatusCallback(NetStatusCallback callback)


    private final NetStatusCallback callback = new NetStatusCallback() {
        @Override
        public void onAvailable(NetHandle handle) {
           //网络可用时
        }

        @Override
        public void onBlockedStatusChanged(NetHandle handle, boolean blocked) {
           //网络状态变化时
        }
    };


下面我们来编写下完整的网络请求实例:

get 请求:

 public void requestByGet() {
        LogUtils.debug("NetRequestUtils  requestByGet");
        NetManager netManager = NetManager.getInstance(null);
        if (!netManager.hasDefaultNet()) {
            LogUtils.debug("NetRequestUtils  network is null");
            return;
        }
        ThreadPoolUtil.submit(() -> {
            NetHandle netHandle = netManager.getDefaultNet();
            netManager.addDefaultNetStatusCallback(callback);
            HttpURLConnection connection = null;
            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                URL url = new URL("http://www.baidu.com");
                URLConnection urlConnection = netHandle.openConnection(url, java.net.Proxy.NO_PROXY);
                if (urlConnection instanceof HttpURLConnection) {
                    connection = (HttpURLConnection) urlConnection;
                }
                connection.setRequestMethod("GET");
                connection.connect();

                //之后可进行url的其他操作
                try (InputStream inputStream = urlConnection.getInputStream()) {
                    byte[] cache = new byte[2 * 1024];
                    int len = inputStream.read(cache);
                    while (len != -1) {
                        outputStream.write(cache, 0, len);
                        len = inputStream.read(cache);
                    }
                } catch (IOException e) {
                    LogUtils.error("NetRequestUtils inner IOException");
                }
                String result = new String(outputStream.toByteArray());
                LogUtils.debug("NetRequestUtils result:" + result);
                getUITaskDispatcher().syncDispatch(() -> Toast.show("成功发起get网络请求:" + result));
                HttpResponseCache.getInstalled().flush();
            } catch (IOException e) {
                LogUtils.error("NetRequestUtils IOException");
            }
        });
    }


post 请求:测试发现,只需要将 connection.setRequestMethod(); 中的参数修改成“POST"即可。

connection.setRequestMethod(“POST”);


网络图片加载:

    /**
     * 请求网络图片
     */

    public void requestNetImage({
        ThreadPoolUtil.submit(() -> {
            String requestUrl = "https://t7.baidu.com/it/u=4162611394,4275913936&fm=193&f=GIF";
            HttpURLConnection connection = null;
            try {
                connection = getHttpURLConnection(requestUrl, "GET");
                connection.connect();
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    //将网络请求数据转换成ImageSource
                    ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
                    ImageSource imageSource = ImageSource.create(connection.getInputStream(), srcOpts);
                    //将ImageSource转换成可以设置给image控件的PixelMap对象
                    PixelMap pixelMap = imageSource.createPixelmap(null);
                    getUITaskDispatcher().syncDispatch(() -> image.setPixelMap(pixelMap));
                }
                connection.disconnect();
            } catch (Exception e) {
                LogUtils.error("NetRequestUtilsException  requestNetImage:" + e.getMessage());
            }
        });
    }

    private HttpURLConnection getHttpURLConnection(String requestURL, String requestMethod) throws IOException {
        URL url = new URL(requestURL);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        //设置连接超时时间
        connection.setConnectTimeout(10 * 1000);
        //设置读取服务器数据超时时间
        connection.setReadTimeout(15 * 1000);
        //设置请求方式
        connection.setRequestMethod(requestMethod);
        return connection;
    }


在加载网络图片时,connection 连接成功后,获取到的是一张图片的输入流。


为了将图片输入流转化成可以显示的 PixelMap 对象,需要先创建 ImageSource 对象。


再通过 imageSource.createPixelmap(null) 创建对应的 pixelMap 对象,最终通过 image.setPixelMap(pixelMap)); 将图片加载到屏幕上。


以下是完整代码示例:

public class NetAbilitySlice extends AbilitySlice {
    Image image;

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_slice_net);
        findComponentById(ResourceTable.Id_btn_request_get).setClickedListener(component -> {
            requestByGet();
        });
        findComponentById(ResourceTable.Id_btn_request_post).setClickedListener(component -> {
            requestByPost();
        });
        findComponentById(ResourceTable.Id_btn_request_image).setClickedListener(component -> {
            requestNetImage();
        });
        image = (Image) findComponentById(ResourceTable.Id_image_neturl);
    }

    public void requestByGet() {
        LogUtils.debug("NetRequestUtils  requestByGet");
        NetManager netManager = NetManager.getInstance(null);
        if (!netManager.hasDefaultNet()) {
            LogUtils.debug("NetRequestUtils  network is null");
            return;
        }
        ThreadPoolUtil.submit(() -> {
            NetHandle netHandle = netManager.getDefaultNet();
            netManager.addDefaultNetStatusCallback(callback);
            HttpURLConnection connection = null;
            LogUtils.debug("NetRequestUtils  ThreadPoolUtil.submit");
            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                LogUtils.debug("NetRequestUtils  URL.new URL");
                URL url = new URL("http://www.baidu.com");
                URLConnection urlConnection = netHandle.openConnection(url, java.net.Proxy.NO_PROXY);
                if (urlConnection instanceof HttpURLConnection) {
                    connection = (HttpURLConnection) urlConnection;
                }
                connection.setRequestMethod("GET");
                connection.connect();
                LogUtils.debug("NetRequestUtils  connection.connect");
                //之后可进行url的其他操作
                try (InputStream inputStream = urlConnection.getInputStream()) {
                    byte[] cache = new byte[2 * 1024];
                    int len = inputStream.read(cache);
                    while (len != -1) {
                        outputStream.write(cache, 0, len);
                        len = inputStream.read(cache);
                    }
                } catch (IOException e) {
                    LogUtils.error("NetRequestUtils inner IOException");
                }
                String result = new String(outputStream.toByteArray());
                LogUtils.debug("NetRequestUtils result:" + result);
                getUITaskDispatcher().syncDispatch(() -> Toast.show("成功发起get网络请求:" + result));
                HttpResponseCache.getInstalled().flush();
            } catch (IOException e) {
                LogUtils.error("NetRequestUtils IOException");
            }
        });
    }

    private final NetStatusCallback callback = new NetStatusCallback() {
        @Override
        public void onAvailable(NetHandle handle) {
            LogUtils.info("NetStatusCallback onAvailable");
        }

        @Override
        public void onBlockedStatusChanged(NetHandle handle, boolean blocked) {
            LogUtils.info("NetStatusCallback onBlockedStatusChanged");
        }
    };

    public void requestByGet1() {
        String requestUrl = "https://www.baidu.com";
        ThreadPoolUtil.submit(() -> {
        HttpURLConnection connection = null;
        try {
            connection = getHttpURLConnection(requestUrl, "GET");
            connection.connect();
            String response = getReturnString(connection.getInputStream());
            ZSONObject zsonObject = ZSONObject.stringToZSON(response);
            LogUtils.info("NetRequestUtils requestByGet1 :" + zsonObject);
            getUITaskDispatcher().syncDispatch(() -> Toast.show("成功发起get网络请求:" + zsonObject));
        } catch (Exception e) {
            LogUtils.error("NetRequestUtils requestByGet1 :" + e.getMessage());
        }
        });
    }

    public void requestByPost1() {
        ThreadPoolUtil.submit(() -> {
            String requestUrl = "http://10.55.20.48:8082/svnplus/fileSystem/uploadMoel?url=http://120.78.215.13/home/svn/666";
            HttpURLConnection connection = null;
            try {
                connection = getHttpURLConnection(requestUrl, "POST");
                connection.connect();
                String response = getReturnString(connection.getInputStream());
                ZSONObject zsonObject = ZSONObject.stringToZSON(response);
                LogUtils.info("NetRequestUtils requestByPost:" + zsonObject);
                getUITaskDispatcher().syncDispatch(() -> Toast.show("成功发起post网络请求:" + zsonObject));
            } catch (Exception e) {
                LogUtils.error("NetRequestUtilsException requestByPost:" + e.getMessage());
                getUITaskDispatcher().syncDispatch(() -> Toast.show("成功发起post网络请求:" + e.getMessage()));
            }
        });
    }

    public void requestByPost() {
        NetManager netManager = NetManager.getInstance(null);
        if (!netManager.hasDefaultNet()) {
            LogUtils.debug("NetRequestUtils  network is null");
            return;
        }
        ThreadPoolUtil.submit(() -> {
            NetHandle netHandle = netManager.getDefaultNet();
            HttpURLConnection connection = null;
            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                URL url = new URL("http://10.55.20.48:8082/svnplus/fileSystem/uploadMoel?url=http://120.78.215.13/home/svn/666");
                URLConnection urlConnection = netHandle.openConnection(url, java.net.Proxy.NO_PROXY);
                if (urlConnection instanceof HttpURLConnection) {
                    connection = (HttpURLConnection) urlConnection;
                }
                connection.setRequestMethod("POST");
                connection.connect();

                //数据解析
                try (InputStream inputStream = urlConnection.getInputStream()) {
                    byte[] cache = new byte[2 * 1024];
                    int len = inputStream.read(cache);
                    while (len != -1) {
                        outputStream.write(cache, 0, len);
                        len = inputStream.read(cache);
                    }
                } catch (IOException e) {
                    LogUtils.error("NetRequestUtils inner IOException");
                }
                String result = new String(outputStream.toByteArray());
                LogUtils.debug("NetRequestUtils result:" + result);
                getUITaskDispatcher().syncDispatch(() -> Toast.show("成功发起post网络请求:" + result));
            } catch (Exception e) {
                LogUtils.error("NetRequestUtilsException requestByPost:" + e.getMessage());
            }
        });
    }

    /**
     * 请求网络图片
     */

    public void requestNetImage() {
        ThreadPoolUtil.submit(() -> {
            String requestUrl = "https://t7.baidu.com/it/u=4162611394,4275913936&fm=193&f=GIF";
            HttpURLConnection connection = null;
            try {
                connection = getHttpURLConnection(requestUrl, "GET");
                connection.connect();
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    //将网络请求数据转换成ImageSource
                    ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
                    ImageSource imageSource = ImageSource.create(connection.getInputStream(), srcOpts);
                    //将ImageSource转换成可以设置给image控件的PixelMap对象
                    PixelMap pixelMap = imageSource.createPixelmap(null);
                    getUITaskDispatcher().syncDispatch(() -> image.setPixelMap(pixelMap));
                }
                connection.disconnect();
            } catch (Exception e) {
                LogUtils.error("NetRequestUtilsException  requestNetImage:" + e.getMessage());
            }
        });
    }

    private HttpURLConnection getHttpURLConnection(String requestURL, String requestMethod) throws IOException {
        URL url = new URL(requestURL);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        //设置连接超时时间
        connection.setConnectTimeout(10 * 1000);
        //设置读取服务器数据超时时间
        connection.setReadTimeout(15 * 1000);
        //设置请求方式
        connection.setRequestMethod(requestMethod);
        return connection;
    }

    private String getReturnString(InputStream is) {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));
            StringBuilder sb = new StringBuilder();
            String line = "";

            while ((line = reader.readLine()) != null) {
                sb.append(line).append("\n");
            }
            is.close();
            return sb.toString();
        } catch (Exception var5) {
            return null;
        }
    }
}


总结


到此本篇文档就要告一段落了。通过本篇的学习,基本掌握了鸿蒙系统中的网络请求及网络图片加载。


最后跟大家分享一些开发过程中的注意事项:


鸿蒙系统中默认的网络请求地址格式是 https,如果想要访问 http 网址,需要修改允许明文信息传输的配置。

鸿蒙官网关于 network 配置文档:

https://developer.harmonyos.com/cn/docs/documentation/doc-guides/basic-config-file-elements-0000000000034463#ZH-CN_TOPIC_0000001064016070__table1343564264211


同样在 entry 模块的 config.json 中(如果存在多个 module,最好在每一个 config.json 文件中均添加上该配置)。

  "deviceConfig": {
    "default": {
      "network": {
        "cleartextTraffic"true
      }
    }
  },


网络请求是耗时操作,必须执行在子线程中,否则报错:

android.os.NetworkOnMainThreadException


在加载网络图片示例中,我们将 connection.getInputStream() 数据流直接转换成了 ImageSource。


但是再请求其他网络地址时,如访问 www.baidu.com 的返回结果就是 html 文件,因此在网络连接成功的后续数据处理中,需要注意数据格式。


作者:杜晨阳

有奖问卷,扫码参与


👇点击关注鸿蒙技术社区👇
了解鸿蒙一手资讯


求分享

求点赞

求在看

文章转载自鸿蒙技术社区,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论