Android程序运行分析——中等复杂程度的NTAG I2C Demo为例(五)
本文主要对NTAG I2C APP源代码中的一个重要Activity——AuthActivity的代码进行解析
前文已经提到,在showAuthDialogFlag为true且mAuthStatus这个变量不等于Disabled的前提下
跳转到 AuthActivity
(见https://blog.****.net/qq_24118527/article/details/82951201)
首先是7种认证状态的定义,使用的是枚举类型
然后密码的定义,同样使用的是枚举类型
OnCreate
下面这个图片里的代码我暂时没看明白
其中putExtra是通过intent传递数据的核心方法,而相对应的,getParcebleExtra是接收传递数据的核心方法
可以传递的内容包括八大基本类型/字符串以及实现了Serializable和Parceble接口的对象
就是这些
// Capture intent to check whether the operation should be automatically launch or not
mTag = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
if(mTag != null && Ntag_I2C_Demo.isTagPresent(mTag)) {
demo = new Ntag_I2C_Demo(mTag, this, MainActivity.getPassword(), MainActivity.getAuthStatus());
}
// Get the context reference
mContext = getApplicationContext();
// Add Foreground dispatcher
mAdapter = NfcAdapter.getDefaultAdapter(this);
pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
常规操作
在UI上更新一下认证状态
OnPause
OnPause这个方法在系统在准备启动或回复另外一个activity时调用,通常在这个方法中将一些消耗CPU的资源释放掉
OnResume
OnResume方法在Activity准备好和用户进行交互的时候调用
接下来这个常规操作,选择我的密码,更新UI,然后调用startDemo函数
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.authPWD1:
//passwd1Button.setBackgroundResource(R.drawable.btn_blue);// 不要修改颜色20180405
passwd2Button.setBackgroundColor(Color.BLACK);
passwd3Button.setBackgroundColor(Color.BLACK);
// Store the password for the auth
MainActivity.setPassword(Pwds.PWD1.getValue());
break;
case R.id.authPWD2:
passwd2Button.setBackgroundResource(R.drawable.btn_blue);
passwd1Button.setBackgroundColor(Color.BLACK);
passwd3Button.setBackgroundColor(Color.BLACK);
// Store the password for the auth
MainActivity.setPassword(Pwds.PWD2.getValue());
break;
case R.id.authPWD3:
passwd3Button.setBackgroundResource(R.drawable.btn_blue);
passwd1Button.setBackgroundColor(Color.BLACK);
passwd2Button.setBackgroundColor(Color.BLACK);
// Store the password for the auth
MainActivity.setPassword(Pwds.PWD3.getValue());
break;
default:
break;
}
startDemo(mTag);
}
startDemo
如果当前的认证状态是Authenticated,就调用demo.Auth方法
关于demo.Auth方法,已经在这篇文章里面写好了
https://blog.****.net/qq_24118527/article/details/82950545
再判断,若demo不为空且demo.isReady,则new一个authTask ,然后再执行之
isReady的实现在之前的文章中介绍过了,很简单
这个AuthTask是一个私有内部类,下一小节介绍
authTask
这是一个异步任务:
启动任务执行的输入参数:Intent
后台任务执行进度:Integer
后台计算结果:Boolean
OnPostExecute(Result result)在后台操作结束时会被调用,计算结果将作为参数传递到此方法中,直接将计算结果传递给UI组件,这个函数里取消显示dialog(可以先看下面两个函数的描述),然后还调用了这个authCompleted(success);
OnPreExecute()在execute函数被调用后立即执行,一般用来在执行任务之前对UI进行标记,这个方法是在UI线程中调用的
里面搞了一个progressDialog的对象,对象的名字就是dialog,Context当然是当前的AutuAcitivity,标题是Authenticating
显示内容是Authenticating against NTAG I2C Plus ...可以取消
doInBackground就是一个认证的过程了,就是demo.Auth,这个不细说了,之前已经写过了
authCompleted
这个函数的实现如下图所示
public void authCompleted(boolean success) {
if (success) {
// Update the status
if(MainActivity.getAuthStatus() == AuthStatus.Unprotected.getValue()) {
MainActivity.setAuthStatus(AuthStatus.Authenticated.getValue());
Toast.makeText(mContext, "Tag Successfully protected", Toast.LENGTH_SHORT)
.show();
// Authenticate in order to let the user use the demos
demo.Auth(MainActivity.getPassword(), AuthStatus.Protected_RW.getValue());
} else if(MainActivity.getAuthStatus() == AuthStatus.Authenticated.getValue()) {
MainActivity.setAuthStatus(AuthStatus.Unprotected.getValue());
Toast.makeText(mContext, "Tag Successfully unprotected", Toast.LENGTH_SHORT)
.show();
} else if(MainActivity.getAuthStatus() == AuthStatus.Protected_RW.getValue()
|| MainActivity.getAuthStatus() == AuthStatus.Protected_W.getValue()
|| MainActivity.getAuthStatus() == AuthStatus.Protected_RW_SRAM.getValue()
|| MainActivity.getAuthStatus() == AuthStatus.Protected_W_SRAM.getValue()) {
MainActivity.setAuthStatus(AuthStatus.Authenticated.getValue());
/*Toast.makeText(mContext, "Successful authentication", Toast.LENGTH_SHORT)
.show();*/
}
updateAuthStatus(MainActivity.getAuthStatus());
// Prepare the result intent for the MainActivity
Intent resultIntent = new Intent();
setResult(Activity.RESULT_OK, resultIntent);
finish();
} else {
if(MainActivity.getAuthStatus() == AuthStatus.Unprotected.getValue()) {
Toast.makeText(mContext, "Error protecting tag",
Toast.LENGTH_SHORT).show();
} else if(MainActivity.getAuthStatus() == AuthStatus.Authenticated.getValue()) {
Toast.makeText(mContext, "Error unprotecting tag",
Toast.LENGTH_SHORT).show();
} else if(MainActivity.getAuthStatus() == AuthStatus.Protected_RW.getValue()
|| MainActivity.getAuthStatus() == AuthStatus.Protected_W.getValue()
|| MainActivity.getAuthStatus() == AuthStatus.Protected_RW_SRAM.getValue()
|| MainActivity.getAuthStatus() == AuthStatus.Protected_W_SRAM.getValue()) {
Toast.makeText(mContext, "Password was not correct, please try again",
Toast.LENGTH_SHORT).show();
}
}
}
看上去这个函数是很复杂的,但是其实就是一些if条件太多,只要稍微整理一下,逻辑还是很清晰的
若你是success
- 若为Unprotected
置为Authenticated,并调用demo.auth
- 若为Authenticated
置为Unprotected
- 若为其他4种状态
置为Authenticated
若你是非success
- 若为Unprotected
报错"Error protecting tag"
- 若为Authenticated
报错"Error unprotecting tag"
- 若为其他4种状态
报错"Password was not correct, please try again"
updateAuthStatus
这个函数没啥好说的,常规操作
onNewIntent
这个函数看不懂,先挖个坑,以后慢慢看