android-How to solve 'android java.security.NoSuchProviderException: no such provider: SUN'

1. The purpose of this post

I would demo how to solve this error when using SecureRandom algorithm in android studio,for example, if we use google authenticator library, it would generate random number by using the SecureRandom object,but when we run the app, this error occurs:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.tom, PID: 21824
    java.lang.ExceptionInInitializerError
        at com.tom.otp.OtpLoginActivity.onCreate(OtpLoginActivity.java:56)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: com.warrenstrange.googleauth.GoogleAuthenticatorException: Could not initialise SecureRandom with the specified provider: SUN. Another provider can be chosen setting the com.warrenstrange.googleauth.rng.algorithmProvider system property.
        at com.warrenstrange.googleauth.ReseedingSecureRandom.buildSecureRandom(ReseedingSecureRandom.java:118)
        at com.warrenstrange.googleauth.ReseedingSecureRandom.<init>(ReseedingSecureRandom.java:84)
        at com.warrenstrange.googleauth.GoogleAuthenticator.<init>(GoogleAuthenticator.java:151)
        at com.tom.otp.OtpLoginPresenter.<clinit>(OtpLoginPresenter.java:45)
        at com.tom.otp.OtpLoginActivity.onCreate(OtpLoginActivity.java:56) 
        at android.app.Activity.performCreate(Activity.java:7136) 
        at android.app.Activity.performCreate(Activity.java:7127) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:6669) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
     Caused by: java.security.NoSuchProviderException: no such provider: SUN
        at sun.security.jca.GetInstance.getService(GetInstance.java:83)
        at sun.security.jca.GetInstance.getInstance(GetInstance.java:206)
        at java.security.SecureRandom.getInstance(SecureRandom.java:348)
        at com.warrenstrange.googleauth.ReseedingSecureRandom.buildSecureRandom(ReseedingSecureRandom.java:101)
        at com.warrenstrange.googleauth.ReseedingSecureRandom.<init>(ReseedingSecureRandom.java:84) 
        at com.warrenstrange.googleauth.GoogleAuthenticator.<init>(GoogleAuthenticator.java:151) 
        at com.tom.otp.OtpLoginPresenter.<clinit>(OtpLoginPresenter.java:45) 
        at com.tom.otp.OtpLoginActivity.onCreate(OtpLoginActivity.java:56) 
        at android.app.Activity.performCreate(Activity.java:7136) 
        at android.app.Activity.performCreate(Activity.java:7127) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:6669) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 

2. Environments

  • Android Studio 3.x
  • gradle wrapper version:
    • distributionUrl=https://services.gradle.org/distributions/gradle-5.4.1-all.zip
  • project build.gradle
    • classpath ‘com.android.tools.build:gradle:3.5.0’
  • google auth library version:
    • implementation group: ‘com.warrenstrange’, name: ‘googleauth’, version: ‘1.4.0’

3. Solution and Code

Because by default, the library uses ‘SUN’ provider as the default SecureRandom algorithm provider, which is deprecated in the android system. So you can change it like this:

Provider[] secureRandomProviders = Security.getProviders("SecureRandom.SHA1PRNG");
System.setProperty("com.warrenstrange.googleauth.rng.algorithmProvider",secureRandomProviders[0].getName());

The code above just lists all the providers in the android system, and choose the first one as the provider.

Clean,rebuild and run the app, everything works.