一:增加一个展现数据的布局

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <ListView        android:id="@+id/contactsView"        android:layout_width="match_parent"        android:layout_height="match_parent"/></LinearLayout>

二:增加BaseActivity

abstract class BaseActivity : AppCompatActivity() {    /**     * kotlin 容许一个类继承另一个类     * kotlin 所有的类都继承自Any类(Any 不是 java.lang.Object)     * Any类是所有类的超类,对于没有超类型申明的类是默认超类     * Kotlin规定一个类能够给继承,必须应用open关键字润饰     * */    /**     * 抽象类:关键字为abstract     *形象函数: abstract fun initView()     *形象属性:abstract var name:String */    /**     *变量能够定义为可变(var)和不可变(val)     * 常量定义:val相当于被final 润饰  var相当于可变非final润饰     *等价于Java:public static final String TAG=BaseActivity.class.getSimpleName()*/    //定义标记    open val TAG: String = this.javaClass.simpleName    //初始化布局View    abstract fun initView()    //初始化数据    abstract fun initData()    //初始化获取布局id,带返回值的形象办法    abstract fun getLayoutId(): Int    /**     * 语法定义     * fun 办法名 (参数名 :参数类型):返回值类型{     *     * return 返回值     *     * }     *     * 无返回值能够应用Unit 代替返回值类型 ?代表可空     * Kotlin 是null平安的语言 Byte ,Short,Int ,Long型的变量都是不能承受null值,如果要存储null值须要应用Byte?,Short?,Int?,Long?     *     *  override fun onCreate(savedInstanceState: Bundle?) :Unit{     *     *  }     **/    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(getLayoutId())        initView()        initData()    }    override fun onDestroy() {        super.onDestroy()    }}

三:定义FourActivity,实现权限受权和联系人数据ContentResolver解析过程间通信

class FourActivity : BaseActivity() {    private val CONTACT_REQUEST_CODE = 1    //ListView布局文件    lateinit var contactsView: ListView    //汇合数据    private val contactsList = ArrayList<String>()    //适配器    private lateinit var adapter: ArrayAdapter<String>    override fun initView() {        contactsView = findViewById<ListView>(R.id.contactsView)        adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, contactsList)        contactsView.adapter = adapter        //权限查看        checkP(this)    }    private fun checkP(context: Context) {        //查看权限是否受权,这个查看的权限是读取手机联系人        if (ContextCompat.checkSelfPermission(                context,                android.Manifest.permission.READ_CONTACTS            ) != PackageManager.PERMISSION_GRANTED        ) {            //没有受权,申请权限受权            //参数类型,Activity,权限组,申请码            ActivityCompat.requestPermissions(                context as Activity,                arrayOf(android.Manifest.permission.READ_CONTACTS),                CONTACT_REQUEST_CODE            )        } else {            //受权了            readContacts()        }    }    /**权限申请点击容许和回绝都会回调onRequestPermissionsResult办法*/    override fun onRequestPermissionsResult(        requestCode: Int,        permissions: Array<out String>,        grantResults: IntArray    ) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults)        when (requestCode) {            CONTACT_REQUEST_CODE -> {                if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {                    //容许受权                    readContacts()                } else {                    //回绝受权                    Toast.makeText(this, "You denied the Permission", Toast.LENGTH_SHORT).show()                }            }        }    }    /**读取联系人操作,应用ContentProvider*/    private fun readContacts() {        //查问联系人数据        contentResolver.query(            ContactsContract.CommonDataKinds.Phone.CONTENT_URI,            null,            null,            null,            null        )?.apply {            while (moveToNext()) {                //获取联系人姓名                val displayName =                    getString(getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))                //获取联系人手机号                val number =                    getString(getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))                contactsList.add("$displayName\n$number")                adapter.notifyDataSetChanged()                /**                 * 剖析log:android.database.StaleDataException: Attempted to access a cursor after it has been                 * 然而同样的代码在android2.2上边没有产生,在android3.0上边产生了,剖析起因在于                android4.0的managedCursor /managedQuery会主动的close一个cursor,然而咱们又手动的敞开了一次,所以导致了这个问题,解决方案是在4.0的代码去掉close这个操作。*/                if (Integer.parseInt(Build.VERSION.SDK) < 11) {                    close()                }            }        }    }    override fun initData() {    }    override fun getLayoutId(): Int {        return R.layout.activity_four    }}

四:增加权限在AndroidManifest

 <uses-permission android:name="android.permission.READ_CONTACTS"/>