lateinit variable not being initialized in a thread - android

So I'm working with the google sheets api in an android app and I'm trying to get the credentials in a separate thread. This is what I have:
GoogleSheets is a class I created to get credentials and cell values of my spreadsheet
private lateinit var sheets: GoogleSheets is a instance variable that I declare at the beginning of the class. I am trying to initialize here:
load.setOnClickListener(View.OnClickListener {
Thread {
sheets = GoogleSheets(requireContext(), "1fs1U9-LMmkmQbQ2Kn-rNVHIQwh6_frAbwaTp7MSyDIA")
}.start()
println(sheets)
println(sheets.getValues("A1"))
})
but It's telling me that the sheets variable hasn't been initialized:
kotlin.UninitializedPropertyAccessException: lateinit property sheets has not been initialized
here is the full class:
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.example.frcscout22.GoogleSheets
import com.example.frcscout22.R
// TODO: AUTOMATICALLY SWITCH TO DATA TAB AFTER LOAD OR CREATE NEW
class Home: Fragment(R.layout.fragment_home) {
private lateinit var sheets: GoogleSheets
private val STORAGE_PERMISSION_CODE = 100
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
#RequiresApi(Build.VERSION_CODES.P)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view: View = inflater.inflate(R.layout.fragment_home, container, false)
val load = view.findViewById<Button>(R.id.button3)
val new = view.findViewById<Button>(R.id.button4)
val editText = view.findViewById<EditText>(R.id.editTextTextPersonName)
if (!checkPermission()) {
println("requested")
requestPermission()
}
new.setOnClickListener(View.OnClickListener {
val sheets = GoogleSheets(requireContext(),"1fs1U9-LMmkmQbQ2Kn-rNVHIQwh6_frAbwaTp7MSyDIA")
sheets.setValues("A1", "this is a test", "USER_ENTERED")
println(sheets.getValues("A1").values)
})
load.setOnClickListener(View.OnClickListener {
Thread {
sheets = GoogleSheets(requireContext(), "1fs1U9-LMmkmQbQ2Kn-rNVHIQwh6_frAbwaTp7MSyDIA")
}.start()
println(sheets)
println(sheets.getValues("A1"))
})
return view
}
private fun requestPermission(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
//Android is 11(R) or above
try {
val intent = Intent()
intent.action = Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
val uri = Uri.fromParts("package", requireActivity().packageName, "Home")
intent.data = uri
storageActivityResultLauncher.launch(intent)
}
catch (e: Exception){
val intent = Intent()
intent.action = Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
storageActivityResultLauncher.launch(intent)
}
}
else{
//Android is below 11(R)
ActivityCompat.requestPermissions(requireActivity(),
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE),
STORAGE_PERMISSION_CODE
)
}
}
private val storageActivityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
//here we will handle the result of our intent
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
//Android is 11(R) or above
if (Environment.isExternalStorageManager()){
//Manage External Storage Permission is granted
}
}
else{
//Android is below 11(R)
}
}
private fun checkPermission(): Boolean{
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
//Android is 11(R) or above
Environment.isExternalStorageManager()
}
else{
//Android is below 11(R)
val write = ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
val read = ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE)
write == PackageManager.PERMISSION_GRANTED && read == PackageManager.PERMISSION_GRANTED
}
}
}
I can't figure out why the varible isn't being initialized. Does it have something to do with it being in a thread? How can I fix this problem? Thanks!!

You're starting another thread to initialize it, so if you check for it immediately, the other thread hasn't had time to initialize the property yet. This is a misuse of lateinit and you are also failing to utilize thread synchronization, so it is susceptible to other bugs.
I suggest loading the sheet with a coroutine and using a suspend function to retrieve the instance when you need to use it anywhere. When using only coroutines to access the property, you don't need to worry about thread synchronization.
Really, this should go in a class that outlives the Fragment so you don't have to reload it every time the Fragment is recreated, but for simplicity, I'll just keep it in your Fragment for this example.
class Home: Fragment(R.layout.fragment_home) {
private val loadSheetsDeferred = viewLifecycle.lifecycleScope.async(Dispatchers.IO) {
GoogleSheets(requireContext(), "1fs1U9-LMmkmQbQ2Kn-rNVHIQwh6_frAbwaTp7MSyDIA")
}
private suspend fun getSheets(): GoogleSheets = loadSheetsDeferred.await()
private val STORAGE_PERMISSION_CODE = 100
#RequiresApi(Build.VERSION_CODES.P)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
//...
new.setOnClickListener { viewLifecycle.lifecycleScope.launch {
getSheets().setValues("A1", "this is a test", "USER_ENTERED")
println(getSheets().getValues("A1").values)
} }
load.setOnClickListener { viewLifecycle.lifecycleScope.launch {
println(getSheets())
println(getSheets().getValues("A1"))
} }
return view
}
//...
}

At a guess the error's telling you it's happening when you do this:
Thread {
sheets = GoogleSheets(requireContext(), "1fs1U9-LMmkmQbQ2Kn-rNVHIQwh6_frAbwaTp7MSyDIA")
}.start()
println(sheets)
lateinit is you promising the compiler you'll have assigned a value to sheets before anything tries to read it, which you're doing with println(sheets). You're assigning it in that thread you just started - but that's very unlikely to have completed before the println statement runs on the current thread!
You also have to worry about synchronisation if you're involving threading like this - just because your worker thread sets the value of sheets, it doesn't mean the current thread will see that updated value. You can have a look here if you're not familiar with that whole issue and the steps you have to take to ensure things stay consistent.
Your best bet with the code you have is to do your println stuff inside the thread after sheets is assigned. If you do anything more complicated than that, and need to get back on the main thread, you can post a Runnable on a view. Honestly, if you can use coroutines instead that would probably make your life easier in the long run

Related

Caused by: java.io.IOException: The Application Default Credentials are not available

I'm working on an android app that interfaces with a google sheet. I was following the api documentation for writing values to certain cells but I'm getting this error here:
Caused by: java.io.IOException: The Application Default Credentials are not available.
I have made sure to set my credentials in google cloud platform for my project and downloaded the .json file to src\main\resources in my android studio project.
here is the code that is supposed to write the data:
package com.example.frcscout22
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.fragment.app.Fragment
import com.google.api.client.http.HttpRequestInitializer
import com.google.api.client.http.javanet.NetHttpTransport
import com.google.api.client.json.gson.GsonFactory
import com.google.api.services.sheets.v4.Sheets
import com.google.api.services.sheets.v4.SheetsScopes
import com.google.api.services.sheets.v4.model.ValueRange
import com.google.auth.http.HttpCredentialsAdapter
import com.google.auth.oauth2.GoogleCredentials
import java.util.*
class Data : Fragment(R.layout.fragment_data) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val spinner = view.findViewById<Spinner>(R.id.defense_spinner)
val aa = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, resources.getStringArray(R.array.Defenses))
aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = aa
view.findViewById<Spinner>(R.id.defense_spinner).visibility = View.GONE
view.findViewById<TextView>(R.id.textView6).visibility = View.GONE
view.findViewById<EditText>(R.id.Team_Defended).visibility = View.GONE
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view: View = inflater!!.inflate(R.layout.fragment_data, container, false)
val checkBox = view.findViewById<CheckBox>(R.id.checkBox)
checkBox.setOnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
view.findViewById<Spinner>(R.id.defense_spinner).visibility = View.VISIBLE
view.findViewById<TextView>(R.id.textView6).visibility = View.VISIBLE
view.findViewById<EditText>(R.id.Team_Defended).visibility = View.VISIBLE
} else {
view.findViewById<Spinner>(R.id.defense_spinner).visibility = View.GONE
view.findViewById<TextView>(R.id.textView6).visibility = View.GONE
view.findViewById<EditText>(R.id.Team_Defended).visibility = View.GONE
}
}
val clear = view.findViewById<Button>(R.id.button2)
clear.setOnClickListener(View.OnClickListener {
view.findViewById<EditText>(R.id.Match_Number).setText("")
view.findViewById<EditText>(R.id.Team_Number).setText("")
view.findViewById<EditText>(R.id.Auto_Points).setText("")
view.findViewById<EditText>(R.id.Teleop_Points).setText("")
view.findViewById<EditText>(R.id.Endgame_Points).setText("")
view.findViewById<EditText>(R.id.Team_Defended).setText("")
view.findViewById<Spinner>(R.id.defense_spinner).setSelection(0)
view.findViewById<CheckBox>(R.id.checkBox).isChecked = false
})
val table : MutableList<MutableList<Any>> = mutableListOf(mutableListOf("test", "test2"))
val values = ValueRange()
values.majorDimension = "ROWS"
values.setValues(table)
val button = view.findViewById<View>(R.id.button)
button.setOnClickListener(View.OnClickListener {
setRow("1fs1U9-LMmkmQbQ2Kn-rNVHIQwh6_frAbwaTp7MSyDIA", "Sheet1!A1:B1", values)
})
// Return the fragment view/layout
return view
}
private fun setRow(spreadSheetID: String, range: String, values: ValueRange) {
val credentials: GoogleCredentials = GoogleCredentials.getApplicationDefault().createScoped(
Collections.singleton(
SheetsScopes.SPREADSHEETS))
val requestInitializer: HttpRequestInitializer = HttpCredentialsAdapter(credentials)
val service: Sheets = Sheets.Builder(NetHttpTransport(), GsonFactory.getDefaultInstance(), requestInitializer).setApplicationName("FRCScout22").build()
service.spreadsheets().values().update(spreadSheetID, range, values)
.setValueInputOption("USER_ENTERED")
.execute();
}
}
Does anyone know why I may be getting this error? Thanks!!
Application Default Credentials (ADC) is a process that looks for the credentials in various places including the env var GOOGLE_APPLICATION_CREDNTIALS.
If GOOGLE_APPLICATION_CREDNTIALS is unset ADC fails and raises an error.

Launching activity from Fragment, Kotlin

I'm new to Kotlin/Android development and I'm making an app to display quizzes. Recently I decided to begin using fragments. On my MainActivity which has three fragments, I'd like one to have a method of clicking a subject and being taken to that particular quiz activity.
Note, there is only one quiz activity, but the intents pass a variable to display the relevant data for the quiz.
I had correctly implemented this when this page was not a fragment but struggling to find a solution this time.
Subject Fragment:
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.financialapp.InformationPage
import com.example.financialapp.databinding.FragmentModuleBinding
import android.content.Intent
class ModuleFragment : Fragment(com.quizapp.R.layout.fragment_module) {
private var _binding: FragmentModuleBinding ? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentModuleBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val subjectOne = binding.tvEnglish
subjectOne.setOnClickListener {
sendIntent(0)
}
val subjectTwo = binding.tvGeography
subjectOne.setOnClickListener {
sendIntent(1)
}
val subjectThree = binding.tvHistory
subjectThree.setOnClickListener{
sendIntent(2)
}
...
}
private fun sendIntent(passedVariable: Int) {
val intent = Intent(this, SubjectPage::class.java)
intent.putExtra("subject", passedVariable)
startActivity(intent)
finish()
}
...
At present I have errors from Intent asking to create a function, same with finish().
Having looked through several tutorials I can't seem to see whether it's possible or not.
finish() is actually called on activity so you can use requireActivity() get hold of the hosting activity of your fragment & instead of using this in Intent params you can use requireContext()
Example:
private fun sendIntent(passedVariable: Int) {
val intent = Intent(requireContext(), MainActivity::class.java)
intent.putExtra("subject", passedVariable)
startActivity(intent)
requireActivity().finish()
}
Actually, as you started to use fragments you can avoid to start another activity.
Use childFragmentManager and just create for your quiz another fragment.
https://developer.android.com/reference/androidx/fragment/app/Fragment#getChildFragmentManager()

Unresolved reference (vars) in Fragment class, MVVM, Viewmodel

I'm following UDACITY free course on developing Android apps with Kotlin and I'm actually at the Viewmodel/MVVM part of the lesson, ie implementing Viewmodel classes for a better separation of concerns. So anyway, Im blocked right now. The exercise I'm on is about creating the Viewmodel class and transferring variables and functions from the Fragment class to this newly created class. I follow the tutorial step by step, check the correct answer on the provided git diff and I still find myself blocked by Unresolved reference errors.
Before changing the code, i had to update my Gradle module file to use ViewModel
//ViewModel
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
Then I had to declare my Viewmodel object in my Fragment class
gameViewModel = ViewModelProviders.of(this).get(GameViewModel::class.java)
ViewModelProviders being deprecated, old course, I had to change, after search, to
gameViewModel = ViewModelProvider(this).get(GameViewModel::class.java)
It seems to be the right way to do, but I'm still left with some Unresolved references on the variables word (gameViewModel.word) and score (gameViewModel.score) in the Fragment class, unable to compile. I dont know if I declared the Viewmodel object correctly or if I'm missing something else...
I dont have this problem, Unresolved reference, with my ViewModel class functions, ie gameViewModel.onCorrect() and gameViewModel.onSkip(). They seem to be properly declared and called in the Fragment class, which begs me the question on my variables, word and score...
My Fragment class
package com.example.android.guesstheword.screens.game
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.NavHostFragment.findNavController
import com.example.android.guesstheword.R
import com.example.android.guesstheword.databinding.GameFragmentBinding
import timber.log.Timber
class GameFragment : Fragment() {
private lateinit var binding: GameFragmentBinding
private lateinit var gameViewModel: GameViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate view and obtain an instance of the binding class
binding = DataBindingUtil.inflate(
inflater,
R.layout.game_fragment,
container,
false
)
Timber.i("onCreateView GameFragment called")
gameViewModel = ViewModelProvider(this).get(GameViewModel::class.java)
Timber.i("ViewModelProvider is called")
binding.correctButton.setOnClickListener {
gameViewModel.onCorrect()
updateScoreText()
updateWordText()
}
binding.skipButton.setOnClickListener {
gameViewModel.onSkip()
updateScoreText()
updateWordText()
}
updateScoreText()
updateWordText()
return binding.root
}
/**
* Called when the game is finished
*/
fun gameFinished() {
val action = GameFragmentDirections.actionGameToScore(gameViewModel.score)
findNavController(this).navigate(action)
}
/** Methods for updating the UI **/
private fun updateWordText() {
binding.wordText.text = gameViewModel.word
}
private fun updateScoreText() {
binding.scoreText.text = gameViewModel.score.toString()
}
override fun onDestroyView() {
super.onDestroyView()
Timber.i("onDestroyView GameFragment called")
}
}
My ViewModel class
package com.example.android.guesstheword.screens.game
import androidx.lifecycle.ViewModel
import timber.log.Timber
var word = ""
var score = 0
private lateinit var wordList: MutableList<String>
class GameViewModel: ViewModel() {
init {
Timber.i("GameViewModel is created")
resetList()
nextWord()
}
override fun onCleared() {
super.onCleared()
Timber.i("GameViewModel is cleared")
}
/**
* Resets the list of words and randomizes the order
*/
fun resetList() {
wordList = mutableListOf(
"queen",
"hospital",
"basketball",
"cat",
"change",
"snail",
"soup",
"calendar",
"sad",
"desk",
"guitar",
"home",
"railway",
"zebra",
"jelly",
"car",
"crow",
"trade",
"bag",
"roll",
"bubble"
)
wordList.shuffle()
}
/**
* Moves to the next word in the list
*/
private fun nextWord() {
//Select and remove a word from the list
if (wordList.isEmpty()) {
//gameFinished()
} else {
word = wordList.removeAt(0)
}
}
/** Methods for buttons presses **/
fun onSkip() {
score--
nextWord()
}
fun onCorrect() {
score++
nextWord()
}
}
Where did I screw up ?
The variables you're trying to access aren't part of the same scope:
var word = ""
var score = 0
private lateinit var wordList: MutableList<String>
class GameViewModel: ViewModel() {
...
your variables are declared outside of the ViewModel, add them inside the class GameViewModel to make them instance variables:
class GameViewModel: ViewModel() {
var word = ""
var score = 0
...
}

Why can't I use an intent to transition back to a previous fragment in my Android app?

I make a transition from a fragment to an activity but I am unable to transition back to the fragment without my app crashing.
Here is my fragment code:
package com.riverstonetech.gositeuk.ui.scotland
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.ProgressBar
import androidx.fragment.app.Fragment
import com.google.firebase.firestore.FirebaseFirestore
import com.riverstonetech.gositeuk.CountriesActivity
import com.riverstonetech.gositeuk.R
import com.riverstonetech.gositeuk.RegionActivity
import kotlinx.android.synthetic.main.fragment_scotland.*
class ScotlandFragment : Fragment() {
// Access a Cloud Firestore instance
val db = FirebaseFirestore.getInstance()
lateinit var adapter : ArrayAdapter<String>
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_scotland, container, false)
(requireActivity() as CountriesActivity).initializeCustomActionBar(R.drawable.scotland_flag, R.string.title_regions)
var regions : ArrayList<String>
val docRef = db.collection("UKSites").document("Scotland")
val progressBar: ProgressBar = root.findViewById(R.id.regionsLoadingProgressBar)
docRef.get()
.addOnSuccessListener { document ->
progressBar?.visibility = ProgressBar.VISIBLE
if (document != null) {
regions = document.get("Regions") as ArrayList<String>
adapter = ArrayAdapter(requireContext(), R.layout.list_item, regions)
regionsListView.adapter = adapter
regionsListView.setOnItemClickListener { parent, view, position, id ->
val intent = Intent(activity!!, RegionActivity::class.java)
intent.putExtra("SUB_COUNTRY", regions[position])
startActivity(intent)
}
progressBar?.visibility = ProgressBar.GONE
} else {
Log.d("Debug", "No such document")
}
}
.addOnFailureListener { exception ->
Log.d("Debug", "get failed with ", exception)
}
return root
}
}
And here is the relevant code in my activity class RegionActivity:
fun previousSubCountryListButtonClicked(view: View) {
val intent: Intent = Intent(this, ScotlandFragment::class.java)
startActivity(intent)
}
Here is the error output in the logcat window:
2020-02-10 15:46:54.089 27008-27008/com.riverstonetech.gositeuk E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.riverstonetech.gositeuk, PID: 27008
java.lang.IllegalStateException: Could not execute method for android:onClick
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:402)
I don't have enough knowledge of fragments and activity to work out why this doesn't work so any help would be appreciated.
You are making this way more complicated than it needs to be.
To return from RegionActivity to the previous Activity/Fragment, you just need to call finish(). That will destroy RegionActivity and return to whatever Activity was underneath it, in the same state it was in when you launched RegionActivity.
I used finish() instead of trying to switch to the fragment using intents.

How to properly implement an interface in android fragment?

folks. I have been working on a project with kotlin and I need to make a fragment that comunicate with the parent activity... I followed exactly what google and other websites suggested but I still get an error "activity does not override anything"... All of the other solutions are not working for me... here is the code .
FRAGMENT
package com.me.assistan.assistant
import android.app.Activity
import android.app.DatePickerDialog
import android.app.TimePickerDialog
import android.content.Context
import android.content.Intent
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CompoundButton
import android.widget.LinearLayout
import android.widget.ToggleButton
import kotlinx.android.synthetic.main.content_newplan.*
import java.util.*
class addingTask : Fragment(), View.OnClickListener{
var func = Functions
var globalTask = GlobalTask
private lateinit var listener: OnTimeSettedListener
override fun onAttach(context: Context?) {
super.onAttach(context)
if (context is OnTimeSettedListener) {
listener = context
} else {
throw ClassCastException(context!!.toString() + " must implement
OnTimeSettedListener.")
}
}
companion object {
fun newInstance(): addingTask {
return addingTask()
}
}
override fun onCreateView(inflater: LayoutInflater?, container:
ViewGroup?,
savedInstanceState: Bundle?): View? {
val view: View = inflater!!.inflate(R.layout.fragment_adding_task,
container,
false)
val activity = activity
view.theTime.setOnClickListener { v ->
listener.onTimeSetListtedener("test")
}
return view
}
interface OnTimeSettedListener{
fun onTimeSetListtedener(comic : String){
println("ok")
}
}
}// Required empty public constructor
And not the MAIN ACTIVITY
class Newplan : AppCompatActivity(), addingTask.OnTimeSettedListener {
var posx = 0f
private var startx = 0f
private var posy = 0f
private var starty = 0f
var backIntent = Intent();
var func = Functions
var globalTask = GlobalTask
val fragment = addingTask()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_newplan)
if(savedInstanceState === null){
var args = Bundle()
supportFragmentManager.beginTransaction()
.add(R.id.taskMain, addingTask.newInstance(),"newTask")
.commit()
}
}
override fun onTimeSettedListener(comic : String){
println("params")
}
}
I get the error on the activity class... When I remove the "override?, the error is gone but nothing happen when I click on the button... What am I doing wrong?
I think you shouldn't add method body to your interface method. It is not allowed in Java. In Kotlin there is no error that showing method body is restricted. But you should remove body. Change your interface like
interface OnTimeSettedListener{
fun onTimeSetListtedener(comic : String)
}
Also actually you are not overriding your Listener's method. Method name in OnTimeSettedListener is onTimeSetListtedener but you are overriding onTimeSettedListener which is not really exist in your code.
Also as #albodelu mentioned answer and #chris mentioned in comments, you cannot write methods in methods. It is not correct usage.
As #chris commented, you need to move the lines below outside of onCreate() method:
override fun onTimeSettedListener(comic: String) {
println("params")
}
You also need to match names replacing
interface OnTimeSettedListener {
fun onTimeSetListtedener(comic : String){
println("ok")
}
}
by
interface OnTimeSettedListener {
fun onTimeSettedListener(comic: String) {
println("ok")
}
}
Update
If you fix the name typo and remove the default implementation of the onTimeSettedListener declaration in the interface inside your fragment, as your activity implements it and Android Studio warns you about the missing override, it's possible to click it and select that the IDE implements it for you to avoid errors doing it:
interface OnTimeSettedListener{
fun onTimeSettedListener(comic : String)
}
You also need to fix the call replacing:
listener.onTimeSetListtedener("test")
by
listener.onTimeSettedListener("test")

Categories

Resources