为保证用户数据和设备的安全,Google针对下一代 Android 系统(Android P) 的应用程序,将要求默认使用加密连接,这意味着 Android P 将禁止 App 使用所有未加密的连接,因此运行 Android P 系统的安卓设备无论是接收或者发送流量,未来都不能明码传输,需要使用下一代(Transport Layer Security)传输层安全协议,而 Android Nougat 和 Oreo 则不受影响。
因此在Android P 使用HttpUrlConnection进行http请求会出现以下异常
W/System.err: java.io.IOException: Cleartext HTTP traffic to **** not permitted
解决方案:
更改网络安全配置
1.在res文件夹下创建一个xml文件夹,然后手动创建:
network_security_config.xml文件,文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
2.接着,在AndroidManifest.xml文件下的application,加上:
<application
...
android:networkSecurityConfig="@xml/network_security_config"
...
/>
3.在AndroidManifest.xml配置文件, 对应的activity里标签中直接插入: android:usesCleartextTraffic="true"
<activity
android:name=".MainActivity"
android:usesCleartextTraffic="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
4. 最后记得打开网络权限AndroidManifest
<uses-permission android:name="android.permission.INTERNET"/>
运行图片出来了
源码:
BindingAdapter.kt
package com.example.lanidemokt.adapter
import android.widget.ImageView
import androidx.databinding.BindingAdapter
import com.bumptech.glide.Glide
class MainActivityBindingAdapter {
companion object {
@BindingAdapter("url")
@JvmStatic
fun loadStudentDetails(view: ImageView?, url: String?) {
var url2 = "http://192.168.1.207:8080/download/kn.png"
Glide.with(view!!).load(url2).into(view)
}
}
}
activity_main.xml
<ImageView
android:id="@+id/picture1"
android:layout_width="300dp"
android:layout_height="200dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/msg3"
app:url="@{`null`}" />
MainActivity.kt
package com.example.lanidemokt
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.databinding.BaseObservable
import androidx.databinding.DataBindingUtil
import com.example.lanidemokt.databinding.ActivityMainBinding
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.Date
class MainActivity : AppCompatActivity() {
/*
* DataBinding 对应一个Binding对象,对象名是布局文件文称加上Binding后缀
* binding,activity_main.xml的布局实例
* xml上所有变量与点击事件,必须是binding的成员属性或者成员方法函数,否则操作界面无效
*
* */
var binding: ActivityMainBinding? = null
private var login: Login? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) // setContentView(R.layout.activity_main)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
initView()
corGlobalTest()
}
/* *
* 在Controller层,将我们的data与model相关联
* */
data class Login(var name: String = "LLL", var msg: String) //意向绑定响应式
data class Student(var name: String = "LLL", var score: Int) : BaseObservable() //双击绑定响应式
private fun initView() {
binding?.msg?.setText("我是谁")
login = Login("LANI", "我是谁")
// binding?.login = Login("LANI", "我是谁")
// 这一步必须要,否则点击没反应,否则界面不显示对应的名字与信息
binding?.setLogin(Login("LANI", "我是谁"))
binding?.setStudent(Student("LEE", 199))
}
/*
* 协程创建
* */
fun corGlobalTest() {
GlobalScope.launch {
println("|--开始global${Date()}")
delay(1000)
println("|--END global${Date()}")
}
println("|--END ${Date()}")
}
}