在我的Android应用程序中,sd卡上有一个app文件,在我们的服务器上也是如此,但服务器中的数据可能会更新。
所以我做了一个活动来检查最新的数据是否可用。
这是一个例子,只有一个按钮" Check",当用户点击此按钮时,我将获取本地数据的信息,然后请求服务器检查它是否可以udpated。(这是由CheckTask
完成的,在检查过程中会显示一个进度对话框。
然后,如果需要更新,我将提供一个对话框告诉用户,他们可以选择"立即下载"或者"稍后下载",如果他们选择"立即下载",将执行DownLoadTask
,并将创建一个新的ProgressDialog以显示下载的进度。< / p>
现在我遇到了一个问题:
除非用户点击&#34;立即下载&#34;否则一切正常然后取消下载。
然后当用户点击&#34;检查&#34;按钮,CheckTask
将无法正常工作。
这是代码:
public class MyActivity extends Activity {
private DecimalFormat format = new DecimalFormat("0.#");
private final int Dialog_Offline_Check_HaveUpdate = 13;
private final int Dialog_Offline_Download = 14;
private CheckTask mCheckTask;
private ProgressDialog mCheckProgressDialog;
private DownloadTask mDownloadTask;
private ProgressDialog mDownloadProgressDialog;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.setupView();
}
private void setupView() {
mCheckProgressDialog = new ProgressDialog(this);
mCheckProgressDialog.setCanceledOnTouchOutside(false);
findViewById(R.id.check).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startCheckTask();
}
});
}
private void startCheckTask() {
if (mDownloadTask != null && !mDownloadTask.isCancelled()) {
showDialog(Dialog_Offline_Download);
} else {
//for debug
String data = String.format("{\"name\":\"%s\",\"size\":123455,\"lastModifiedTime\":\"2014-1-1\",\"hasUpdate\":false}", "Old Data");
AppData appData = null;
try {
appData = buildMapData(data);
} catch (JSONException e) {
e.printStackTrace();
}
if (mCheckTask != null) mCheckTask.cancel(true);
mCheckTask = new CheckTask();
mCheckTask.execute(String.format("http://xxxx?t=%s", appData.lastModifiedTime));
}
}
private void startDownLoadTask() {
if (mDownloadTask != null) {
mDownloadTask.cancel(true);
}
mDownloadTask = new DownloadTask();
mDownloadTask.execute("https://dl.google.com/android/adt/adt-bundle-windows-x86-20131030.zip"); //for debug
showDialog(Dialog_Offline_Download);
}
@Override
protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
switch (id) {
case Dialog_Offline_Check_HaveUpdate:
builder.setTitle("Check Update").setPositiveButton("Download Now", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
startDownLoadTask();
}
}).setNegativeButton("Download Later", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
}).setMessage("Latest Data avaiable!");
return builder.create();
case Dialog_Offline_Download:
mDownloadProgressDialog = new ProgressDialog(this);
mDownloadProgressDialog.setTitle("Download Latest Data");
mDownloadProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDownloadProgressDialog.setMax(100);
mDownloadProgressDialog.setButton(DialogInterface.BUTTON_POSITIVE, "Do it in Background", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
}
});
mDownloadProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
if (mDownloadTask != null)
mDownloadTask.cancel(true);
}
});
mDownloadProgressDialog.setMessage("");
return mDownloadProgressDialog;
}
return null;
}
@Override
protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
switch (id) {
case Dialog_Offline_Check_HaveUpdate:
String msgg;
AppData appData1 = (AppData) args.getSerializable("data");
if (appData1 != null) {
msgg = String.format("%s\n%s: %s \n%s: %s\n%s: %s", "New Data Avaiable",
"Name", appData1.name,
"Size", makeFileSizeReadable(appData1.size),
"Last Update Time", appData1.lastModifiedTime);
} else {
msgg = "";
}
((AlertDialog) dialog).setMessage(msgg);
break;
}
}
private String makeFileSizeReadable(long size) {
double value;
String unit;
if (size < 1024) {
// < 1k
value = size;
unit = "Byte";
} else if (size < 1024 * 1024) {
// 1k,1M
value = size / 1024d;
unit = "Kb";
} else {
value = size / 1024d / 1024d;
unit = "Mb";
}
return String.format("%s %s", format.format(value), unit);
}
class CheckTask extends AsyncTask<String, Void, AppData> {
private String errorMsg;
private boolean cancel = false;
@Override
protected AppData doInBackground(String... urls) {
String url = urls[0];
//for debug
String response = String.format("{\"name\":\"%s\",\"size\":222222,\"lastModifiedTime\":\"2014-1-5\",\"hasUpdate\":true}", "New Data");
Log.d("map.setting", String.format("start parse result: [%s]", response));
AppData md = null;
try {
md = buildMapData(response);
} catch (JSONException e) {
e.printStackTrace();
Log.e("map.setting", "error when parse:" + e.getMessage());
}
Log.d("map.setting", "get md:" + md);
return md;
}
@Override
protected void onPreExecute() {
mCheckProgressDialog.setMessage("Checking...");
mCheckProgressDialog.show();
}
@Override
protected void onPostExecute(AppData appData) {
mCheckProgressDialog.dismiss();
if (appData == null) {
return;
}
if (appData.hasUpdate) {
Bundle bd = new Bundle();
bd.putSerializable("data", appData);
showDialog(Dialog_Offline_Check_HaveUpdate, bd);
} else {
Toast.makeText(MyActivity.this, "Your data is the latest!", Toast.LENGTH_SHORT).show();
}
}
}
private AppData buildMapData(String response) throws JSONException {
JSONObject root = new JSONObject(response);
String name = root.getString("name");
long size = root.getLong("size");
String lastModifiedTime = root.getString("lastModifiedTime");
boolean hasUpdate = root.getBoolean("hasUpdate");
AppData md = new AppData();
md.name = name;
md.lastModifiedTime = lastModifiedTime;
md.size = size;
md.hasUpdate = hasUpdate;
return md;
}
class DownloadTask extends AsyncTask<String, Integer, String> {
@Override
protected String doInBackground(String... sUrl) {
try {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return null;
}
int fileLength = connection.getContentLength();
// download the file
input = connection.getInputStream();
output = new FileOutputStream(Environment.getExternalStorageDirectory() + "/tmp.data", false);
byte data[] = new byte[4096];
int total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
if (fileLength > 0)
publishProgress(total * 100 / fileLength, total, fileLength);
output.write(data, 0, count);
}
} catch (Exception e) {
return null;
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
} finally {
// wl.release();
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
//progress current total
if (mDownloadProgressDialog != null) {
mDownloadProgressDialog.setProgress(values[0]);
String msg = String.format("Progress:%s/%s", makeFileSizeReadable(values[1]), makeFileSizeReadable(values[2]));
mDownloadProgressDialog.setMessage(msg);
}
}
@Override
protected void onPostExecute(String res) {
//map file downloaded replace the old file
}
@Override
protected void onCancelled() {
super.onCancelled();
}
}
}
class AppData implements Serializable {
public String name;
public String lastModifiedTime;
public long size;
public boolean hasUpdate;
}
任何人都可以找到问题所在?
答案 0 :(得分:0)
你在HONEYCOMB之后遇到AsynTask的错误吗?
执行顺序 首次引入时,AsyncTasks在单个后台线程上串行执行。从DONUT开始,这被改为一个线程池,允许多个任务并行运行。从HONEYCOMB开始,任务在单个线程上执行,以避免由并行执行引起的常见应用程序错误。
如果您真的想要并行执行,可以使用THREAD_POOL_EXECUTOR调用executeOnExecutor(java.util.concurrent.Executor,Object [])。
在我们的项目中,我们使用AsynTask,如下所示:
public void executeParallelly(Params... params) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
task.execute(params);
} else {
task.executeOnExecutor(AsynTask.THREAD_POOL_EXECUTOR, params);
}
}