I'm working on NFC and currently try to write code for the Open Mobile API built into Android 9.0, but don't understand the way to pass the Executor parameter in SEService.
public class MainActivity extends Activity implements SEService.OnConnectedListener {
final String LOG_TAG = "NfcTest";
private SEService seService;
private Button button;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setLayoutParams(new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
button = new Button(this);
button.setLayoutParams(new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
button.setText("Click Me");
button.setEnabled(false);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
try {
Reader[] readers = seService.getReaders();
if (readers.length < 1)
return;
Session session = readers[0].openSession();
Channel channel = session.openLogicalChannel(new byte[]{
(byte) 0xF0, 0x51, (byte) 0xBC, 0x53, 0x54, 0x69, 0x64,
(byte) 0x4D, 0x6F, 0x62, 0x69, (byte) 0x6C,
(byte) 0x65, 0x2D, (byte) 0x49, 0x44});
byte[] respApdu = channel.transmit(new byte[]{
(byte) 0x90, 0x10, 0x00, 0x00, 0x00});
channel.close();
// Parse response APDU and show text but remove SW1 SW2 first
byte[] helloStr = new byte[respApdu.length - 2];
System.arraycopy(respApdu, 0, helloStr, 0, respApdu.length - 2);
Toast.makeText(MainActivity.this, new String(helloStr), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.i(LOG_TAG, "Message: " + e.getClass().getCanonicalName());
if(e.getClass().isInstance(new NoSuchElementException()))
Toast.makeText(MainActivity.this, "NFC sim", Toast.LENGTH_LONG).show();
else if (e.getClass().isInstance(new IOException())){
Toast.makeText(MainActivity.this, "No sim found", Toast.LENGTH_LONG).show();
}
else{
Toast.makeText(MainActivity.this, "Normal sim", Toast.LENGTH_LONG).show();
}
}
}
});
layout.addView(button);
setContentView(layout);
try {
seService = new SEService(this, this,this);
} catch (SecurityException e) {
Log.e(LOG_TAG, "Binding not allowed, uses-permission org.simalliance.openmobileapi.SMARTCARD?");
} catch (Exception e) {
Log.e(LOG_TAG, "Exception: " + e.getMessage());
}
}
@Override
protected void onDestroy() {
if (seService != null && seService.isConnected()) {
seService.shutdown();
}
super.onDestroy();
}
public void serviceConnected(SEService service) {
Log.i(LOG_TAG, "seviceConnected()");
button.setEnabled(true);
}
@Override
public void onConnected() {
}
}
Problem occurs on:
seService = new SEService(this, this,this);
First and last parameter accepted the middle one executer appears error!
java.util.concurrent.Executor this
How to pass this?
You get this error because the second aregument of the constructor SEService
must be a java.util.concurrent.Executor
. You MainActivity (this
object) does not implement an executor.
THis executor is used by the SEService to invoke callback methods. So you have to create such an executor yourself in order to pass it to SEService
. YOu could, for instance, simply create an ExecutorService
with a single worker thread to handle the callbacks:
ExecutorService pool = Executors.newSingleThreadExecutor();
seService = new SEService(this, pool, this);
Be aware though, that these callbacks are then executed on a worker thread (not the main thread of your app). Consequently, if you want to perform any UI operations from within the callbacks, you will need to explicitly run them on the UI thread, e.g.
runOnUiThread(new Runnable() {
void run() {
button.setEnabled(true); // ... or some other UI modifications
}
});