android文件上传可能是一个比较耗时的操作,如果为上传操作带上进度提示则可以更好的提高用户体验,最后效果如下图:
项目源码:http://download.csdn.net/detail/shinay/4965230
注意:此方法可能已经实现,推荐引用开源框架通过AsyncHttpClient进行文件上传:http://blog.csdn.net/jdsjlzx/article/details/41694323
这里只贴出代码,可根据实际情况自行修改。
- package com.lxb.uploadwithprogress.http;
- import java.io.File;
- import org.apache.http.HttpResponse;
- import org.apache.http.client.HttpClient;
- import org.apache.http.client.methods.HttpPost;
- import org.apache.http.entity.mime.content.FileBody;
- import org.apache.http.impl.client.DefaultHttpClient;
- import org.apache.http.protocol.BasicHttpContext;
- import org.apache.http.protocol.HttpContext;
- import org.apache.http.util.EntityUtils;
- import android.app.ProgressDialog;
- import android.content.Context;
- import android.os.AsyncTask;
- import com.lxb.uploadwithprogress.http.CustomMultipartEntity.ProgressListener;
- public class HttpMultipartPost extends AsyncTask<String, Integer, String> {
- private Context context;
- private String filePath;
- private ProgressDialog pd;
- private long totalSize;
- public HttpMultipartPost(Context context, String filePath) {
- this.context = context;
- this.filePath = filePath;
- }
- @Override
- protected void onPreExecute() {
- pd = new ProgressDialog(context);
- pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- pd.setMessage("Uploading Picture...");
- pd.setCancelable(false);
- pd.show();
- }
- @Override
- protected String doInBackground(String... params) {
- String serverResponse = null;
- HttpClient httpClient = new DefaultHttpClient();
- HttpContext httpContext = new BasicHttpContext();
- HttpPost httpPost = new HttpPost("上传URL, 如:http://www.xx.com/upload.php");
- try {
- CustomMultipartEntity multipartContent = new CustomMultipartEntity(
- new ProgressListener() {
- @Override
- public void transferred(long num) {
- publishProgress((int) ((num / (float) totalSize) * 100));
- }
- });
- // We use FileBody to transfer an image
- multipartContent.addPart("data", new FileBody(new File(
- filePath)));
- totalSize = multipartContent.getContentLength();
- // Send it
- httpPost.setEntity(multipartContent);
- HttpResponse response = httpClient.execute(httpPost, httpContext);
- serverResponse = EntityUtils.toString(response.getEntity());
- } catch (Exception e) {
- e.printStackTrace();
- }
- return serverResponse;
- }
- @Override
- protected void onProgressUpdate(Integer... progress) {
- pd.setProgress((int) (progress[0]));
- }
- @Override
- protected void onPostExecute(String result) {
- System.out.println("result: " + result);
- pd.dismiss();
- }
- @Override
- protected void onCancelled() {
- System.out.println("cancle");
- }
- }
- package com.lxb.uploadwithprogress.http;
- import java.io.FilterOutputStream;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.nio.charset.Charset;
- import org.apache.http.entity.mime.HttpMultipartMode;
- import org.apache.http.entity.mime.MultipartEntity;
- public class CustomMultipartEntity extends MultipartEntity {
- private final ProgressListener listener;
- public CustomMultipartEntity(final ProgressListener listener) {
- super();
- this.listener = listener;
- }
- public CustomMultipartEntity(final HttpMultipartMode mode,
- final ProgressListener listener) {
- super(mode);
- this.listener = listener;
- }
- public CustomMultipartEntity(HttpMultipartMode mode, final String boundary,
- final Charset charset, final ProgressListener listener) {
- super(mode, boundary, charset);
- this.listener = listener;
- }
- @Override
- public void writeTo(OutputStream outstream) throws IOException {
- super.writeTo(new CountingOutputStream(outstream, this.listener));
- }
- public static interface ProgressListener {
- void transferred(long num);
- }
- public static class CountingOutputStream extends FilterOutputStream {
- private final ProgressListener listener;
- private long transferred;
- public CountingOutputStream(final OutputStream out,
- final ProgressListener listener) {
- super(out);
- this.listener = listener;
- this.transferred = 0;
- }
- public void write(byte[] b, int off, int len) throws IOException {
- out.write(b, off, len);
- this.transferred += len;
- this.listener.transferred(this.transferred);
- }
- public void write(int b) throws IOException {
- out.write(b);
- this.transferred++;
- this.listener.transferred(this.transferred);
- }
- }
- }
上面为两个主要的类,下面放一个调用的Activity
- package com.lxb.uploadwithprogress;
- import java.io.File;
- import com.lxb.uploadwithprogress.http.HttpMultipartPost;
- import android.app.Activity;
- import android.content.Context;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.Toast;
- public class MainActivity extends Activity implements OnClickListener {
- private Context context;
- private EditText et_filepath;
- private Button btn_upload;
- private Button btn_cancle;
- private HttpMultipartPost post;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- context = this;
- setContentView(R.layout.activity_main);
- et_filepath = (EditText) findViewById(R.id.et_filepath);
- btn_upload = (Button) findViewById(R.id.btn_upload);
- btn_cancle = (Button) findViewById(R.id.btn_cancle);
- btn_upload.setOnClickListener(this);
- btn_cancle.setOnClickListener(this);
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.btn_upload:
- String filePath = et_filepath.getText().toString();
- File file = new File(filePath);
- if (file.exists()) {
- post = new HttpMultipartPost(context, filePath);
- post.execute();
- } else {
- Toast.makeText(context, "file not exists", Toast.LENGTH_LONG).show();
- }
- break;
- case R.id.btn_cancle:
- if (post != null) {
- if (!post.isCancelled()) {
- post.cancel(true);
- }
- }
- break;
- }
- }
- }
当然,在Android中使用MultipartEntity类,必须为项目增加相应的jar包,httpmime-4.1.2.jar。
最后放上代码,工程里已包含jar。
地址:
http://download.csdn.net/detail/shinay/4965230
http://blog.csdn.net/rwyz1314/article/details/6798222
加入两个权限
一个是联网,另一个是读写SD卡
- <uses-permission android:name="android.permission.INTERNET"></uses-permission>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
下载地址是本人的另外一台主机,现在当服务器了,路径可以测试
http://210.30.12.1:8080/mp3/DJ.mp3
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.io.RandomAccessFile;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.net.URLConnection;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Environment;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.ProgressBar;
- import android.widget.TextView;
- import android.widget.Toast;
- public class FileDownProcessBarActivity extends Activity {
- /** Called when the activity is first created. */
- private static final String Path="http://210.30.12.1:8080/mp3/DJ.mp3";
- private ProgressBar progressBar;
- private TextView textView;
- private Button button;
- private int FileLength;
- private int DownedFileLength=0;
- private InputStream inputStream;
- private URLConnection connection;
- private OutputStream outputStream;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- progressBar=(ProgressBar) findViewById(R.id.progressBar1);
- textView=(TextView) findViewById(R.id.textView2);
- button=(Button) findViewById(R.id.button1);
- button.setOnClickListener(new ButtonListener());
- }
- class ButtonListener implements OnClickListener{
- @Override
- public void onClick(View v) {
- DownedFileLength=0;
- // TODO Auto-generated method stub
- Thread thread=new Thread(){
- public void run(){
- try {
- DownFile(Path);
- } catch (Exception e) {
- // TODO: handle exception
- }
- }
- };
- thread.start();
- }
- }
- private Handler handler=new Handler()
- {
- public void handleMessage(Message msg)
- {
- if (!Thread.currentThread().isInterrupted()) {
- switch (msg.what) {
- case 0:
- progressBar.setMax(FileLength);
- Log.i("文件长度----------->", progressBar.getMax()+"");
- break;
- case 1:
- progressBar.setProgress(DownedFileLength);
- int x=DownedFileLength*100/FileLength;
- textView.setText(x+"%");
- break;
- case 2:
- Toast.makeText(getApplicationContext(), "下载完成", Toast.LENGTH_LONG).show();
- break;
- default:
- break;
- }
- }
- }
- };
- private void DownFile(String urlString)
- {
- /*
- * 连接到服务器
- */
- try {
- URL url=new URL(urlString);
- connection=url.openConnection();
- if (connection.getReadTimeout()==5) {
- Log.i("---------->", "当前网络有问题");
- // return;
- }
- inputStream=connection.getInputStream();
- } catch (MalformedURLException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- /*
- * 文件的保存路径和和文件名其中Nobody.mp3是在手机SD卡上要保存的路径,如果不存在则新建
- */
- String savePAth=Environment.getExternalStorageDirectory()+"/DownFile";
- File file1=new File(savePAth);
- if (!file1.exists()) {
- file1.mkdir();
- }
- String savePathString=Environment.getExternalStorageDirectory()+"/DownFile/"+"DJ.mp3";
- File file =new File(savePathString);
- if (!file.exists()) {
- try {
- file.createNewFile();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- /*
- * 向SD卡中写入文件,用Handle传递线程
- */
- Message message=new Message();
- try {
- outputStream=new FileOutputStream(file);
- byte [] buffer=new byte[1024*4];
- FileLength=connection.getContentLength();
- message.what=0;
- handler.sendMessage(message);
- while (DownedFileLength<FileLength) {
- outputStream.write(buffer);
- DownedFileLength+=inputStream.read(buffer);
- Log.i("-------->", DownedFileLength+"");
- Message message1=new Message();
- message1.what=1;
- handler.sendMessage(message1);
- }
- Message message2=new Message();
- message2.what=2;
- handler.sendMessage(message2);
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
android自定义Dialog实现文件下载和下载进度
http://blog.csdn.net/vipa1888/article/details/7459200
最近要实现一个检验更新的功能,当进入程序的时候,开始请求服务器,然后得到服务器的响应更新结果!如果需要更新的话,就打开一个Dialog,在Dialog上面下载文件,于是自己研究了一个自定义dialog的实现,也完成了在dialog上面有进度的下载文件(自己的作图技术查,随便画了一个背景),效果图如下:
效果如上,下面我把代码贴出来:
主界面Activity: 主界面就定义了一个Button,当点击Button后,弹出Dialog
- package com.spring.sky.dialog.download;
- import android.app.Activity;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.Button;
- import android.widget.ImageView;
- /**
- * 主界面
- * @author spring sky
- */
- public class MainActivity extends Activity implements
- android.view.View.OnClickListener {
- private Button bt;
- private ImageView imageView;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- init();
- }
- private void init() {
- bt = (Button) this.findViewById(R.id.bt);
- bt.setOnClickListener(this);
- imageView = (ImageView) findViewById(R.id.imageview);
- }
- @Override
- public void onClick(View v) {
- DownloadDialog dialog = new DownloadDialog(this,
- "http://img308.ph.126.net/AM2zg9CNx0kG8K3jY122RQ==/3902932027070067384.jpg");
- dialog.setImageView(imageView); //当前下载的是一个图片,所以下载完成后,把这个图片显示在界面上
- dialog.show();
- }
- }
main.xml:
- <?xml version="1.0" encoding="utf-8"?>
- <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <Button
- android:id="@+id/bt"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="弹出框下载文件" />
- <ImageView
- android:id="@+id/imageview"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- />
- </LinearLayout>
- </ScrollView>
自定义的Dialog : 这个基本就是实现Dialog的布局,还有Dialog的背景透明效果,然后用户点击了下载,启动一个新线程下载,同时用handler来发送消息,让下载操作的进度在Dialog的view上面呈现出来,当下载完成的时候,点击按钮就可以看见下载的图片了! (我测试为了简单就用了一个ImageView把图片显示出来)
- package com.spring.sky.dialog.download;
- import java.io.FileOutputStream;
- import java.io.InputStream;
- import java.net.URL;
- import java.net.URLConnection;
- import android.app.Dialog;
- import android.content.Context;
- import android.graphics.BitmapFactory;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import android.view.View;
- import android.widget.Button;
- import android.widget.ImageView;
- import android.widget.ProgressBar;
- import android.widget.TextView;
- import android.widget.Toast;
- /***
- * dialog文件下载
- * @author spring sky <br>
- * QQ :840950105
- */
- public class DownloadDialog extends Dialog implements
- android.view.View.OnClickListener {
- private static final int DOWNLOAD_PREPARE = 0;
- private static final int DOWNLOAD_WORK = 1;
- private static final int DOWNLOAD_OK = 2;
- private static final int DOWNLOAD_ERROR = 3;
- private static final String TAG = "IndexActivity";
- private Context mContext;
- private Button bt;
- private ProgressBar pb;
- /** 下载过程中不能点击 */
- private boolean isClick = false;
- private boolean downloadOk = false;
- private TextView tv;
- /**
- * 下载的url
- */
- private String url = null;
- private String filePath;
- /**
- * 文件大小
- */
- int fileSize = 0;
- /**
- * 下载的大小
- */
- int downloadSize = 0;
- /**
- * handler
- */
- private Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case DOWNLOAD_PREPARE:
- Toast.makeText(mContext, "准备下载", Toast.LENGTH_SHORT).show();
- pb.setVisibility(ProgressBar.VISIBLE);
- Log.e(TAG, "文件大小:" + fileSize);
- pb.setMax(fileSize);
- break;
- case DOWNLOAD_WORK:
- Log.e(TAG, "已经下载:" + downloadSize);
- pb.setProgress(downloadSize);
- int res = downloadSize * 100 / fileSize;
- tv.setText("已下载:" + res + "%");
- bt.setText(FileUtil.FormetFileSize(downloadSize) + "/"
- + FileUtil.FormetFileSize(fileSize));
- break;
- case DOWNLOAD_OK:
- downloadOk = true;
- bt.setText("下载完成显示图片");
- downloadSize = 0;
- fileSize = 0;
- Toast.makeText(mContext, "下载成功", Toast.LENGTH_SHORT).show();
- break;
- case DOWNLOAD_ERROR:
- downloadSize = 0;
- fileSize = 0;
- Toast.makeText(mContext, "下载失败", Toast.LENGTH_SHORT).show();
- break;
- }
- super.handleMessage(msg);
- }
- };
- private ImageView imageView;
- public DownloadDialog(Context context, String url) {
- super(context, R.style.Theme_CustomDialog);
- mContext = context;
- this.url = url;
- filePath = FileUtil.getPath(mContext, url);
- }
- @Override
- public void cancel() {
- super.cancel();
- }
- /**
- * 下载文件
- */
- private void downloadFile() {
- try {
- URL u = new URL(url);
- URLConnection conn = u.openConnection();
- InputStream is = conn.getInputStream();
- fileSize = conn.getContentLength();
- if (fileSize < 1 || is == null) {
- sendMessage(DOWNLOAD_ERROR);
- } else {
- sendMessage(DOWNLOAD_PREPARE);
- FileOutputStream fos = new FileOutputStream(filePath);
- byte[] bytes = new byte[1024];
- int len = -1;
- while ((len = is.read(bytes)) != -1) {
- fos.write(bytes, 0, len);
- fos.flush();
- downloadSize += len;
- sendMessage(DOWNLOAD_WORK);
- }
- sendMessage(DOWNLOAD_OK);
- is.close();
- fos.close();
- }
- } catch (Exception e) {
- sendMessage(DOWNLOAD_ERROR);
- e.printStackTrace();
- }
- }
- /***
- * 得到文件的路径
- *
- * @return
- */
- public String getFilePath() {
- return filePath;
- }
- private void init() {
- bt = (Button) this.findViewById(R.id.down_bt);
- bt.setOnClickListener(this);
- tv = (TextView) this.findViewById(R.id.down_tv);
- pb = (ProgressBar) this.findViewById(R.id.down_pb);
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.down_bt:
- if (isClick) {
- // 启动一个线程下载文件
- Thread thread = new Thread(new Runnable() {
- @Override
- public void run() {
- downloadFile();
- }
- });
- thread.start();
- isClick = false;
- }
- if (downloadOk) // 下载完成后 ,把图片显示在ImageView上面
- {
- imageView.setImageBitmap(BitmapFactory.decodeFile(filePath));
- cancel();
- }
- break;
- default:
- break;
- }
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.download_layuot);
- init();
- }
- /**
- * @param what
- */
- private void sendMessage(int what) {
- Message m = new Message();
- m.what = what;
- handler.sendMessage(m);
- }
- public void setImageView(ImageView imageView) {
- this.imageView = imageView;
- }
- @Override
- public void show() {
- isClick = true;
- downloadOk = false;
- super.show();
- }
- }
dialog的download_layuot.xml布局文件: 这个使用了相对布局,让ProgressBar和TextView呈现在一个居中位置,看起来就像连在一起的效果!同时Button来实现文件大小的显示
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@drawable/dialog"
- android:orientation="vertical" >
- <TextView
- android:layout_margin="5dip"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:text="有新的版本更新"
- android:textSize="20dip"
- android:textColor="@android:color/white" />
- <RelativeLayout
- android:layout_margin="10dip"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- >
- <ProgressBar
- android:layout_centerHorizontal="true"
- android:layout_centerVertical="true"
- android:id="@+id/down_pb"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="260dip"
- android:layout_height="wrap_content"
- />
- <TextView
- android:layout_centerHorizontal="true"
- android:layout_centerVertical="true"
- android:id="@+id/down_tv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="开始下载..."
- android:textColor="@android:color/white"
- android:textSize="20sp" />
- </RelativeLayout>
- <Button
- android:layout_gravity="center_horizontal"
- android:id="@+id/down_bt"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:text="点击下载"
- android:textColor="@android:color/black"
- android:textSize="16sp"
- android:layout_marginTop="10dip"
- android:layout_marginBottom="10dip" />
- </LinearLayout>
在dialog中需要一个样式,这个样式可以实现Dialog后面的背景透明:
- <?xml version="1.0" encoding="utf-8"?>
- <shape xmlns:android="http://schemas.android.com/apk/res/android">
- <stroke android:width="3dp"/>
- <corners android:radius="3dp" />
- <padding android:left="10dp" android:top="10dp"
- android:right="10dp" android:bottom="10dp" />
- <solid android:color="@android:color/transparent"/>
- </shape>
还有一个FileUtil.java的文件工具类:
- package com.spring.sky.dialog.download;
- import java.io.File;
- import java.io.IOException;
- import java.sql.Timestamp;
- import java.text.DecimalFormat;
- import android.content.Context;
- import android.os.Environment;
- import android.util.Log;
- /**
- * 文件工具类
- * @author spring sky
- *
- */
- public class FileUtil {
- /**
- * 获取目录名称
- * @param url
- * @return FileName
- */
- public static String getFileName(String url)
- {
- int lastIndexStart = url.lastIndexOf("/");
- if(lastIndexStart!=-1)
- {
- return url.substring(lastIndexStart+1, url.length());
- }else{
- return new Timestamp(System.currentTimeMillis()).toString();
- }
- }
- /**
- * 判断SD卡是否存在
- * @return boolean
- */
- public static boolean checkSDCard() {
- if (android.os.Environment.getExternalStorageState().equals(
- android.os.Environment.MEDIA_MOUNTED)) {
- return true;
- } else {
- return false;
- }
- }
- /**
- * 保存目录目录到目录
- * @param context
- * @return 目录保存的目录
- */
- public static String setMkdir(Context context)
- {
- String filePath = null;
- if(checkSDCard())
- {
- filePath = Environment.getExternalStorageDirectory()+File.separator+"yishuabao"+File.separator+"downloads";
- }else{
- filePath = context.getCacheDir().getAbsolutePath()+File.separator+"yishuabao"+File.separator+"downloads";
- }
- File file = new File(filePath);
- if(!file.exists())
- {
- file.mkdirs();
- Log.e("file", "目录不存在 创建目录 ");
- }else{
- Log.e("file", "目录存在");
- }
- return filePath;
- }
- /**
- * 获取路径
- * @return
- * @throws IOException
- */
- public static String getPath(Context context,String url)
- {
- String path = null;
- try {
- path = FileUtil.setMkdir(context)+File.separator+url.substring(url.lastIndexOf("/")+1);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return path;
- }
- /**
- * 获取文件的大小
- *
- * @param fileSize
- * 文件的大小
- * @return
- */
- public static String FormetFileSize(int fileSize) {// 转换文件大小
- DecimalFormat df = new DecimalFormat("#.00");
- String fileSizeString = "";
- if (fileSize < 1024) {
- fileSizeString = df.format((double) fileSize) + "B";
- } else if (fileSize < 1048576) {
- fileSizeString = df.format((double) fileSize / 1024) + "K";
- } else if (fileSize < 1073741824) {
- fileSizeString = df.format((double) fileSize / 1048576) + "M";
- } else {
- fileSizeString = df.format((double) fileSize / 1073741824) + "G";
- }
- return fileSizeString;
- }
- }