How to get person name while reading messages from device in android? - android

I'm trying to get all messages from the user's phone, user number, text messages are retrieved successfully. But the problem is how can I get the UserName of the message sender saved in the user mobile device.
I'm getting the error Caused by: java.lang.NullPointerException: cur.getString(cur.getColumnIndex("person")) must not be null
Here is the method to get user SMS.
fun getSMS() {
msgArrayList = ArrayList()
msgArrayList?.clear()
val uriSMSURI: Uri = Uri.parse("content://sms/inbox")
val cur: Cursor? = contentResolver.query(uriSMSURI, null, null, null, null)
while (cur != null && cur.moveToNext()) {
val person: String = cur.getString(cur.getColumnIndex("person")) // error in this line occurs
val date: String = cur.getString(cur.getColumnIndex("date"))
val address: String = cur.getString(cur.getColumnIndex("address"))
val body: String = cur.getString(cur.getColumnIndexOrThrow("body"))
val model = AllMessagesModel(address ,body,person,date)
msgArrayList?.add(model)
}
cur?.close()
allMsgAdapter = MessageAdapter(this, msgArrayList)
val layoutManager =
LinearLayoutManager(applicationContext, RecyclerView.VERTICAL, false)
rvMessages!!.layoutManager = layoutManager
rvMessages?.adapter = allMsgAdapter
}
How can I solve this issue?

Related

Firebase Realtime Database has a different data key from the Kotlin data class [duplicate]

This question already has answers here:
Drop "is" prefix for Firebase Firestore fields for Boolean Values
(2 answers)
Prevent firebase from taking the method name as variable in Firebase
(2 answers)
Closed 5 months ago.
I have multiple data classes and all upload fine to Firebase Realtime database except for this one key "isCompleted" gets changed to "completed" in the database.
My data class:
data class MaintenanceLog(
val isCompleted: Boolean? = null,
val brand: String? = null,
val clientCode: String? = null,
val dateOfSubmission: Double? = null,
val details: String? = null,
val equipmentID: String? = null,
val id: String? = null,
val model: String? = null,
val name: String? = null,
val photosArray: List<String>? = null,
val refNum: String? = null,
val restaurantID: String? = null,
var hidden: Boolean? = null,
val userSelectedDate: Double? = null,
val wasFutureMaintCreated: Boolean? = null,
val workLogRef: String? = null,
val contractorCode: String? = null,
val isCalendarEvent: Boolean? = null,
val calendarEvent_venueName: String? = null,
val createdBy: String? = null
)
Implementation:
val demoLog = MaintenanceLog(
isCompleted = true,
id = "DemoLog22222",
equipmentID = "demo_equipID_123456",
refNum = "DemoRefNum_123456",
dateOfSubmission = APSDate.getCurrentDatabaseFormattedTime(),
details = "Maintenance Log created from Work Log - Demo Description",
photosArray = null,
workLogRef = "DemoRefNum_123456",
createdBy = "Demo User",
clientCode = "Demo Client",
restaurantID = "Demo Restaurant",
brand = "Demo Brand",
model = "Demo Model",
name = "Demo User",
userSelectedDate = APSDate.dateFromComponents(timeIn_Year, timeIn_Month, timeIn_Day, timeIn_Hour, timeIn_Minute),
wasFutureMaintCreated = false)
dbRef.child(FirebaseLocations.MAINTENANCE_RECORDS.code).child("111_demo_path").setValue(demoLog)
The demo log when setting the value:
And the firebase value:
Why is "isCompleted" getting changed to "completed" when uploaded to the database?

Arraylist remains null even when data is being passed to it

I'm working on a firebase chatting app. I want to maintain chats between two different users for this I'm creating a parent node as +923478302658#Chat and within it, a child node as +923478302658-+923065015216 within it messages for both participants.
Here is my Chat Model:
class AllChatsModel {
var chatID: String? = null
var chatStarterName: String? = null
var chatRecieverName: String? = null
var chatStartTD: String? = null
var chatLastMessage: String? = null
var chatLastMsgTime: String? = null
var chatHeadActive: Boolean? = null
var chatMessages: ArrayList<MessageModel>? = null
}
And here is the function to send a message:
private fun sendMessage(message: String) {
val dateFormat = SimpleDateFormat("dd MMMM, yyyy 'at' HH:mm aaa")
val calendar = Calendar.getInstance()
val currentTime: String = dateFormat.format(calendar.time)
val chatID = databaseReference!!.push().key
val chatModel = AllChatsModel()
chatModel.chatStarterName = (sharedPreference?.userName)
chatModel.chatRecieverName = signUpEntity?.userUID
chatModel.chatStartTD = currentTime
chatModel.chatLastMessage = message
chatModel.chatLastMsgTime = currentTime
val chatMessagesList: ArrayList<MessageModel>? = chatModel?.chatMessages // debugs gives null here
val messageID = databaseReference!!.push().key
val messageModel = MessageModel()
messageModel.messageID = messageID
messageModel.messageText = message
messageModel.messageTime = currentTime
messageModel.msgSenderID = FirebaseAuth.getInstance().uid
messageModel.msgSenderName = (sharedPreference?.userName)
messageModel.msgSenderNo = (currentUserNo)
messageModel.msgReceiverID = signUpEntity?.userUID
messageModel.msgReceiverName = signUpEntity?.userName
messageModel.msgReceiverNo = signUpEntity?.userPhone
chatMessagesList?.add(messageModel) // here chatMessagesList is null
chatModel.chatMessages = chatMessagesList
FirebaseDatabase.getInstance().reference.child("${currentUserNo}#Chat")
.child("${currentUserNo}-${signUpEntity?.userPhone}")
.child("ChatMessages").setValue(chatModel)
txtInputMsg.setText("")
}
I want to get the firebase nodes structure like this but the app crashes. Why I'm not getting the data like that in the attached pic.
[1]: https://i.stack.imgur.com/QOW8c.png
I guess there is an error in how you define val chatMessagesList variable in sendMessage() function. Try to fix it to:
val chatMessagesList: ArrayList<MessageModel> = chatModel?.chatMessages ?: ArrayList<MessageModel>()
Using an Elvis operator ?: we guarantee that chatMessagesList variable won't be null.
When you write this code:
val chatMessagesList: ArrayList<MessageModel>? = chatModel?.chatMessages // debugs gives null here
chatModel?.chatMessages property isn't created yet, so it is null.
Just replace it with the next line and it will work:
val chatMessagesList: ArrayList<MessageModel> = chatModel?.chatMessages ?: ArrayList<MessageModel>()
Or you can just write:
val chatMessagesList = ArrayList<MessageModel>()
because you create a new object of AllChatsModel class in sendMessage() function, that's why chatModel?.chatMessages will always be null until it is initialized.

Get contacts in Android without duplicates

I've got the following code to retrieve a contact list with Name + PhoneNumber:
#SuppressLint("Range")
fun getNamePhoneDetails(): ArrayList<List<String>>? {
val names = ArrayList<List<String>>()
val cr = contentResolver
val cur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
null, null, null)
if (cur!!.count > 0) {
while (cur.moveToNext()) {
val id = cur.getString(cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NAME_RAW_CONTACT_ID))
val name = cur.getString(cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))
val number = cur.getString(cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
names.add(listOf(id, name, number))
}
}
return names
}
The output is correct once no contact has two phone numbers. However once any contact has two phone numbers I get the contact twice. It has the same id and name, but a different phone number. How can I make it so that the returned list does not have a contact twice but all phone numbers inside a list?
Something like
[1, Name Name, [phonenumber1, phonenumber2]],[2, Name Name, [phonenumber1]]
Then I could just iterate through the phonenumberlist and have all numbers as valid strings.
You should rather create a POJO Object and than assign the data into it and return a list of that POJO Object and then you can make use of distinct extension on the list to get a filtered result they way you want it .
This is how you can achieve what you want :
Create a POJO Object :
data class Contact(
val id : String ,
val name : String,
val number : String)
And then when retrieveing the data you can do the following :
#SuppressLint("Range")
fun getNamePhoneDetails(): MutableList<Contact>? {
val names = MutableList<Contact>()
val cr = contentResolver
val cur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
null, null, null)
if (cur!!.count > 0) {
while (cur.moveToNext()) {
val id = cur.getString(cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NAME_RAW_CONTACT_ID))
val name = cur.getString(cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))
val number = cur.getString(cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
names.add(Contact(id , name , number))
}
}
return names
}
And then while retreiving the data you need to just filter the list in the following manner :
val list = getNamePhoneDetails()
list.distinctBy { it.number }.forEach { println(it) }

Android: get contacts with anniversary date event

I want to fetch a list of local contacts with an anniversary date set.
I'm doing the following:
object WithAnniversary {
const val INDEX_CONTACT_ID = 0
const val INDEX_CONTACT_NAME = 1
const val INDEX_CONTACT_ANNIVERSARY = 2
const val INDEX_CONTACT_PHOTO = 3
val PROJECTION = arrayOf(
CommonDataKinds.Event.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
CommonDataKinds.Event.START_DATE,
CommonDataKinds.Phone.PHOTO_URI
)
const val WHERE = "${ContactsContract.Data.MIMETYPE} = ? AND " +
"${CommonDataKinds.Event.TYPE} = " +
"${CommonDataKinds.Event.TYPE_ANNIVERSARY}"
val SELECTION = arrayOf(CommonDataKinds.Event.CONTENT_ITEM_TYPE)
val SORT_ORDER: String? = null
}
#Throws(Exception::class)
fun obtainContactsWithAnniversaries(): List<Contact> {
val list = mutableListOf<Contact>()
val cursor = context.contentResolver.query(
ContactsContract.Data.CONTENT_URI,
WithAnniversary.PROJECTION,
WithAnniversary.WHERE,
WithAnniversary.SELECTION,
WithAnniversary.SORT_ORDER
)
if (cursor != null) {
while (cursor.moveToNext()) {
val id = cursor.getLong(WithAnniversary.INDEX_CONTACT_ID)
val name = cursor.getString(WithAnniversary.INDEX_CONTACT_NAME)
val date = cursor.getString(WithAnniversary.INDEX_CONTACT_ANNIVERSARY)
val avatarUri = cursor.getString(WithAnniversary.INDEX_CONTACT_PHOTO)
try {
val contact = contactFactory.create(id.toString(), name, null, date, avatarUri)
list.add(contact)
} catch (e: Exception) {
Log.d(TAG, "Could not parse contact with name: $name")
}
}
cursor.close()
return list.sorted()
} else {
throw Exception("Unable to retrieve contacts, returned cursor is null")
}
}
I use the exact same process for retrieving contacts with birthday dates, but using TYPE_BIRTHDAY instead of TYPE_ANNIVERSARY, but for some reason this doesn't work for anniversaries.
I have checked my local contact list and I have some contacts with birthdays and anniversaries. I can retrieve a list with contacts with birthdays but the list of contacts with anniversaries is empty.
Any help will be appreciated.
I assume the issue is with the conversion of the cursor row to your custom Contact class.
When I replace that part with just a log your code works for me:
...
while (cursor.moveToNext()) {
val id = cursor.getLong(WithAnniversary.INDEX_CONTACT_ID)
val name = cursor.getString(WithAnniversary.INDEX_CONTACT_NAME)
val date = cursor.getString(WithAnniversary.INDEX_CONTACT_ANNIVERSARY)
val avatarUri = cursor.getString(WithAnniversary.INDEX_CONTACT_PHOTO)
Log.d("TEMP", "contact $id $name $date $avatarUri")
}
...
Log:
D/TEMP: contact 98014 Test1 1979-10-06 content://com.android.contacts/contacts/98014/photo
contact 4603 test 1990-07-22 content://com.android.contacts/contacts/4603/photo
contact 98341 Voice Mail 2013-11-06 null

How to get SMS threads

I'm trying to get a list of SMS conversations on Android. I made this Kotlin code:
kotlin
val threads = contentResolver.query(Telephony.Threads.CONTENT_URI, null, null, null, Telephony.Threads.DATE)
This throws this error:
java.lang.RuntimeException: java.lang.IllegalArgumentException: Invalid column null
I don't think am querying it the right way. What can I do to fix it? Thank you in advance.
To fetch an Inbox message try this code:
First, create a Model class of messages name Message
data class Message (
var messageNumber:String?=null,
var messageContent:String?=null
)
Then fetch inbox message list like this:
private fun fetchInboxMsg(): ArrayList<Message>? {
val messageList = ArrayList<Message>()
val uriSms: Uri = Uri.parse("content://sms")
val cursor = contentResolver.query(
uriSms, arrayOf("DISTINCT address", "body"), //DISTINCT
"address IS NOT NULL) GROUP BY (address", //GROUP BY
null, null
)
if (cursor!!.count > 0) {
cursor.moveToFirst()
for (i in 0 until cursor.count) {
val number: String? = cursor.getString(cursor.getColumnIndex("address"))
val content: String? = cursor.getString(cursor.getColumnIndex("body"))
val message = Message(number, content)
messageList.add(message)
cursor.moveToNext()
}
}
cursor.close()
return messageList
}
Don't forget to provide permission READ_SMS

Categories

Resources