Skip to content

Instantly share code, notes, and snippets.

@EvgenyPlaksin
Created March 18, 2023 20:27
Show Gist options
  • Save EvgenyPlaksin/ff760d3354fe0dafa8b9bcc3c1d76525 to your computer and use it in GitHub Desktop.
Save EvgenyPlaksin/ff760d3354fe0dafa8b9bcc3c1d76525 to your computer and use it in GitHub Desktop.
package com.lnight.getrestricteddata
import android.content.ContentUris
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.net.Uri
import android.os.*
import android.provider.CallLog
import android.provider.ContactsContract
import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import android.Manifest
import com.google.i18n.phonenumbers.PhoneNumberUtil
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
if(permissions.all { it.value }) {
val handler = Handler(Looper.getMainLooper())
val runnable = object : Runnable {
override fun run() {
registerAudioFocusChangeListener()
handler.postDelayed(this, 100)
}
}
handler.post(runnable)
val imageView = findViewById<ImageView>(R.id.imageView_screenshot)
val button = findViewById<Button>(R.id.button_screenshot)
button.setOnClickListener { _ ->
val bitmap = screenShot(window.decorView.rootView)
bitmap?.let {
println("bitmap is not null -> $it")
imageView.setImageBitmap(it)
}
println("bitmap is null -> $bitmap")
}
}
}.launch(arrayOf(Manifest.permission.READ_CALL_LOG, Manifest.permission.READ_CONTACTS))
}
private fun screenShot(view: View): Bitmap? {
val bitmap = Bitmap.createBitmap(
view.width,
view.height, Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bitmap)
view.draw(canvas)
return bitmap
}
private fun registerAudioFocusChangeListener() {
val cancellationSignal = CancellationSignal()
val cursor = contentResolver.query(
CallLog.Calls.CONTENT_URI,
null,
CallLog.Calls.TYPE + " = ?",
arrayOf(CallLog.Calls.INCOMING_TYPE.toString()),
CallLog.Calls.DATE + " DESC",
cancellationSignal
)
if (cursor != null && cursor.moveToFirst()) {
val indexPhone = cursor.getColumnIndex(CallLog.Calls.NUMBER)
val phoneNumber = cursor.getString(if (indexPhone < 0) 0 else indexPhone)
val indexName = cursor.getColumnIndex(CallLog.Calls.CACHED_NAME)
val name = cursor.getString(if (indexName < 0) 0 else indexName)
if (lastPhoneData != Pair(phoneNumber, name)) {
if (isContact(this, phoneNumber)) {
println("$lastPhoneData | $phoneNumber | $name")
val indexLookup = cursor.getColumnIndex(CallLog.Calls.CACHED_LOOKUP_URI)
val lookupUri = cursor.getString(if (indexLookup < 0) 0 else indexLookup)
if(lookupUri != null) {
val contactId = ContentUris.parseId(Uri.parse(lookupUri))
val contactUri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI,
contactId
)
val contactCursor = contentResolver.query(
contactUri,
arrayOf(
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.PHOTO_URI
),
null,
null,
null
)
val contactName =
if (contactCursor != null && contactCursor.moveToFirst()) {
val indexName =
contactCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)
contactCursor.getString(if (indexName < 0) 0 else indexName)
} else {
""
}
contactCursor?.close()
val photoUri =
if (contactCursor != null && contactCursor.moveToFirst()) {
val indexPhoto =
contactCursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)
contactCursor.getString(if (indexPhoto < 0) 0 else indexPhoto)
} else {
""
}
contactCursor?.close()
val dataTv = findViewById<TextView>(R.id.data_tv)
dataTv.text =
"phone number: $phoneNumber\ncontactName: $contactName\nimageUri: $photoUri"
lastPhoneData = Pair(phoneNumber, contactName)
} else {
val indexUri = cursor.getColumnIndex(CallLog.Calls.CACHED_PHOTO_URI)
val imageUri = cursor.getString(if (indexUri < 0) 0 else indexUri)
val dataTv = findViewById<TextView>(R.id.data_tv)
dataTv.text = "phone number: $phoneNumber\nname: $name\nimageUri: $imageUri"
lastPhoneData = Pair(phoneNumber, name)
}
} else {
val indexUri = cursor.getColumnIndex(CallLog.Calls.CACHED_PHOTO_URI)
val imageUri = cursor.getString(if (indexUri < 0) 0 else indexUri)
val dataTv = findViewById<TextView>(R.id.data_tv)
dataTv.text = "phone number: $phoneNumber\nname: $name\nimageUri: $imageUri"
lastPhoneData = Pair(phoneNumber, name)
}
Toast.makeText(this, phoneNumber, Toast.LENGTH_SHORT).show()
}
cursor.close()
cancellationSignal.cancel()
}
}
private fun isContact(context: Context, phoneNumber: String): Boolean {
val normalizedNumber = phoneNumber.removeCountryCode()
val uri = Uri.withAppendedPath(
ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(normalizedNumber)
)
println(normalizedNumber)
println(uri)
val projection = arrayOf(ContactsContract.PhoneLookup.DISPLAY_NAME)
var contactName: String? = null
context.contentResolver.query(uri, projection, null, null, null)?.use { cursor ->
if (cursor.moveToFirst()) {
val indexName = cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME)
contactName = if (indexName >= 0) cursor.getString(indexName) else null
}
}
return contactName != null
}
private fun String.removeCountryCode(): String {
val phoneInstance = PhoneNumberUtil.getInstance()
try {
val phoneNumber = phoneInstance.parse(this, null)
return phoneNumber?.nationalNumber?.toString() ?: this
}catch (_ : Exception) {
}
return this
}
companion object {
var lastPhoneData: Pair<PhoneNumber, CallerName>? = null
}
}
typealias PhoneNumber = String
typealias CallerName = String
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment