Как использовать Executor в SEservice (Open Mobile API для Android 9.0) - PullRequest
0 голосов
/ 13 декабря 2018

Я работаю над NFC и в настоящее время пытаюсь написать код для Open Mobile API, встроенного в Android 9.0, но не понимаю, как передать параметр Executor в 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() {

    }
}

Проблемапроисходит:

seService = new SEService(this, this,this);

При первом и последнем принятом параметре в среднем исполнителе появляется ошибка!

java.util.concurrent.Executor this

Как пройти это?

1 Ответ

0 голосов
/ 13 декабря 2018

Вы получаете эту ошибку, потому что второй аргумент конструктора SEService должен быть java.util.concurrent.Executor.Вы MainActivity (this объект) не реализует исполнителя.

Этот исполнитель используется SEService для вызова методов обратного вызова.Таким образом, вы должны создать такого исполнителя самостоятельно, чтобы передать его SEService.Вы можете, например, просто создать ExecutorService с одним рабочим потоком для обработки обратных вызовов:

ExecutorService pool = Executors.newSingleThreadExecutor();
seService = new SEService(this, pool, this);

Имейте в виду, что эти обратные вызовы затем выполняются в рабочем потоке (а не в основном потоке)вашего приложения).Следовательно, если вы хотите выполнить какие-либо операции пользовательского интерфейса из обратных вызовов, вам необходимо явно запустить их в потоке пользовательского интерфейса, например,

runOnUiThread(new Runnable() {
    void run() {
        button.setEnabled(true); // ... or some other UI modifications
    }
});
...