网络
原生http
界面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<Button
android:id="@+id/send_request"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send Request" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/response_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
在界面上显示获得的报文
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
TextView responseText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button sendRequest = (Button) findViewById(R.id.send_request);
responseText = (TextView) findViewById(R.id.response_text);
sendRequest.setOnClickListener(this);
}
private void showResponse(final String response_text) {
// 必须在主进程中才能修改UI
runOnUiThread(new Runnable() {
@Override
public void run() {
responseText.setText(response_text);
}
});
}
连接http
测试原生的Http连接方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
void sendRequestWithHttpURLConnection() {
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
// 建立连接
URL url = new URL("https://dawn-k.github.io");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
// 获取服务返回的流
InputStream in = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(in));
// 拼接成 response
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();
// 上面一行很容易漏下,一定要注意
}
// 注册监听器
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.send_request:
sendRequestWithHttpURLConnection();
break;
}
}
权限
需要网络权限
1
<uses-permission android:name="android.permission.INTERNET" />
OkHttp
OkHttp 是一个通用的流行的开源库. 界面和 showResponse 我们采用和上文一样的方式.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void testOKHttp() {
new Thread(new Runnable() {
@Override
public void run() {
try {
// 构建GET方法的请求
Request request = new Request.Builder()
.url("http://www.baidu.com")
.build();
// 发起请求
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
String responseData = response.body().string();
// 显示数据
showResponse(responseData);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
最后修改 onClick 方法中点击按钮对应的函数为 testOKHttp
post
post请求需要修改如下.
1
2
3
4
5
6
7
8
9
10
// 构建一个请求体(也就是想传的参数)
RequestBody requestBody = new FormBody.Builder()
.add("username", "admin")
.add("password", "123456")
.build();
// 发起post请求
Request request = new Request.Builder()
.url("http://www.baidu.com")
.post(requestBody)
.build();
剩下的部分和之前的一样
配置服务器
下载 Apache httpd
假设安装位置为 D:/myDevEnvironment/Apache24
, 下述 APACHE_HOME
.
先在 %APACHE_HOME/conf/httpd.conf
里面, 把安装位置修改为
Define SRVROOT "D:/myDevEnvironment/Apache24"
ServerRoot "${SRVROOT}"
然后在命令行中进入 %APACHE_HOME/bin , 然后输入 httpd -k install
最后打开bin下的 ApacheMonitor.exe , 然后启动服务, 在浏览器里输入 127.0.0.1 即可访问到 Apache 默认页面了. 可以在刚才的配置文件中改端口, 默认是80
下文的文件都放在 %APACHE_HOME/htdocs
下即可. 可通过 127.0.0.1/file_name
访问
解析 xml
准备好get_data.xml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<apps>
<app>
<id>1</id>
<name>Google Maps</name>
<version>1.0</version>
</app>
<app>
<id>2</id>
<name>Chrome</name>
<version>2.1</version>
</app>
<app>
<id>3</id>
<name>Google Play</name>
<version>2.3</version>
</app>
</apps>
XmlPullParser
原生的解决方式, 直接用 XmlPullParser
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
void testOKHttp() {
new Thread(new Runnable() {
@Override
public void run() {
try {
// 宿主机测试时用 127.0.0.1
// 对于手机来说,宿主机就是 10.0.2.2
Request request = new Request.Builder()
.url("http://10.0.2.2/get_data.xml")
.build();
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
String responseData = response.body().string();
parseXMLWithPull(responseData);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
private void parseXMLWithPull(String xmlData) {
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(xmlData));
int eventType = xmlPullParser.getEventType();
String id = "";
String name = "";
String version = "";
// 一直循环到文件结尾
while (eventType != XmlPullParser.END_DOCUMENT) {
// 当前元素的名字(比如 <app> 1 </app>这种)
String nodeName = xmlPullParser.getName();
// 判断类型
switch (eventType) {
case XmlPullParser.START_TAG:
// 对于相应的类型,将下一个元素存入字符串(因为当前的还是标签)
if ("id".equals(nodeName)) {
id = xmlPullParser.nextText();
} else if ("name".equals(nodeName)) {
name = xmlPullParser.nextText();
} else if ("version".equals(nodeName)) {
version = xmlPullParser.nextText();
}
break;
case XmlPullParser.END_TAG:
if ("app".equals(nodeName)) {
Log.d("MainActivity", "id is " + id);
Log.d("MainActivity", "name is " + name);
Log.d("MainActivity", "version is " + version);
}
break;
default:
break;
}
eventType = xmlPullParser.next();
}
} catch (Exception e) {
e.printStackTrace();
}
}
书上还提到了一种 SAX方法, 此处不再赘述.
解析 json
准备好get_data.json文件
[{
"id": "5",
"version": "5.5",
"name": "Clash of Clans"
},
{
"id": "6",
"version": "7.0",
"name": "Boom Beach"
},
{
"id": "7",
"version": "5.5",
"name": "Clash Royale"
}
]
JSONObject
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void parseJSONWithJSONObject(String jsonData) {
try {
JSONArray jsonArray = new JSONArray(jsonData);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String id = jsonObject.getString("id");
Log.d("MainActivity", "id is " + id);
String name = jsonObject.getString("name");
Log.d("MainActivity", "name is " + name);
String version = jsonObject.getString("version");
Log.d("MainActivity", "version is " + version);
}
} catch (Exception e) {
e.printStackTrace();
}
}
GSON
新建 app类, 此处略去 getter 和 setter
1
2
3
class App {
private String id, name, version;
}
然后添加依赖
1
implementation 'com.google.code.gson:gson:2.8.5'
最后编写解析函数
1
2
3
4
5
6
7
8
9
10
private void parseJSONWithGSON(String jsonData) {
Gson gson = new Gson();
List<App> appList = gson.fromJson(jsonData, new TypeToken<List<App>>() {
}.getType());
for (App app : appList) {
Log.d("MainActivity", "id is " + app.getId());
Log.d("MainActivity", "name is " + app.getName());
Log.d("MainActivity", "version is " + app.getVersion());
}
}
HttpUtil
创建一个通用的工具类, 进行封装 先创建一个接口类
1
2
3
4
5
public interface HttpCallbackListener {
void onFinish(String response);
void onError(Exception e);
}
再创建 HttpUtil (其实若是只使用里面的 OkHttp, 然后把原生的删掉的话就不需要上面的接口类了)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import android.content.pm.PackageManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.BufferedSink;
public class HttpUtil {
/*
使用方法:
HttpUtil.sendHttpRequest("http://www.baidu.com", new okhttp3.Callback() {
@Override
public void onError(Exception e) {
// 处理异常情况
}
@Override
public void onFinish(String response){
// 得到服务器返回的具体内容
String responseData = response.body().string();
}
});
*/
public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
try {
URL url = new URL(address);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
connection.setDoInput(true);
connection.setDoOutput(true);
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
} catch (Exception e) {
if (listener != null) {
listener.onError(e);
}
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}).start();
}
/*
使用方法:
HttpUtil.sendOkHttpRequest("http://www.baidu.com", new okhttp3.Callback() {
@Override
public void onFailure(Call call, IOException e) {
// 处理异常情况
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// 得到服务器返回的具体内容
String responseData = response.body().string();
}
});
*/
public static void sendOkHttpRequest(String address, okhttp3.Callback callback) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(address)
.build();
client.newCall(request).enqueue(callback);
}
}
原生下载器
原生下载器在下载单个文件的时候非常好用, 在多文件下载的时候会受到系统对于并发下载量的限制, 比如小米只能同时下载两个文件.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
private void downloadFiles(String dirName, String[] fileNames) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(Config.getBaseUrl() + "/download/" + dirName + "/" + fileName));
Log.d(TAG, "begin to download " + Config.getBaseUrl() + "/download/" + dirName + "/" + fileName);
// request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);//下载中与下载完成后都会在通知中显示| 另外可以选 DownloadManager.Request.VISIBILITY_VISIBLE 仅在下载中时显示在通知中,完成后会自动隐藏
request.setTitle(fileName);
request.setDescription("正在下载图像序列");
request.setAllowedOverRoaming(false);
request.setDestinationInExternalFilesDir(DicomViewer.this, Environment.DIRECTORY_DOCUMENTS, File.separator + dirName + File.separator + fileName);
// request.setDestinationUri(new Uri(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) + "/" + dirName + "/" + fileName));
// subpath 实际上是文件名
// request.setDestinationInExternalFilesDir(DicomViewer.this, Environment.DIRECTORY_DOWNLOADS, fileName);
DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
long downloadId = downloadManager.enqueue(request);
Log.d(TAG, "download id : " + downloadId);
listen(fileName, downloadId);
}
private void listen(final String fileName, final long Id) {
// 注册广播监听系统的下载完成事件。
IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long ID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if (ID == Id) {
// Toast.makeText(getApplicationContext(), " 文件:" + fileName + " 任务:" + Id + " 下载完成!", Toast.LENGTH_SHORT).show();
// Log.d(TAG, "try to compress " + zipFilePath + " to " + getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS));
Log.d(TAG, "文件 " + fileName + " 下载完成 " + System.currentTimeMillis() / 1000 + " s");
// 记得在代码中自动增加这个文件夹
// FileUtil.decompressFile(getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath(), zipFilePath);
// Toast.makeText(getApplicationContext(), "解压完成", Toast.LENGTH_SHORT).show();
}
}
};
registerReceiver(broadcastReceiver, intentFilter);
}