先说声 sorry 不好意思 拖了 两三天了。。。。
ok 正文:
额 开始做程序前 先把要测试的服务器和文件准备好撒~
1、配置AndroidManifest.xml,既然是要向本地sdcard 写内容,访问URL 权限是必须滴
2、设置layout了,
1)在activity_main.xml中加入一个listView,加入listView的要注意啊
android:layout_height="match_parent"这个参数一定得是match_parent的
2)新建一个单行布局
弄个这样的就好了
注意 没开始下载时 那个进度条 应该隐藏的
在progressBar中加这样一句话就好了android:visibility="invisible"
隐藏后效果:
3、写代码:package com.example.bolg_download_file;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.content.ClipData.Item;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener
{
private ListView mListView;
private DownLoadAdapter mAdapter;
private Map mItemLoadThreads;// 用于存放已启动的进度条 ,
// 在点击启动线程的时候设置值
private Map mItemLoadHandlers;
private Map mItemProgressInfo;// 用于存放所有进度条的信息,在创建bar的时候就要设置值了
class ViewHolder
{
ImageView mImageView;
TextView mTitle;
TextView mSubtitle;
Button mButton;
ProgressBar mBar;
}
class BarInfo
{ // 用来分装 Bar(进度条)的信息
boolean isDownLoad;// 是否已经下载,这个参数
// 我暂时没有使用,但是想要将下载系统做的更完善,应该是需要它的,大家可以完善下~嘿嘿
boolean visible;// bar是否显示
int currentProgress;// 进度条当前的值
int maxProgress;// 进度条的最大值
}
class DownLoadHandler extends Handler
{
private ProgressBar bar;
public void setBar(ProgressBar bar)
{
this.bar = bar;
}
@Override
public void handleMessage(Message msg)
{
BarInfo bi = (BarInfo) msg.obj;
bar.setVisibility(View.VISIBLE);
bar.setMax(bi.maxProgress);
bar.setProgress(bi.currentProgress);
}
}
class DownLoadAdapter extends BaseAdapter
{
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
/*
* 前面做 ListView优化时 有说过现在再说一下撒 主要参数: position:代表ListView的当前行号,
* convertView:代表ListView的缓存layout
*/
View layout = null;
ViewHolder holder = null;
if (convertView == null)
{
layout = getLayoutInflater().inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.mBar = (ProgressBar) layout
.findViewById(R.id.progressBar1);
holder.mImageView = (ImageView) layout
.findViewById(R.id.p_w_picpathView1);
holder.mTitle = (TextView) layout.findViewById(R.id.textView1);
holder.mSubtitle = (TextView) layout
.findViewById(R.id.textView2);
holder.mButton = (Button) layout.findViewById(R.id.button1);
holder.mButton.setTag(position);// 将当前行号 给button
holder.mButton.setOnClickListener(MainActivity.this);// 设置点击事件
layout.setTag(holder);
}
else
{
layout = convertView;
holder = (ViewHolder) layout.getTag();
}
// 设置控件内容
DownLoadHandler dlh = null;
if (!mItemLoadHandlers.containsKey(position))
{// 给每一行分配一个handler
dlh = new DownLoadHandler();
mItemLoadHandlers.put(position, dlh);
dlh.setBar(holder.mBar);
}
else
{
dlh = mItemLoadHandlers.get(position);
dlh.setBar(holder.mBar);
}
if (!mItemProgressInfo.containsKey(position))
{// 设置 BarInfo 如果当前行已经存在就不用设置了
BarInfo value = new BarInfo();
value.currentProgress = 0;
value.isDownLoad = false;
value.maxProgress = 0;
value.visible = false;
mItemProgressInfo.put(position, value);
}
holder.mTitle.setText("title:" + position);
BarInfo bi = mItemProgressInfo.get(position);
if (bi.visible)
{
holder.mBar.setVisibility(View.VISIBLE);
}
else
{
holder.mBar.setVisibility(View.INVISIBLE);
}
holder.mBar.setMax(bi.maxProgress);
holder.mBar.setProgress(bi.currentProgress);
return layout;
}
@Override
public int getCount()
{
// 目前先把他写死了,我服务器提供了 15个下载文件了
return 9;
}
@Override
public Object getItem(int position)
{
return null;
}
@Override
public long getItemId(int position)
{
return 0;
}
}
@Override
public void onClick(View v)// 这里的view 是触发事件的空间
{
int position = (Integer) v.getTag();
BarInfo bi = mItemProgressInfo.get(position);
if (!mItemLoadThreads.containsKey(position))
{// 判断当前行是否已启动了线程,如果没启动就启动一个线程执行下载功能
// 因为前面 在做list_item的时候将progressbar的显示调成隐藏的了,这里得把他弄出来撒
DownLoadThread dt = new DownLoadThread(position);
dt.start();
mItemLoadThreads.put(position, dt);
}
else
// 如果已经启动了就 通知用户 该软件正在下载
{
Toast.makeText(MainActivity.this, "该文件正在下载。。。请稍后撒~~~",
Toast.LENGTH_SHORT).show();
// toast的最后一个参数代表Toast的显示时间:
// 主要有两个值:LENGTH_SHOT表示 较短时间
// LENGTH_LONG表示 较长时间
}
}
private final static String NET_WORK_PATH = "http://10.0.2.2:8080/download/";// 前面有说过这里为什么是10.0.2.2
class DownLoadThread extends Thread
{
int position;
public DownLoadThread(int position)
{
this.position = position;
}
@Override
public void run()
{
InputStream is = null;
OutputStream os = null;
try
{
BarInfo bi = mItemProgressInfo.get(position);
String fileName = "abc" + position + ".zip";
File file = Environment.getExternalStorageDirectory();
os = new FileOutputStream(file.getAbsoluteFile() + "/"
+ fileName);
URL u = new URL(NET_WORK_PATH + fileName);// 这里写这么长只是构造文件名而已不用过多纠结撒
URLConnection urlConn = u.openConnection();
bi.maxProgress = urlConn.getContentLength();// 获取文件大小;要注意这里的文件大小单位是字节,所以文件过大的话
// 最好用long类型的了
is = urlConn.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
int sum = 0;
bi.visible = true;
while (-1 != (len = is.read(buffer)))
{
sum += len;
Message msg = new Message();
bi.currentProgress = sum;
os.write(buffer);
msg.arg1 = position;
msg.obj = bi;
mItemLoadHandlers.get(position).sendMessage(msg);
}
os.flush();// 嘿嘿 下载完后 java 的io要flush一下输出流的缓存的,上回我没写哦,不知道大家
// 有没有发现这个错误撒 嘿嘿~
// 下载完后 做一些 数据的更改撒
bi.visible = false;
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initUi();
initData();
}
private void initData()
{
mItemLoadThreads = new HashMap();
mItemProgressInfo = new HashMap();
mItemLoadHandlers = new HashMap();
}
private void initUi()
{
mListView = (ListView) findViewById(R.id.listView1);
mAdapter = new DownLoadAdapter();
mListView.setAdapter(mAdapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
今天的代码 有些多撒 正常下载是没有问题的 这篇的代码 存在一个问题 那就是会跳行,嘿嘿 留给大家这个问题了,
明天说说怎么处理撒。