package cn.koolcloud.ipos.appstore.adapter;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import cn.koolcloud.ipos.appstore.AppStoreApplication;
import cn.koolcloud.ipos.appstore.R;
import cn.koolcloud.ipos.appstore.api.ApiService;
import cn.koolcloud.ipos.appstore.cache.ImageDownloader;
import cn.koolcloud.ipos.appstore.constant.Constants;
import cn.koolcloud.ipos.appstore.download.common.DownloadConstants;
import cn.koolcloud.ipos.appstore.download.common.DownloadUtil;
import cn.koolcloud.ipos.appstore.download.common.DownloaderErrorException;
import cn.koolcloud.ipos.appstore.download.database.DownloadDBOperator;
import cn.koolcloud.ipos.appstore.download.entity.DownloadBean;
import cn.koolcloud.ipos.appstore.download.providers.DownloadEngineCallback;
import cn.koolcloud.ipos.appstore.download.providers.Downloader;
import cn.koolcloud.ipos.appstore.entity.App;
import cn.koolcloud.ipos.appstore.fragment.tab.NormalListFragment;
import cn.koolcloud.ipos.appstore.utils.ConvertUtils;
import cn.koolcloud.ipos.appstore.utils.Env;
import cn.koolcloud.ipos.appstore.utils.Logger;
import cn.koolcloud.ipos.appstore.utils.Utils;
/**
* <p>Title: GeneralAppsListAdapter.java</p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2013</p>
* <p>Company: All In Pay</p>
* @author Teddy
* @date 2013-11-8
* @version
*/
public class UpdateAppsListAdapter extends BaseAdapter implements DownloadEngineCallback {
private static final String TAG = "GeneralAppsListAdapter";
public static final int GENERAL_APPS_INSTALL_REQUEST = 1;
private static final int HANDLE_DOWNLOAD_PROCESS = 2;
private static final int HANDLE_DOWNLOAD_PROCESS_DONE = 3;
private static final int HANDLE_START_NEW_PROCESS = 4;
private List<App> dataList = new ArrayList<App>();
private Activity ctx;
private LayoutInflater mInflater;
private AppStoreApplication mApplication;
private Handler mHandler;
private String savePath;
//break point download fields
private Downloader downloader; //file downloader
private DownloadDBOperator mDBOper;
private Map<Integer, AppItemViewHolder> holderMap = new HashMap<Integer, AppItemViewHolder>(); //save every item
private Map<Integer, DownloadBean> downloadBeanMap = new HashMap<Integer, DownloadBean>(); //save every download bean
private Map<String, Integer> posMap = new HashMap<String, Integer>(); //save position with download_id key and position value when download finished
private Queue<DownloadBean> queueTaskList = new LinkedList<DownloadBean>();
private boolean isRunningDownload = false;
public UpdateAppsListAdapter(Activity context, List<App> dataSource, Handler handler, AppStoreApplication application) {
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.ctx = context;
dataList = dataSource;
this.mApplication = application;
downloader = new Downloader(null, application, null);
mDBOper = DownloadDBOperator.getInstance(application);
mHandler = handler;
downloader.setDownloadEngineCallback(this);
}
@Override
public int getCount() {
return dataList.size();
}
@Override
public Object getItem(int arg0) {
return dataList.get(arg0);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
AppItemViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.update_software_list_item, null);
holder = new AppItemViewHolder();
holder.rootRelativeLayout = (RelativeLayout) convertView.findViewById(R.id.general_software_list_item);
holder.progressLinearLayout = (LinearLayout) convertView.findViewById(R.id.process_bar_layout);
holder.progressBar = (ProgressBar) convertView.findViewById(R.id.processbar);
holder.shadeImageView = (ImageView) convertView.findViewById(R.id.software_icon);
holder.hdImageView = (ImageView) convertView.findViewById(R.id.hd_tag);
holder.firstRelImageView = (ImageView) convertView.findViewById(R.id.first_rel);
holder.downloadButton = (Button) convertView.findViewById(R.id.download_bt);
holder.ignoreTextView = (TextView) convertView.findViewById(R.id.ignore_bt);
holder.softwareName = (TextView) convertView.findViewById(R.id.software_item_name);
holder.softwareVersionTextView = (TextView) convertView.findViewById(R.id.software_version);
holder.softwareVersionNameTextView = (TextView) convertView.findViewById(R.id.software_version_name);
holder.dividerTextView = (TextView) convertView.findViewById(R.id.software_update_divider);
holder.releaseDateTextView = (TextView) convertView.findViewById(R.id.software_release_date);
holder.softwareSizeTextView = (TextView) convertView.findViewById(R.id.software_size);
holder.softwarePatchSizeTextView = (TextView) convertView.findViewById(R.id.software_patch_size);
holder.mergeApkTextView = (TextView) convertView.findViewById(R.id.mergeapk_tv);
holder.downloadProcessTextView = (TextView) convertView.findViewById(R.id.download_process);
holder.newFeatureTextView = (TextView) convertView.findViewById(R.id.new_feature);
holder.newFeatureDetailTextView = (TextView) convertView.findViewById(R.id.new_feature_detail);
convertView.setTag(holder);
} else {
holder = (AppItemViewHolder) convertView.getTag();
}
final App appInfo = dataList.get(position);
//save holder in map then to update by thread
holderMap.put(position, holder);
//init download info
initDownloadComponents(appInfo, position);
setDownloadButtonStatus(holder, appInfo);
holder.softwareName.setText(appInfo.getName());
holder.softwareVersionNameTextView.setText(appInfo.getName());
holder.softwareSizeTextView.setText(ConvertUtils.bytes2kb(Long.parseLong(appInfo.getSize())));
//app icon
Bitmap defaultBitmap = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.moren_icon);
ImageDownloader.getInstance(ctx).download(appInfo.getIconFileName(), defaultBitmap, holder.shadeImageView);
holder.downloadButton.setOnClickListener(new DownloadButtonOnClickListener(position));
return convertView;
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
File file = (File) msg.obj;
Env.install(ctx, file, GENERAL_APPS_INSTALL_REQUEST);
}
};
private void setDownloadButtonStatus(AppItemViewHolder holder, App app) {
int installedStatus = Env.isAppInstalled(ctx, app.getPackageName(), app.getVersionCode(), mApplication.getInstalledAppsInfo());
boolean hasDownloadTask = mDBOper.isHasDownloadTaskByUrl(ApiService.getDownloadAppUrl(), app.getDownloadId());
//need to continue download
if (hasDownloadTask) {
if (isRunningDownload) {
holder.downloadButton.setText(Utils.getResourceString(mApplication, R.string.pause));
} else {
holder.downloadButton.setText(Utils.getResourceString(mApplication, R.string.go_continue));
}
holder.progressLinearLayout.setVisibility(View.VISIBLE);
holder.progressBar.setProgress(downloader.getProgress());
} else {
if (installedStatus == Constants.APP_NO_INSTALLED_DOWNLOAD) {
holder.downloadButton.setText(Utils.getResourceString(mApplication, R.string.download));
} else if (installedStatus == Constants.APP_NEW_VERSION_UPDATE) {
holder.downloadButton.setText(Utils.getResourceString(mApplication, R.string.str_update));
} else if (installedStatus == Constants.APP_INSTALLED_OPEN) {
holder.downloadButton.setText(Utils.getResourceString(mApplication, R.string.open));
}
}
}
private void initDownloadComponents(App app, int pos) {
DownloadBean downloadBean = generateDownloadBean(app);
posMap.put(downloadBean.downloadId, pos);
downloadBeanMap.put(pos, downloadBean);
}
private DownloadBean generateDownloadBean(App app) {
DownloadBean downloadBean = new DownloadBean();
downloadBean.url = ApiService.getDownloadAppUrl();
downloadBean.fileId = app.getId();
downloadBean.fileName = app.getName();
downloadBean.fileVersion = app.getVersion();
downloadBean.downloadId = app.getDownloadId();
downloadBean.versionCode = app.getVersionCode();
downloadBean.packageName = app.getPackageName();
downloadBean.fileSize = Long.parseLong(app.getSize());
int installedStatus = Env.isAppInstalled(ctx, app.getPackageName(), app.getVersionCode(), mApplication.getInstalledAppsInfo());
downloadBean.installedStatus = installedStatus;
String fileName = app.getVersion() + "_" + app.getName() + ".apk";
downloadBean.savePath = DownloadUtil.getAbsoluteFilePath(mApplication, fileName);
return downloadBean;
}
class DownloadButtonOnClickListener implements View.OnClickListener {
private App app;
private int position;
public DownloadButtonOnClickListener(int pos) {
this.app = dataList.get(pos);
this.position = pos;
}
@Override
public void onClick(View view) {
Button button = (Button) view;
DownloadBean downloadBean = downloadBeanMap.get(position);
File file = new File(downloadBean.savePath);
boolean hasDownloadTask = mDBOper.isHasDownloadTaskByUrl(ApiService.getDownloadAppUrl(), app.getDownloadId());
if (hasDownloadTask ||
downloadBean.installedStatus == Constants.APP_NO_INSTALLED_DOWNLOAD ||
downloadBean.installedStatus == Constants.APP_NEW_VERSION_UPDATE) {
//start download
if (downloadBtnSwitcher(downloadBean, downloadBean.isAPKDownloading)) {
if (!isRunningDownload) {
button.setText(Utils.getResourceString(mApplication, R.string.pause));
downloadBean.startTime = System.currentTimeMillis();
downloadBean.flag = true;
downloadBean.isAPKDownloading = true;
try {
Logger.d("click to download :" + downloadBean.fileName);
downloader.setDownloadBean(downloadBean);
downloader.startDownloader();
} catch (DownloaderErrorException e) {
Logger.d(e.getLocalizedMessage());
downloadBean.flag = false;
e.printStackTrace();
}
new RefreshDownloadProcessThread(position).start();
isRunningDownload = true;
} else {
button.setClickable(false);
button.setText(Utils.getResourceString(mApplication, R.string.waiting));
queueTaskList.add(downloadBean);
}
} else {//stop download
button.setText(Utils.getResourceString(mApplication, R.string.go_continue));
isRunningDownload = false;
downloadBean.flag = false;
downloadBean.isAPKDownloading = false;
downloader.pauseDownloader();
}
} else if (downloadBean.installedStatus == Constants.APP_DOWNLOADED_INSTALL) {
Env.install(ctx, file, GENERAL_APPS_INSTALL_REQUEST);
} else if (downloadBean.installedStatus == Constants.APP_INSTALLED_OPEN) {
Intent intent = Env.getLaunchIntent(mApplication, app.getPackageName(), mApplication.getInstalledAppsInfo());
ctx.startActivity(intent);
}
downloadBeanMap.put(position, downloadBean);
}
}
//class for update ui components
class RefreshDownloadProcessThread extends Thread {
private int position;
public RefreshDownloadProcessThread(int pos) {
this.position = pos;
}
@Override
public void run() {
int refreshNum = 1000;// refresh after 1s
DownloadBean downloadBean = downloadBeanMap.get(position);
while (downloadBean.flag) {
int nowProgress = downloader.getProgress();
Message msg = myHandler.obtainMessage();
msg.what = HANDLE_DOWNLOAD_PROCESS;
msg.obj = nowProgress;
msg.arg1 = nowProgress;
msg.arg2 = position;
myHandler.sendMessage(msg);
try {
Thread.sleep(refreshNum);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Handler myHandler = new Handler() {
AppItemViewHolder holder;
@Override
public void handleMessage(Message msg) {
holder = holderMap.get(msg.arg2);
switch (msg.what) {
case HANDLE_DOWNLOAD_PROCESS:
int progress = 0;
if (msg.arg1 >= 100) {
progress = 99;
} else {
progress = msg.arg1;
}
holder.progressLinearLayout.setVisibility(View.VISIBLE);
// holder.downloadProcessTextView.setVisibility(View.VISIBLE);
// holder.downloadProcessTextView.setText(progress + "%");
holder.downloadButton.setClickable(true);
holder.progressBar.setProgress(progress);
break;
case HANDLE_DOWNLOAD_PROCESS_DONE:
int progressDone = msg.arg1;
// holder.downloadProcessTextView.setText(progressDone + "%");
// holder.downloadProcessTextView.setVisibility(View.GONE);
holder.progressBar.setProgress(progressDone);
holder.progressLinearLayout.setVisibility(View.INVISIBLE);
//change download button status
holder.downloadButton.setText(Utils.getResourceString(mApplication, R.string.install));
DownloadBean downloadedBean = (DownloadBean) msg.obj;
downloadedBean.installedStatus = Constants.APP_DOWNLOADED_INSTALL;
downloadedBean.downloadedFile = new File(downloadedBean.savePath);
downloadBeanMap.put(msg.arg2, downloadedBean);
//install the app then refresh adapter
File downloadedFile = new File(downloadedBean.savePath);
Message message = mHandler.obtainMessage();
message.obj = downloadedFile;
message.what = NormalListFragment.GENERAL_APPS_INSTALL_REQUEST;
mHandler.sendMessage(message);
// Env.install(ctx, downloadedFile, SOFTWARE_DETAIL_LEFT_REQUEST);
myHandler.sendEmptyMessageDelayed(HANDLE_START_NEW_PROCESS, 2000);
break;
case HANDLE_START_NEW_PROCESS:
//get a new task to run
if (queueTaskList != null && queueTaskList.size() > 0) {
DownloadBean newBean = queueTaskList.poll();
int pos = posMap.get(newBean.downloadId);
holder = holderMap.get(pos);
holder.progressLinearLayout.setVisibility(View.VISIBLE);
runNewTask(newBean, pos);
}
break;
default:
break;
}
}
};
/**
* @Title: runNewTask
* @Description: get a new task from queue then start to download
* @param downloadBean
* @param position
* @return: void
*/
private void runNewTask(DownloadBean downloadBean, int position) {
downloader.setDownloadEngineCallback(this);
downloadBean.startTime = System.currentTimeMillis();
downloadBean.flag = true;
downloadBean.isAPKDownloading = true;
try {
Logger.d("start to download :" + downloadBean.fileName);
downloader.setDownloadBean(downloadBean);
downloader.startDownloader();
} catch (DownloaderErrorException e) {
Logger.d(e.getLocalizedMessage());
downloadBean.flag = false;
e.printStackTrace();
}
new RefreshDownloadProcessThread(position).start();
isRunningDownload = true;
downloadBeanMap.put(position, downloadBean);
AppItemViewHolder holder = holderMap.get(position);
holder.downloadButton.setText(Utils.getResourceString(mApplication, R.string.pause));
}
private boolean downloadBtnSwitcher(DownloadBean downloadBean, boolean currentStatus) {
downloadBean.isAPKDownloading = !currentStatus;
downloadBean.flag = !currentStatus;
return !currentStatus;
}
class AppItemViewHolder {
RelativeLayout rootRelativeLayout;
LinearLayout progressLinearLayout;
ProgressBar progressBar;
ImageView shadeImageView;
ImageView hdImageView;
ImageView firstRelImageView;
Button downloadButton;
TextView ignoreTextView; //ignore text view
TextView softwareName; //app name
TextView softwareVersionTextView; //msg text view
TextView softwareVersionNameTextView; //version name
TextView softwareSizeTextView; //app size
TextView dividerTextView; //divider
TextView releaseDateTextView;
TextView softwarePatchSizeTextView;
TextView mergeApkTextView;
TextView downloadProcessTextView;
TextView newFeatureTextView;
TextView newFeatureDetailTextView;
}
@Override
public void callbackWhenDownloadTaskListener(int state, DownloadBean bean,
String info) {
// TODO Auto-generated method stub
Logger.d("state:" + state + " info:" + info);
long endTime = System.currentTimeMillis();
Message msg = myHandler.obtainMessage();
msg.what = HANDLE_DOWNLOAD_PROCESS_DONE;
if (state == DownloadConstants.DOWNLOAD_STATE_DONE) {
msg.arg1 = 100;
} else {
msg.arg1 = downloader.getProgress();
}
isRunningDownload = false;
bean.flag = false;
bean.isAPKDownloading = false;
msg.arg2 = posMap.get(bean.downloadId);
msg.obj = bean;
myHandler.sendMessage(msg);
Logger.d("total time:" + DateFormat.format("mm:ss", endTime - bean.startTime) + "->position:" + msg.arg2);
}
}