В настоящее время я работаю над приложением Android HCE. My HCE service
берет APDU с устройства чтения. Устройство чтения отправляет их непрерывно. Так что processCommandApdu()
в моем HCE service
вызывается довольно часто. Заходит большинство времени READER_STATE_APDU
. Это проприетарный апд, и он распознается только устройством чтения и моим андроидом HCE service
. Он содержит некоторую информацию о читателе и специальный байт MESSAGE
. В большинстве случаев MESSAGE
байт 0x00, что означает отсутствие сообщений. Но иногда это указывает на какое-то событие. Это может быть ошибка или что-то еще. Мой HCE service
должен подтвердить MESSAGE
байт в ответ APDU. И устройство считывателя очищает MESSAGE
байт, когда получил ответ APDU от моего HCE service
.Архитектура приложения Android HCE
Теперь моя идея - разобрать READER_STATE_APDU
в processCommandApdu()
и показать соответствующие Activity
пользователю.
Например, когда MESSAGE
байт 0x00 Я хочу начать ReaderActivity
, чтобы показать информацию читателю пользователю. И когда MESSAGE
байт SOME_ERROR
Я хочу начать ErrorActivity
, чтобы показать пользователю ошибку.
Так что мой processCommandApdu()
может быть, как это (псевдокод):
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras)
{
...
if commandApdu is READER_STATE_APDU
{
if messageByte is NO_MESSAGE
{
create intent for ReaderActivity and start it
}
else if messageByte is SOME_ERROR
{
create intent for ErrorActivity and start it
}
...
}
...
}
Конечно эти мероприятия должны иметь соответствующие режимы запуска или флаги в намерениях.
Но, как я уже говорил ранее, MESSAGE
байт SOME_ERROR
только для одной транзакции, и я хочу, чтобы показать ErrorActivity
к пользователю в течение некоторого времени и предотвратить ReaderActivity
от запуска.
Так что я могу представить себе следующий код в моем HCE service
(псевдокоде):
boolean mStartReaderActivity;
...
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras)
{
...
if commandApdu is READER_STATE_APDU
{
if messageByte is NO_MESSAGE
{
if (mStartReaderActivity)
{
create intent for ReaderActivity and start it
}
}
else if messageByte is SOME_ERROR
{
if (mStartReaderActivity)
{
mStartReaderActivity = false;
}
create intent for ErrorActivity and start it
}
...
}
...
}
...
public int onStartCommand(Intent intent, int flags, int startId)
{
if intent is INTENT_ERROR_CONFIRMED
{
mStartReaderActivity = true;
}
}
и в моем ErrorActivity
(псевдокоде):
public void onConfirmErrorButtonClick()
{
create INTENT_ERROR_CONFIRMED and start service
}
Но это решение кажется ненадежным , Я мог бы, например, использовать SharedPreferences
сохранить mStartReaderActivity
по моему HCE service
отдыха (псевдокод):
boolean mStartReaderActivity;
...
public void onCreate()
{
...
loadStartActivityFromPreferences();
...
}
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras)
{
...
if commandApdu is READER_STATE_APDU
{
if messageByte is NO_MESSAGE
{
if (mStartReaderActivity)
{
create intent for ReaderActivity and start it
}
}
else if messageByte is SOME_ERROR
{
if (mStartReaderActivity)
{
mStartReaderActivity = false;
saveStartActivityToPreferences();
}
create intent for ErrorActivity and start it
}
...
}
...
}
...
public int onStartCommand(Intent intent, int flags, int startId)
{
if intent is INTENT_ERROR_CONFIRMED
{
mStartReaderActivity = true;
saveStartActivityToPreferences();
}
}
Но нет никакой гарантии, что INTENT_ERROR_CONFIRMED
будут созданы и отправлены и доставлены. Например, Android может убить процесс до того, как пользователь нажал кнопку. Таким образом, HCE service
может зависеть от mStartReaderActivity==false
.
Есть ли способ справиться с этим?
Или, может быть, я должен изменить архитектуру? Например, следует ли использовать один Activity
с Fragments
и сохранить mStartReaderActivity (well, mShowReaderFragment in new terms)
в Activity
через savedINstanceState
?
Возможно, какое-либо другое решение?
Большое спасибо за ответ. Но я думаю, что ваше решение похоже на мое (см. 'SaveStartActivityToPreferences()' и 'loadStartActivityFromPreferences()' в моем вопросе), и если да, то он не работает. Например, служба «HCE» получила «ERROR» и установила флаг (и сохранила в prefs). Затем «ErrorActivity» запускается и отображается пользователю. Затем Android убивает процесс, и пользователь не нажимает кнопку, и если да, флаг не очищается. Затем 'HCE service' перезапускается и читает флаг из настроек. Теперь флаг всегда указывает, что 'ReaderActivity' не должен быть запущен – fighter0ik
Вы можете переопределить onDestroy, я обновил свой ответ – LaurentY
@ fighter0ik, если это полезно, пожалуйста, примите ответ – LaurentY