Lambda causes unexpected token - android-studio

I'm having a problem because of lambda. It says that it has unexpected tokens but there are no helpful solutions in the debugger. I am new to programming and I have no idea what to do especially because in the tutorial I follow it's the same thing with no errors. The code and the screenshot are bellow. Thanks
image
when {
getButtonText == "Edit Profile" -> startActivity(
Intent(
context,
AccountSettingsActivity::class.java
)
)
getButtonText == "Follow" -> {
firebaseUser?.uid.let { it1 ->
FirebaseDatabase.getInstance().reference
.child("Follow").child(it1.toString())
.child("Following").child(profileId)
.setValue(true)
}
firebaseUser?.uid.let { it1 ->
FirebaseDatabase.getInstance().reference
.child("Follow").child(profileId)
.child("Followers").child(it1.toString())
.setValue(true)
}
}
}
getButtonText == "Following" -> {
firebaseUser?.uid.let { it1 ->
FirebaseDatabase.getInstance().reference
.child("Follow").child(it1.toString())
.child("Following").child(profileId)
.removeValue()
}
firebaseUser?.uid.let { it1 ->
FirebaseDatabase.getInstance().reference
.child("Follow").child(profileId)
.child("Followers").child(it1.toString())
.removeValue()
}
}
}

} <<<<
getButtonText == "Following" ->
The marked bracket is closing the when block and should be removed. When using Android Studio you should be able to hit Ctrl+Alt+L to auto fix your formatting, including indentation. This will probably help you spot these kind of mistakes in the future

Related

Why replace `capitalize` with a check for whether it is lowercase before `titlecase` is called?

When using Kotlin 1.5, Android Studio warns that String.capitalize is deprecated.
The suggested replacement is:
myString.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() })
Why is the check for isLowerCase neccessary?
Why can't I just do this:
myString.replaceFirstChar { it.titlecase(Locale.getDefault()) })
A quote from the ticket:
Additionally, users may have varied expectations about the behavior of fun String.capitalize(): String, and the expectations do not always coincide with what we have implemented (see the KEEP discussion). The function titlecases the first char of the receiver String only if it is a lower case letter. For instance, the result of "DŽ".capitalize() is "DŽ", while "dž".capitalize() is "Dž". Given the different expectations, we would like to introduce replaceFirstChar function to let users code exactly what they want.
The replacements are verbose, but preserve the behavior as close as possible. The resulting code can be simplified further if a more simple behavior is desired, for example to String.replaceFirstChar { it.uppercaseChar() }.
Below is the original answer based on my thoughts. Please also check comment as there is a good note regarding ff:
I suppose this is because they wanted to replicate original behavior. Currently capitalize implemented as:
public fun String.capitalize(locale: Locale): String {
if (isNotEmpty()) {
val firstChar = this[0]
if (firstChar.isLowerCase()) {
return buildString {
val titleChar = firstChar.titlecaseChar()
if (titleChar != firstChar.uppercaseChar()) {
append(titleChar)
} else {
append(this#capitalize.substring(0, 1).uppercase(locale))
}
append(this#capitalize.substring(1))
}
}
}
return this
}
Also, according to the note:
The title case of a character is usually the same as its upper case with several exceptions.
There are some corner cases:
fun check(x: String) {
println(x.capitalize())
println(x.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() })
println(x.replaceFirstChar { it.titlecase() })
}
fun main() {
check("dz")
check("DZ")
}
Output (playground):
Dz
Dz
Dz
DZ
DZ
Dz

Implement PIN with BiometricPromt

I am using BiometricPromt in my application.
Now I need to implement way for user to enter the PIN when Biometric is not available or enrolled.
I can use .setDeviceCredentialAllowed(true) but problem with it is when Biometric is not available or enrolled it won't show any dialog, and even if user use PIN if Biometric is available it doesn't registrate it in onAuthenticationSucceeded.
So now I am trying to implement negative button so user can enter PIN and I can catch it and see if user entered it correctly but I can't find anywhere if it is possible to do with default android PIN manager, so I don't have to implement any 3rd party library?
My current code is:
fun biometricCheck(context: Context, fragment: FragmentActivity){
val executor = ContextCompat.getMainExecutor(context)
val biometricManager = BiometricManager.from(context)
init(fragment)
when {
biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS -> {
authUser(executor, context, fragment)
}
biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> {
//No hardware
}
biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> {
//Hardware unvailable
}
biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> {
//NONE ENROLLED
}
}
}
private fun init(fragment: FragmentActivity){
//Some code
}
private fun authUser(executor: Executor, context: Context, fragment: FragmentActivity) {
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("Authentication")
//.setSubtitle("Owner confirmation")
.setDescription("Scan fingerprint or enter PIN")
//.setDeviceCredentialAllowed(true)
.setNegativeButtonText("TEST")
.build()
val biometricPrompt = BiometricPrompt(fragment, executor,
object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationSucceeded(
result: BiometricPrompt.AuthenticationResult
) {
super.onAuthenticationSucceeded(result)
val intent = Intent(context, MainActivity::class.java)
context.startActivity(intent)
}
override fun onAuthenticationError(
errorCode: Int, errString: CharSequence
) {
super.onAuthenticationError(errorCode, errString)
//Error auth
if (errorCode == BiometricConstants.ERROR_USER_CANCELED) {
//Some long code
}
}
if(errorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON) {
Log.e(TAG, "User clicked")
//loginWithPassword() // I don't know what to implement here
}
}
override fun onAuthenticationFailed() {
super.onAuthenticationFailed()
//Failed auth
}
})
biometricPrompt.authenticate(promptInfo)
}

AndroidStudio kotlin AlertDialogue with spinner populated with setItems

I want to show a modal dialogue for the user to select a Bluetooth device in the case that I can't guess it from the device names.
It appears that AlertDialogue has the facility to show a spinner / dropdown.
The alert dialogue builder has a method setItems which I seem to think is what I need, however, its parameter is CharSequence[] but I have some sort of array of strings (I can't tell exactly what I have because everything is just val).
private fun showDialog() {
val names = (bta!!.bondedDevices).map { z -> z.name };
// What is the type of names? How can you find this out?
// How can you make it into a CharSequence[]?
val ab = AlertDialog.Builder(this);
ab.setTitle("Select device");
ab.setIcon(android.R.drawable.ic_dialog_alert); // I'd prefer a question mark.
ab.setPositiveButton("Select"){dialogueInterface, which -> Toast.makeText(applicationContext, "Selected", Toast.LENGTH_LONG).show()};
ab.setNeutralButton("Cancel"){dialogueInterface, which -> Toast.makeText(applicationContext, "Cancelled", Toast.LENGTH_LONG).show()};
ab.setItems(names); // None of the following functions can be called with the arguments supplied.
val a = ab.create();
a.setCancelable(false);
a.show();
}
I think this works in Java, but it doesn't in kotlin
CharSequence[] cs = list.toArray(new CharSequence[list.size()]);
So:
In AndroidStudio how can you tell the type of a variable? (In VisualStudio if you hover over a var then the tooltip tells you.)
How in kotlin do you make a CharSequence[]?
fun elmFind() {
// Find device
val pairedDevices: Set<BluetoothDevice>? = bta!!.bondedDevices
// Try to guess.
for (device in pairedDevices!!) {
if (device.name.contains("obd")) {
elmConnect(device.name);
return;
}
}
// Still going therefore didn't find one therefore ask.
val cs: Array<CharSequence> = pairedDevices.map { z -> z.name }.toTypedArray()
var elmDeviceName: String = ""
val ab = AlertDialog.Builder(this);
ab.setTitle("Select device");
ab.setIcon(android.R.drawable.ic_dialog_alert);
ab.setPositiveButton("Select") { dialogueInterface, which ->
elmConnect(elmDeviceName);
};
ab.setNeutralButton("Cancel") { dialogueInterface, which ->
Toast.makeText(
applicationContext,
"Cancelled",
Toast.LENGTH_LONG
).show()
};
ab.setItems(cs) { dialog, which -> elmDeviceName = cs[which].toString() };
val a = ab.create();
a.setCancelable(false);
a.show();
}
Will this work with the local variable elmDeviceName being used to get the value of the selected item in the case when the OK button is pressed?

Grails security filter all action but except one

I'm gonna create a security filter for my project. I check if !session.user then redirect to action error.
Here is my current code:
all(controller: 'accounting|installation|installer|sales|service|serviceOrder|document', action: '*') {
before = {
if (!session.user) {
redirect(controller: 'installation', action: 'errors')
return false
}
}
after = { Map model ->
}
afterView = { Exception e ->
}
}
However the point is that session.user being created in controller 'installation' and action 'index'. So how can I filter without index action?
Any suggestions will be appreciated. Thanks.
You can use invert:true
e.g
def filters = {
allExceptIndex(controller:"installation",action:"index",invert:true) {
before = {
}
after = { Map model ->
}
afterView = { Exception e ->
}
}
}
For further reference see Blog
Try this
all(controller: 'accounting|installation|installer|sales|service|serviceOrder|document', action: '*') {
before = {
if (!(controllerName == 'installation' && actionName == 'index')) {
if (!session.user) {
redirect(controller: 'installation', action: 'errors')
return false
}
}
}
after = { Map model ->
}
afterView = { Exception e ->
}
}
Hope I have understood your question ,Since you want to exclude action index then ,try this ..
all(controller: 'accounting|installation|installer|sales|service|serviceOrder|document', action: '*',actionExclude:'index'){....
Regards

How to about Gpars runForkJoin and forkOffChild methods

I'm trying to work with these methods with no success and i`ll be happy if someone can help me.
I'm using groovy and i have 2 maps of strings.
I want to match between the strings of the 2 maps with threads (using by gpars)
For example :
def firstMap = ["a":"A", "b":"B"]
def secondMap = ["c":"C", "a":A"]
The normal way to equale between the maps is to
fistMap.findAll().each { first ->
secondMap.findAll.each { second ->
if (first.key.equals(second.key) && (first.value.equlas(second.value))
//saveItIntoArray
}
}
I want to do it with gpars thread so i tried :
withPool(2) {
runForkJoin(firstMap) { task ->
task.each {
secondMap.each {
//equals
}
forChild(?)
}
}
}
I kind of new with this and i really don't know how to make it work.
I will appreciate any help.
Thanks,
Or.
What I'd suggest is using parallel collections:
def firstMap = ["a":"A", "b":"B"]
def secondMap = ["c":"C", "a":"A"].asImmutable()
withPool{
println firstMap.findAllParallel { fk, fv -> secondMap.findResult { sk, sv -> fk == sk && fv == sv ? [(fk):fv] : null } }
}

Resources