前段时间一直在忙高通项目的需求,同事转给我一个证书安装的bug给我,一直没时间解,给Marvell提case,个把月了还不给回复,囧!求人不如求己正好最近需求做完了,索性就自己跟下代码。
证书安装入口在设置-->安全里,相应代码如下:
android:title="@string/credentials_install"
android:summary="@string/credentials_install_summary"
android:persistent="false">
android:targetPackage="com.android.certinstaller"
android:targetClass="com.android.certinstaller.CertInstallerMain"/>
当我们点击“从存储设备安装证书”时,就会通过intent进入CertInstallerMain。在onCreate里对相应action做处理
if (Credentials.INSTALL_ACTION.equals(action)
|| Credentials.INSTALL_AS_USER_ACTION.equals(action)) {
Bundle bundle = intent.getExtras();//这里获取的bundle为空。
由于bundle未空会执行如下代码:
if (bundle == null
|| bundle.isEmpty()
|| (bundle.size() == 1
&& (bundle.containsKey(KeyChain.EXTRA_NAME)
|| bundle.containsKey(Credentials.EXTRA_INSTALL_AS_UID)))) {
final Intent openIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
openIntent.setType("*/*");
openIntent.putExtra(Intent.EXTRA_MIME_TYPES, ACCEPT_MIME_TYPES);
openIntent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, true);
startActivityForResult(openIntent, REQUEST_OPEN_DOCUMENT);
这里就会弹出一个类似文件管理的界面,选择相应的证书后会自动安装证书。
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OPEN_DOCUMENT) {
if (resultCode == RESULT_OK) {
startInstallActivity(null, data.getData());
} else {
finish();
}
} else if (requestCode == REQUEST_INSTALL) {
setResult(resultCode);
finish();
} else {
Log.w(TAG, "unknown request code: " + requestCode);
}
}
private void startInstallActivity(String mimeType, byte[] value) {
Intent intent = new Intent(this, CertInstaller.class);
if ("application/x-pkcs12".equals(mimeType)) {
intent.putExtra(KeyChain.EXTRA_PKCS12, value);
} else if ("application/x-x509-ca-cert".equals(mimeType)
|| "application/x-x509-user-cert".equals(mimeType)
|| "application/x-x509-server-cert".equals(mimeType)
|| "application/x-pem-file".equals(mimeType)
|| "application/pkix-cert".equals(mimeType)) {
intent.putExtra(KeyChain.EXTRA_CERTIFICATE, value);
} else {
throw new IllegalArgumentException("Unknown MIME type: " + mimeType);
}
startActivityForResult(intent, REQUEST_INSTALL);
}
进入CertInstaller后,如果没有设置设置锁屏会先提示设置锁屏
protected void onCreate(Bundle savedStates) {
super.onCreate(savedStates);
mCredentials = createCredentialHelper(getIntent());
mState = (savedStates == null) ? STATE_INIT : STATE_RUNNING;
if (mState == STATE_INIT) {
if (!mCredentials.containsAnyRawData()) {
toastErrorAndFinish(R.string.no_cert_to_saved);
finish();
} else if (mCredentials.hasPkcs12KeyStore()) {
showDialog(PKCS12_PASSWORD_DIALOG);
} else {
MyAction action = new InstallOthersAction();
if (needsKeyStoreAccess()) {
sendUnlockKeyStoreIntent();
mNextAction = action;
} else {
action.run(this);
}
}
设置完成后在进行证书安装
protected void onResume() {
super.onResume();
if (mState == STATE_INIT) {
mState = STATE_RUNNING;
} else {
if (mNextAction != null) {
mNextAction.run(this);
}
}
}
最终会调用installOthers()方法
if (mCredentials.hasKeyPair()) { saveKeyPair(); finish(); } else { X509Certificate cert = mCredentials.getUserCertificate(); if (cert != null) { // find matched private key /* modify by yangzhiming 20150803 for bug 60294 start */ String key = null; try{ key = Util.toMd5(cert.getPublicKey().getEncoded()); }catch (RuntimeException ex) { toastErrorAndFinish(R.string.invalid_cert); return; } /* modify by yangzhiming 20150803 for bug 60294 end */ Map map = getPkeyMap(); byte[] privatekey = map.get(key); if (privatekey != null) { Log.d(TAG, "found matched key: " + privatekey); map.remove(key); savePkeyMap(map); mCredentials.setPrivateKey(privatekey); } else { Log.d(TAG, "didn't find matched private key: " + key); } } nameCredential(); } CA证书安装的大致流程就是这样了。