您的位置:首页 > 理论基础 > 计算机网络

【Android基础】二、网络编程

2016-05-31 10:59 453 查看
1、从网络中下载图片,使用HttpURLConnection进行访问网络的操作

2.访问网络的操作不能放在主线程中,开一个子线程通过发送消息到UI线程,在UI线程修改界面

Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 0:
Toast.makeText(ImageActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
break;
case 1:
ImageView imageView = (ImageView) findViewById(R.id.iv_pic);
//把位图对象显示在ImageView
imageView.setImageBitmap((Bitmap) msg.obj);
break;
default:
break;
}
}
};


public void download(View v) {
new Thread(new Runnable() {
@Override
public void run() {
//1.确定网址
String path = "http://192.168.56.1:8080/pic.jpg";
try {
//2.把网址封装成一个URL对象
URL url = new URL(path);
//3.获取客户端和服务端的连接对象,此时还没有建立连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//4.对连接对象进行初始化,设置请求方法,连接超时,读取超时
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
//5.发送请求,与服务端建立连接
conn.connect();
//如果响应码为200,说明连接成功
if (conn.getResponseCode() == 200) {
//获取服务器响应头中的流,流的数据就是客户端请求的数据
InputStream is = conn.getInputStream();
//使用位图工厂对象从将流里的数据读取出来构造成位图对象
Bitmap bitmap = BitmapFactory.decodeStream(is);
Message msg = new Message();
msg.obj = bitmap;
msg.what = 1;
handler.sendMessage(msg);
} else {
Message msg = Message.obtain();
msg.what = 0;
handler.sendMessage(msg);
}

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

}


3.图片缓存到本地,直接从本地读取

BtmapFactory对象直接从File中解压位图对象,参数为File文件的绝对路径

public void download(View v) {
//1.确定网址
final String path = "http://192.168.56.1:8080/pic.jpg";
final File file = new File(getCacheDir(), "pic.jpg");
if (file.exists()) {
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
imageView.setImageBitmap(bitmap);
} else {
new Thread(new Runnable() {
@Override
public void run() {

try {
//2.把网址封装成一个URL对象
URL url = new URL(path);
//3.获取客户端和服务端的连接对象,此时还没有建立连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//4.对连接对象进行初始化,设置请求方法,连接超时,读取超时
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
//5.发送请求,与服务端建立连接
conn.connect();
//如果响应码为200,说明连接成功
if (conn.getResponseCode() == 200) {
//获取服务器响应头中的流,流的数据就是客户端请求的数据
InputStream is = conn.getInputStream();
//使用位图工厂对象从将文件里的数据读取出来构造成位图对象
FileOutputStream fos = new FileOutputStream(file);
byte[] bytes = new byte[1024];
int len = 0;
if ((len = is.read(bytes)) != -1) {
fos.write(bytes,0,len);
}
fos.close();
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
Message msg = new Message();
msg.obj = bitmap;
msg.what = 1;
handler.sendMessage(msg);
} else {
Message msg = Message.obtain();
msg.what = 0;
handler.sendMessage(msg);
}

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

4000
}


3.从网络下载文本数据

这里使用字节数组输出流,读取输入流文本数据时,同步把数据写入字节数组输出流,直接通过字节数组输出流构造字符串返回,而不需要写入本地文件

public String getTextFromStream(InputStream is){
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int len = 0;
try {
if((len = is.read(b))!=-1){
bos.write(b,0,len);
}
String text = new String(bos.toByteArray());
return text;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}


4.使用POST方法提交数据

String data = "";
//添加POST请求的两行属性
conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length",data.length() + "");
//设置打开输出流,拿到输出流
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
//使用输出流往服务器提交数据
os.write(data.getBytes());


二、多线程下载

需要两次请求网络

第一次请求网络获得文件长度,并且创建一个RandomAccessFile对象生成空的临时文件,设置临时文件的大小为获取的资源文件的长度,并计算每一个线程下载文件的起始位置和结束位置。

public void download() {
new Thread() {
@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.connect();
if (conn.getResponseCode() == 200) {
//获得网络请求返回的流的字节长度
int length = conn.getContentLength();
File file = new File(Environment.getExternalStorageDirectory(),"QQ.exe");
//使用随机存文件对象生成临时文件
RandomAccessFile raf = new RandomAccessFile(file, "rwd");
//设置临时文件的大小
raf.setLength(length);
//计算出每一个线程应该下载多少字节
int size = length / THREADCOUNT;
for (int i = 0; i < THREADCOUNT; i++) {
//计算每一个线程下载的起始位置和结束位置
int startIndex = i * size;
int endIndex = (i + 1) * size - 1;
if (i == THREADCOUNT - 1) {
endIndex = length - 1;
}
new DownloadThread(startIndex, endIndex, i).start();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();

}


第二次请求网络下载文件。通过Range属性设置线程的请求数据区间,请求部分数据成功的返回码为206,还需要设置写入文件的起始位置raf.seek()

断点续传:创建一个临时文件记录线程的下载进度,再次下载时读取临时文件,修改下载区间

class DownloadThread extends Thread {
int startIndex;
int endIndex;
int threadId;

public DownloadThread(int startIndex, int endIndex, int threadId) {
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
}

@Override
public void run() {
try {
File progressFile = new File(threadId + ".txt");
if (progressFile.exists()) {
FileInputStream fis = new FileInputStream(progressFile);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
startIndex += Integer.parseInt(br.readLine());
}

URL url = new URL(MutiThreadActivity.path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
//设置本次请求的数据区间
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
if (conn.getResponseCode() == 206) {
InputStream is = conn.getInputStream();
byte[] b = new byte[1024];
int len = 0;
int total = 0;
File file = new File(Environment.getExternalStorageDirectory(),"QQ.exe");
RandomAccessFile raf = new RandomAccessFile(file, "rwd");
//设置写入文件的开始位置
raf.seek(startIndex);
while ((len = is.read(b)) != -1) {
raf.write(b, 0, len);
total += len;
RandomAccessFile progressRaf = new RandomAccessFile(progressFile, "rwd");
progressRaf.write((total + "").getBytes());
progressRaf.close();
}
raf.close();
//全部下载完毕后删除临时记录文件
MutiThreadActivity.finishThread++;
synchronized (MutiThreadActivity.path) {
for (int i = 0; i < MutiThreadActivity.THREADCOUNT; i++) {
File f = new File(threadId + ".txt");
f.delete();
}
MutiThreadActivity.finishThread = 0;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}


使用到的输入输出流:

RandomAccessFile:可以设置写入的位置

FileOutputStream:直接写入文件中

ByteArrayOutputStream:写入的数据存储在一个字节数组中,转换成字节数组,创建字符串

InputStream:读取数据到一个字节数组中

BufferedReader:按行读取,返回一个String,参数是InputStreamReader(FileInputStream)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: