Kotlin dialog/alert without MainActivity, without custom layout - android

After inspecting and trying to implement at least 8 different suggested solutions to display a message box/dialog/alert in android studio 3.2.1, I've noticed I have been unable to find any suggested solution that either:
Works without having a main activity and/or without a button that is pressed before it shows the message.
Complemented with how to import the required libraries.
6 out of 8 of my attempts are currently bottlenecked at at either of those two points. Individually troubleshooting each single one of those attempts have not led to a working case for a single approach. Therefore I have the question:
How can one display the value of a string accountType in GateKeeper.kt?
This summarizes my attempts so far:
package com.greyblocks.gatekeeper
import android.accounts.Account
import android.accounts.AccountManager
import android.app.Activity
import android.app.AlertDialog
import android.content.DialogInterface
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.View
import android.widget.TextView
import android.widget.Toast
import java.io.File
import java.io.PrintWriter
import com.google.android.material.snackbar.Snackbar
//import android.support.design
//import com.greyblocks.gatekeepersample.MainActivity
import android.widget.AdapterView
import android.content.ContextWrapper
import android.widget.EditText
import android.util.Log
import com.google.android.material.R.id.title
import com.greyblocks.gatekeeper.R.id.info
#Suppress("unused")
open class GateKeeper(private val accountManager: AccountManager,
private val accountType: String) {
fun getCurrentAccount(): Account? {
val accounts = accountManager.getAccountsByType(accountType)
if (accounts.isNotEmpty()) {
return accounts[0]
}
return null
}
fun getAuthToken(): String? {
val account = getCurrentAccount()
return account?.let { accountManager.peekAuthToken(getCurrentAccount(), AccountAuthenticator.AUTHTOKEN_TYPE_FULL_ACCESS) }
}
fun enter(user: String, password: String?, authToken: String, userData: Bundle? = null) {
if (getCurrentAccount() != null) {
logout()
}
accountManager.addAccountExplicitly(Account(user, accountType), password, userData)
accountManager.setAuthToken(getCurrentAccount(), AccountAuthenticator.AUTHTOKEN_TYPE_FULL_ACCESS, authToken)
}
fun saveUserData(key: String, value: Long) {
accountManager.setUserData(getCurrentAccount(), key, value.toString())
}
fun saveUserData(key: String, value: Int) {
accountManager.setUserData(getCurrentAccount(), key, value.toString())
}
fun saveUserData(key: String, value: String) {
accountManager.setUserData(getCurrentAccount(), key, value)
}
fun getUserData(key: String, defaultData: String? = null): String? {
return accountManager.getUserData(getCurrentAccount(), key) ?: defaultData
}
fun getLong(key: String): Long {
return accountManager.getUserData(getCurrentAccount(), key)?.toLongOrNull() ?: 0L
}
fun getInt(key: String): Int {
return accountManager.getUserData(getCurrentAccount(), key)?.toIntOrNull() ?: 0
}
fun logout() {
//try to write something to screen:
print("Maximum of a or b is " );
Log.d("TAG", "message")
println("other message")
//info("London is the capital of Great Britain")
// debug(5) // .toString() method will be executed
// warn(null) // "null" will be printed
// toast("Hello, ${name.text}!")
fun print(message: Any?) {}
var message:String
message="D";
fun print(message: String) {}
//try to write something to file:
//writeToTxt(accountType); Crashes upon pressing logout
if (getCurrentAccount() != null) {
accountManager.invalidateAuthToken(accountType, getAuthToken())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
accountManager.removeAccountExplicitly(getCurrentAccount())
} else {
#Suppress("DEPRECATION")
accountManager.removeAccount(getCurrentAccount(), null, null)
}
}
}
#Suppress("MemberVisibilityCanBePrivate")
fun isLoggedIn(): Boolean {
return getAuthToken() != null
}
fun checkUserAuth(activity: Activity) {
if (!isLoggedIn()) {
accountManager.addAccount(accountType, AccountAuthenticator.AUTHTOKEN_TYPE_FULL_ACCESS, null, null, activity,
null, null)
activity.finish()
}
}
//Attempt 0: Can't find an import for alert
// fun messageBox(String inputString){
// alert("Testing alerts") {
// title = "Alert"
// yesButton { toast("Yess!!!") }
// noButton { }
// }.show()
// }
//Attempt 1: Problem: needs to be called from an object "this" which does not exist in this file.
// fun showNormalAlert(v: View){
// val dialog = AlertDialog.Builder(this).setTitle("Kotlin Study").setMessage("Alert Dialog")
// .setPositiveButton("Confirm", { dialog, i ->
// val applicationContext=null;
// Toast.makeText(applicationContext, "Hello Friends", Toast.LENGTH_LONG).show()
// })
// .setNegativeButton("Cancel", { dialog, i -> })
// dialog.show()
// }
//Attempt 2: Can't find somefile.txt
// fun writeToTxt(input: String) {
// File("somefile.txt").printWriter().use { out ->
// out.println("${input}, ${"text1"}")
//
// }
// }
//Attempt 3: can't find file.txt
fun writeToTxt(input: String) {
PrintWriter("file.txt").use {
for (i in 1..5) {
println(i)
}
}
}
//Attempt 4: Do not know yet how to create a parentview in the middle of this code
// fun writeToTxt(input: String) {
// Snackbar.make(parentView, "The string = ", Snackbar.LENGTH_LONG).show()
// }
//Attempt 5: Don't yet know how to import the design
// fun onSNACK(view: View){
// //Snackbar(view)
// val snackbar = Snackbar.make(view, "Replace with your own action",
// Snackbar.LENGTH_LONG).setAction("Action", null)
// snackbar.setActionTextColor(Color.BLUE)
// val snackbarView = snackbar.view
// snackbarView.setBackgroundColor(Color.LTGRAY)
// val textView =
// snackbarView.findViewById(android.support.design.R.id.snackbar_text) as TextView
// textView.setTextColor(Color.BLUE)
// textView.textSize = 28f
// snackbar.show()
// }
//Attempt 6: Don't yet know how to generate the AdapterView<*>
// fun showPopup(parent: AdapterView<*>, view: View,
// position: Int, rowId: Long) {
// val result: String;
// val context = ContextWrapper(null)
// val dialog = AlertDialog.Builder(ContextWrapper(null)).show()
// val adb = AlertDialog.Builder(context)
//
// adb.setTitle("List")
// adb.setMessage(" selected Item is=" + parent.getItemAtPosition(position))
// adb.setPositiveButton("Ok", null)
// adb.show()
// Snackbar.make(view, "Invalid username or password", Snackbar.LENGTH_LONG).show()
// }
//Attempt 7: Crashes App upon opening
// #Throws(Exception::class)
// fun shouldSetView() {
// val context = ContextWrapper(null)
// val builder = AlertDialog.Builder(context)
// val view = EditText(context)
// builder.setView(view)
//
// val alert = builder.create()
// //shadowOf(alert).getView()
// view as View
// }
//Attempt 8: Can't import inflate
// fun showNewNameDialog() {
// val dialogBuilder = AlertDialog.Builder(this)
// val inflater = this.layoutInflater
// val dialogView = inflater.inflate(R.layout.custom_dialog, null)
// dialogBuilder.setView(dialogView)
//
// val editText = dialogView.findViewById<View>(R.id.editTextName) as EditText
//
// dialogBuilder.setTitle("Custom dialog")
// dialogBuilder.setMessage("Enter Name Below")
// dialogBuilder.setPositiveButton("Save", { dialog, whichButton ->
// //do something with edt.getText().toString();
//
// // Add Name in list
// nameList.add(editText.text.toString())
// // Handler code here.
// val intent = Intent(this, NewKitListActivity::class.java)
// startActivity(intent);
//
// })
// dialogBuilder.setNegativeButton("Cancel", { dialog, whichButton ->
// //pass
// })
// val b = dialogBuilder.create()
// b.show()
// }
}
For completeness: I found the MainActivityin gatekeepersample/java/com.greyblocks.gatekeepersample/MainActivity.kt. I have been able to add a button in the layout at gatekeeper/res/layout/activity_main.xml, and inside that button I am able to display alert dialogs. However my question remains how to display alert dialogs outside the MainActivity without modifying the layout. The comments have suggested to do it through a "service". I am looking into that.

Related

Dialog from extended class opens, but does not close using dialog.dismiss() Kotlin?

I had seen other questions like this, but they don't apply to this specific situation.
I have RegisterActivity extend from BaseFunctions, where the dialog is created, displayed, and closed.
I can display the dialog by using the function controlProgressDialog(true), but I cannot close it by using controlProgressDialog(false).
Here is the code:
RegisterActivity.kt:
package com.toxicflame427.flowr.activities
import android.app.Dialog
import android.os.Bundle
import android.text.TextUtils
import com.google.firebase.auth.FirebaseAuth
import com.toxicflame427.flowr.R
import com.toxicflame427.flowr.databinding.ActivityRegisterBinding
class RegisterActivity : BaseFunctions(){
private lateinit var binding : ActivityRegisterBinding
override fun onCreate(savedInstanceState: Bundle?) {
binding = ActivityRegisterBinding.inflate(layoutInflater)
super.onCreate(savedInstanceState)
setContentView(binding.root)
removeToolStatusBar()
applyEvents()
}
private fun applyEvents(){
binding.registerButton.setOnClickListener{
registerUser()
}
}
private fun validateRegisterCredentials() : Boolean{
return when{
TextUtils.isEmpty(binding.emailRegisterInput.text.toString().trim{it <= ' '}) -> {
controlSnackBar("Please enter your email address", true)
false
}
TextUtils.isEmpty(binding.passwordRegisterInput.text.toString().trim{it <= ' '}) -> {
controlSnackBar("Please enter your password", true)
false
}
TextUtils.isEmpty(binding.passwordConfirmRegisterInput.text.toString().trim{it <= ' '}) -> {
controlSnackBar("Please confirm your password", true)
false
}
binding.passwordRegisterInput.text.toString().trim{it <= ' '} != binding.passwordConfirmRegisterInput.text.toString().trim{it <= ' '} -> {
controlSnackBar("Password and confirmation password do not match", true)
false
}
else -> {
true
}
}
}
private fun registerUser(){
if(validateRegisterCredentials()){
//Trying to display the dialog, it works
controlProgressDialog(true)
val email = binding.emailRegisterInput.text.toString().trim{ it <= ' ' }
val password = binding.passwordRegisterInput.text.toString().trim { it <= ' ' }
FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, password)
.addOnCompleteListener{ task ->
//Trying to close the dialog, does not work
controlProgressDialog(false)
if (task.isSuccessful) {
//Just in case, in case i forget how to get the user
//val firebaseUser = task.result!!.user!!
finish()
} else {
controlSnackBar(task.exception!!.message.toString(), true)
}
}
}
}
And BaseFunctions.kt:
package com.toxicflame427.flowr.activities
import android.app.Dialog
import android.content.Context
import android.os.Build
import android.view.WindowInsets
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.google.android.material.snackbar.Snackbar
import com.toxicflame427.flowr.R
open class BaseFunctions : AppCompatActivity() {
fun removeToolStatusBar(){
//Check the API level of the device, lower api levels require a different
// method of hiding the status bar
#Suppress("DEPRECATION")
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
//New way of removing status bar
window.insetsController?.hide(WindowInsets.Type.statusBars())
} else {
//Old way must still be used if targeting older devices
window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
)
}
}
fun controlSnackBar(message : String, isError : Boolean){
val snackBar : Snackbar = Snackbar.make(findViewById(android.R.id.content), message, Snackbar.LENGTH_LONG)
val snackBarView = snackBar.view
if(isError){
snackBarView.setBackgroundColor(ContextCompat.getColor(this, android.R.color.holo_red_light))
snackBar.show()
} else {
snackBarView.setBackgroundColor(ContextCompat.getColor(this, android.R.color.holo_green_dark))
snackBar.show()
}
}
//This is the function attempted to be used
fun controlProgressDialog(showDialog : Boolean){
val progressDialog = Dialog(this)
progressDialog.setCancelable(false)
progressDialog.setCanceledOnTouchOutside(false)
progressDialog.setContentView(R.layout.progress_dialog)
if(showDialog){
progressDialog.show()
} else {
progressDialog.dismiss()
}
}
}
I marked comments in the code what function is being used and where I am trying it.
I had tried using different contexts. applicationContext causes the whole app to crash, base context does the same thing, 'this' works but does not let me close the dialog, this#RegisterActivity works but also wont let me close the dialog, I had tried changing the condition under the controlProgressDialog() and that did not work either.
Users can register to the app by entering their credentials to be used in Firebase Authentication. I want the dialog to display while the users data is being authenticated and it to close when the users data is done being authenticated. So far, opening the dialog works, but closing it does not. The app does not crash or anything, just just the dialog does not want to dismiss.
The only thing the dialog displays is a spinning wheel and the text "Please wait..."
Any help will be greatly appreciated!
The problem is, when you call controlProgressDialog(false),
it creates a new instance of Dialog which is why the older dialog is not dismissed.
There are 2 solution to this:
First is to return an instance of Dialog when calling controlProgressDialog.
For example:
fun getProgressDialog(): Dialog {
val progressDialog = Dialog(this)
progressDialog.setCancelable(false)
progressDialog.setCanceledOnTouchOutside(false)
progressDialog.setContentView(R.layout.progress_dialog)
return progressDialog
}
// Show the dialog.
val dialog = getProgressDialog()
dialog.show()
// dismiss the dialog.
if(dialog.isShowing) dialog.dismiss()
Second is to hold a global reference to a Dialog variable in the Activity & then handle show / dismiss.

Why is the code giving me an unresolved reference when I imported the file and the function is there?

I'm working with AWS Amplify + Android Studio. In the backend.kt file, I call UserData.setSignedIn which gives me a Unresolved reference: setSignedIn error. I imported the file where this function is but it still gives me that error. Here are the two files:
package com.wcsng.dlocapp
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.service.autofill.UserData
import android.util.Log
import com.amplifyframework.AmplifyException
import com.amplifyframework.api.aws.AWSApiPlugin
import com.amplifyframework.auth.AuthChannelEventName
import com.amplifyframework.auth.AuthException
import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin
import com.amplifyframework.auth.cognito.AWSCognitoAuthSession
import com.amplifyframework.auth.result.AuthSessionResult
import com.amplifyframework.auth.result.AuthSignInResult
import com.amplifyframework.core.Amplify
import com.amplifyframework.core.InitializationStatus
import com.amplifyframework.hub.HubChannel
import com.amplifyframework.hub.HubEvent
import com.wcsng.dlocapp.UserData.setSignedIn
object Backend {
private const val TAG = "Backend"
fun initialize(applicationContext: Context) : Backend {
try {
Amplify.addPlugin(AWSCognitoAuthPlugin())
Amplify.addPlugin(AWSApiPlugin())
Amplify.configure(applicationContext)
Log.i(TAG, "Initialized Amplify")
} catch (e: AmplifyException) {
Log.e(TAG, "Could not initialize Amplify", e)
}
Log.i(TAG, "registering hub event")
// listen to auth event
Amplify.Hub.subscribe(HubChannel.AUTH) { hubEvent: HubEvent<*> ->
when (hubEvent.name) {
InitializationStatus.SUCCEEDED.toString() -> {
Log.i(TAG, "Amplify successfully initialized")
}
InitializationStatus.FAILED.toString() -> {
Log.i(TAG, "Amplify initialization failed")
}
else -> {
when (AuthChannelEventName.valueOf(hubEvent.name)) {
AuthChannelEventName.SIGNED_IN -> {
updateUserData(true)
Log.i(TAG, "HUB : SIGNED_IN")
}
AuthChannelEventName.SIGNED_OUT -> {
updateUserData(false)
Log.i(TAG, "HUB : SIGNED_OUT")
}
else -> Log.i(TAG, """HUB EVENT:${hubEvent.name}""")
}
}
}
}
Log.i(TAG, "retrieving session status")
// is user already authenticated (from a previous execution) ?
Amplify.Auth.fetchAuthSession(
{ result ->
Log.i(TAG, result.toString())
val cognitoAuthSession = result as AWSCognitoAuthSession
// update UI
this.updateUserData(cognitoAuthSession.isSignedIn)
when (cognitoAuthSession.identityId.type) {
AuthSessionResult.Type.SUCCESS -> Log.i(TAG, "IdentityId: " + cognitoAuthSession.identityId.value)
AuthSessionResult.Type.FAILURE -> Log.i(TAG, "IdentityId not present because: " + cognitoAuthSession.identityId.error.toString())
}
},
{ error -> Log.i(TAG, error.toString()) }
)
return this
}
private fun updateUserData(withSignedInStatus : Boolean) {
UserData.setSignedIn(withSignedInStatus) // ERROR IS HERE
}
fun signOut() {
Log.i(TAG, "Initiate Signout Sequence")
Amplify.Auth.signOut(
{ Log.i(TAG, "Signed out!") },
{ error -> Log.e(TAG, error.toString()) }
)
}
fun signIn(callingActivity: Activity) {
Log.i(TAG, "Initiate Signin Sequence")
Amplify.Auth.signInWithWebUI(
callingActivity,
{ result: AuthSignInResult -> Log.i(TAG, result.toString()) },
{ error: AuthException -> Log.e(TAG, error.toString()) }
)
}
// Backend.kt
// pass the data from web redirect to Amplify libs
fun handleWebUISignInResponse(requestCode: Int, resultCode: Int, data: Intent?) {
Log.d(TAG, "received requestCode : $requestCode and resultCode : $resultCode")
if (requestCode == AWSCognitoAuthPlugin.WEB_UI_SIGN_IN_ACTIVITY_CODE) {
Amplify.Auth.handleWebUISignInResponse(data)
}
}
}
package com.wcsng.dlocapp
import android.graphics.Bitmap
import android.location.Location
import android.provider.ContactsContract
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.amplifyframework.datastore.generated.model.LocationData
// a singleton to hold user data (this is a ViewModel pattern, without inheriting from ViewModel)
object UserData {
private const val TAG = "UserData"
//
// observable properties
//
// signed in status
private val _isSignedIn = MutableLiveData<Boolean>(false)
var isSignedIn: LiveData<Boolean> = _isSignedIn
fun setSignedIn(newValue : Boolean) {
// use postvalue() to make the assignation on the main (UI) thread
_isSignedIn.postValue(newValue)
}
// a note
data class Location(val id: String, val name: String, val map: String, var location: String) {
override fun toString(): String = name
// return an API NoteData from this Note object
val data : LocationData?
get() = LocationData.builder()
.name(this.name)
.id(this.id)
.map(this.map)
.location(this.location)
.build()
// static function to create a Note from a NoteData API object
companion object {
fun from(locationData : LocationData) : Location {
val result = Location(locationData.id, locationData.name, locationData.map, locationData.location)
return result
}
}
}
}
Thanks for the help

Login button needs to be clicked twice to login

i'm making an app on AndroidStudio and I need to verify credentials when they log in to the app. The app works with an API and to verifiy credentials i created this function in the database to check someones email and password:
(postgresql)
create or replace function login (emailf text, passwordf text)
returns boolean
language plpgsql
as
$$
declare pp text;
begin
pp = (select pass_w from utilizador where utilizador.email = emailf);
if (pp = passwordf) then return true;
else return false;
end if; end
$$
I'm parsing the data through this CheckLoginas function:
var bola: Boolean? = null
fun CheckLoginas(c: Context?, email: String, pass: String): Boolean? {
var mQueue: RequestQueue
mQueue = Volley.newRequestQueue(c);
var url = "https://myurl.com" + "/utilizador/login/" + email + "/" + pass
val request = JsonArrayRequest(Request.Method.GET, url, null, Response.Listener {
response ->try {
var jsonArray = JSONArray()
jsonArray = response.getJSONArray(0)
for (i in 0 until jsonArray.length())
{
val jsonObject : JSONObject? = jsonArray.getJSONObject(i)
//val user = jsonArray.getJSONObject(i)
//val bool = jsonObject.getBoolean("login")
val boo : Boolean = jsonObject!!.getBoolean("login")
println("im inside CheckLoginas boo $boo\n\n")
bola = boo
}
} catch (e: JSONException) {
e.printStackTrace()
}
}, Response.ErrorListener { error -> error.printStackTrace() })
mQueue?.add(request)
return bola
}
'bola' variable is a global variable because I needed to return a boolean from the function so I can know if the credentials check (or not) in another activity.
The Problem:
To login when the credentials are correct, I have to press twice in the login button. If the email and password are correct, the first time I press it gives me the "Wrong credentials" error and in the second time it logs in. I already tried to do it with a while(), I checked it step by step and it seems fine, nothing seems to work to fix this error... The function works, the API too, and the app itself kinda works too, it just has this bug of clicking twice on the button... This is the activity code:
package com.example.crowdzero
import CheckLoginas
import Database
import android.content.Intent
import android.os.Bundle
import android.view.View.OnFocusChangeListener
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.textfield.TextInputLayout
import java.lang.Thread.sleep
class Login : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
val log_in_btn_log_in = findViewById<Button>(R.id.log_in_btn_log_in)
val log_in_btn_registar = findViewById<Button>(R.id.log_in_btn_registar)
log_in_btn_log_in.setOnClickListener {
verificacao()
}
log_in_btn_registar.setOnClickListener {
val intent = Intent(this, Registo::class.java)
startActivity(intent)
}
}
private fun verificacao() {
val log_in_input_text_email = findViewById<TextInputLayout>(R.id.log_in_input_text_email)
val log_in_input_text_password = findViewById<TextInputLayout>(R.id.log_in_input_text_password)
val string_email = log_in_input_text_email?.getEditText()?.getText().toString()?.trim()
val string_password = log_in_input_text_password?.getEditText()?.getText().toString()?.trim()
if (string_email.isNullOrEmpty())
{
log_in_input_text_email.setError(" ")
}
else if (string_password.isNullOrEmpty())
{
log_in_input_text_password.setError(" ")
}
else
{
val email = log_in_input_text_email.editText?.text.toString()
val password = log_in_input_text_password.editText?.text.toString()
//var baca = CheckLoginas(this,email,password)
println(email)
println(password)
var baca: Boolean? = null
baca = CheckLoginas(this, email, password)
//baca = CheckLoginas(this,email,password)
if (baca == false) {
//Toast.makeText(this, "Esta conta não está registada", Toast.LENGTH_SHORT).show();
println("Im inside if in login baca $baca")
} else if (baca == true) {
Toast.makeText(this, email, Toast.LENGTH_SHORT).show();
Toast.makeText(this, password, Toast.LENGTH_SHORT).show();
val intent = Intent(this, Home::class.java)
startActivity(intent)
finish()
}
}
}
}
When I test this with an actual email and password from the database, baca variable stays false when it should be true, since CheckLoginas boo var is true. This is what is causing the problem.
image that shows it
I'm fairly new to the Database-API-App thing, so please forgive me if its a trivial thing
You are calling baca = CheckLoginas(this, email, password)
baca will not update immedietly, the next line if (baca == false) will be executed before you API response arrives, so after you got some response baca becomes true. This is why you need to click twice.
SOLVED:
I pretty much inserted the CheckLoginas function inside the login.kt file. It works now! It looks like this now:
package com.example.crowdzero
import Database
import android.content.Intent
import android.os.Bundle
import android.view.View.OnFocusChangeListener
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.Response
import com.android.volley.toolbox.JsonArrayRequest
import com.android.volley.toolbox.Volley
import com.google.android.material.textfield.TextInputLayout
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.lang.Thread.sleep
class Login : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
val log_in_btn_log_in = findViewById<Button>(R.id.log_in_btn_log_in)
val log_in_btn_registar = findViewById<Button>(R.id.log_in_btn_registar)
log_in_btn_log_in.setOnClickListener {
verificacao()
}
log_in_btn_registar.setOnClickListener {
val intent = Intent(this, Registo::class.java)
startActivity(intent)
}
}
private fun verificacao() {
val log_in_input_text_email = findViewById<TextInputLayout>(R.id.log_in_input_text_email)
val log_in_input_text_password = findViewById<TextInputLayout>(R.id.log_in_input_text_password)
val string_email = log_in_input_text_email?.getEditText()?.getText().toString()?.trim()
val string_password = log_in_input_text_password?.getEditText()?.getText().toString()?.trim()
if (string_email.isNullOrEmpty())
{
log_in_input_text_email.setError(" ")
}
else if (string_password.isNullOrEmpty())
{
log_in_input_text_password.setError(" ")
}
else
{
val email = log_in_input_text_email.editText?.text.toString()
val password = log_in_input_text_password.editText?.text.toString()
var mQueue: RequestQueue
mQueue = Volley.newRequestQueue(this);
var url = "https://myurl.com" + "/utilizador/login/" + email + "/" + password
val request = JsonArrayRequest(Request.Method.GET, url, null, Response.Listener {
response ->try {
var jsonArray = JSONArray()
jsonArray = response.getJSONArray(0)
for (i in 0 until jsonArray.length())
{
val jsonObject : JSONObject? = jsonArray.getJSONObject(i)
//val user = jsonArray.getJSONObject(i)
//val bool = jsonObject.getBoolean("login")
val boo : Boolean = jsonObject!!.getBoolean("login")
println("im inside CheckLoginas boo $boo\n\n")
if (boo == false) {
Toast.makeText(this, "Esta conta não está registada", Toast.LENGTH_SHORT).show();
} else if (boo == true) {
Toast.makeText(this, email, Toast.LENGTH_SHORT).show();
Toast.makeText(this, password, Toast.LENGTH_SHORT).show();
val intent = Intent(this, Home::class.java)
startActivity(intent)
finish()
}
}
} catch (e: JSONException) {
e.printStackTrace()
}
}, Response.ErrorListener { error -> error.printStackTrace() })
mQueue?.add(request)
}
}
}

Kotlin Android Full Sized Camera instead of Thumbnail?

thanks for looking by! I've pretty much finished my little application i've been working on. I tried the app on my phone and found an error that I wasn't aware of when using the emulator (rookie mistake I suppose). So when the app is started the user can add like a "happy place" that looks the following:
the issue starts when the user wants to add a picture that he wants to take with the Camera itself. (That itself works). Taking the picture and also displaying it in that small box works (partly). But here is also my issue. After trying the app out on the phone i realised that the taken picture had terrible quality. I googled that issue and found out that i have used a method that only get's me the thumbnail on not the actual full sized picture. I googled more to find out how i can get that to work, unfortnunately i only found the documentation and i couldn't really figure it out either way what i had to change.
Here is my code that contains all info regarding the camera functionality:
package eu.sampa.happyPlaces.activities
import android.Manifest
import android.app.Activity
import android.app.DatePickerDialog
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.ImageDecoder
import android.location.Location
import android.location.LocationManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Looper
import android.provider.MediaStore
import android.provider.Settings
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.google.android.gms.location.*
import com.google.android.libraries.places.api.Places
import com.google.android.libraries.places.api.model.Place
import com.google.android.libraries.places.widget.Autocomplete
import com.google.android.libraries.places.widget.model.AutocompleteActivityMode
import com.karumi.dexter.Dexter
import com.karumi.dexter.MultiplePermissionsReport
import com.karumi.dexter.PermissionToken
import com.karumi.dexter.listener.PermissionRequest
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
import eu.sampa.happyPlaces.R
import eu.sampa.happyPlaces.database.DatabaseHandler
import eu.sampa.happyPlaces.models.HappyPlaceModel
import eu.sampa.happyPlaces.utils.GetAddressFromLatLng
import kotlinx.android.synthetic.main.activity_add_happy_place.*
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.OutputStream
import java.lang.Exception
import java.text.SimpleDateFormat
import java.util.*
class AddHappyPlaceActivity : AppCompatActivity(), View.OnClickListener {
// Creates a variable for GALLERY Selection which will be later used in the onActivityResult method.
companion object {
private const val GALLERY = 1
private const val CAMERA = 2
private const val IMAGE_DIRECTORY = "HappyPlacesImages"
private const val PLACE_AUTOCOMPLETE_REQUEST_CODE = 3
}
private var saveImageToInternalStorage : Uri? = null
private var mLatitude : Double = 0.0
private var mLongitude : Double = 0.0
// For the swipe feature
private var mHappyPlaceDetails : HappyPlaceModel? = null
// Will be initialized later for the get current position functionality
// https://medium.com/#droidbyme/get-current-location-using-fusedlocationproviderclient-in-android-cb7ebf5ab88e
private lateinit var mFusedLocationClient: FusedLocationProviderClient
// Creating the variables of Calender Instance and DatePickerDialog listener to use it for date selection
// A variable to get an instance calendar using the default time zone and locale.
private var cal = Calendar.getInstance()
/* A variable for DatePickerDialog OnDateSetListener.
* The listener used to indicate the user has finished selecting a date. It will be initialized later. */
private lateinit var dateSetListener : DatePickerDialog.OnDateSetListener
// Used to increment when someone clicks on the Add Photo button see below in onClick function
private var addButtonClicked = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_happy_place)
// Adds the back button on the ActionBar
setSupportActionBar(toolbar_add_place)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
toolbar_add_place.setNavigationOnClickListener {
onBackPressed()
}
// For the Places API
if(!Places.isInitialized()) {
Places.initialize(this#AddHappyPlaceActivity, resources.getString(R.string.google_maps_key))
}
if(intent.hasExtra(MainActivity.EXTRA_PLACE_DETAILS)) {
mHappyPlaceDetails = intent.getParcelableExtra(MainActivity.EXTRA_PLACE_DETAILS) as HappyPlaceModel
}
// Initialize the DatePicker and sets the selected date
// https://www.tutorialkart.com/kotlin-android/android-datepicker-kotlin-example/
dateSetListener = DatePickerDialog.OnDateSetListener{
_, year, month, dayOfMonth ->
cal.set(Calendar.YEAR, year)
cal.set(Calendar.MONTH, month)
cal.set(Calendar.DAY_OF_MONTH, dayOfMonth)
updateDateInView()
}
// Automatically sets the current date
updateDateInView()
// Uses functionality in the onClick function below
et_date.setOnClickListener(this)
tv_add_image.setOnClickListener(this)
btn_save.setOnClickListener(this)
et_location.setOnClickListener(this)
tv_select_current_location.setOnClickListener(this)
if(mHappyPlaceDetails != null) {
supportActionBar?.title = "Edit Happy PLace"
et_title.setText(mHappyPlaceDetails!!.title)
et_description.setText(mHappyPlaceDetails!!.description)
et_date.setText(mHappyPlaceDetails!!.date)
et_location.setText(mHappyPlaceDetails!!.location)
mLatitude = mHappyPlaceDetails!!.latitude
mLongitude = mHappyPlaceDetails!!.longitude
saveImageToInternalStorage = Uri.parse(mHappyPlaceDetails!!.image)
iv_place_image.setImageURI(saveImageToInternalStorage)
btn_save.text = "UPDATE"
}
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
}
// This is a override method after extending the onclick listener interface (gets created automatically)
override fun onClick(v: View?) {
when (v!!.id) {
R.id.et_date -> {
DatePickerDialog(this#AddHappyPlaceActivity, dateSetListener,
cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)).show()
}
R.id.tv_add_image -> {
val pictureDialog = AlertDialog.Builder(this)
pictureDialog.setTitle("Select Action")
val pictureDialogItems = arrayOf("Select photo from gallery", "Capture photo from camera")
pictureDialog.setItems(pictureDialogItems) {
_, which ->
when(which) {
0 -> choosePhotoFromGallery()
1 -> takePhotoFromCamera()
}
}
pictureDialog.show()
/* Used to display the Dialog to get to the menu after the user
* denied access 2 or more times */
addButtonClicked += 1
if (addButtonClicked > 2) {
if (ContextCompat.checkSelfPermission(this#AddHappyPlaceActivity,
Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
showRationalDialogForPermissions()
}
if (ContextCompat.checkSelfPermission(this#AddHappyPlaceActivity,
Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
showRationalDialogForPermissions()
}
if (ContextCompat.checkSelfPermission(this#AddHappyPlaceActivity,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
showRationalDialogForPermissions()
}
}
}
R.id.btn_save -> {
when {
et_title.text.isNullOrEmpty() -> {
Toast.makeText(this, "Please enter title", Toast.LENGTH_SHORT).show()
}
et_description.text.isNullOrEmpty() -> {
Toast.makeText(this, "Please enter description", Toast.LENGTH_SHORT)
.show()
}
et_location.text.isNullOrEmpty() -> {
Toast.makeText(this, "Please select location", Toast.LENGTH_SHORT)
.show()
}
saveImageToInternalStorage == null -> {
Toast.makeText(this, "Please add image", Toast.LENGTH_SHORT).show()
}
else -> {
// Assigning all the values to data model class.
val happyPlaceModel = HappyPlaceModel(
if(mHappyPlaceDetails == null) 0 else mHappyPlaceDetails!!.id,
et_title.text.toString(),
saveImageToInternalStorage.toString(),
et_description.text.toString(),
et_date.text.toString(),
et_location.text.toString(),
mLatitude,
mLongitude
)
// Here we initialize the database handler class.
val dbHandler = DatabaseHandler(this)
if (mHappyPlaceDetails == null) {
val addHappyPlace = dbHandler.addHappyPlace(happyPlaceModel)
if (addHappyPlace > 0) {
setResult(Activity.RESULT_OK)
finish() // Gets us back to MainActivity
}
} else{
val updateHappyPlace = dbHandler.updateHappyPlace(happyPlaceModel)
// greater than zero indicates that everything worked out
if (updateHappyPlace > 0) {
setResult(Activity.RESULT_OK)
finish() // Gets us back to MainActivity
}
}
}
}
}
// For the Places API
R.id.et_location -> {
try{
// This is the list of fields that need to be passed
val fields = listOf(Place.Field.ID, Place.Field.NAME, Place.Field.LAT_LNG, Place.Field.ADDRESS)
// Start the autocomplete intent with a unique request code.
val intent = Autocomplete.IntentBuilder(AutocompleteActivityMode.FULLSCREEN, fields).build(this#AddHappyPlaceActivity)
startActivityForResult(intent, PLACE_AUTOCOMPLETE_REQUEST_CODE)
}catch (e: Exception) {
e.printStackTrace()
Toast.makeText(this, "Couldnt load it", Toast.LENGTH_SHORT).show()}
}
R.id.tv_select_current_location -> {
if (!isLocationEnabled()) {
Toast.makeText(this, "Your location provider is turned off. Please turn it on.", Toast.LENGTH_SHORT).show()
// This will redirect the user to settings from where you need to turn on the location provider.
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)
} else {
// https://www.androdocs.com/kotlin/getting-current-location-latitude-longitude-in-android-using-kotlin.html
Dexter.withActivity(this)
.withPermissions(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION).withListener(object : MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
if (report!!.areAllPermissionsGranted()) {
requestNewLocationData()
}
}
override fun onPermissionRationaleShouldBeShown(
permissions: MutableList<PermissionRequest>?,
token: PermissionToken?
) {
showRationalDialogForPermissions()
}
}).onSameThread()
.check()
}
}
}
}
// https://stackoverflow.com/questions/51313359/get-current-location-android-kotlin
private fun isLocationEnabled(): Boolean {
val locationManager: LocationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER )
}
// Method used for taking pictures with the Camera
private fun takePhotoFromCamera() {
// Asking for permissions using DEXTER Library
Dexter.withContext(this).withPermissions(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA
).withListener(object : MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
// Here after all the permission are granted launch the Camera to capture an image
val galleryIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(galleryIntent, CAMERA )
}
override fun onPermissionRationaleShouldBeShown(permissions: MutableList<PermissionRequest>?, token: PermissionToken?) {
token?.continuePermissionRequest()
}
}).onSameThread().check()
}
// Method used for image selection from GALLERY/PHOTOS
private fun choosePhotoFromGallery() {
// Asking for permissions using DEXTER Library
Dexter.withContext(this).withPermissions(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA
).withListener(object : MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
// Here after all the permission are granted, launch the gallery to select and image.
val galleryIntent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
startActivityForResult(galleryIntent,
GALLERY
)
}
override fun onPermissionRationaleShouldBeShown(permissions: MutableList<PermissionRequest>?, token: PermissionToken?) {
token?.continuePermissionRequest()
}
}).onSameThread().check()
}
// Message to be shown if user denies access and possibly send him to the settings
private fun showRationalDialogForPermissions() {
AlertDialog.Builder(this).setMessage("It looks like you have turned off " +
"permissions required for this feature").setPositiveButton("GO TO SETTINGS")
{ _, _ ->
try{
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val uri = Uri.fromParts("package", packageName, null)
intent.data = uri
startActivity(intent)
} catch (e: ActivityNotFoundException) {
e.printStackTrace()
}
}.setNegativeButton("Cancel") { dialog, _ ->
dialog.dismiss()
}.show()
}
// Handles the chosen Image from the startActivityResult from choosePhotoFromGallery and takePhotoFromCamera
#RequiresApi(Build.VERSION_CODES.P)
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(resultCode == Activity.RESULT_OK) {
if(requestCode == GALLERY) {
if(data != null) {
val contentURI = data.data
// For more info go to https://stackoverflow.com/questions/56651444/deprecated-getbitmap-with-api-29-any-alternative-codes
try {
if(Build.VERSION.SDK_INT < 28) {
// Here this is used to get an bitmap from URI
val selectedImageBitmap = MediaStore.Images.Media.getBitmap(this.contentResolver, contentURI)
// Saving an image which is selected from GALLERY. And printed the path in logcat
saveImageToInternalStorage = saveImageToInternalStorage(selectedImageBitmap)
Log.e("Saved image: ", "Path :: $saveImageToInternalStorage")
iv_place_image!!.setImageBitmap(selectedImageBitmap) // Set the selected image from GALLERY to imageView
} else {
val selectedImageBitmapSource = contentURI?.let { ImageDecoder.createSource(this.contentResolver, it) }
val selectedImageBitmap = selectedImageBitmapSource?.let { ImageDecoder.decodeBitmap(it) }
// Saving an image which is selected from GALLERY. And printed the path in logcat
saveImageToInternalStorage = selectedImageBitmap?.let { saveImageToInternalStorage(it) }
Log.e("Saved image: ", "Path :: $saveImageToInternalStorage")
iv_place_image.setImageBitmap(selectedImageBitmap)
}
} catch (e: IOException) {
e.printStackTrace()
Toast.makeText(this#AddHappyPlaceActivity, "Failed to load the Image!", Toast.LENGTH_SHORT).show()
}
}
// Camera result will be received here
} else if(requestCode == CAMERA){
val thumbNail : Bitmap = data!!.extras!!.get("data") as Bitmap // Bitmap from camera
// Saving an image which is selected from CAMERA. And printed the path in logcat
saveImageToInternalStorage = saveImageToInternalStorage(thumbNail)
Log.e("Saved image: ", "Path :: $saveImageToInternalStorage")
iv_place_image.setImageBitmap(thumbNail) // Set to the imageView
// For the Places API
} else if(requestCode == PLACE_AUTOCOMPLETE_REQUEST_CODE) {
val place : Place = Autocomplete.getPlaceFromIntent(data!!)
et_location.setText(place.address)
mLatitude = place.latLng!!.latitude
mLongitude = place.latLng!!.longitude
}
}
}
// A function to update the selected date in the UI with selected format.
private fun updateDateInView() {
val myFormat = "dd.MM.yyyy"
val sdf = SimpleDateFormat(myFormat, Locale.getDefault())
et_date.setText(sdf.format(cal.time).toString())
}
/* https://android--code.blogspot.com/20 18/04/android-kotlin-save-image-to-internal.html
Uri gives us the location back */
private fun saveImageToInternalStorage(bitmap: Bitmap):Uri {
// Get the context wrapper instance
val wrapper = ContextWrapper(applicationContext)
// This line returns a directory in the internal storage
var file = wrapper.getDir(IMAGE_DIRECTORY, Context.MODE_PRIVATE)
// First we give the location and then we generate a random Name for the Image
file = File(file, "${UUID.randomUUID()}.jpg")
//
try {
val stream : OutputStream = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.JPEG,100, stream)
stream.flush()
stream.close()
}catch (e: IOException) {
e.printStackTrace()
}
// Return the saved image uri
return Uri.parse(file.absolutePath)
}
private fun requestNewLocationData() {
var mLocationRequest = LocationRequest()
mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
mLocationRequest.interval = 1000
mLocationRequest.numUpdates = 1
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper())
}
private val mLocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
val mLastLocation: Location = locationResult.lastLocation
mLatitude = mLastLocation.latitude
Log.e("Current Latitude", "$mLatitude")
mLongitude = mLastLocation.longitude
Log.e("Current Longitude", "$mLongitude")
val addressTask = GetAddressFromLatLng(this#AddHappyPlaceActivity, mLatitude, mLongitude)
addressTask.setAddressListener(object : GetAddressFromLatLng.AddressListener {
override fun onAddressFound(address: String?) {
Log.e("Address ::", "" + address)
et_location.setText(address) // Address is set to the edittext
}
override fun onError() {
Log.e("Get Address ::", "Something is wrong...")
}
})
addressTask.executeGetAddress()
}
}
}

Check if EditText is empty kotlin android

How do you check if an EditText is empty? input type number
package com.example.www.myapplication
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
val inter:Int=editText.text.toString().toInt()
val year: Int = Calendar.getInstance().get(Calendar.YEAR)
val res:Int=year-inter
textView.text=res.toString()
}
}
Harness Kotlin power by using inline extension functions:
editText.text.isNotEmpty().apply {
//do something
}
or use let
Here is the full example with explanation.
//init the edittext
val etMessage = findViewById(R.id.et_message) as EditText
//init the button
val btnClick = findViewById(R.id.btn_click) as Button
btnClick.setOnClickListener{
//read value from EditText to a String variable
val msg: String = etMessage.text.toString()
//check if the EditText have values or not
if(msg.trim().length>0) {
Toast.makeText(applicationContext, "Message : "+msg, Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(applicationContext, "Please enter some message! ", Toast.LENGTH_SHORT).show()
}
}
You can be done by below way
if (mEdtDeviceName.text.toString().trim().isNotEmpty() ||
mEdtDeviceName.text.toString().trim().isNotBlank()) {
// your code
} else {
Toast.makeText(activity, "Error Msg", Toast.LENGTH_SHORT).show()
}
Hey I am using like this in kotlin
val input = editText?.text.toString().trim()
if (input.isNullOrBlank()) {
//Your code for blank edittext
}
Hope this will help you..let me know if any issue....
try this out:
bottom.setOnClickListener{
val new = addText.text.toString()
if (new = isNotEmpty()) {
//do something
} else {
Toast.makeText(context, "Enter some message ", Toast.LENGTH_SHORT).show()
}
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val btnSignUp : Button = findViewById(R.id.signUp)
val et_username : EditText = findViewById(R.id.etUsername)
val et_email : EditText = findViewById(R.id.etEmail)
val et_password : EditText = findViewById(R.id.etPassword)
btnSignUp.setOnClickListener{
val user_msg_error: String = et_username.text.toString()
//check if the EditText have values or not
if(user_msg_error.trim().isEmpty()) {
et_username.error = "Required"
Toast.makeText(applicationContext, "User Name Required ", Toast.LENGTH_SHORT).show()
}
else if (et_email.text.toString().trim().isEmpty()) {
et_email.error = "Required"
Toast.makeText(applicationContext, "Email Required ", Toast.LENGTH_SHORT).show()
}
else if (et_password.text.toString().trim().isEmpty()) {
et_password.error = "Required"
Toast.makeText(applicationContext, "Password Required ", Toast.LENGTH_SHORT).show()
}
else{
Toast.makeText(applicationContext, "Login Successful ", Toast.LENGTH_SHORT).show()
// After successful login u will move on next page/ activity
val i = Intent(this,SecondActivity::class.java)
startActivity(i)
}
}
}
}
Try this:
if(TextUtils.isEmpty(editText.getText().toString())){
//Do
}
Been a new guy Tried lots and this Worked for me
if(!editTextTerminalName.text.toString().trim().isNotEmpty()) {
editTextTerminalName?.error = "Required"
}else if(!editTextPassword.text.toString().trim().isNotEmpty()){
editTextPassword?.error = "Required"
}else{
avi.visibility= View.VISIBLE // v letter should be capita
}
if (regemail.isEmpty())
{
Toast.makeText(this,"Enter Email..!!!",Toast.LENGTH_LONG).show()
}
Same solution but using class TextUtil and .isEmpty(charsequence:)
btnGo.setOnClickListener{
val input1 = etName.text.toString.trim() // 1
if(TextUtils.isEmpty(input1)){ // 2
etName.error = "Enter a name" // 3
return#setOnClickListener //4
}
//code to store a Bundle or insert in a sqlitedb etc
// go to secondactiviy
}
user only typed spacebars??? .trim() helps with that
TextUtil is a class .isEmpty one of its methods
displays a clickable red (!) in the EditText and when it is pressed displays "Enter a name" of course you can use getString(R.string.somename)
restarts onclicklistener / "restricts" some actions like change to other acivity, avoinding (for example) passing null a bundle() or insert a null in a db
Just do this, i was facing the same issue. :)
button.setOnClickListener {
val checkUsername = userName.text.toString()
if (checkUsername.isNullOrBlank()) {
Toast.makeText(context, "Please enter your name", Toast.LENGTH_SHORT).show()
} else {
val action = UserLoginFragmentDirections.actionUserLoginFragmentToBmiFragment()
findNavController().navigate(action)
}
}

Categories

Resources