BroadcastReceiver doesn't receive the broadcasted intent in the right time(Receiver's onReceive is being late to be called)

走远了吗. 提交于 2019-12-13 18:22:57

问题


I have 2 different android applications.

  1. Sender Application
  2. Receiver Application

Sender Application has:

  1. a method : callMethodA() , and it's been called in a random time. Everytime callMethodA() is executed, I catch it in before advice in my aspect and send a String "a" to Receiver App. with Intent (with sendBroadcast). And in around advice, I want to wait a result from the Receiver App and taking an action to the callMethodA() method like cancelling its execution(by returning null) or proceed its execution.

Receiver Application is doing :

  1. receiving the String coming from Sender App by BroadcastReceiver.
  2. according to received String, it sends this string to an Automaton. And after automaton finishes its process, it's immediately broadcasts the result to Sender App.

But my problem here is, I cannot receive the 1st result in the Sender App's aspect( it has to be catched by BroadcastReceiver in the Aspect of Sender App. then in the around advice, callMethodA() is being cancelled or proceeded.). So because of I cannot receive the 1st result in time, every action taken by around advice is slipping. Like let's say:

  • callMethodA() is called for the 1st time, then aspect sent a string to the receiver, in this moment around advice doesn't wait for the result and just takes action according to NULL value.
  • Then callMethodA() is called for the 2nd time, in that moment, aspect received the result from the receiver but the result is belong to 1st call actually!!

So I'm always missing the 1st result for 1st call of callMethodA() and so the actions are slipping.

For simplified version of the question, please refer to : Can we call an external method between before and around advices? (For the same pointcut)

Here's my code :

Receiver APP

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;
    }

}

Sender App

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;
    }


}

ReceiverLOG :

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

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

...

SenderLOG:

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...
---------------------

...

来源:https://stackoverflow.com/questions/22862310/broadcastreceiver-doesnt-receive-the-broadcasted-intent-in-the-right-timerecei

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!