I have a button that runs an AsyncTask to download some info from the web, and put that info into a local variable in the activity, which can be viewed by pressing another button. Also, I update a view in the UI to state whether the sync is running or ready.
For some reason, sometimes the onPostExecute does not update the UI and local variable as expected, though sometimes it does. I checked with debugger, and the code that updates the variable (handleDownloadComplete) is running, but still the UI and show data button don't update properly. Note: issue happens mostly when connection times out, but still I saw with debugger that the return value was correct - "Connection timed out", yet activity doesn't update.
Thanks!
The AsyncTask class:
public class DownloadDataTask extends AsyncTask<String, Integer, String> {
public interface DownloadCompleteHandler
{
void handleDownloadComplete(String result);
}
private DownloadCompleteHandler handler;
@Override
protected String doInBackground(String... urls) {
try {
return downloadUrl(urls[0]);
} catch (IOException e) {
return "Unable to retrieve web page. URL may be invalid.";
}
}
@Override
protected void onPostExecute(String result) {
handler.handleDownloadComplete(result);
}
private String downloadUrl(String urlStr) throws IOException
{
InputStream is = null;
String result = new String();
try {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();
int response = conn.getResponseCode();
is = conn.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null) {
result += inputLine;
}
}
catch (MalformedURLException ex) {
result = "Malformed URL: " + urlStr;
}
catch (SocketTimeoutException ex) {
result = "Connection timed out";
}
finally {
if (is != null)
is.close();
}
return result;
}
public void setHandler(DownloadCompleteHandler handler) {
this.handler = handler;
}
}
The Activity:
public class MainActivity extends Activity implements DownloadDataTask.DownloadCompleteHandler{
private String downloadResult = "";
private Boolean isSyncing = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onResume() {
super.onResume();
checkNetworkConnection();
}
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putString(KEY_DOWNLOAD_RESULT, downloadResult);
savedInstanceState.putBoolean(KEY_IS_SYNCING, isSyncing);
super.onSaveInstanceState(savedInstanceState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
downloadResult = savedInstanceState.getString(KEY_DOWNLOAD_RESULT);
isSyncing = savedInstanceState.getBoolean(KEY_IS_SYNCING);
updateAppDataView();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
settingsMenu();
return true;
case R.id.action_show_result:
showUrlResultDialog();
return true;
case R.id.action_sync:
getHttpData();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
void settingsMenu() {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
}
private void checkNetworkConnection() {
ConnectivityManager connMgr = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
// test app connection
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.titleNoNetwork).setMessage(R.string.msgNoNetwork);
builder.setCancelable(false);
builder.setNegativeButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
}
private void getHttpData()
{
if (isSyncing) return;
isSyncing = true;
TextView view = (TextView)findViewById(R.id.textWebResult);
view.setText("Syncing");
String serverId = PreferenceManager.getDefaultSharedPreferences(this).getString(getString(R.string.keyServerIp), "");
String url = "https://" + serverId;
DownloadDataTask downloader = new DownloadDataTask();
downloader.setHandler(this);
downloader.execute(url);
}
public void handleDownloadComplete(String result)
{
downloadResult = result;
TextView view = (TextView)findViewById(R.id.textWebResult);
view.setText("Ready");
isSyncing = false;
}
private void showUrlResultDialog()
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.titleUrlResultData).setMessage(downloadResult);
builder.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
}
Edit: I noticed I was missing onSaveInstanceState
and onRestoreInstanceState
implementation, and thought it might be the cause since the problem only occurs when the connection times out, which might cause the activity to restart from some reason. So I added them (also in the code above), but the problem still occurs...
Any ideas anyone?