安卓网络编程学习(1)——java原生网络编程(1)
写在前面
马上要进行第二轮冲刺,考虑到自己的APP在第一轮冲刺的效果不尽人意,有很多网络方面的小BUG,这里就系统学习一下网络编程,了解来龙去脉,以便更好的对项目进行优化处理。
http协议
http协议的定义和工作流程
要进行http请求,首先要知道什么是http协议。http是什么意思?HyperText Transfer Protocol 翻译过来就是超文本传输协议。协议就是约定的意思,内容是Http相关的格式,http协议是基于TCP/IP协议之上的应用层协议。这就涉及到计算机网络的知识了,但奈何我的计算机网络不是很好,就不班门弄斧了。那么http协议是如何工作的呢?如下图:

客户端发起请求(request)到服务器,服务器响应请求(response)到客户端。我们一直在做的APP其实就是客户端,负责发起请求然后接受内容。类似的,我们的网页也是一个客户端,发起请求然后接收内容。可能这也是为什么现在能够做到写一个web前端就能同时部署到手机端和桌面端的原因吧。
http协议的常用请求方式
在之前学习java web的过程中,了解到了get和post这两种最常用的,其实还有put delete head trace options connect,但对于我们做客户端开发,只要了解前面的四种即可了。一般来说,get用于请求数据,post用于提交数据,put用于更新数据,delete用于删除数据。
关于http其他的知识,之前学习java web时已经基本了解过了,这里就不再过多阐述了。
使用java的api发起网络请求
这里我们使用阳光沙滩网站提供的API,可以让你在本地架设一个服务器,类似tomcat.具体的原理我也不大懂.
clone完之后我们用java -jar启动该jar包即可。


出现你放API的地址即说明部署成功了。
事不宜迟,先贴代码:
new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL("http://10.0.2.2:9102/get/text");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.9");
connection.setRequestProperty("Accept","*/*");
connection.connect();
//结果码
int responseCode = connection.getResponseCode();
if(responseCode==200){
Map<String, List<String>> headerFields = connection.getHeaderFields();
Set<Map.Entry<String, List<String>>> entries = headerFields.entrySet();
for(Map.Entry<String,List<String>> entry:entries){
Log.d(TAG,entry.getKey()+"=="+entry.getValue());
}
InputStream inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String json = bufferedReader.readLine();
//Log.d(TAG,"json -->"+json);
Gson gson = new Gson();
GetTextItem getTextItem = gson.fromJson(json, GetTextItem.class);
updateUI(getTextItem);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
代码解析
我们请求数据不能在主线程进行,需要新建一个子线程,但实际开发中不建议如此使用,这里主要为了学习java API
可以看到,我们首先定义了一个URL,然后把请求地址放进去,新建一个连接并返回成HttpURLConnection类型,通过这个对象来设置请求参数,并用connect()方法来发出请求。
而后通过返回响应码来确定是否请求成功,若成功则提取数据并用GSON转成相应的json数据,输出。
注意事项
要发起网络请求,首先需要在manifest中设置网络权限:
<uses-permission android:name="android.permission.INTERNET" />
但这样还不够,由于我们的安卓在某个版本后不再支持访问http类型的地址了,想要访问需要进行配置,可以这样设置:
<application
android:usesCleartextTraffic="true"
但这样配置过于简略,我们可以设置xml配置文件来进行详细的配置,如:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true"/>
</network-security-config>
然后在manifest中使用:
android:networkSecurityConfig="@xml/network_security_config"
也要放到application标签中。
Tips1:如果发现配置好了还是无法使用,请把APP卸载再安装,有奇效哦!
Tips2:这里使用了Gsonformat来生成bean类,这是一个输入json就可以自动生成bean类的插件,建议百度下载。
使用java原生API请求图片
在上面的操作里,我们使用了glide工具包来帮我们处理图片的载入,那我们如何使用java API来实现呢?接下来我们来简单的处理一下:
new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL("https://cdn.sunofbeaches.com/images/ad/shop-ad.png");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.9");
connection.setRequestProperty("Accept","*/*");
connection.connect();
int responseCode = connection.getResponseCode();
if(responseCode==HttpURLConnection.HTTP_OK){
InputStream inputStream = connection.getInputStream();
//转成BitMap
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
//更新UI,要在主线程
runOnUiThread(new Runnable() {
@Override
public void run() {
ImageView imageView = findViewById(R.id.result_image);
imageView.setImageBitmap(bitmap);
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
}
}).start();
获取到内容后,转成bitmap然后设置到Image即可。但这样的用法并不值得被提倡,因为如果我们的图片过大,甚至会导致我们的APP崩掉,我们要对其进行一定的压缩,压缩到适合我们APP使用的大小。
下面是一段常见的算法:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
//拿到图片的大小
BitmapFactory.decodeResource(getResources(), R.mipmap.test_pic,options);
ImageView imageView = findViewById(R.id.result_image);
int outHeight = options.outHeight;
int outWidth = options.outWidth;
Log.d(TAG,"outHeight ==>"+outHeight);
Log.d(TAG,"outWidth ==>"+outWidth);
//拿控件的尺寸
int measuredHeight = imageView.getMeasuredHeight();
int measuredWidth = imageView.getMeasuredWidth();
//
Log.d(TAG,"measuredHeight ==>"+measuredHeight);
Log.d(TAG,"measuredWidth ==>"+measuredWidth);
options.inSampleSize = 1;
//图片的宽度/控件的宽度
// 图片的高度/控件的高度
//取两者之间的小值
if(outHeight > measuredHeight || outWidth > measuredWidth){
int subHeight = outHeight/measuredHeight;
int subWidth = outWidth/measuredWidth;
options.inSampleSize = subHeight > subWidth ?subWidth:subHeight;
}
options.inJustDecodeBounds = false;
Log.d(TAG,"inSampleSize ==>"+options.inSampleSize);
//根据控件大小,动态地计算sample值
final Bitmap bigImage = BitmapFactory.decodeResource(getResources(), R.mipmap.test_pic,options);
imageView.setImageBitmap(bigImage);
这里通过计算比例得到一个相对合适的比例值,然后再将这个bitmap设置给image控件。这就是安卓大图片的处理方式了。
实际开发中,我们都会用开源框架来解决,比如glide,XUtils等等。框架能做的事要更多,但基本的还是离不开这些。
总结
主要是简单学习了一下如何使用java原声API来请求(get)数据。为了不让博客太长,把其余一些内容放置到下篇博客了。
希望学习了之后能够更好的开发我们自己的APP。
安卓网络编程学习(1)——java原生网络编程(1)的更多相关文章
- 安卓网络编程学习(1)——java原生网络编程(2)
写在前面 该博客紧接上篇博客:https://www.cnblogs.com/wushenjiang/p/12937531.html,继续学习post请求,带参数的post和get请求以及文件上传与下 ...
- 转 网络编程学习笔记一:Socket编程
题外话 前几天和朋友聊天,朋友问我怎么最近不写博客了,一个是因为最近在忙着公司使用的一些控件的开发,浏览器兼容性搞死人:但主要是因为这段时间一直在看html5的东西,看到web socket时觉得很有 ...
- Java 原生网络编程.
一.概念 Java 语言从其诞生开始,就和网络紧密联系在一起.在 1995 年的 Sun World 大会上,当时占浏览器市场份额绝对领先的网景公司宣布在浏览器中支持Java,从而引起一系列的公司产品 ...
- Java原生网络编程
一些常见术语 编程中的Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面 ...
- 网络编程学习笔记一:Socket编程
“一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...
- 网络编程学习笔记-全零网络IP地址0.0.0.0详谈
RFC: - Addresses in this block refer to source hosts on "this" network. Address may be use ...
- JAVA学习篇--JAVA两种编程模式控制
在Drp项目中,解说了两种编程模式Model 1和Model2.以下是对这两种模式的简单理解.以及因为Model2是基于MVC架构的模式,就将我们易混淆的MVC与我们之前学的三层架构进行对照学习一下. ...
- 多线程编程学习一(Java多线程的基础).
一.进程和线程的概念 进程:一次程序的执行称为一个进程,每个 进程有独立的代码和数据空间,进程间切换的开销比较大,一个进程包含1—n个线程.进程是资源分享的最小单位. 线程:同一类线程共享代码和数据空 ...
- 多线程编程学习六(Java 中的阻塞队列).
介绍 阻塞队列(BlockingQueue)是指当队列满时,队列会阻塞插入元素的线程,直到队列不满:当队列空时,队列会阻塞获得元素的线程,直到队列变非空.阻塞队列就是生产者用来存放元素.消费者用来获取 ...
随机推荐
- (转)ATOM介绍和使用
一,Atom介绍 Atom 是 Github 开源的文本编辑器,这个编辑器完全是使用Web技术构建的(基于Node-Webkit).启动速度快,提供很多常用功能的插件和主题,可以说Atom已经足以胜任 ...
- 解决Chrome插件安装时出现的“程序包无效”问题
问题原因,新版的插件头部文件的修改,导致旧版的插件包无法使用,解决方式:解压. 1.把下载后的.crx扩展名的离线Chrome插件的文件扩展名改成.zip或者.rar(如果看不到Chrome插件的扩展 ...
- C++课程设计,12306模拟写起来就是这么粗暴
这篇文章很详细,也很多希望可以好好看看!看完C++稳过! 一.12306应该具备那些功能 1.查询(一个月以内的): 1.查车票:出发地+目的地+出发时间->显示经过两站车票信息 (余票,车次信 ...
- keras-深度学习处理文本数据
深度学习用于自然语言处理是将模式识别应用于单词.句子和段落,这与计算机视觉是将模式识别应用于像素大致相同.深度学习模型不会接收原始文本作为输入,它只能处理数值张量,因此我们必须将文本向量化(vecto ...
- session与cookie的浅谈
cookie的用途: 当你浏览网页时,会有一些推送消息,大多数是你最近留意过的同类东西,比如你想买桌子,上淘宝搜了一下,结果连着几天会有各种各样的桌子的链接.这是因为你浏览某个网页的时候,WEB 服务 ...
- gVim配置文件分享
前言 直接可以把这个配置覆盖掉现在安装目录Vim底下的"_vimrc"文件 效果图 Code: set number set tabstop=4 set softtabstop=4 ...
- libevent(八)激活事件
激活事件添加流程 事件发生后,需要把对应的event加入到激活事件队列中. 整个流程如下: 对于定时器事件,在timeout_process过程中,会将事件从最小堆中删除. 激活事件处理流程 在eve ...
- socket编程之并发回射服务器2
承接上文:socket编程之并发回射服务器 为了让服务器进程的终止一经发生,客户端就能检测到,客户端需要能够同时处理两个描述符:套接字和用户输入. 可以使用select达到这一目的: void str ...
- 聊聊算法——BFS和DFS
如果面试字节跳动和腾讯,上来就是先撕算法,阿里就是会突然给你电话,而且不太在意是周末还是深夜, 别问我怎么知道的,想确认的可以亲自去试试.说到算法,直接力扣hard三百题也是可以的,但似乎会比较伤脑, ...
- SpringBoot:整合Shiro
目录 1.Shiro简介 1.1.什么是Shiro? 1.2.有哪些功能 1.3.Shiro架构(外部) 1.4.Shiro架构(内部) 2.HelloWorld 3.Shiro整合Spring Bo ...