第6章 Android SDK版本与兼容
有关SDK中的各个版本
SDK最低版本
以最低版本设置值为标准,操作系统将会拒绝将应用安装在系统版本低于标准的设备上。
SDK目标版本
指应用是为哪个API级别设计的。大多数情况下,目标版本即最新发布的Android版本。
降低SDK目标版本可以保证即使在高于目标版本的设备上,应用仍可以正常运行,且运行行为仍和目标版本保持一致。
SDK编译版本
编译版本是在你开发时Android Studio寻找类包导入语句中的类和方法时,编译目标确定的具体的基准系统版本。即编译版本是开发时假想的设备的版本,因此最佳选择是最新的API级别。
SDK编译版本是开发者和编译器之间享有的信息,等开发完成后这个假想的设备就不存在了,所以SDK版本不会被通知给操作系统。
有关安全添加新版本API中的代码
在低版本中添加高版本的特有代码会报错。
首先需要按下CTRL+enter添加对应的类包。
两种解决方法:可以先检查设备的编译版本。
也可以注释这一段代码用高版本的API开发。
有关挑战练习
报告编译版本
找到了一些设置文本内容的方法的文档:
setText()
append()
这里只要用setText()就可以了,要想使用append()需要先setText(null)。
private CharSequence mCompile;
mCompile="API Level "+Build.VERSION.SDK_INT;
mAPILevelTextView.setText(mCompile);
限制作弊次数
这个问题我先前是想直接在主activity里设置一个静态全局变量,然后子activity直接调用就可以了。
//QuizActivity
public static int mCheatNum=3;
//CheatActivity
QuizActivity.mCheatNum--;
CharSequence mCheatTip;
mCheatTip="还剩"+QuizActivity.mCheatNum+"次作弊机会"; Toast.makeText(CheatActivity.this,mCheatTip,Toast.LENGTH_SHORT).show();
不过这样似乎使得两个类之间,耦合度变高,不是很好。所以还是传参数吧。
在换成传参数的方法之前,我需要记录一下我的发现:设置为全局静态的成员变量,在旋转屏幕前后,即便没有将这个成员变量保存在Bundle中,其值不会被清空。我想是因为只要这个activity被创建过了,这个静态的变量就一直存在于内存空间中,直到这个应用彻底被系统从内存中摧毁。原理可能和Bundle一样,不过我总感觉不稳,所以还是老老实实存Bundle里面吧。
首先需要修改newIntent()方法和setAnswerShownResult()方法,将剩余作弊机会加入参数。
public static Intent newIntent(Context packageContext, boolean answerIsTrue,int CheatChance)
{
Intent intent=new Intent(packageContext,CheatActivity.class);
intent.putExtra(EXTRA_ANSWER_IS_TRUE,answerIsTrue);
intent.putExtra(EXTRA_CHEAT_CHANCE,CheatChance);
return intent;
}
private void setAnswerShownResult(boolean isAnswerShown,int mCheatChance)
{
Intent data=new Intent();
data.putExtra(EXTRA_ANSWER_SHOWN,isAnswerShown);
data.putExtra(EXTRA_CHEATED_CHANCE,mCheatChance);
setResult(RESULT_OK,data);
}
新增一个需要在主activity中得到剩余可用作弊机会的方法。
public static int returnCheatChance(Intent result)
{
return result.getIntExtra(EXTRA_CHEATED_CHANCE,0);
}
修改在主activity中得到传递的信息的方法。
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data)
{
if (resultCode!=RESULT_OK)
{
return;
}
if (requestCode==REQUEST_CODE_CHEAT)
{
if (data==null)
{
return;
}
mIsCheater=CheatActivity.wasAnswerShown(data);
mCheatChance=CheatActivity.returnCheatChance(data);
mQuestionBank[mCurrentIndex].setCheated(mIsCheater);
updateQuestion();
}
}
禁用作弊按钮和显示剩余可作弊次数都在updateQuestion()方法中使用。
private void updateQuestion()
{
//...
if (mCheatChance==0)
{
mCheatButton.setEnabled(false);
}
else
{
mCheatButton.setEnabled(true);
}
//...
CharSequence mChanceTip;
mChanceTip="Cheat Chance:"+mCheatChance;
mCheatChancetextview.setText(mChanceTip);
}
会出现从子activity返回时,如果已经作弊了cheatchance不能及时更新的问题。需要在从子activity中返回时就调用一次updateQuestion()方法。
protected void onActivityResult(int requestCode,int resultCode,Intent data)
{
if (resultCode!=RESULT_OK)
{
return;
}
if (requestCode==REQUEST_CODE_CHEAT)
{
if (data==null)
{
return;
}
mIsCheater=CheatActivity.wasAnswerShown(data);
mCheatChance=CheatActivity.returnCheatChance(data);
mQuestionBank[mCurrentIndex].setCheated(mIsCheater);
updateQuestion();
}
}
有关在旋转前后存储数据的同前几次。
之后发现有一个bug,就是在子activity中一直点击显示答案,剩余作弊次数会变成负的。还好这个不是很复杂,只需要在查看答案的监听器里面加一个判断剩余可以作弊的次数的语句,如果不能作弊就把这个按钮禁用掉。
mShowAnswerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//..
mCheatChance--;
if (mCheatChance==0)
{
mShowAnswerButton.setEnabled(false);
}
//..
}
});
感觉自己写的好长啊。。