android 附件(图片)上传下载功能开发

这篇博客主要介绍了在Android中如何实现附件上传和下载功能,特别是从图库选择图片或使用相机拍照获取图片的上传过程。文章详细阐述了11种不同的附件状态,并通过逐步讲解和代码示例来简化复杂的流程。
摘要由CSDN通过智能技术生成

说明:附件上传,选择上传的附件只做了从图库选择图片或者拍照获取图片,实际也可以上传其他类型的文件,附件分为11中状态,未上传,准备上传,上传中,上传失败,上传成功,未下载,准备下载,下载中,下载成功,下载失败,已和服务器同步,看似有点复杂,其实也挺简单。

下面我将从无到有,一个一个伴随着效果图以及代码片段进行讲解

一:空白的附件列表界面如下:



点击“添加图片”按钮后:会弹出如下的选择菜单,提示是从图库选择图片还是拍照获取图片
二:选择图片菜单界面如下:





三:当选择4张图片或者拍照得到图片后,显示界面如下所示:

可以看到每个条目有一张缩略图,文件名,文件大小,最后修改日期,文件状态,以及右侧的操作按钮组成,文件状态还有一个隐藏的TextView,可以用来显示上传或下载的进度


四:点击题目中的文件名,可以修改文件的名字(只有未上传状态可以修改)
这里点击第二张范爷的图片的文件名
界面如图所示:


五:重命名后的界面如图所示:文件名改成了范爷一枚.jpg了



六:点击每个条目的上传按钮,可以讲它们加入未上传队列,这时候图片将一张张上传到服务器,每一张图片的状态依次改变为:未上传→准备上传→上传中(这是现实进度)→上传完成→已和服务器同步
如图所示:


七:所有的上传队列中图片上传完成后,会弹出确认框,是否保存刚刚上传的这些图片,如果确认,图片的状态就变成了“已和服务器同步”状态了,失败的会变成未上传状态
如图所示:




这里可以看到最后又张图片上传失败了,可以进行重试






前面讲解的都是添加上传的操作,下载讲解删除和下载的操作
说明:所有的删除和取消相关的操作,都是长按条目弹出的
一:删除未上传的图片
长按上面图片的范爷条目,会弹出如下对话框



点击删除按钮后这张图片便被移除了



二:删除已和“已和服务器同步状态”,点击条目,会弹出一样的删除对话框,但是点击删除按钮后,可以选择只从本地删除还是从服务器和本地都删除,如图所示:


如果点击“服务器和本地都删除”则图片会被从本地列表和服务器删除,但是如果点击“只从本地删除”则图片变成“未下载”状态
三:将所有的图片只从本地删除后,界面如图所示


这时候,和上传功能相反,如果点击右侧的下载按钮,图片的状态变化如下:
未下载→准备下载→下载中(显示进度)→下载完成(下次进入附件列表会变成已和服务器同步),如果下载失败会显示“下载失败”并可以重试

四:下载界面如图所示:



五:位于上传下载队列中,但是还没有开始上传和下载的都是可以取消操作的,这里就不截图了
当然,点击本地存在的图片或者已下载完成的图片,是可以发起系统调用查看图片的(实际上任何文件都可以查看)


下面就是核心的代码了:主要是一个Activity:AttachmentActivity,这个就是主界面了,3个帮助类DownLoadUtil:用来下载的帮助类,UploadUtil:用来上传的帮助类,FileIconHelper:用来显示缩略图的帮助类,AttachmentInfo附件实体类,至于其他一些简单常量及没有提到的方法,就不多少了,自行替换就是了。

各个功能点都在代码中有详细的注释:请看代码
AttachmentInfo:
package com.flagcloud.android.mqservice.model.entity;

import java.io.File;
import java.util.Date;
import java.util.HashMap;

import com.flagcloud.android.mqservice.util.CommonHelper;
import com.flagcloud.android.mqservice.util.ConvertUtil;

import android.text.format.Time;

/**
 * 附件信息实体类
 * 
 * @author hdp
 * 
 */
public class AttachmentInfo {
	public static final int NOT_UPLOAD = 1, PREPARE_UPLOAD = 2, UP_LOADING = 3,
			UP_LOADING_SUCCESS = 4, UP_LOADING_FAIL = 5, NOT_DOWNLOAD = 6,
			PREPARE_DOWNLOAD = 7, DOWN_LOADING = 8, DOWN_LOADING_SUCCESS = 9,
			DOWN_LOADING_FAIL = 10, ALREADY_SAVE = 11;
	// 本地有,服务器也已保存,则为已保存状态
	static {
		addToStateMap(1, "未上传");
		addToStateMap(2, "准备上传");
		addToStateMap(3, "上传中:");
		addToStateMap(4, "上传完成");
		addToStateMap(5, "上传失败");
		addToStateMap(6, "未下载");
		addToStateMap(7, "准备下载");
		addToStateMap(8, "下载中:");
		addToStateMap(9, "下载完成");
		addToStateMap(10, "下载失败");
		addToStateMap(11, "已和服务器同步");
	}
	public static HashMap<Integer, String> stateMap;
	// 服务器返回属性
	public String id;
	public String fileName; // 文件名
	public String path; // 文件路径,服务器路径
	public long size; // 文件大小,字节
	public String time;
	// 自定义属性
	public int state; //文件状态
	public int progress = 0; // 操作进度
	public String fileNativePath; // 文件在本地的地址

	public static void addToStateMap(int state, String stateText) {
		if (stateMap == null) {
			stateMap = new HashMap<Integer, String>();
		}
		stateMap.put(state, stateText);
	}

	public AttachmentInfo() {

	}

	public AttachmentInfo(String name, String path, long size,
			String modifyTime, int state, int progress, String fileNativePath) {
		super();
		this.fileName = name;
		this.path = path;
		this.size = size;
		this.time = modifyTime;
		this.state = state;
		this.progress = progress;
		this.fileNativePath = fileNativePath;
	}

	public AttachmentInfo(File file, int state) {
		if (file.exists()) {
			// 如果文件存在
			this.state = state;
			this.fileName = file.getName();
			this.fileNativePath = file.getAbsolutePath();
			this.size = file.length();
			try {
				this.time = ConvertUtil.dateToString(new Date(file
						.lastModified()));
			} catch (Exception e) {
				CommonHelper.log("根据文件信息创建附件转化时间时不正确", e.getMessage());
			}
		}

	}
}



AttachmentActivity:
package com.flagcloud.android.mqservice.biz.attachment;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.UUID;

import android.app.Activity;
import android.app.Dialog;
import android.content.ContentValues;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.flagcloud.android.mqservice.R;
import com.flagcloud.android.mqservice.adapter.AttachmentAdapter;
import com.flagcloud.android.mqservice.async.DownLoadAttachmentListTask;
import com.flagcloud.android.mqservice.async.DownLoadAttachmentListTask.OnDownLoadAtListFinishedListener;
import com.flagcloud.android.mqservice.async.ServiceNoteOperationTask;
import com.flagcloud.android.mqservice.async.ServiceNoteOperationTask.OnServiceNoteOperationFinishedListener;
import com.flagcloud.android.mqservice.biz.attachment.DownLoadUtil.OnDownLoadProcessListener;
import com.flagcloud.android.mqservice.biz.attachment.UploadUtil.OnUploadProcessListener;
import com.flagcloud.android.mqservice.common.Constant;
import com.flagcloud.android.mqservice.common.ResponseObjectUtil;
import com.flagcloud.android.mqservice.model.bindingmodel.ServiceNoteAttachmentsBindingModel;
import com.flagcloud.android.mqservice.model.entity.AttachmentInfo;
import com.flagcloud.android.mqservice.model.entity.ServiceNoteAttachmentInfo;
import com.flagcloud.android.mqservice.model.listitem.OperationListItemViewModel;
import com.flagcloud.android.mqservice.util.CommonHelper;
import com.flagcloud.android.mqservice.util.FileUtil;
import com.flagcloud.android.mqservice.util.GetAbsolutePathUtil;
import com.flagcloud.android.mqservice.util.GsonUtil;
import com.flagcloud.android.mqservice.util.ImageUtil;
import com.flagcloud.android.mqservice.view.dialog.ConfirmDialog;
import com.flagcloud.android.mqservice.view.dialog.InputAndConfirmDialog;
import com.google.gson.reflect.TypeToken;

//附件活动
public class AttachmentActivity extends Activity implements
		OnUploadProcessListener, OnDownLoadProcessListener {

	private static final String TAG = "AttachmentActivity";
	private static final String PHOTO_PATH = FileUtil.sdcardPath
			+ File.separator + FileUtil.APP_FILE_DIRECTOR + File.separator
			+ FileUtil.PHOTO_DIR; // 压缩后的图片存放的目录
	// 自定义上传相关消息
	private static final int TO_UPLOAD_FILE = 1;// 去上传文件
	private static final int UPLOAD_FILE_DONE = 2; // 上传完的响应
	private static final int UPLOAD_IN_PROCESS = 4; // 上传中(更新进度)
	// 自定义下载相关消息
	private static final int TO_DOWNLOAD_FILE = 5; // 去下载文件
	private static final int DOWNLOAD_FILE_DONE = 6; // 下载文件完成
	private static final int DOWNLOAD_IN_PROCESS = 7; // 文件下载中(更新进度)

	private ArrayList<AttachmentInfo> attachmentInfoList = new ArrayList<AttachmentInfo>();
	private SharedPreferences sp;
	private File photoFile;
	public static final int REQUEST_CODE_JOBREPORT = 0x0061,
			REQUEST_CODE_OTHER = 0x0062;
	private Uri photoUri;
	private String subPhotoPath; // 图片目录
	private String serviceNoteId = null;
	private AttachmentInfo currentUpLoadPhotoInfo; // 当前正在上传的对象
	private AttachmentInfo currentDownLoadFileInfo; // 当前正在下载的对象
	private AttachmentAdapter attachmentAdapter;
	private boolean isFirstComeIn; // 是否是首次进入
	private int longClickPosition = -1; // 长按的位置
	private Boolean isUpLoading = false; // 是否有图片正在上传
	private Boolean isDownLoading = false; // 是否有文件正在下载
	private int currentUploadFileTotalSize = 0; // 图片大小加上头部尾部长度
	private long currentDownLoadFileTotalSize = 0; // 当前下载的文件大小

	private Button goBackButton;
	private ListView fileInfoListView;
	private TextView topTitle;
	private InputAndConfirmDialog changeFileNameDialog;
	private Button selectFileButton; // 选择附件的按钮
	private RelativeLayout selectFileRL; // 下部选择文件的整体布局
	private AttachmentInfo selectedNewInfo; // 用户选择的新的附件
	private Button delButton;
	private Button undoButton;
	private Button cancelButton;
	private Dialog menuDialog;
	private Dialog selectImageDialog;
	private ConfirmDialog confirmDialog;
	private Dialog selectDeleteTypeDialog;
	// 下载附件列表的异步任务
	private DownLoadAttachmentListTask downLoadSNList;

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			doGoBack();
		}
		return super.onKeyDown(keyCode, event);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_up_load_attachment);
		// 创建图片的保存目录
		initializeView();
		addListener();
		sp = PreferenceManager.getDefaultSharedPreferences(this);
		// 将选择的图片保存到应用目录下的photos+任务单id为文件夹的子目录下
		// 进入即创建图片缓存目录,创建photos目录
		boolean success = FileUtil.createSDDir(FileUtil.APP_FILE_DIRECTOR
				+ File.separator + FileUtil.PHOTO_DIR);
		if (!success) {
			Toast.makeText(this, "文件夹创建失败", Toast.LENGTH_SHORT).show();
			return;
		}
		Log.i(TAG, "getAttachmentListFromServer执行了");
		Intent i = getIntent();
		serviceNoteId = i.getStringExtra("serviceNoteId");
		if (TextUtils.isEmpty(serviceNoteId)) {
			Toast.makeText(this, "任务单id有误", Toast.LENGTH_SHORT).show();
			return;
		}
		// 创建子目录
		boolean success2 = FileUtil.createSDDir(FileUtil.APP_FILE_DIRECTOR
				+ File.separator &#
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
package com.loopj.android.image; import android.content.Context; import android.graphics.Bitmap; import android.util.AttributeSet; import android.widget.ImageView; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class SmartImageView extends ImageView { private static final int LOADING_THREADS = 4; private static ExecutorService threadPool = Executors.newFixedThreadPool(LOADING_THREADS); private SmartImageTask currentTask; public SmartImageView(Context context) { super(context); } public SmartImageView(Context context, AttributeSet attrs) { super(context, attrs); } public SmartImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } // Helpers to set image by URL public void setImageUrl(String url) { setImage(new WebImage(url)); } public void setImageUrl(String url, SmartImageTask.OnCompleteListener completeListener) { setImage(new WebImage(url), completeListener); } public void setImageUrl(String url, final Integer fallbackResource) { setImage(new WebImage(url), fallbackResource); } public void setImageUrl(String url, final Integer fallbackResource, SmartImageTask.OnCompleteListener completeListener) { setImage(new WebImage(url), fallbackResource, completeListener); } public void setImageUrl(String url, final Integer fallbackResource, final Integer loadingResource) { setImage(new WebImage(url), fallbackResource, loadingResource); } public void setImageUrl(String url, final Integer fallbackResource, final Integer loadingResource, SmartImageTask.OnCompleteListener completeListener) { setImage(new WebImage(url), fallbackResource, loadingResource, completeListener); } // Helpers to set image by contact address book id public void setImageContact(long contactId) { setImage(new ContactImage(contactId)
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值