Receive input from Android application EditText and send to Kafka - android

The language used is Kotlin, implemented by Android Studio.
I want to change the EditText existing in the xml of the layout folder into String type and send it as Kafka value, but I keep getting an error somewhere.
It is said that it is impossible to conclude the visible error theory. Where exactly is the problem?
class Registration() : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.Sign_Up)
val rc: Button = findViewById(R.id.Registration_Completed)
val id: EditText = findViewById(R.id.ID)
val pw: EditText = findViewById(R.id.PW)
val UserID = id.text.toString() //convert id to string
val UserPW = pw.text.toString() //convert pw to string
rc.setOnClickListener {
val intent = Intent(this, next_activity::class.java)
Producer()
Toast.makeText(this, "registration completed", Toast.LENGTH_SHORT).show()
startActivity(intent)
}
}
Below is the Producer code
class Producer {
companion object {
#JvmStatic
fun main(args: String){
val TOPIC= "test"
val SERVERS = "localhost:9092"
val configs = Properties()
configs.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, SERVERS)
configs.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringSerializer")
configs.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringSerializer")
val producer = KafkaProducer<String, String>(configs)
var record: ProducerRecord<String, String> =ProducerRecord(TOPIC,"print")
Up to this point, the output is normal.
producer.send(ProducerRecord(TOPIC, UserID))
producer.send(ProducerRecord(TOPIC, UserPW))
producer.close()
try {
producer.send(ProducerRecord<String, String> (TOPIC, "SUCCESS!"))
} catch (exception:Exception)
{
exception.printStackTrace()
}
finally { producer.close() }
The connection may not work well because the cord is partially cut.
I used the id and pw variables in the Producer by dragging the EditText to Internal fun() under the Registration class.
Producer and connection, how to pull variables, etc., function errors, etc. Which is the problem?

Related

Extract Data from firebase

Unable to extract information from the datasnapshot received from firebase.
Currently, I am able to get the dataSnapshot from firebase, but I am having problems extracting the information from it.
In the example below I have a lobby with the code "81MUB" and inside I have a list of players (only using one player in the example). Data from FireBase
{
"81MUB": [
{
"name": "Alejandro",
"points": 0
}
]
}
Data Class
data class Player(
val name: String,
val points: Int
)
Listener
fun getCode(): String {
val index = ('A'..'Z') + ('1'..'9')
var code = ""
for (i in 0..4){
code += index[Random().nextInt(index.size)]
}
return code
}
class MviewModel : ViewModel() {
private val _Players: MutableLiveData<MutableList<Player>> =
MutableLiveData(mutableListOf<Player>(Player("Alejandro", 0)))
private var _LobbyCode: String = ""
private val dataBase = FirebaseDatabase.getInstance()
fun getPlayer(): MutableLiveData<MutableList<Player>> = _Players
fun createLobby() {
_LobbyCode = getCode()
}
fun listener() {
val postListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
}
override fun onCancelled(databaseError: DatabaseError) {
// Getting Post failed, log a message
}
}
dataBase.reference.child(_LobbyCode).addValueEventListener(postListener)
}
}
Any tips?
Each time you call getCode() you are generating a new random code. When reading data, you always use the exact same code that exists in the database. So in code, it should look like this:
val db = Firebase.database.reference
val codeRef = db.child("81MUB")
codeRef.get().addOnCompleteListener {
if (it.isSuccessful) {
val snapshot = it.result
val name = snapshot.child("name").getValue(String::class.java)
val points = snapshot.child("points").getValue(Long::class.java)
Log.d("TAG", "$name/$points")
} else {
Log.d("TAG", error.getMessage()) //Never ignore potential errors!
}
}
The result in the logcat will be:
Alejandro/0
If you however want to map the 81MUB node into an object of type Player, then your data class should look like this:
data class Player(
val name: String? = null,
val points: Int? = null
)
And in code:
val db = Firebase.database.reference
val codeRef = db.child("81MUB")
codeRef.get().addOnCompleteListener {
if (it.isSuccessful) {
val snapshot = it.result
val player = snapshot.getValue(Player::class.java)
Log.d("TAG", "${player.name}/${player.points}")
} else {
Log.d("TAG", error.getMessage()) //Never ignore potential errors!
}
}
Which will produce the exact same output as above.
You might also take into consideration, using the DatabaseReference#push() method which:
Create a reference to an auto-generated child location. The child key is generated client-side and incorporates an estimate of the server's time for sorting purposes.
Instead of using your codes.

How do I store a String for later use in Kotlin?

I am trying to store the String from the Hours and Number for use in a new activity. I have found ways of doing it with intent but do not want the strings sent through to the next activity. Is there any way of me saving my String data and being able to call it to a different activity?
class ChecksStartUp : AppCompatActivity() {
lateinit var hours: EditText
lateinit var number: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
getSupportActionBar()?.hide()
setContentView(R.layout.activity_Checks_pg1)
val number = findViewById(R.id.machineFleetNumberId)
val hours = findViewById(R.id.machineHoursId)
val dButton = findViewById<RadioButton>(R.id.dButtonId)
val eButton = findViewById<RadioButton>(R.id.eButtonId)
val hButton = findViewById<RadioButton>(R.id.hButtonId)
val proceedButton = findViewById<Button>(R.id.proceedButtonId)
proceedButton.setOnClickListener {
if (dButton.isChecked()) {
val intent = Intent(this, DPage::class.java)
startActivity(intent)
}
if (eButton.isChecked()) {
val intent = Intent(this, EPage::class.java)
startActivity(intent)
}
if (hButton.isChecked()) {
val intent = Intent(this, HPage::class.java)
}
}
}
}
Alot of different ways to store data. Simplest way is to create singleton class - object.
In Android studio create new Kotlin file/class, choose Object.
this is short example:
object GlobalVariables { var hourses:String?="" var number:Int?= null }
access:
GlobalVariables.number=3 - set
val number =GlobalVariables.number - get
You can access this data everywhere you want in your classes, fragments and activites , but remember - when app is terminated data is immediately lost.

How to add new object in Kotlin SharedPreferences

I have this preference manager
class JournalManager {
lateinit var pref: SharedPreferences
lateinit var editor: SharedPreferences.Editor
lateinit var con: Context
var PRIVATE_MODE: Int = 0
constructor(con: Context?) {
if (con != null) {
this.con = con
}
if (con != null) {
pref = con.getSharedPreferences(PREF_NAME,PRIVATE_MODE)
}
editor = pref.edit()
}
companion object {
val PREF_NAME: String = "Journal"
val KEY_TEXT: String = "text"
}
fun createJournalSession(
text: EditText,
) {
editor.putString(KEY_TEXT, text.toString())
editor.commit()
}
fun getJournalDetails(): Map<String, String>
{
var journal: Map<String, String> = HashMap<String, String>()
pref.getString(KEY_TEXT,null)?.let { (journal as HashMap).put(KEY_TEXT, it) }
return journal
}
fun DeleteJournal() {
editor.clear()
editor.commit()
var i: Intent = Intent(con, JournalActivity::class.java)
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
con.startActivity(i)
}
}
And I'm looking for solution to add objects in it but my app is crashing, here is a sample of how I try to add object
lateinit var journalSession: JournalManager
override fun onCreate(savedInstanceState: Bundle?) {...}
fun openDialog() {
val dialog = MaterialDialog(this)
.noAutoDismiss()
.customView(R.layout.layout_new_journal)
//set initial preferences
dialog.findViewById<Button>(R.id.save_btn).setOnClickListener{
val note = dialog.findViewById<EditText>(R.id.new_journal_input)
//add to preference
journalSession.createJournalSession(
note
)
dialog.dismiss()
}
dialog.findViewById<Button>(R.id.cancel_btn).setOnClickListener {
dialog.dismiss()
}
dialog.show()
}
Any suggestion?
Update
Let me make it clear what I'm looking for:
At the beginning I do not have any data, nor shared preference in device (shared preference will create when user saves it's first journal).
2.When user adds new journal it suppose to be stored (as of sample) like this
journal [{
note="this was user first note"
}]
Then when next time user adds new journal, it suppose to be stored (as of sample) like this
journal [{
note="this was user first note"
},
{note="this was user second note"
}]
and so on...
PS So far all videos, articles anything else I've found on web was with same logic: (they've had a List and then store that list into preferences!), my case is not like that, I do not have any list to store my list will be created one by one, during the time just like any real world apps.
Now, any idea how to make it happen, and what should I change in my code?
SharedPreferences saves primitive type data and Srting. For saving object like List you can use GSON library (by Google) to convert the object into JSON String.
1. Import Dependency:
implementation 'com.google.code.gson:gson:2.8.6'
2. Basic Usage:
val studentJsonString = Gson().toJson(student) //object -> String
val student = Gson().fromJson(studentJsonString, Student.class) //String -> object
3. For List:
val typeToken = TypeToken<List<Student>>(){}
val students = Gson().fromJson(studentsJsonString, typeToken.getType())

How to observe data inside viewmodel?

I have connect my android application to firebase and am using it to retrieve Authentication details and data from firestone. I am using an MVVM architecture and live data for this. The problem is that I need to retrieve email address first and then used this data to query the firestone which contain documents with ID = emailID. You can see my viewmodel. The value for the emailID is null when every I run this. How can I accomplish this while following the MVVP style of coding ?
#Edit: I need to understand how can check if the live data has been initialised with a value in the case where one livedata value depends on the other.
class ProfileViewModel(): ViewModel() {
var random =""
private var _name = MutableLiveData<String>()
val userName
get()=_name
private var _post = MutableLiveData<String>()
val userPost
get()=_post
private var _imgUrl = MutableLiveData<Uri>()
val userImgUrl
get()=_imgUrl
private var _emailId = MutableLiveData<String>()
val userEmailId
get()=_emailId
init{
getUserDataFromProfile()
getUserPostFromFirestone()
}
private fun getUserPostFromFirestone() {
val mDatabaseInstance: FirebaseFirestore = FirebaseFirestore.getInstance()
// _emailId.observe(getApplication(), Observer {
//
// } )
if(_emailId.value!=null){
mDatabaseInstance.collection("users").document(_emailId.value)
.get()
.addOnCompleteListener { task ->
if (task.isSuccessful) {
_post.value = task.result?.data?.get("post").toString()
} else {
// Log.w("firestone", "Error getting documents.", task.exception)
_post.value = "Unable to Retrieve"
}
}
}
}
private fun getUserDataFromProfile() {
val mAuth = FirebaseAuth.getInstance()
val currentUser = mAuth.currentUser
random = currentUser?.displayName!!
_name.value = currentUser?.displayName
_post.value = "Unknown"
_imgUrl.value = currentUser?.photoUrl
_emailId.value = currentUser?.email
}
}
If you write a wrapper over the Firebase call and expose it as a LiveData (or, in this case, I'll pretend it's wrapped in a suspendCoroutineCancellable), in which case whenever you want to chain stuff, you either need MediatorLiveData to combine multiple LiveDatas into a single stream (see this library I wrote for this specific purpose) or just switchMap.
private val auth = FirebaseAuth.getInstance()
val imgUrl: LiveData<Uri> = MutableLiveData<Uri>(auth.currentUser?.photoUrl)
val emailId: LiveData<String> = MutableLiveData<String>(auth.currentUser?.email)
val post = emailId.switchMap { emailId ->
liveData {
emit(getUserByEmailId(emailId))
}
}
you can set observer to LiveData and remove it when you don't need it:
class ProfileViewModel : ViewModel() {
private val _email = MutableLiveData<String>()
private val emailObserver = Observer<String> { email ->
//email is here
}
init {
_email.observeForever(emailObserver)
}
override fun onCleared() {
_email.removeObserver(emailObserver)
super.onCleared()
}
}
Try using coroutines for the sequential execution of the code. so once you get the output of one and then the second one starts executing. If this isnt working Please let me know i can try help you.
init{
viewModelScope.launch{
getUserDataFromProfile()
getUserPostFromFirestone()
}
}

Android (Kotlin) - How do I wait for an asynchronous task to finish?

I am new to Android and Kotlin and am currently working on a centralized API router class.
To achieve this I am using the Fuel Framework.
For the doAsync function, I use the Anko for Kotlin library.
To retrieve an authorization token from the API I currently use this method:
private fun Login(username: String, password: String, callback: (Map<Boolean, String>) -> Unit) {
"/auth/token.json".httpPost()
.header(mapOf("Content-Type" to "application/json"))
.body("""{"username":"$username", "password":"$password"}""", Charsets.UTF_8)
.response { request, response, result ->
request.headers.remove("Accept-Encoding")
when (result) {
is Result.Failure -> {
// val data = result.get()
val ex = result.getException()
val serverResponseJson = response.data.toString(Charsets.UTF_8)
var exceptionMessage = ex.message
val jelement = JsonParser().parse(serverResponseJson)
val jobject = jelement.asJsonObject
val serverResponseError = if (jobject.has("Error")) jobject.get("Error").asString else jobject.get("detail").asString
callback(mapOf(Pair(false, serverResponseError)))
}
is Result.Success -> {
val data = result.get()
val returnJson = data.toString(Charsets.UTF_8)
Log.println(Log.ASSERT, "RESULT_LOGIN", returnJson)
callback(mapOf(Pair(true, returnJson)))
}
}
}
}
I invoke this login method at
val btnLogin = findViewById<Button>(R.id.btn_login)
btnLogin.setOnClickListener { _ ->
doAsync {
val username = findViewById<EditText>(R.id.input_username_login)
val password = findViewById<EditText>(R.id.input_password_login)
Login(username.text.toString(), password.text.toString()) {
// Request was successful
if (it.containsKey(true)) {
// Parse return Json
// e.g. {"id":"36e8fac0-487a-11e8-ad4e-c471feb11e42","token":"d6897a230fd7739e601649bf5fd89ea4b93317f6","expiry":"2018-04-27T17:49:48.721278Z"}
val jelement = JsonParser().parse(it.getValue(true))
val jobject = jelement.asJsonObject
// save field for class-scope access
Constants.token = jobject.get("token").asString
Constants.id = jobject.get("id").asString
}
else{
Toast.makeText(this#LoginActivity, it.getValue(false), Toast.LENGTH_SHORT).show()
}
}
}[30, TimeUnit.SECONDS]
var test = Constants.id;
}
In a separate Constants class, I store the token and id like this:
class Constants {
companion object {
val baseUrl: String = "BASE_URL_TO_MY_API"
val contentTypeJson = "application/json"
lateinit var STOREAGE_PATH: String
// current user details
lateinit var id: String
lateinit var token: String
lateinit var refresh_token: String
// logged in User
lateinit var user: User
}
How do I make sure that the test variable is set after the asynchronous task is done? Currently, I run into
lateinit property id has not been initialized
I have come across the option to limit the task to a timeout such as I have done with [30, TimeUnit.SECONDS], unfortunately, this did not help.
Thanks for the help! Cheers.
I think the problem is where you want to access the result:
val btnLogin = findViewById<Button>(R.id.btn_login)
btnLogin.setOnClickListener { _ ->
doAsync {
val username = findViewById<EditText>(R.id.input_username_login)
val password = findViewById<EditText>(R.id.input_password_login)
var test: String? = null
Login(username.text.toString(), password.text.toString()) {
// Request was successful
if (it.containsKey(true)) {
// Parse return Json
// e.g. {"id":"36e8fac0-487a-11e8-ad4e-c471feb11e42","token":"d6897a230fd7739e601649bf5fd89ea4b93317f6","expiry":"2018-04-27T17:49:48.721278Z"}
val jelement = JsonParser().parse(it.getValue(true))
val jobject = jelement.asJsonObject
// save field for class-scope access
Constants.token = jobject.get("token").asString
Constants.id = jobject.get("id").asString
}
else{
Toast.makeText(this#LoginActivity, it.getValue(false), Toast.LENGTH_SHORT).show()
}
}
test = Constants.id // here test variable surely set if result was successful, otherwise it holds the null value
test?.let{
resultDelivered(it)
}
}[30, TimeUnit.SECONDS]
}
fun resultDelivered(id: String){
// here we know that the async job has successfully finished
}

Categories

Resources