BroadcastReceiver не получает переданное намерение в нужное время (вызов onReceive Receiver опаздывает)

У меня есть 2 разных приложения для Android.

  1. Приложение отправителя
  2. Приложение-приемник

Приложение-отправитель имеет:

  1. метод : callMethodA() , и он был вызван в случайное время. Каждый раз, когда выполняется callMethodA(), я улавливаю его перед советом в моем аспекте и отправляю строку «a» в приложение Receiver. с намерением (с помощью sendBroadcast). И по совету, я хочу дождаться результата от приложения-приемника и выполнить действие с методом callMethodA(), например отменить его выполнение (путем возврата null) или продолжить его выполнение.

Приложение Receiver делает:

  1. получение строки из приложения-отправителя с помощью BroadcastReceiver.
  2. в соответствии с полученной строкой он отправляет эту строку автомату. И после того, как автомат завершит свой процесс, он сразу же транслирует результат в Sender App.

Но моя проблема в том, что я не могу получить 1-й результат в аспекте приложения-отправителя (он должен быть перехвачен BroadcastReceiver в аспекте приложения-отправителя. Затем в совете вокруг callMethodA() отменяется или продолжается.). Таким образом, из-за того, что я не могу получить 1-й результат вовремя, каждое действие, предпринятое по совету, проскальзывает. Как скажем:

  • callMethodA() вызывается в первый раз, затем аспект отправляет строку получателю, в этот момент окружной совет не ждет результата, а просто выполняет действие в соответствии со значением NULL.
  • Затем callMethodA() вызывается во второй раз, в этот момент аспект получил результат от получателя, но на самом деле результат принадлежит 1-му вызову!!

Поэтому я всегда пропускаю 1-й результат для 1-го вызова callMethodA(), и поэтому действия проскальзывают.

Упрощенную версию вопроса см. по адресу: Можем ли мы вызвать внешний метод между советами «до» и «вокруг»? (Для того же pointcut)

Вот мой код:

Приложение-приемник

ReceiverActivity.java
public class ReceiverActivity extends Activity {

    int state = 1;
    String automatonResult = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_receiver);
        registerReceiver(receiverResultsA, new IntentFilter("ResultsA"));
        registerReceiver(receiverResultsB, new IntentFilter("ResultsB"));

    }

    // Broadcast Receiver for the string "a" coming from Sender1.
    public BroadcastReceiver receiverResultsA = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Bundle bundle = intent.getExtras();
            if (bundle != null) {
                String sentStringA = bundle.getString("resultA");

                writeToFile("----------------------------------------------\n");
                writeToFile("Received  :  " + sentStringA);

                AutomatonAB(sentStringA);

            }
        }
    };

    public BroadcastReceiver receiverResultsB = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Bundle bundle = intent.getExtras();
            if (bundle != null) {
                String sentStringB = bundle.getString("resultB");

                writeToFile("----------------------------------------------\n");
                writeToFile("Received  :  " + sentStringB);

                AutomatonAB(sentStringB);

            }
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // unregisterReceiver(receiverResultsPackageNumber);
        unregisterReceiver(receiverResultsA);
        unregisterReceiver(receiverResultsB);
        writeToFile("exiting...\n\n\n");

    }

    // Automaton for checking the strings coming from the senders. In the end,
    // it broadcasts the result to the senders (FAIL or SUCCESS)
    public String AutomatonAB(String string_receivedString) {
        int int_convertedStringValue = 0;

        // to use Java version below than 1.7, 'cause string value
        // cannot be used on switch...
        if (string_receivedString.equals("a")) {
            int_convertedStringValue = 1;
        } else if (string_receivedString.equals("b")) {
            int_convertedStringValue = 2;

        } else {
            System.out.println("No input");
        }

        switch (int_convertedStringValue) {

        case 1:
            switch (state) {
            case 1:
                state = 2;
                writeToFile("Status : Passing from State 1 to State 2");
                // Status : Passing from State 1 to State 2 :
                automatonResult = "Success2";

                break;
            case 2:
                state = 3;
                writeToFile("Status : Passing from State2 to Failure State");
                // Status : Passing from State2 to Failure State :
                automatonResult = "FailureA";

                break;

            default:

                break;

            }

            break;

        case 2:
            switch (state) {
            case 1:
                state = 3;
                writeToFile("Status : Passing from State 1 to Failure State");
                // Status : Passing from State 1 to Failure State :
                automatonResult = "FailureB";
                break;

            case 2:
                state = 1;
                writeToFile("Status : Passing from State 2 to State 1");
                // Status : Passing from State 2 to State 1 :
                automatonResult = "Success1";
                break;
            default:
                break;
            }

            break;

        default:
            break;
        }

        writeToFile("Automaton Result : " + automatonResult + "\n");
        if (automatonResult.equals("Success2")
                || automatonResult.equals("FailureA")) {
            // Broadcast the automaton result to the senderA
            Intent intent = new Intent("intent_AutomatonResultA");
            intent.putExtra("automatonResult_Put_StringA", automatonResult);
            sendBroadcast(intent);
            // Broadcast the automaton result to the senderB
        } else if (automatonResult.equals("Success1")
                || automatonResult.equals("FailureB")) {
            Intent intent = new Intent("intent_AutomatonResultB");
            intent.putExtra("automatonResult_Put_StringB", automatonResult);
            sendBroadcast(intent);
        }
        // to make automaton keep going on the next turns.
        if (state == 3) {
            state = 1;
            writeToFile("Automaton is in Error State and closing...");
        }
        return automatonResult;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    public File writeToFile(String log_String) {

        File file = new File("/storage/extSdCard/ReceiverLog.txt");
        try {

            if (!file.exists()) {
                file.createNewFile();
            }
            FileWriter fw = new FileWriter(file.getAbsoluteFile(), true);
            BufferedWriter bw = new BufferedWriter(fw);

            bw.newLine();
            bw.append(log_String);
            bw.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }

}

Приложение отправителя

Sender1Activity.java

public class Sender1Activity extends Activity {
    Button btn_send;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_sender1);
        btn_send = (Button) findViewById(R.id.buttonSend);

    }



    // callMethodA() is called in the random time. It's just provides randomness
    public Handler methodCallerHandler = new Handler();
    public Runnable hMyValueTask = new Runnable() {
        public void run() {

            int n = new Random().nextInt(3000);
            callMethodA(new View(getApplicationContext()));
            methodCallerHandler.postDelayed(hMyValueTask, (long) n);

        }
    };

    // The actual method who starts everything, it does simply nothing for now.
    public String callMethodA(View v) {

        String string = "String";
        return string;


    }

    public void startCallMethodA(View v){

        methodCallerHandler.removeCallbacks(hMyValueTask);
        methodCallerHandler.post(hMyValueTask);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public void onDestroy() {
//      unregisterReceiver(broadcastReceiver_AutomatonResult);
    }

    public File writeToFile(String log_String) {

        File file = new File("/storage/extSdCard/Sender1Log.txt");
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            FileWriter fw = new FileWriter(file.getAbsoluteFile(), true);
            BufferedWriter bw = new BufferedWriter(fw);

            bw.newLine();
            bw.append(log_String);
            bw.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }

}

Test.aj

public aspect Test {
    String GRANT;
    int i=1;
    int y=1;
    int z=1;
    BroadcastReceiver broadcastReceiver_AutomatonResult = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            writeToFile("a Broadcast has been received..." + " : " + z );
            Bundle bundle = intent.getExtras();
            if (bundle != null) {
                GRANT = bundle.getString("automatonResult_Put_StringA");
            }
        z++;
        }
    };

    pointcut pointcut_onCreate(Activity activity) : execution(void onCreate(..)) && target(activity);

    // pointcut for the callMethodA() execution.
    pointcut pointcut_CatchMethod(Activity activity) :  execution(String callMethodA(*))
     && target(activity);

    pointcut pointcut_onDestroy(Activity activity) : execution(void onDestroy()) && target(activity);


    //Registering the receiver when onCreate() executed.
    void around(Activity activity) : pointcut_onCreate(activity) {
        writeToFile("onCreate catched...\n");
        writeToFile("BroadcastReceiver is registering...");
        activity.registerReceiver(broadcastReceiver_AutomatonResult,
                new IntentFilter("intent_AutomatonResultA"));
        proceed(activity);
    }


    //Unregistering the broadcastreceiver when onDestroy called in the activity.
    void around(Activity activity) : pointcut_onDestroy(activity){
        writeToFile("onDestroy, BroadcastReceiver is unregistering..");
        activity.unregisterReceiver(broadcastReceiver_AutomatonResult);
        writeToFile("Exiting from the Application");
        proceed(activity);
    }

    //send string "a" to Receiver App, everytime before 'callMethodA()' is executed in the activity.
    before(Activity activity) : pointcut_CatchMethod(activity){
        writeToFile("Sending string 'a' with an Intent : " + i);

        Intent intent = new Intent("ResultsA");
        intent.putExtra("resultA", "a");
        activity.sendBroadcast(intent);

        writeToFile("String 'a' has been sent");
        i++;
    }

    //around callMethodA() is executed, we are taken actions according to the  
    //GRANT value which has returned by Broadcast from Receiver App.
    String around(Activity activity) : pointcut_CatchMethod(activity){

        writeToFile("GRANT value is : " + GRANT + " in around advice : " + y);

        //Actual problem is here!!, for the first value for GRANT has not been received from  
        //the receiver App. So GRANT value is null. In other words, onReceive method of BroadcastReceiver
        //has not been called yet!!. So I'm giving a simple string value for GRANT to avoid my program to
        //throw nullpointerexception.
        if(GRANT == null){
            GRANT ="null";
        }

        // if GRANT==FailureA, then manipulate callMethodA() to return null. 
        // i.e. Cancelling the method to be executed
        if (GRANT.equals("FailureA")) {
            writeToFile("Automaton failed, Returning NULL : " + y);
            writeToFile("callMethodA() cancelled...");
            writeToFile("---------------------\n\n");
            y++;

            return null;

        } else if (GRANT.equals("null")) {
            writeToFile("Automaton result seems to be null : " + y);
            writeToFile("callMethodA() cancelled...");
            writeToFile("---------------------\n\n");
            y++;

            return null;
        }

        //Else, it means that GRANT = Success2 and we'are proceeding and let callMethodA() to continue. 
        writeToFile("Automaton succeeded, Proceeding : " + y);
        writeToFile("callMethodA() executing...");

        String s = proceed(activity);

        writeToFile("Return String :  " + s);
        writeToFile("---------------------\n\n");
        y++;

        return s;

    }



    public File writeToFile(String log_String) {

        File file = new File("/storage/extSdCard/Sender1Log.txt");

        try {

            if (!file.exists()) {
                file.createNewFile();
            }

            FileWriter fw = new FileWriter(file.getAbsoluteFile(), true);
            BufferedWriter bw = new BufferedWriter(fw);

            bw.newLine();
            bw.append(log_String);
            bw.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }


}

Журнал приемника:

----------------------------------------------

Received  :  a
Status : Passing from State 1 to State 2
Automaton Result : Success2

----------------------------------------------

Received  :  a
Status : Passing from State2 to Failure State
Automaton Result : FailureA

Automaton is in Error State and closing...
----------------------------------------------

Received  :  a
Status : Passing from State 1 to State 2
Automaton Result : Success2

----------------------------------------------

Received  :  a
Status : Passing from State2 to Failure State
Automaton Result : FailureA

Automaton is in Error State and closing...
----------------------------------------------

Received  :  a
Status : Passing from State 1 to State 2
Automaton Result : Success2

----------------------------------------------

Received  :  a
Status : Passing from State2 to Failure State
Automaton Result : FailureA

Automaton is in Error State and closing...
----------------------------------------------

Received  :  a
Status : Passing from State 1 to State 2
Automaton Result : Success2

...

ЛОГ отправителя:

onCreate catched...

BroadcastReceiver is registering...
Sending string 'a' with an Intent : 1
String 'a' has been sent
GRANT value is : null in around advice : 1
Automaton result seems to be null : 1
callMethodA() cancelled...
---------------------


a Broadcast has been received... : 1
Sending string 'a' with an Intent : 2
String 'a' has been sent
GRANT value is : Success2 in around advice : 2
Automaton succeeded, Proceeding : 2
callMethodA() executing...
Return String :  String
---------------------


a Broadcast has been received... : 2
Sending string 'a' with an Intent : 3
String 'a' has been sent
GRANT value is : FailureA in around advice : 3
Automaton failed, Returning NULL : 3
callMethodA() cancelled...
---------------------


a Broadcast has been received... : 3
Sending string 'a' with an Intent : 4
String 'a' has been sent
GRANT value is : Success2 in around advice : 4
Automaton succeeded, Proceeding : 4
callMethodA() executing...
Return String :  String
---------------------


a Broadcast has been received... : 4
Sending string 'a' with an Intent : 5
String 'a' has been sent
GRANT value is : FailureA in around advice : 5
Automaton failed, Returning NULL : 5
callMethodA() cancelled...
---------------------


a Broadcast has been received... : 5
Sending string 'a' with an Intent : 6
String 'a' has been sent
GRANT value is : Success2 in around advice : 6
Automaton succeeded, Proceeding : 6
callMethodA() executing...
Return String :  String
---------------------


a Broadcast has been received... : 6
Sending string 'a' with an Intent : 7
String 'a' has been sent
GRANT value is : FailureA in around advice : 7
Automaton failed, Returning NULL : 7
callMethodA() cancelled...
---------------------

...

person Adnan Bal    schedule 04.04.2014    source источник
comment
Я думаю, что моя проблема связана с: - Нет четкого различия между советами до и вокруг. Другими словами, на вызов onReceive() нет времени, поэтому значение GRANT изменить нельзя. Так что это ноль в первый раз. - Итак, теперь есть ли способ вызвать внешний метод (в этом примере получение трансляции с помощью onReceive() ) между советами до и после, или я открыт для новых способов решения проблемы.   -  person Adnan Bal    schedule 07.04.2014
comment
Для решения обратитесь к: stackoverflow.com/questions/23043441/   -  person Adnan Bal    schedule 15.04.2014