У меня есть 2 разных приложения для Android.
- Приложение отправителя
- Приложение-приемник
Приложение-отправитель имеет:
- метод :
callMethodA()
, и он был вызван в случайное время. Каждый раз, когда выполняетсяcallMethodA()
, я улавливаю его перед советом в моем аспекте и отправляю строку «a» в приложение Receiver. с намерением (с помощью sendBroadcast). И по совету, я хочу дождаться результата от приложения-приемника и выполнить действие с методомcallMethodA()
, например отменить его выполнение (путем возвратаnull
) или продолжить его выполнение.
Приложение Receiver делает:
- получение строки из приложения-отправителя с помощью BroadcastReceiver.
- в соответствии с полученной строкой он отправляет эту строку автомату. И после того, как автомат завершит свой процесс, он сразу же транслирует результат в 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...
---------------------
...