/****************************************************************************
* Copyright (C) 2012 HS Coburg.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
* This file is part of the Open eCard App.
*
* GNU General Public License Usage
* This file may be used under the terms of the GNU General Public
* License version 3.0 as published by the Free Software Foundation
* and appearing in the file LICENSE.GPL included in the packaging of
* this file. Please review the following information to ensure the
* GNU General Public License version 3.0 requirements will be met:
* http://www.gnu.org/copyleft/gpl.html.
*
* Other Usage
* Alternatively, this file may be used in accordance with the terms
* and conditions contained in a signed written agreement between
* you and ecsec GmbH.
*
***************************************************************************/
package org.openecard.android.activities;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import iso.std.iso_iec._24727.tech.schema.ConnectionHandleType;
import iso.std.iso_iec._24727.tech.schema.EstablishContext;
import iso.std.iso_iec._24727.tech.schema.EstablishContextResponse;
import iso.std.iso_iec._24727.tech.schema.ListIFDs;
import iso.std.iso_iec._24727.tech.schema.ListIFDsResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import org.openecard.android.ApplicationContext;
import org.openecard.android.R;
import org.openecard.common.I18n;
import org.openecard.common.enums.EventType;
import org.openecard.common.interfaces.Dispatcher;
import org.openecard.common.interfaces.DispatcherException;
import org.openecard.common.interfaces.EventCallback;
import org.openecard.common.sal.state.CardStateEntry;
import org.openecard.recognition.CardRecognition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This Activity shows information about the currently used ecard.
*
* @author Dirk Petrautzki <petrautzki@hs-coburg.de>
*/
public class CardInfoActivity extends Activity implements EventCallback {
// logger and translation
private static final Logger logger = LoggerFactory.getLogger(CardInfoActivity.class);
private final I18n lang = I18n.getTranslation("android");
// gui constants
private static final String REQUEST_CARD = "android.cardinfo.request_card";
private static final String REQUEST_TEMINAL = "android.cardinfo.request_terminal";
private static final String NO_CARD = "android.cardinfo.cardname";
private ApplicationContext appContext;
private CardRecognition recognition;
private HashMap<String, TerminalFragment> fragments = new HashMap<String, TerminalFragment>();
private TextView textInfo;
private LinearLayout linearLayoutCardInfoActivity;
private int numTerminals;
private int numCards;
private List<String> ifdNames;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set up the window layout
setContentView(R.layout.cardinfo);
linearLayoutCardInfoActivity = (LinearLayout) findViewById(R.id.linearLayoutCardActivity);
textInfo = (TextView) findViewById(R.id.label_info);
// register for events
appContext = ((ApplicationContext) getApplicationContext());
recognition = appContext.getRecognition();
// get an instance of FragmentTransaction from your Activity
FragmentManager fragmentManager = getFragmentManager();
try {
Dispatcher dispatcher = appContext.getEnv().getDispatcher();
EstablishContext establishContext = new EstablishContext();
EstablishContextResponse response = (EstablishContextResponse) dispatcher.deliver(establishContext);
ListIFDs listIFDs = new ListIFDs();
listIFDs.setContextHandle(response.getContextHandle());
ListIFDsResponse listIFDsResponse = (ListIFDsResponse) dispatcher.deliver(listIFDs);
ifdNames = listIFDsResponse.getIFDName();
numTerminals = ifdNames.size();
if (ifdNames.size() == 0) {
textInfo.setVisibility(View.VISIBLE);
textInfo.setText(lang.translationForKey(REQUEST_TEMINAL));
} else {
textInfo.setVisibility(View.GONE);
for (String ifdName : ifdNames) {
addTerminalFragment(fragmentManager, ifdName);
}
}
} catch (DispatcherException e) {
logger.error("Couldn't get initial state of IFDs.", e);
} catch (InvocationTargetException e) {
logger.error("Couldn't get initial state of IFDs.", e);
}
fragmentManager.executePendingTransactions();
appContext.getEnv().getEventManager().registerAllEvents(this);
}
@Override
protected void onStart() {
super.onStart();
ConnectionHandleType cHandle = new ConnectionHandleType();
for (String ifdName : ifdNames) {
cHandle.setIFDName(ifdName);
CardStateEntry entry = appContext.getCardStates().getEntry(cHandle);
if (entry != null) {
TerminalFragment fragment = fragments.get(ifdName);
numCards++;
cHandle = entry.handleCopy();
String cardType = cHandle.getRecognitionInfo().getCardType();
InputStream is = recognition.getCardImage(cardType);
Drawable drawable = Drawable.createFromStream(is, null);
fragment.updateFragment(drawable, recognition.getTranslatedCardName(cardType));
}
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
// No call for super(). Bug on API Level > 11.
}
@Override
public void signalEvent(final EventType eventType, final Object eventData) {
runOnUiThread(new UiUpdateRunnable(eventType, eventData));
}
private void removeTerminalFragment(FragmentManager fragmentManager, String ifdName) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
TerminalFragment fragment = fragments.get(ifdName);
fragmentTransaction.remove(fragment);
fragments.remove(ifdName);
fragmentTransaction.commit();
}
private void addTerminalFragment(FragmentManager fragmentManager, String ifdName) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
TerminalFragment fragment = new TerminalFragment();
fragment.setIFDName(ifdName);
fragment.setRecognition(recognition);
fragments.put(ifdName, fragment);
fragmentTransaction.add(R.id.cardInfoLinearLayout, fragment);
fragmentTransaction.commit();
}
/**
* This Runnable updates the UI depending on the happended event.
*
* @author Dirk Petrautzki <petrautzki@hs-coburg.de>
*/
private final class UiUpdateRunnable implements Runnable {
private final EventType eventType;
private final Object eventData;
private UiUpdateRunnable(EventType eventType, Object eventData) {
this.eventType = eventType;
this.eventData = eventData;
}
@Override
public void run() {
FragmentManager fragmentManager = getFragmentManager();
if (eventType.equals(EventType.CARD_RECOGNIZED)) {
ConnectionHandleType ch = (ConnectionHandleType) eventData;
String cardType = ch.getRecognitionInfo().getCardType();
InputStream is = recognition.getCardImage(cardType);
Drawable drawable = Drawable.createFromStream(is, null);
TerminalFragment myFragment = fragments.get(ch.getIFDName());
myFragment.updateFragment(drawable, recognition.getTranslatedCardName(cardType));
numCards++;
} else if (eventType.equals(EventType.CARD_REMOVED)) {
ConnectionHandleType ch = (ConnectionHandleType) eventData;
Drawable drawable;
if (appContext.usingNFC()) {
try {
drawable = Drawable.createFromStream(getAssets().open("NFC-logo.png"), null);
} catch (IOException e) {
logger.error("Coudn't load nfc logo; using default no card image.", e);
InputStream is = recognition.getNoCardImage();
drawable = Drawable.createFromStream(is, null);
}
} else {
InputStream is = recognition.getNoCardImage();
drawable = Drawable.createFromStream(is, null);
}
TerminalFragment myFragment = fragments.get(ch.getIFDName());
myFragment.updateFragment(drawable, lang.translationForKey(NO_CARD));
numCards--;
} else if (eventType.equals(EventType.TERMINAL_ADDED)) {
ConnectionHandleType ch = (ConnectionHandleType) eventData;
addTerminalFragment(fragmentManager, ch.getIFDName());
numTerminals++;
} else if (eventType.equals(EventType.TERMINAL_REMOVED)) {
ConnectionHandleType ch = (ConnectionHandleType) eventData;
removeTerminalFragment(fragmentManager, ch.getIFDName());
numTerminals--;
}
// pending transactions must be executed before invalidating the layout
try {
fragmentManager.executePendingTransactions();
} catch (NullPointerException e) {
// ignore
}
if (numTerminals == 0) {
textInfo.setText(lang.translationForKey(REQUEST_TEMINAL));
textInfo.setVisibility(View.VISIBLE);
} else if (numCards == 0) {
textInfo.setText(lang.translationForKey(REQUEST_CARD));
textInfo.setVisibility(View.VISIBLE);
} else {
textInfo.setVisibility(View.GONE);
}
linearLayoutCardInfoActivity.invalidate();
}
}
}