Android Open Source - irma_android_management Credential List Activity






From Project

Back to project page irma_android_management.

License

The source code is released under:

GNU General Public License

If you think the Android project irma_android_management listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * CredentialListActivity.java//www .j  a v a 2  s .  c  o m
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * 
 * Copyright (C) Wouter Lueks, Radboud University Nijmegen, Februari 2013.
 */

package org.irmacard.androidmanagement;

import java.io.IOException;
import java.util.ArrayList;

import net.sourceforge.scuba.smartcards.CardServiceException;
import net.sourceforge.scuba.smartcards.IsoDepCardService;

import org.irmacard.android.util.credentials.CredentialPackage;
import org.irmacard.androidmanagement.dialogs.AlertDialogFragment;
import org.irmacard.androidmanagement.dialogs.CardMissingDialogFragment;
import org.irmacard.androidmanagement.dialogs.ChangePinDialogFragment;
import org.irmacard.androidmanagement.dialogs.ConfirmDeleteDialogFragment;
import org.irmacard.androidmanagement.dialogs.ConfirmDeleteDialogFragment.ConfirmDeleteDialogListener;
import org.irmacard.androidmanagement.util.TransmitResult;
import org.irmacard.credentials.idemix.IdemixCredentials;
import org.irmacard.credentials.info.CredentialDescription;

import org.irmacard.credentials.util.CardVersion;
import org.irmacard.credentials.util.log.LogEntry;
import org.irmacard.idemix.IdemixService;
import android.app.DialogFragment;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

/**
 * An activity representing a list of Credentials. This activity has different
 * presentations for handset and tablet-size devices. On handsets, the activity
 * presents a list of items, which when touched, lead to a
 * {@link CredentialDetailActivity} representing item details. On tablets, the
 * activity presents the list of items and item details side-by-side using two
 * vertical panes.
 * <p>
 * The activity makes heavy use of fragments. The list of items combined with
 * log and settings buttons is a {@link MenuFragment} and the item details (if
 * present) is a {@link CredentialDetailFragment}.
 * <p>
 * This activity also implements the required {@link MenuFragment.Callbacks}
 * interface to listen for item selections and button callbacks.
 */
public class CredentialListActivity extends FragmentActivity implements
    MenuFragment.Callbacks, ConfirmDeleteDialogListener,
    CardMissingDialogFragment.CardMissingDialogListener,
    ChangePinDialogFragment.ChangePinDialogListener,
    AlertDialogFragment.AlertDialogListener,
    CredentialDetailFragment.Callbacks,
    SettingsFragment.Callbacks {

  /**
   * Whether or not the activity is in two-pane mode, i.e. running on a tablet
   * device.
   */
  private boolean mTwoPane;
  
  private ArrayList<CredentialPackage> credentials;
  private ArrayList<LogEntry> logs;
  private Tag tag;

  private NfcAdapter nfcA;
  private PendingIntent mPendingIntent;
  private IntentFilter[] mFilters;
  private String[][] mTechLists;

  private String TAG = "CredentialListActivity";

  private interface CardProgram {
    public TransmitResult run(IdemixService is) throws CardServiceException;
  }

  private enum Action {
    NONE,
    DELETE_CREDENTIAL,
    CHANGE_CARD_PIN,
    CHANGE_CREDENTIAL_PIN
  }

  private enum State {
    NORMAL,
    TEST_CARD_PRESENCE,
    WAITING_FOR_CARD,
    CONFIRM_ACTION,
    PERFORM_ACTION,
    ACTION_PERFORMED,
    ACTION_FAILED
  }

  private Action currentAction = Action.NONE;
  private State currentState = State.NORMAL;
  private DialogFragment cardMissingDialog;

  // Needed to delete credentials
  private CredentialDescription toBeDeleted;

  // Needed to change PINs
  private String old_pin;
  private String new_pin;
  private int tries;

  // Deal properly with failures
  private Exception exception;

  private String cardPin;
  private CardVersion cardVersion;

  // Requests
  private int SETTINGS_REQUEST = 11;
  private int DETAIL_REQUEST = 12;

  // PIN lengths
  private int CRED_PIN_LENGTH = 4;
  private int CARD_PIN_LENGTH = 6;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    // Pass the list of CredentialPackages on to the ListFragement
    Intent intent = getIntent();
    @SuppressWarnings("unchecked")
    ArrayList<CredentialPackage> credentials = (ArrayList<CredentialPackage>) intent
        .getSerializableExtra(WaitingForCardActivity.EXTRA_CREDENTIAL_PACKAGES);
    setCredentials(credentials);
    
    @SuppressWarnings("unchecked")
    ArrayList<LogEntry> logs = (ArrayList<LogEntry>) intent
        .getSerializableExtra(WaitingForCardActivity.EXTRA_LOG_ENTRIES);
    setLogs(logs);

    Tag tag = (Tag) intent
        .getParcelableExtra(WaitingForCardActivity.EXTRA_TAG);
    setTag(tag);

    cardPin = (String) intent.getSerializableExtra(WaitingForCardActivity.EXTRA_CARD_PIN);
    cardVersion = (CardVersion) intent.getSerializableExtra(WaitingForCardActivity.EXTRA_CARD_VERSION);

    setContentView(R.layout.activity_credential_list);

    if (findViewById(R.id.credential_detail_container) != null) {
      // The detail container view will be present only in the
      // large-screen layouts (res/values-large and
      // res/values-sw600dp). If this view is present, then the
      // activity should be in two-pane mode.
      mTwoPane = true;

      // In two-pane mode, list items should be given the
      // 'activated' state when touched.
      ((MenuFragment) getSupportFragmentManager()
          .findFragmentById(R.id.credential_menu_fragment))
          .setTwoPaneMode(true);

      InitFragment initFragment = new InitFragment();
      getSupportFragmentManager().beginTransaction()
          .replace(R.id.credential_detail_container, initFragment)
          .commit();

      Log.i("blaat", "Simulating initial click!!");
      ((MenuFragment) getSupportFragmentManager()
          .findFragmentById(R.id.credential_menu_fragment)).simulateListClick(0);
      
      // Do not show action bar in two-pane mode
      getActionBar().hide();
    }

        // NFC stuff
        nfcA = NfcAdapter.getDefaultAdapter(getApplicationContext());
        mPendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

        // Setup an intent filter for all TECH based dispatches
        IntentFilter tech = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
        mFilters = new IntentFilter[] { tech };

        // Setup a tech list for all IsoDep cards
        mTechLists = new String[][] { new String[] { IsoDep.class.getName() } };
  }

    @Override
    public void onResume() {
        super.onResume();
        if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(getIntent().getAction())) {
            processIntent(getIntent());
        }
        if (nfcA != null) {
          nfcA.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists);
        }
    }

    @Override
    public void onPause() {
      super.onPause();
      if (nfcA != null) {
        nfcA.disableForegroundDispatch(this);
      }
    }

    @Override
    public void onNewIntent(Intent intent) {
        Log.i(TAG, "Discovered tag with intent: " + intent);
        setIntent(intent);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
      // Menu is only inflated in single pane mode

        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return !mTwoPane;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_history:
          onLogSelected();
          return true;
        case R.id.menu_settings:
          onSettingsSelected();
          return true;
        default:
          return super.onOptionsItemSelected(item);
        }
    }

    public void processIntent(Intent intent) {
        tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
      IsoDep isotag = IsoDep.get(tag);
      if (isotag != null) {
        // We are waiting for the card, notify dialog
        if (currentState == State.WAITING_FOR_CARD) {
          cardMissingDialog.dismiss();
          gotoState(State.TEST_CARD_PRESENCE);
        }
      }
    }

  private void setCredentials(ArrayList<CredentialPackage> credentials) {
    this.credentials = credentials;
  }

  private void setLogs(ArrayList<LogEntry> logs) {
    this.logs = logs;
  }

  private void setTag(Tag tag) {
    this.tag = tag;
  }

  /**
   * Callback method from {@link MenuFragment.Callbacks} indicating
   * that the item with the given ID was selected.
   */
  @Override
  public void onItemSelected(short id) {
    CredentialPackage credential = null;
    for(CredentialPackage cp : credentials) {
      if(cp.getCredentialDescription().getId() == id) {
        credential = cp;
      }
    }

    if (mTwoPane) {
      // In two-pane mode, show the detail view in this activity by
      // adding or replacing the detail fragment using a
      // fragment transaction.
      Bundle arguments = new Bundle();
      arguments.putSerializable(CredentialDetailFragment.ARG_ITEM, credential);
      CredentialDetailFragment fragment = new CredentialDetailFragment();
      fragment.setArguments(arguments);
      getSupportFragmentManager().beginTransaction()
          .replace(R.id.credential_detail_container, fragment)
          .commit();

    } else {
      // In single-pane mode, simply start the detail activity
      // for the selected item ID.
      Log.i(TAG, "Starting detail activity");
      Intent detailIntent = new Intent(this,
          CredentialDetailActivity.class);
      detailIntent.putExtra(CredentialDetailFragment.ARG_ITEM, credential);
      startActivityForResult(detailIntent, DETAIL_REQUEST);
    }
  }
  
  /**
   * Callback method from {@link MenuFragment.Callbacks} indicating
   * that the log was selected.
   */
  public void onLogSelected() {
    Log.i("cla", "log selected");
    if (mTwoPane) {
      // In two-pane mode, show the detail view in this activity by
      // adding or replacing the detail fragment using a
      // fragment transaction.
      Bundle arguments = new Bundle();
      arguments.putSerializable(LogFragment.ARG_LOG, logs);
      LogFragment fragment = new LogFragment();
      fragment.setArguments(arguments);
      getSupportFragmentManager().beginTransaction()
          .replace(R.id.credential_detail_container, fragment)
          .commit();
    } else {
      // In single-pane mode, simply start the detail activity
      // for the the log
      Intent logIntent = new Intent(this, LogActivity.class);
      logIntent.putExtra(LogFragment.ARG_LOG, logs);
      startActivity(logIntent);
    }
  }

  /**
   * Callback method from {@link MenuFragment.Callbacks} indicating
   * that the settings were selected.
   */
  public void onSettingsSelected() {
    Log.i("cla", "settings selected");
    if (mTwoPane) {
      // In two-pane mode, show the detail view in this activity by
      // adding or replacing the detail fragment using a
      // fragment transaction.
      Bundle arguments = new Bundle();
      arguments.putSerializable(SettingsFragment.ARG_CARD_VERSION, cardVersion);
      SettingsFragment fragment = new SettingsFragment();
      fragment.setArguments(arguments);
      getSupportFragmentManager().beginTransaction()
          .replace(R.id.credential_detail_container, fragment)
          .commit();

    } else {
      // In single-pane mode, simply start the detail activity
      // for the selected item ID.
      Intent settingsIntent = new Intent(this, SettingsActivity.class);
      settingsIntent.putExtra(SettingsFragment.ARG_CARD_VERSION, cardVersion);
      startActivityForResult(settingsIntent, SETTINGS_REQUEST);
    }
  }

  @Override
  public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(requestCode == SETTINGS_REQUEST) {
      if(resultCode == SettingsActivity.RESULT_CHANGE_CARD_PIN)
        onChangeCardPIN();
      else if(resultCode == SettingsActivity.RESULT_CHANGE_CRED_PIN)
        onChangeCredPIN();
    } else if(requestCode == DETAIL_REQUEST) {
      if (resultCode == CredentialDetailActivity.RESULT_DELETE) {
        CredentialDescription cd = (CredentialDescription) data
            .getSerializableExtra(CredentialDetailActivity.ARG_RESULT_DELETE);
        onDeleteCredential(cd);
      }
    }
  }

  public void onCardMissingCancel() {
    // If cancelled we cannot continue with the action
    gotoState(State.NORMAL);
  }

  public void onCardMissingRetry() {
    // We should retry
    gotoState(State.TEST_CARD_PRESENCE);
  }

  @Override
  public void onPINChange(String old_pin, String new_pin) {
    this.old_pin = old_pin;
    this.new_pin = new_pin;
    gotoState(State.PERFORM_ACTION);
  }

  @Override
  public void onPINChangeCancel() {
    // If cancelled we cannot continue, returning to normal
    gotoState(State.NORMAL);
  }

  protected ArrayList<CredentialPackage> getCredentials() {
    return credentials;
  }

  public ArrayList<LogEntry> getLogs() {
    return logs;
  }

  public CardVersion getCardVersion() {
    return cardVersion;
  }

  private void gotoState(State state) {
    String TAG = "CLA:State";

    //State previousState = currentState;
    currentState = state;

    switch(state) {
    case NORMAL:
      Log.i(TAG, "Returning to default state");
      break;
    case TEST_CARD_PRESENCE:
      Log.i(TAG, "Checking card presence");

      // This is the start of a new action so we should reset some state
      tries = -1;

      new CheckCardPresentTask(this).execute(tag);
      break;
    case WAITING_FOR_CARD:
      Log.i(TAG, "Going to wait for card");
      cardMissingDialog = new CardMissingDialogFragment();
      cardMissingDialog.show(getFragmentManager(), "cardmissing");
      break;
    case CONFIRM_ACTION:
      Log.i(TAG, "Confirming action");
      ChangePinDialogFragment pinDialog;

      switch(currentAction) {
      case DELETE_CREDENTIAL:
        ConfirmDeleteDialogFragment confirmDialog = ConfirmDeleteDialogFragment.getInstance(toBeDeleted);
        confirmDialog.show(getFragmentManager(), "confirm_delete");
        break;
      case CHANGE_CARD_PIN:
        pinDialog = ChangePinDialogFragment.getInstance("card", tries,
            new_pin, CARD_PIN_LENGTH);
        pinDialog.show(getFragmentManager(), "change_card_pin");
        break;
      case CHANGE_CREDENTIAL_PIN:
        pinDialog = ChangePinDialogFragment.getInstance("credential",
            tries, new_pin, CRED_PIN_LENGTH);
        pinDialog.show(getFragmentManager(), "change_cred_pin");
        break;
      case NONE:
        Log.i(TAG, "Illegal state, returning to normal");
        currentState = State.NORMAL;
        break;
      }

      break;
    case ACTION_FAILED:
      Log.i(TAG, "Action failed");
      AlertDialogFragment f = AlertDialogFragment.getInstance(
          "Action Failed", exception.getMessage());
      f.show(getFragmentManager(), "alert");
      break;
    case ACTION_PERFORMED:
      Log.i(TAG, "Action succeeded");
      completeAction();
      gotoState(State.NORMAL);
      break;
    case PERFORM_ACTION:
      Log.i(TAG, "Performing action");
      runAction();
      break;
    }
  }

    private class CheckCardPresentTask extends AsyncTask<Tag, Void, TransmitResult> {
      private final String TAG = "CheckCardPresentTask";

    protected CheckCardPresentTask(Context context) {
      }

    @Override
    protected TransmitResult doInBackground(Tag... arg0) {
      IsoDep tag = IsoDep.get(arg0[0]);

      // Make sure time-out is long enough (10 seconds)
      tag.setTimeout(10000);

      IdemixService is = new IdemixService(new IsoDepCardService(tag));
      TransmitResult result = null;

      try {
        is.open();
        is.close();
        result = new TransmitResult(TransmitResult.Result.SUCCESS);
      } catch (CardServiceException e) {
        Log.e(TAG, "Unable to select idemix applet");
        e.printStackTrace();
        return new TransmitResult(e);
      } finally {
        try {
          tag.close();
        } catch (IOException e) {
          Log.e(TAG, "Failed to close tag connection");
          e.printStackTrace();
        }
      }

      return result;
    }

    @Override
    protected void onPostExecute(TransmitResult tresult) {
      switch(tresult.getResult()) {
      case FAILURE:
        gotoState(State.WAITING_FOR_CARD);
        Log.i(TAG, "Cannot connect to card, proceeding to waiting for card");
        break;
      case SUCCESS:
        gotoState(State.CONFIRM_ACTION);
        break;
      default:
        // Nothing to do?
        break;
      }
    }
    }

    private class TransmitAPDUsTask extends AsyncTask<Tag, Void, TransmitResult> {
      private final String TAG = "TransmitAPDUsTask";
      private CardProgram cardProgram;

    protected TransmitAPDUsTask(Context context, CardProgram cardProgram) {
        this.cardProgram = cardProgram;
      }

    @Override
    protected TransmitResult doInBackground(Tag... arg0) {
      IsoDep tag = IsoDep.get(arg0[0]);

      // Make sure time-out is long enough (10 seconds)
      tag.setTimeout(10000);

      IdemixService is = new IdemixService(new IsoDepCardService(tag));
      TransmitResult result = null;

      try {
        is.open();


        Log.i(TAG,"Performing requested actions now");
        result = cardProgram.run(is);
        is.close();
        Log.i(TAG, "Performed action succesfully!");
      } catch (Exception e) {
        Log.e(TAG, "Reading verification caused exception");
        e.printStackTrace();
        return new TransmitResult(e);
      } finally {
        try {
          tag.close();
        } catch (IOException e) {
          Log.e(TAG, "Failed to close tag connection");
          e.printStackTrace();
        }
      }

      return result;
    }

    @Override
    protected void onPostExecute(TransmitResult tresult) {
      switch(tresult.getResult()) {
      case SUCCESS:
        Log.i(TAG, "Complete succesfully, finishing task");
        gotoState(State.ACTION_PERFORMED);
        break;
      case FAILURE:
        Log.i(TAG, "Action failed, notifying user");
        exception = tresult.getException();
        gotoState(State.ACTION_FAILED);
        break;
      case INCORRECT_PIN:
        Log.i(TAG, "Pincode incorrect, notifying user");
        tries = tresult.getTries();
        if(tries > 0) {
          gotoState(State.CONFIRM_ACTION);
        } else {
          exception = new Exception("You have no more pin tries left, the card is now blocked");
          gotoState(State.ACTION_FAILED);
        }
      }
    }
    }

  @Override
  public void onConfirmDeleteOK() {
    gotoState(State.PERFORM_ACTION);
  }

  @Override
  public void onConfirmDeleteCancel() {
    gotoState(State.NORMAL);
    // If in twoPane mode return to detailed view upon cancel
    if(!mTwoPane) {
      onItemSelected(toBeDeleted.getId());
    }
  }

  public void onChangeCardPIN() {
    Log.i(TAG, "Change card PIN called");
    currentAction = Action.CHANGE_CARD_PIN;
    gotoState(State.TEST_CARD_PRESENCE);
  }

  public void onChangeCredPIN() {
    Log.i(TAG, "Change cred PIN called");
    currentAction = Action.CHANGE_CREDENTIAL_PIN;
    gotoState(State.TEST_CARD_PRESENCE);
  }

  public void runAction() {
    CardProgram program = null;

    switch (currentAction) {
    case DELETE_CREDENTIAL:
      program = new CardProgram() {
        @Override
        public TransmitResult run(IdemixService is) throws CardServiceException {
          is.sendCardPin(cardPin.getBytes());
          IdemixCredentials ic = new IdemixCredentials(is);
          ic.removeCredential(toBeDeleted);
          return new TransmitResult(TransmitResult.Result.SUCCESS);
        }
      };
      break;
    case CHANGE_CARD_PIN:
      program = new CardProgram() {
        @Override
        public TransmitResult run(IdemixService is) throws CardServiceException {
          int tries;
          tries = is.sendCardPin(old_pin.getBytes());

          // Only continu if Card Pin was correct initially
          if(tries == -1) {
            tries = is.updateCardPin(old_pin.getBytes(), new_pin.getBytes());
          }

          if (tries == -1) {
            return new TransmitResult(TransmitResult.Result.SUCCESS);
          } else {
            return new TransmitResult(tries);
          }
        }
      };
      break;
    case CHANGE_CREDENTIAL_PIN:
      program = new CardProgram() {
        @Override
        public TransmitResult run(IdemixService is) throws CardServiceException {
          is.sendCardPin(cardPin.getBytes());
          int tries = is.updateCredentialPin(new_pin.getBytes());
          if (tries == -1) {
            return new TransmitResult(TransmitResult.Result.SUCCESS);
          } else {
            return new TransmitResult(tries);
          }
        }
      };
      break;
    default:
      // Nothing to do?
      break;
    }
    new TransmitAPDUsTask(this, program).execute(tag);
  }

  public void completeAction() {
    // This is run after action completes succesfully
    switch (currentAction) {
    case DELETE_CREDENTIAL:
      Log.i("CLA:completeAction", "Removing item from list");

      // Find deleted package
      int deletedIdx = -1;
      for(int i = 0 ; i <  credentials.size(); i++) {
        CredentialPackage cp = credentials.get(i);
        System.out.println("Examining credential: " + cp.toString());
        if(cp.getCredentialDescription().getId() == toBeDeleted.getId()) {
          deletedIdx = i;
        }
      }

      if(deletedIdx == -1) {
        Log.i("CLA:completeAction", "Failed to locate credential");
      } else {
        credentials.remove(deletedIdx);
      }

      if(mTwoPane) {
        if(credentials.size() > 0) {
          int new_idx = deletedIdx > 0 ? deletedIdx - 1 : 0;
          ((MenuFragment) getSupportFragmentManager()
              .findFragmentById(R.id.credential_menu_fragment)).simulateListClick(new_idx);
        } else {
          InitFragment initFragment = new InitFragment();
          getSupportFragmentManager().beginTransaction()
              .replace(R.id.credential_detail_container, initFragment)
              .commit();
        }
      } else {
        ((MenuFragment) getSupportFragmentManager()
            .findFragmentById(R.id.credential_menu_fragment)).updateList();
      }
      break;
    case CHANGE_CARD_PIN:
      // We need to cache the new PIN now
      cardPin = new_pin;

      // Return to settings in single-pane mode
      if(!mTwoPane)
        onSettingsSelected();
      break;
    case CHANGE_CREDENTIAL_PIN:
      if(!mTwoPane)
        onSettingsSelected();
      break;
    default:
      // Nothing to do?
    }
  }

  public void onDeleteCredential(CredentialDescription cd) {
    Log.i("blaat", "Delete credential called");
    toBeDeleted = cd;
    currentAction = Action.DELETE_CREDENTIAL;
    Log.i("blaat", "Will delete: " + cd.toString());

    gotoState(State.TEST_CARD_PRESENCE);
  }

  @Override
  public void onAlertDismiss() {
    // Returning to normal state
    gotoState(State.NORMAL);
  }
}




Java Source Code List

org.irmacard.androidmanagement.CredentialDetailActivity.java
org.irmacard.androidmanagement.CredentialDetailFragment.java
org.irmacard.androidmanagement.CredentialListActivity.java
org.irmacard.androidmanagement.InitFragment.java
org.irmacard.androidmanagement.LogActivity.java
org.irmacard.androidmanagement.LogFragment.java
org.irmacard.androidmanagement.MenuFragment.java
org.irmacard.androidmanagement.SettingsActivity.java
org.irmacard.androidmanagement.SettingsFragment.java
org.irmacard.androidmanagement.WaitingForCardActivity.java
org.irmacard.androidmanagement.adapters.CredentialAttributeAdapter.java
org.irmacard.androidmanagement.adapters.CredentialListAdapter.java
org.irmacard.androidmanagement.adapters.LogListAdapter.java
org.irmacard.androidmanagement.dialogs.AlertDialogFragment.java
org.irmacard.androidmanagement.dialogs.CardMissingDialogFragment.java
org.irmacard.androidmanagement.dialogs.ChangePinDialogFragment.java
org.irmacard.androidmanagement.dialogs.ConfirmDeleteDialogFragment.java
org.irmacard.androidmanagement.util.TransmitResult.java