我有 2 个不同的 android 应用程序。
- 发件人申请
- 接收机申请
发件人应用程序具有:
- 一个方法 :
callMethodA()
,它是在随机时间内被调用的。每次callMethodA()
执行时,我都会在我的方面提出建议,然后将字符串“a”发送到 Receiver App。带有意图(带有 sendBroadcast)。在周围的建议中,我想等待接收器应用程序的结果并对callMethodA()
方法采取行动,例如取消其执行(通过返回null
)或继续执行。
接收器应用程序正在做:
- 通过 BroadcastReceiver 接收来自 Sender App 的字符串。
- 根据收到的字符串,它将这个字符串发送给自动机。自动机完成其过程后,它会立即将结果广播给 Sender App。
但我的问题是,我无法在 Sender App 的方面收到第一个结果(它必须由 BroadcastReceiver 在 Sender App 的方面捕获。然后在周围的建议中,callMethodA()
正在被取消或继续。)。所以由于我不能及时收到第一个结果,周围建议采取的每一个行动都在下滑。就像我们说:
callMethodA()
第一次被调用,然后方面向接收者发送一个字符串,此时周围的建议不等待结果,只是根据 NULL 值采取行动。- 然后
callMethodA()
是第2次调用,那一刻,aspect收到了receiver的结果但是结果却是第一次调用的!!
所以我总是错过第一次调用的第一个结果,callMethodA()
所以动作正在下滑。
有关问题的简化版本,请参阅: 我们可以在 before 和 around 建议之间调用外部方法吗?(对于相同的切入点)
这是我的代码:
接收端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;
}
}
发件人应用
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;
}
}
测试.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...
---------------------
...