MailCore / mailcore2

MailCore 2 provide a simple and asynchronous API to work with e-mail protocols IMAP, POP and SMTP. The API has been redesigned from ground up.
Other
2.6k stars 623 forks source link

Android> Can't run mailcore operations on thread other than main thread #1891

Open Sumit-Chakole opened 3 years ago

Sumit-Chakole commented 3 years ago

Similar to- https://github.com/MailCore/mailcore2/issues/1561, that question is also not satisfactory answer

We have developed an android app that uses the lib for fetching all the emails from a given mailbox. It works perfectly fine except it blocks the UI till the mails are getting downloaded. So we are trying to run it on a separate thread to keep the main thread responsive.

However, whenever we run it on the main thread, we are getting crash following crash- A/libc: Fatal signal 7 (SIGBUS), code 1 (BUS_ADRALN), fault addr 0x710070f080e01 in tid 11517 (com.xxx), pid 11517 (com.xxx)

App code here-

MailSyncService (Android Service) onStartCommand method-

mailClient.initIMAPSession(credential, new MailClient.Listener() {
                @Override
                public void resolve(WritableMap result) {
                    Log.d("zzzzzzz", "startMailSync: ");
                     new Thread(() -> {
                        WritableNativeMap obj = new WritableNativeMap();
                        obj.putString("folder", "INBOX");
                        int FLAGS = 1;
                        int HEADERS = 2;
                        int STRUCTURE = 4;
                        int INTERNAL_DATE = 8;
                        int HEADER_SUBJECT = 32;
                        int EXTRA_HEADERS = 512;

                        int REQUEST_PARAMS =
                                // eslint-disable-next-line no-bitwise
                                HEADERS | STRUCTURE | INTERNAL_DATE | HEADER_SUBJECT | FLAGS | EXTRA_HEADERS;
                        obj.putInt("requestKind", REQUEST_PARAMS);
                        mailClient.getMails(obj);
                     }).start();
                }

                @Override
                public void reject(String s, String message) {
                    Log.e("zzzzzzz", "startMailSync: " + message);
                }
            });

MailClient Class

public void getMails(final ReadableMap obj) {
        final String folder = obj.getString("folder");
        final int requestKind = obj.getInt("requestKind");
        final int lastId;
        if (obj.hasKey("lastId"))
            lastId = obj.getInt("lastId");
        else lastId = 1;
        final int limit;
        if (obj.hasKey("limit")) limit = obj.getInt("limit");
        else limit = 5000;

        final IndexSet indexSet = IndexSet.indexSetWithRange(new Range(lastId, limit));
        final IMAPFetchMessagesOperation messagesOperation = imapSession.fetchMessagesByUIDOperation(folder, requestKind,
                indexSet);

        final WritableMap result = Arguments.createMap();
        final WritableArray mails = Arguments.createArray();
        messagesOperation.start(new OperationCallback() {
            @Override
            public void succeeded() {
                // Return results
            }

            @Override
            public void failed(final MailException e) {
                Log.e("zzzzzz", "failed: " + e.errorCode() + " " + e.getMessage());
            }
        });
    }
Sumit-Chakole commented 3 years ago

Any help on this?

dinhvh commented 3 years ago

Could you show me a trace that shows that it's blocking the main thread when you download the list of emails?

Sumit-Chakole commented 3 years ago

@dinhvh Thanks for replying 👍 UI goes too slow when mailcore is downloading emails. We have built a react native app that connects with the native layers where mailcore is implemented. UI built on react native goes pretty unresponsive to clicks or scroll actions of users.

Trace as requested by you are here- W/InputEventReceiver: Slow Input: took 132ms in dispatching, now at finishInputEvent (MotionEvent: event_seq=417, seq=150436, action=ACTION_DOWN)

PrantikMondal commented 3 years ago

Similar to- #1561, that question is also not satisfactory answer

We have developed an android app that uses the lib for fetching all the emails from a given mailbox. It works perfectly fine except it blocks the UI till the mails are getting downloaded. So we are trying to run it on a separate thread to keep the main thread responsive.

However, whenever we run it on the main thread, we are getting crash following crash- A/libc: Fatal signal 7 (SIGBUS), code 1 (BUS_ADRALN), fault addr 0x710070f080e01 in tid 11517 (com.xxx), pid 11517 (com.xxx)

App code here-

MailSyncService (Android Service) onStartCommand method-

mailClient.initIMAPSession(credential, new MailClient.Listener() {
                @Override
                public void resolve(WritableMap result) {
                    Log.d("zzzzzzz", "startMailSync: ");
                     new Thread(() -> {
                        WritableNativeMap obj = new WritableNativeMap();
                        obj.putString("folder", "INBOX");
                        int FLAGS = 1;
                        int HEADERS = 2;
                        int STRUCTURE = 4;
                        int INTERNAL_DATE = 8;
                        int HEADER_SUBJECT = 32;
                        int EXTRA_HEADERS = 512;

                        int REQUEST_PARAMS =
                                // eslint-disable-next-line no-bitwise
                                HEADERS | STRUCTURE | INTERNAL_DATE | HEADER_SUBJECT | FLAGS | EXTRA_HEADERS;
                        obj.putInt("requestKind", REQUEST_PARAMS);
                        mailClient.getMails(obj);
                     }).start();
                }

                @Override
                public void reject(String s, String message) {
                    Log.e("zzzzzzz", "startMailSync: " + message);
                }
            });

MailClient Class

public void getMails(final ReadableMap obj) {
        final String folder = obj.getString("folder");
        final int requestKind = obj.getInt("requestKind");
        final int lastId;
        if (obj.hasKey("lastId"))
            lastId = obj.getInt("lastId");
        else lastId = 1;
        final int limit;
        if (obj.hasKey("limit")) limit = obj.getInt("limit");
        else limit = 5000;

        final IndexSet indexSet = IndexSet.indexSetWithRange(new Range(lastId, limit));
        final IMAPFetchMessagesOperation messagesOperation = imapSession.fetchMessagesByUIDOperation(folder, requestKind,
                indexSet);

        final WritableMap result = Arguments.createMap();
        final WritableArray mails = Arguments.createArray();
        messagesOperation.start(new OperationCallback() {
            @Override
            public void succeeded() {
                // Return results
            }

            @Override
            public void failed(final MailException e) {
                Log.e("zzzzzz", "failed: " + e.errorCode() + " " + e.getMessage());
            }
        });
    }

How you made this setup for android? Can you share the idea? It would be great then.