Kotlin安卓:实现okhttp3持续登录,同步到webview 发表于 2019-08-19 更新于 2019-08-19
广州
开发 android kotlin Kotlin安卓:实现okhttp3持续登录,同步到webview ❄️2winter 2019-08-19 2019-08-19 经常用httpclient请求的的情况下,一般就是用jsoup解析,去爬数据,用okhttp3实现cookie的保存。
这里做的是用okhttp3实现登录请求,然后直接将登录后可访问的页面Cookie同步加载到webview里面去。
将账号与密码保存到shareP ····下次打开webview就可以直接访问已登录页面了。
下面开始具体实现步骤:语言:kotlin,库: okhttp3 组件: webview
先看看一个简单的页面:第一次打开弹出一个账户,填写我们需要的账号与密码
保存到:SharedPreferences。下次登录自动调用login方法,利用okhttp3去请求登录页面。
下面会具体讲。
看看代码部分:首先会检查是否添加过账号,添加了就调用登录方法,没有就弹出对话框(这个对话框不可以返回,触摸关闭哦!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 val pr = getSharedPreferences("login_flag" , Context.MODE_PRIVATE)login_flag = pr.getString("login_flag" ,"null" ) if (login_flag == "null" ){ Toast.makeText(this @MainActivity ,"未添加过账户" ,Toast.LENGTH_SHORT).show() val dialog = AlertDialog.Builder(this @MainActivity ) val tem_layout = layoutInflater.inflate(R.layout.add,null ) dialog.setView(tem_layout) .setCancelable(false ) .setTitle("添加账户" ) .setPositiveButton("确认" ,object :DialogInterface.OnClickListener{ override fun onClick (dialog: DialogInterface ?, which: Int ) { val login_new_name = tem_layout.findViewById<EditText>(R.id.add_name) val login_new_pass = tem_layout.findViewById<EditText>(R.id.add_pass) if (login_new_pass.text.toString()=="" && login_new_pass.text.toString()=="" ){ Toast.makeText(this @MainActivity ,"不可以为空" ,Toast.LENGTH_SHORT).show() }else { val newPr = getSharedPreferences("login_info" ,Context.MODE_PRIVATE) val pr_editor = newPr.edit() pr_editor.putString("login_name" ,login_new_name.text.toString()) pr_editor.putString("login_pass" ,login_new_pass.text.toString()) pr_editor.apply() val pr2 = getSharedPreferences("login_flag" ,Context.MODE_PRIVATE) pr2.edit().putString("login_flag" ,"true" ).apply() Toast.makeText(this @MainActivity ,"账号:${login_new_name.text.toString()} ,密码:${login_new_pass.text.toString()} " ,Toast.LENGTH_SHORT).show() } } }) .setNegativeButton("取消" ,null ) .create() .show() }else { val pr3 = getSharedPreferences("login_info" ,Context.MODE_PRIVATE) val tem_name = pr3.getString("login_name" ,"null" ) val tem_pass = pr3.getString("login_pass" ,"null" ) Toast.makeText(this @MainActivity ,"账号:${tem_name} ,密码:${tem_pass} " ,Toast.LENGTH_SHORT).show() Toast.makeText(this @MainActivity ,"正在登录" ,Toast.LENGTH_SHORT).show() login.myLogin(tem_name,tem_pass,myhandle) }
下面看看登录类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 class Login (){ var cookieStore = HashMap<String, List<Cookie>?>() val logUrl = "https://www.login.com" val myManage = "https://www.logined.com" val client = OkHttpClient.Builder().cookieJar( object : CookieJar { override fun saveFromResponse (httpUrl: HttpUrl , list: List <Cookie >) { cookieStore[httpUrl.host()] = list } override fun loadForRequest (httpUrl: HttpUrl ) : List<Cookie> { val cookies = cookieStore[httpUrl.host()] return cookies ?: ArrayList() } }).build() fun myLogin (user: String , pw: String , hand: Handler ) { val isFailLogin = Regex(".*bad.*" ) val isSuccLogin= Regex(".*ok.*" ) var res = "" if (user.isNotEmpty() && pw.isNotEmpty()) { thread { val myinfo = FormBody.Builder() .add("admin_name" , user) .add("admin_pass" , pw) .build() var request = Request.Builder().url(this .logUrl).post(myinfo).build() var response = this .client.newCall(request).enqueue(object : Callback { override fun onResponse (call: Call , response: Response ) { var res = response.body()?.string() Log.d("here" ,res) var msg = Message() msg.what = 1 hand.sendMessage(msg) } override fun onFailure (call: Call , e: IOException ) { var msg: Message = Message() msg.what = 4 hand.sendMessage(msg) } }) } } else { var msg: Message = Message()msg.what = 4 hand.sendMessage(msg) }}}
下面回到主线程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 主线程有三个东西:handle webview 还有一个用来同步cookie的方法 syncCookie()先看看handle var myhandle = object :Handler(Looper.getMainLooper()){ override fun handleMessage (msg: Message ) { when (msg.what){ 1 -> { synCookie() Toast.makeText(this @MainActivity ,"登录ok" ,Toast.LENGTH_SHORT).show() web.loadUrl(login.myManage) 2 -> { } } Log.d("msg" ,msg.what.toString()) }} 看看webview的设置: val web = findViewById<WebView>(R.id.web)var web_set = web.settingsweb_set.javaScriptEnabled = true web_set.javaScriptCanOpenWindowsAutomatically = true web.webViewClient = object :WebViewClient(){ override fun shouldOverrideUrlLoading (view: WebView ?, request: WebResourceRequest ?) : Boolean { return false }} web.webChromeClient = WebChromeClient() 下面看看同步方法:AS会提示过时,不用理会 fun synCookie () { CookieSyncManager.createInstance(this ) var cookM = CookieManager.getInstance() cookM.setAcceptCookie(true ) Log.d("cookie" ,login.cookieStore.toString()) var sessionCookie: Cookie = login.cookieStore["www.xxx.com" ]!![0 ] Log.d("sess" ,"name:${sessionCookie.name()} ;value:${sessionCookie.value()} ;domain:${sessionCookie.domain()} " ) var cookies = sessionCookie.name() + "=" + sessionCookie.value() + ";domain=" + sessionCookie.domain() cookM.setCookie("https://logined.com" ,cookies) CookieSyncManager.getInstance().sync() }
看一下:
成功的图:自动登录到logined页面了。
最后梳理一下:
分两个部分:请求类,主界面的handle
请求类定义了请求url,主界面的handle收到指定信息,实现是否调用同步方法进行webview的cookie同步(其实就是把cookie保留下来,再去调用webview时候,已经有了Cookie买就不用登录了。好了。完了,kotlin的资料太少,参考的都是java的,我不会Java。)
❄️2winter
ReactNative FullStack Developer
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ❄️2winter !