作弊者是注定会失败的。当然,如果他们能一直避开反作弊手段,那就另当别论了。正所谓 道高一尺,魔高一丈,也许他们能做到。 GeoQuiz应用有些大漏洞,你的任务就是堵住它们。从易到难,以下为待解决的三个漏洞。
用户作弊后,可以旋转CheatActivity来清除作弊痕迹。
CheatActivity中添加:
public class CheatActivity extends AppCompatActivity {
//漏洞1
private boolean mIsShowAnswer;
private static final String bug1 = "bug1";
}
@Override
protected void onSaveInstanceState(Bundle saveInstanceState){
super.onSaveInstanceState(saveInstanceState);
saveInstanceState.putBoolean(bug1, mIsShowAnswer);
}
public class CheatActivity extends AppCompatActivity {
if (savedInstanceState != null){
mIsShowAnswer = savedInstanceState.getBoolean(bug1, false);
if (mIsShowAnswer){
setAnswerShownResult(mIsShowAnswer);
}
}
}
可能多次调用setResult(int resultCode, Intent data)(竖屏时点击cheat-showanswer,这里调用一次setResult函数,然后旋转屏幕,点击后退键,这里又调用一次setResult函数),简单的测试似乎没有什么问题?
作弊返回后,用户可以旋转QuizActivity来清除mIsCheater变量值。
QuizActivity中添加:
private boolean mIsCheater = false;
//漏洞2
private static final String bug2 = "bug2";
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate(Bundle) called");
setContentView(R.layout.activity_quiz);
if (savedInstanceState != null){
mCurrentIndex = savedInstanceState.getInt(KEY_INDEX, 0);
mIsCheater = savedInstanceState.getBoolean(bug2, false);
}
mShowAnswerButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
if (mAnswerIsTrue)
mAnswerTextView.setText(R.string.true_button);
else
mAnswerTextView.setText(R.string.false_button);
mIsShowAnswer = true;
setAnswerShownResult(true);
}
});
}
@Override
protected void onSaveInstanceState(Bundle saveInstanceState){
super.onSaveInstanceState(saveInstanceState);
Log.i(TAG, "onSaveInstanceState");
saveInstanceState.putInt(KEY_INDEX, mCurrentIndex);
saveInstanceState.putBoolean(bug2, mIsCheater);
}
用户可以不断单击NEXT按钮,跳到偷看过答案的问题,从而使作弊纪录丢失。 祝好运!
这里保留堵住漏洞1的代码,在此基础上添加代码
在QuizActivity中添加:
public class QuizActivity extends AppCompatActivity {
//漏洞3
private boolean[] mIsCheater = new boolean[mQuestionBank.length];
private static final String bug3 = "bug3";
}
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate(Bundle) called");
setContentView(R.layout.activity_quiz);
for (int i = 0; i < mQuestionBank.length; i++)
mIsCheater[i] = false;
if (savedInstanceState != null){
mCurrentIndex = savedInstanceState.getInt(KEY_INDEX, 0);
mIsCheater = savedInstanceState.getBooleanArray(bug3);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if (resultCode != Activity.RESULT_OK){
return;
}
if (requestCode == REQUEST_CODE_CHEAT){
if (data == null){
return;
}
mIsCheater[mCurrentIndex] = CheatActivity.wasAnswerShown(data);
}
}
private void checkAnswer(boolean userPressedTrue) {
boolean answerIsTrue = mQuestionBank[mCurrentIndex].isAnswerTrue();
int messageResId = 0;
mQuestionBank[mCurrentIndex].setAnswered(1);
if (mIsCheater[mCurrentIndex]) {
messageResId = R.string.judgment_toast;
} else {
if (userPressedTrue == answerIsTrue) {
messageResId = R.string.correct_toast;
} else {
messageResId = R.string.incorrect_toast;
}
}
Toast.makeText(this, messageResId, Toast.LENGTH_SHORT).show();
}
@Override
protected void onSaveInstanceState(Bundle saveInstanceState){
super.onSaveInstanceState(saveInstanceState);
Log.i(TAG, "onSaveInstanceState");
saveInstanceState.putInt(KEY_INDEX, mCurrentIndex);
saveInstanceState.putBooleanArray(bug3, mIsCheater);
}