【问题标题】:Add self signed certificate using retrofit call使用改造调用添加自签名证书
【发布时间】:2019-10-22 05:39:28
【问题描述】:

我想使用改造添加自签名证书,因为我需要传递上下文但在通过 MVC 模型传递上下文时遇到一些问题

改造客户端

object RetrofitClient    {
  fun call(context: Context): Webservice {
    val webservice by lazy {
        Retrofit.Builder()
            //  .baseUrl("http://68.183.183.255:8080")
            //.baseUrl("http://my-json-server.typicode.com")
            .baseUrl("https://54roh005p5.execute-api.us-west-2.amazonaws.com/mdv/cloud/login/")
            .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
            .addConverterFactory(ScalarsConverterFactory.create())
            .client(SelfSigningClientBuilder.createClient(context))
            .build().create(Webservice::class.java)
    }
    return webservice
  }
}

存储库

class TodoRepository(context:Context) {

   private var client:Webservice = RetrofitClient.call(context)
   //suspend fun getTodo(id: String) = client.getTodo(id)
   suspend fun getTodo(id: User) = client.getTodo(id)
}

视图模型

class NetworkViewModel(context: Context) : ViewModel() {

  var repository: TodoRepository  = TodoRepository(context)
  fun getTodo(arg : User):LiveData<Response<com.example.myapplication.entity.UserData>> {
    val result = liveData(Dispatchers.IO) {
        val retrivedTodo = repository.getTodo(arg)

        emit(retrivedTodo)
      }
    return result
   }
}

主活动

networkViewModel=ViewModelProviders.of(this).get(NetworkViewModel(this)::class.java)

报错

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapplication/com.example.myapplication.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.example.myapplication.network.NetworkViewModel

我做错了什么。如果有更好的方法请推荐

【问题讨论】:

  • 为什么要将上下文传递给每个类?只需创建一个应用程序类并从那里获取上下文
  • 我试过它给我错误 MyApp.getContext() must not be null
  • 添加您的 MyApp 代码。我会更新
  • 类 MainApplication : Application() { init { instance = this } 伴随对象 { private var instance: MainApplication? = null fun applicationContext() : Context { return instance!!.applicationContext } } 覆盖 fun onCreate() { super.onCreate() val context: Context = MainApplication.applicationContext() } }
  • 类 MainApplication : Application() { 伴侣对象 { private lateinit var instance: MainApplication fun applicationContext() : Context { return instance.applicationContext } } override fun onCreate() { super.onCreate() instance =这个 } }

标签: android ssl kotlin retrofit2


【解决方案1】:

创建一个应用程序类并在需要时使用这个应用程序上下文,而不是从一个类到另一个类传递上下文。请检查以下内容:

class MainApplication : Application() {
    companion object {
        private lateinit var instance: MainApplication

        fun applicationContext() : Context {
            return instance.applicationContext
        }
    }

    override fun onCreate() {
        super.onCreate()
        instance = this
    }
}

然后,在AndroidManifest 的应用程序标签中添加这个android:name=".MainApplication"

然后调用 MainApplication.applicationContext() 从任何地方获取 Context。

【讨论】:

    【解决方案2】:

    不要通过构造函数初始化 ViewModel 对象:- NetworkViewModel(this)::class.java 是错误的。使用:-

     networkViewModel = ViewModelProviders.of(this).get(NetworkViewModel::class.java)
    

    【讨论】:

      【解决方案3】:

      您可以自定义您的 OkHttpClients sslSocketFactory

      例如(Retrofit 的客户端设置)

      val retrofit Retrofit
          .Builder()
          .client(client)
          .baseUrl(BASE_URL)
          .addConverterFactory(GsonConverterFactory.create(gson))
          .build()
      

      例如(OkHttpsClient 的 sslSocketFactory 设置)

        val client =OkHttpClient.Builder()
                  .sslSocketFactory(sslContextWithSS.getSocketFactory())
                  .build()
      

      例如(SSLSocketFactory 带有自定义证书)

              val keyStore = readKeyStore() //your method to obtain KeyStore
              val sslContext = SSLContext.getInstance("SSL")
              val trustManagerFactory = TrustManagerFactory.getInstance(getDefaultAlgorithm())
              trustManagerFactory.init(keyStore)
              val keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
              keyManagerFactory.init(keyStore, "keystore_pass".toCharArray())
              sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), SecureRandom())
              client.setSslSocketFactory(sslContext.getSocketFactory())
      

      通过您的CustomCertificate 获取KeyStore

       fun readKeyStore()= KeyStore.getInstance(KeyStore.getDefaultType()).also{
        try (val inputStream = context.getResources().openRawResource(R.raw.custom_certificate)) {
              it.load(inputStream, getPassword());
          }
      }
      
      
      

      【讨论】:

        猜你喜欢
        • 2023-04-02
        • 2019-08-23
        • 2016-02-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-21
        • 1970-01-01
        相关资源
        最近更新 更多