I\'m trying to install certificates without prompting the user. I know this is not good practice, but that\'s what PM wants.
Using KeyChain.createInstallIntent(), I
This thread is a bit dated already, nevertheless since I stumbled upon the same issue and couldn't find any "out of the box" solution for Android O or later, I thought I'd share what I came up with and which worked well for me when trying to install Certificates (CA and others) to the Android Trusted credentials "User" store:
// Supply context, e.g. from "Context context = getApplicationContext();"
// String fileName points to the file holding the certificate to be installed. pem/der/pfx tested.
RandomAccessFile file = new RandomAccessFile(fileName, "r");
byte[] certificateBytes = new byte[(int)file.length()];
file.read(certificateBytes);
Class> keyChainConnectionClass = Objects.requireNonNull(context.getClassLoader()).loadClass("android.security.KeyChain$KeyChainConnection");
Class> iKeyChainServiceClass = Objects.requireNonNull(context.getClassLoader()).loadClass("android.security.IKeyChainService");
Method keyChainBindMethod = KeyChain.class.getMethod("bind", Context.class);
Method keyChainConnectionGetServiceMethod = keyChainConnectionClass.getMethod("getService");
Object keyChainConnectionObject = keyChainBindMethod.invoke(null, context);
Object iKeyChainServiceObject = keyChainConnectionGetServiceMethod.invoke(keyChainConnectionObject);
Method installCaCertificate = iKeyChainServiceClass.getDeclaredMethod("installCaCertificate", byte[].class);
installCaCertificate.invoke(iKeyChainServiceObject, certificateBytes);
Note that if you want to silently install a certificate this way, your app needs to be a system app, i.e. it needs to have
android:sharedUserId="android.uid.system"
declared in it's manifest.
Cheers!