深入理解Android之Java Security第二部分(Final)
分类:Android开发系列
!
KeyChainAliasCallback response,
String[] keyTypes, Principal[] issuers,
String host, intport,String alias) {
……
//Action的值为“com.android.keychain.CHOOSER“
Intent intent = newIntent(ACTION_CHOOSER);
intent.putExtra(EXTRA_RESPONSE, new AliasResponse(response));
intent.putExtra(EXTRA_HOST, host);
intent.putExtra(EXTRA_PORT, port);
intent.putExtra(EXTRA_ALIAS, alias);
intent.putExtra(EXTRA_SENDER, PendingIntent.getActivity(activity, 0,
new Intent(), 0));
activity.startActivity(intent);
}
“com.android.keychain.CHOOSER“这个Intent将好多年来一直默默无名但是又重要无比的keychain这个apk来响应。
(1) KeyChainActivity
直接来看图22中那个框是咋处理的吧。
[–>KeyChainActivity.java:: showCertChooserDialog]
private void showCertChooserDialog() {
new AliasLoader().execute();
}
[–>KeyChainActivity.java::AliasLoader]
private class AliasLoader extendsAsyncTask<Void, Void, CertificateAdapter> {
@Override protectedCertificateAdapter doInBackground(Void…params) {
//借助Binder和Native KeyStore交互,获取alias列表
String[] aliasArray = mKeyStore.saw(Credentials.USER_PRIVATE_KEY);
List<String> aliasList = ((aliasArray== null)
?Collections.<String>emptyList(): Arrays.asList(aliasArray));
Collections.sort(aliasList);
return new CertificateAdapter(aliasList);
}
@Override protected voidonPostExecute(CertificateAdapter adapter) {
displayCertChooserDialog(adapter);//显示图22所示的对话框!
}
}
[–>KeyChainActivity.java::displayCertChooserDialog]
private voiddisplayCertChooserDialog(final CertificateAdapter adapter) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
……
if……
else {
…..
builder.setPositiveButton(R.string.allow_button,
new DialogInterface.OnClickListener(){
@Override public void onClick(DialogInterface dialog, int id) {
int listViewPosition = lv.getCheckedItemPosition();
int adapterPosition = listViewPosition-1;
String alias = ((adapterPosition >= 0)
?adapter.getItem(adapterPosition) : null);
finish(alias);
}
});
}
…
final Dialog dialog =builder.create();
……
}
关键函数是这个finish,注意它是带参数的,非常容易和Activity的finish()混淆!
[–>KeyChainActivity.java::finish]
private void finish(String alias) {
……
IKeyChainAliasCallback keyChainAliasResponse
= IKeyChainAliasCallback.Stub.asInterface(
getIntent().getIBinderExtra(KeyChain.EXTRA_RESPONSE));
if (keyChainAliasResponse != null) {
new ResponseSender(keyChainAliasResponse,alias).execute();
return;
}
finish();
}
[–>KeyChainActivity.java:ResponseSender]
private class ResponseSender extends AsyncTask<Void,Void, Void> {
private IKeyChainAliasCallback mKeyChainAliasResponse;
private String mAlias;
…….
@Override protected VoiddoInBackground(Void… unused) {
try {
if (mAlias != null) {
KeyChain.KeyChainConnection connection =
KeyChain.bind(KeyChainActivity.this);
try {
//这里的Service不是Native的KeyStore,而是keychain里的KeyChainService
connection.getService().setGrant(mSenderUid,mAlias, true);
} ……
}
mKeyChainAliasResponse.alias(mAlias);//调用我们的回调函数
(2)KeyChainService
KeyChainService也在keychain.apk中,这玩意开机就会启动,因为keychain有一个BroadcastReceiver会接收BOOT_COMPLETE消息,这个BR然后启动KeyChainService。
不甚酒力,体会不了酒的美味,但却能感受知已的妙处。