Reputation: 87
I am working on an app that will launch an AsyncTask to read magnetic card data. The main thread sleeps and every second checks to see if a boolean flag, waitForStripe, has been set to false. If so it will continue. I can see the AsyncTask doInBackground exit but it never reaches the onPostExecute. Originally I set the waitForSwipe variable in onPostExecute of the AsyncTask. I have worked around this by set the boolean at the end of doInBackground but I am puzzled with post execute method is not called.
I am including some logging where the onPostExecute is declared correctly. In this run, onPostExecute sets caMainWaitForStripe but still does not seem to execute.
10:04:45.940: D/Ca.PocessTrans(5360): CaiSerial
10:04:45.960: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:1
10:04:45.960: D/CaiReader(5360): requesting startSwipeCard in background.
10:04:45.960: D/CaiReader(5360): doInBackground main thread? false
10:04:46.000: I/System.out(5360): top of read loop 1, started: false
10:04:46.520: I/System.out(5360): wait for swipe
10:04:46.520: I/System.out(5360): wait for start 1
10:04:46.520: I/System.out(5360): top of read loop 2, started: false
10:04:46.960: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:2
10:04:47.030: I/System.out(5360): wait for swipe
10:04:47.030: I/System.out(5360): wait for start 2
10:04:47.030: I/System.out(5360): top of read loop 3, started: false
10:04:47.540: I/System.out(5360): wait for swipe
10:04:47.540: I/System.out(5360): wait for start 3
... here it was just waiting for me to swipe the card
01-08 10:04:50.090: I/System.out(5360): top of read loop 9, started: false
01-08 10:04:50.600: I/System.out(5360): wait for swipe
01-08 10:04:50.600: I/System.out(5360): wait for start 9
01-08 10:04:50.600: I/System.out(5360): top of read loop 10, started: false
01-08 10:04:50.960: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:6
01-08 10:04:51.110: I/System.out(5360): wait for swipe
01-08 10:04:51.110: I/System.out(5360): wait for start 10
01-08 10:04:51.110: I/System.out(5360): top of read loop 11, started: false
01-08 10:04:51.120: I/System.out(5360): starting data
01-08 10:04:51.130: I/System.out(5360): read 121 - bytes:121: val: 02
... echoing the bytes read from card
01-08 10:04:51.490: I/System.out(5360): read 121 - bytes:121: val: 6F
01-08 10:04:51.500: I/System.out(5360): read 121 - bytes:121: val: 03
01-08 10:04:51.510: I/System.out(5360): wait for swipe
01-08 10:04:51.510: I/System.out(5360): top of read loop 12, started: true
01-08 10:04:51.520: I/System.out(5360): end data
01-08 10:04:51.520: I/System.out(5360): Exiting card reader total read 121
01-08 10:04:51.550: I/System.out(5360): lrc ok
01-08 10:04:51.550: I/System.out(5360): computed checksum: 6f
01-08 10:04:51.550: I/System.out(5360): checksum ok
01-08 10:04:51.680: D/CaiReader(5360): RS232 setting Enc Data
01-08 10:04:51.680: D/EpayData(5360): setEncryptedData : good swipe
.. echoing encrypted data
01-08 10:04:51.680: D/CaiReader(5360): leaving 'wait for stripe'
01-08 10:04:51.960: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:7
01-08 10:04:52.960: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:8
01-08 10:04:53.970: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:9
01-08 10:04:54.970: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:10
01-08 10:04:55.970: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:11
01-08 10:04:56.970: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:12
01-08 10:04:57.970: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:13
01-08 10:04:58.970: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:14
01-08 10:04:59.970: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:15
01-08 10:05:00.970: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:16
01-08 10:05:01.970: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:17
01-08 10:05:02.970: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:18
01-08 10:05:03.970: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:19
01-08 10:05:04.970: D/Ca.ProcessTrans(5360): wait for swipe, sleeping...:20
01-08 10:05:05.970: D/Ca.PocessTrans(5360): break timeout 'wait for swipe'
01-08 10:05:06.120: D/CaiReader(5360): Done, result: Data set
I am thoroughly puzzled, it looks like onPostExecute is fired as the CaiReader (AsyncTask) goes out of scope, instead of after leaving wait for swipe.
Here is the asyncTask:
class CaiReader extends AsyncTask<EpayData, Long, String> {
private final String S_TAG = "CaiReader";
protected void onProgressUpdate(Integer... progress) {
Log.d("Progress", "Progress");
}
@Override
protected void onPostExecute(String result) {
Log.d(S_TAG, "Done, result: " + result);
// caMainWaitSwipe = false;
}
// protected void onPostExecute(Long result) {
// Log.d(S_TAG, "Done, result: " + result);
//}
/**
* this is controlling task. It launches card reader.
*/
@Override
protected String doInBackground(EpayData... params) {
Log.d(S_TAG, "requesting startSwipeCard in background.");
showThread(S_TAG, "doInBackground");
EpayData epayData = params[0];
byte[] scan = caiSerialReader.readCard();
if (scan == null) {
return "failure";
}
Map<String, String> rs232Map = CaiRs232Read.parseScan(scan);
String KSN = rs232Map.get(CaiSerialReader.RS232_KSN);
String encBlock = rs232Map.get(CaiSerialReader.RS232_ENC_BLOCK);
Log.d(S_TAG, "RS232 setting Enc Data");
epayData.setEncryptedData(encBlock, KSN);
Log.d("CAPTURE", "KSN: " + KSN);
Log.d("CAPTURE", "encBlock: " + encBlock);
caMainWaitSwipe = false;
Log.d(S_TAG, "leaving 'wait for stripe' ");
String success = "set";
return success;
}
}
The calling program:
if (readerType == ReaderType.RS232) {
Log.d("Ca.PocessTrans", "CaiSerial");
caMainWaitSwipe = true;
int i = 0;
CaiReader caiReader = (CaiReader) new CaiReader().execute(epayData);
while (caMainWaitSwipe) {
i++;
if (i > 20) {
Log.d("Ca.PocessTrans", "break timeout 'wait for swipe'");
return DsiParser.timedOutError();
}
try {
Log.d("Ca.ProcessTrans", "wait for swipe, sleeping...:" + i);
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.d("Ca.ProcessTrans", "process tran interrupted exception");
e.printStackTrace();
}
}
Log.d("Ca.PocessTrans", "exit rs232 wait for stripe");
}
if (!epayData.isReadGood()) {
return DsiParser.swipeError();
}
}
Log.d("Ca.PocessTrans", "data read");
authorizeTransaction(epayData);
Upvotes: 0
Views: 424
Reputation: 132982
Currently your are not overriding AsyncTask
onPostExecute()
because you are returning String
from doInBackground()
but receiving result as Long
so Change your code as :
class CaiReader extends AsyncTask<EpayData, Long, String> {
private final String S_TAG = "CaiReader";
protected void onProgressUpdate(Integer... progress) {
Log.d("Progress", "Progress");
}
@Override
protected void onPostExecute(String result) { //<< chnage to String
Log.d(S_TAG, "Done, result: " + result);
}
/**
* this is controlling task. It launches card reader.
*/
@Override
protected String doInBackground(EpayData... params) {
//your code here
return null; //<< return string from here
}
}
Upvotes: 0
Reputation: 3134
I think there is something wrong with your onPostExecute method signature. The parameter should be of type string instead of type long. I recommend putting the @Override annotation on top of every overridden method so that the compiler can tell you what's wrong. Another thing is that you don't need a loop to check the status, you can do all this in a method and call it on onPostExecute.
Upvotes: 1
Reputation: 44571
If your main thread is sleeping then it won't be calling the Async
and your onPostExecute()
won't be reached. Have your doInBackground()
sleep every second or however long you want or until condition is reached. Then you can return this value to your main activity, call a function, or whatever you want to do on the UI
. Main thread shouldn't sleep. Alternatively, you could use a timer on the UI
Upvotes: 0