I’m trying to save informations about deleting contacts in .txt log, but when i’m deleting any contact, nothing happens. If i Block or Unblock Wipe Data, there is info in logs, but no while i’m deleting or moving contacts to the bin.
My MainActivity.kt:
package com.example.test2
import android.annotation.SuppressLint
import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.database.ContentObserver
import android.database.Cursor
import android.net.Uri
import android.os.Bundle
import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.os.UserManager
import android.provider.ContactsContract
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.example.test2.databinding.ActivityMainBinding
import java.io.File
import java.io.FileWriter
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*
class MainActivity : AppCompatActivity() {
private lateinit var devicePolicyManager: DevicePolicyManager
private lateinit var componentName: ComponentName
private val disallowFactoryReset = "no_factory_reset"
private lateinit var binding: ActivityMainBinding
private lateinit var contactsObserver: ContentObserver
@SuppressLint("WrongConstant")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
devicePolicyManager = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
componentName = ComponentName(this, MyDeviceAdminReceiver::class.java)
// Ustawienie tekstu przycisków na podstawie zasobów ciągów
binding.activateButton.setText(R.string.activate_button_text)
binding.deactivateButton.setText(R.string.deactivate_button_text)
binding.blockWipeDataButton.setText(R.string.block_wipe_data_button_text)
binding.unblockWipeDataButton.setText(R.string.unblock_wipe_data_button_text)
binding.activateButton.setOnClickListener {
if (!devicePolicyManager.isAdminActive(componentName)) {
val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName)
startActivity(intent) // Uruchamianie intencji
}
}
binding.deactivateButton.setOnClickListener {
if (devicePolicyManager.isAdminActive(componentName)) {
devicePolicyManager.removeActiveAdmin(componentName)
}
}
binding.blockWipeDataButton.setOnClickListener {
// Blokowanie możliwości resetowania do ustawień fabrycznych
devicePolicyManager.addUserRestriction(this.componentName, UserManager.DISALLOW_FACTORY_RESET)
devicePolicyManager.addUserRestriction(this.componentName, UserManager.DISALLOW_NETWORK_RESET)
saveLog("Zablokowano możliwość resetowania do ustawień fabrycznych: ${getCurrentDateTime()}")
}
binding.unblockWipeDataButton.setOnClickListener {
if (devicePolicyManager.isAdminActive(componentName)) {
// Odblokowywanie możliwości resetowania do ustawień fabrycznych
devicePolicyManager.clearUserRestriction(this.componentName, disallowFactoryReset)
devicePolicyManager.clearUserRestriction(this.componentName, UserManager.DISALLOW_NETWORK_RESET)
saveLog("Odblokowano możliwość resetowania do ustawień fabrycznych: ${getCurrentDateTime()}")
}
}
// Utwórz instancję obserwatora kontaktów
contactsObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
override fun onChange(selfChange: Boolean, uri: Uri?) {
super.onChange(selfChange, uri)
// Sprawdź, czy zmiana dotyczy usunięcia kontaktu
if (uri != null && uri.toString().contains("contacts")) {
saveLog("Usunięto kontakt: ${getContactDetails(uri)}")
}
}
}
// Zarejestruj obserwatora kontaktów
contentResolver.registerContentObserver(
ContactsContract.Contacts.CONTENT_URI,
true,
contactsObserver
)
}
override fun onDestroy() {
super.onDestroy()
// Odrejestruj obserwatora kontaktów
contentResolver.unregisterContentObserver(contactsObserver)
}
private fun saveLog(logMessage: String) {
val logsDir = getLogsDirectory()
val logFile = File(logsDir, "app_logs.txt")
try {
val writer = FileWriter(logFile, true)
writer.append("$logMessage\n")
writer.flush()
writer.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
private fun getLogsDirectory(): File {
val logsDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "logs")
if (!logsDir.exists()) {
logsDir.mkdirs()
Log.d("Path", logsDir.absolutePath)
}
return logsDir
}
private fun getCurrentDateTime(): String {
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val date = Date()
return dateFormat.format(date)
}
@SuppressLint("Range")
private fun getContactDetails(contactUri: Uri): String {
val resolver: ContentResolver = contentResolver
val cursor: Cursor? = resolver.query(contactUri, null, null, null, null)
cursor?.use {
if (it.moveToFirst()) {
val nameIndex = it.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)
val numberIndex = it.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)
if (nameIndex != -1 && numberIndex != -1) {
val name = it.getString(nameIndex)
val number = it.getString(numberIndex)
return "Nazwa: $name, Numer: $number, Data: ${getCurrentDateTime()}"
}
} else {
// Kontakt nie istnieje, został prawdopodobnie przeniesiony do kosza
return "Kontakt przeniesiony do kosza: $contactUri, Data: ${getCurrentDateTime()}"
}
}
return ""
}
}
Also add permissions to AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
I tried to retrieve contact information using ContentResolver.query() and Cursor. Initially, I attempted to access contact details through ContactsContract.Contacts.CONTENT_URI, and then checked if the cursor contains the relevant columns (e.g., DISPLAY_NAME and HAS_PHONE_NUMBER) and retrieved the data accordingly. Additionally, I tried to handle the situation when a contact does not exist (moved to trash), which was part of my approach to solving the problem.