I was just making a simple program that sends string that's typed in an EditText into a TextView in another activity, I'm a beginner and was following a kotlin tutorial on the internet, the program would crash whenever it gets the string from the 1st activity, The code of the 1st activity looks like this:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.button).setOnClickListener {
val message: String? = findViewById<EditText>(R.id.sameer).text.toString()
val kash = Intent(this, kos::class.java)
intent.putExtra("sameer", message)
startActivity(kash)
}
}
}
and the code for the 2nd activity goes like this:
class kos: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.kos)
val kanye: Bundle? = intent.extras
val shaheer = kanye!!.getString("sameer")
Toast.makeText(this, shaheer , Toast.LENGTH_SHORT)
findViewById<TextView>(R.id.UserisHambola).text = shaheer
}
}
I've tried to check when does the error start to happen, it appears that it starts to happen after declaring variable "shaheer" in the 2nd activity, if I delete that code with all the other codes after it, the program doesn't crash, I don't know why does this crash happen, Thank you for your time <3
Try to replace kanye!!.getString("sameer") with kanye?.getStringExtra("sameer") ?: "no data". This way the program will not crash if no value is passed under "sameer" key and the default "no data" will be stored to val shaheer. If you see no data in the toast, you passed the variable between activities incorrectly.
You do this in MainActivity:
val kash = Intent(this, kos::class.java)
intent.putExtra("sameer", message)
startActivity(kash)
You put the extra with the key "sameer" into the Intent referenced by the variable intent. You probably want to put the extra into the Intent referenced by the variable kash. Try this instead:
val kash = Intent(this, kos::class.java)
kash.putExtra("sameer", message)
startActivity(kash)
Related
I am making recyclerview in kotlin in android studio. I'm trying to set up an event listener that puts a button in the recyclerview and outputs a toast message. Even if this#[activity name] is entered instead of this in context, a toast message is not displayed. What went wrong?
The error code is as follows.
Unresolved reference: #UpdateActivity
class UpdateActivity : AppCompatActivity() {
private val vBinding by lazy {ActivityUpdateBinding.inflate(layoutInflater)}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(vBinding.root)
var recyclerViewAdapter = CustomAdapter()
recyclerViewAdapter.listData = arrayListOf<String>("a", "b", "c")
vBinding.uploadedRecyclerView.adapter = recyclerViewAdapter
vBinding.uploadedRecyclerView.layoutManager = LinearLayoutManager(this)
} // onCreate End
class CustomAdapter:RecyclerView.Adapter<CustomAdapter.Holder>(){
var listData = arrayListOf<String>()
class Holder(val vBinding:UploadedRecyclerBinding):RecyclerView.ViewHolder(vBinding.root){
fun setData(name:String){
vBinding.name.text = name
vBinding.getBtn.setOnClickListener {
**Toast.makeText(this#UpdateActivity, "test", Toast.LENGTH_SHORT).show()**
// ↑A compilation error occurs here.**
}
}
} // Holder end
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val vBinding = UploadedRecyclerBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return Holder(vBinding)
}
override fun onBindViewHolder(holder: Holder, position: Int) {
val name = listData[position]
holder.setData(name)
}
override fun getItemCount(): Int {
return listData.size
}
} // CustomAdapter end
} // UpdateActivity end
you could try put context into constructor of adapter when you create it, and use this context to show a toast. something like this:
class CustomAdapter(
private val mContext: Context
):RecyclerView.Adapter<CustomAdapter.Holder>(){
and in holder class:
Toast.makeText(mContext, "test", Toast.LENGTH_SHORT).show()
finally, when you create adapter in activity:
var recyclerViewAdapter = CustomAdapter(this)
Normally, we'll create adapter class in another file, so use this#UpdateActivity in adapter is bad idea
Instead of using the local context in Toast, always use applicationContext when showing it. So, you should replace that creation of Toast message as,
Toast.makeText(applicationContext, "test", Toast.LENGTH_SHORT).show()
Simple kotlin app under android studio that makes a loadURL to a local address:-
The function often fails, probably due to local net latency with:
Web Page not available
The web page at http://192.168.1.144/apikey/webcam could not be loaded because:
net: ERR_ADDRESS_UNREACHABLE
I have
android:usesCleartextTraffic="true"
<uses-permission android:name="android.permission.INTERNET"/>
in the manifest, and the loadurl often is fine
In order to capture the error and provide a message an
onReceivedError()
action is used.
It never fires
Is the syntax of the onReceivedError correct? It refers to WebView rather than my instance myWebview (which causes a reference error), and I've moved the scope around to no effect.
The Android Studio comment says that the function is never used. A big hint, but I can't see which scope to place it in.
Or is this type of error one of those not caught by OnReceivedError. If so, how which function would?
Ideally I'd like to increase the 'wait' time of the LoadUrl function so that the lazy local IP can respond.
I've copied this from other examples.
I'd really welcome some help please
Here is my class code:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create the NotificationChannel
val name = getString(R.string.channel_name)
val descriptionText = getString(R.string.channel_description)
val importance = NotificationManager.IMPORTANCE_DEFAULT
val CHANNEL_ID = "only_channel"
val mChannel = NotificationChannel(CHANNEL_ID, name, importance)
mChannel.description = descriptionText
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(mChannel)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create channel to show notifications.
val channelId = getString(R.string.default_notification_channel_id)
val channelName = getString(R.string.default_notification_channel_name)
val notificationManager = getSystemService(NotificationManager::class.java)
notificationManager?.createNotificationChannel(NotificationChannel(channelId,
channelName, NotificationManager.IMPORTANCE_HIGH))
}
val myWebView: WebView = findViewById(R.id.webview)
/*myWebView.loadUrl("https://amazon.co.uk")*/
myWebView.webViewClient = WebViewClient()
myWebView.setWebViewClient(object : WebViewClient() {
fun onReceivedError(view: WebView , errorCode: Int, description: String, failingUrl: String, getContext: Context) {
Log.i("WEB_VIEW_TEST", "error code:$errorCode")
Toast.makeText(getContext, "Webcam not reachable",Toast.LENGTH_SHORT ).show()
}
})
WebView.setWebContentsDebuggingEnabled(true)
/*5 March 2021*/
myWebView.clearCache(true)
myWebView.loadUrl("http://192.168.1.144/apikey/webcam")
val disable_button: Button = findViewById(R.id.disable)
disable_button.setOnClickListener {
myWebView.loadUrl("http://192.168.1.144/apikey/disable")
}
fun onReceivedError(
view: WebView,
request: WebResourceRequest,
error: WebResourceError
) {
Toast.makeText(this, "Webcam not reachable", Toast.LENGTH_SHORT).show()
}
}
}
i have 3 activitiy when i start my app i can go 1 activity to second but i cant go third it crashes
this is code of my third( last activity )
class thirdActivity3 : AppCompatActivity() {
private lateinit var textView: TextView
private lateinit var textView2: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_third3)
textView = findViewById(R.id.textView)
textView2 = findViewById(R.id.textView2)
val extras = intent.extras
if(extras != null){
textView.text = extras.getString("NAME") //getString("NAME","")
textView2.text = extras.getInt("AGE").toString() //getInt("AGE",0).toString()
}
}
}
and this is my second activity
class secondActivity2 : AppCompatActivity() {
private lateinit var inputTextAge:EditText
private lateinit var finishButton: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second2)
inputTextAge=findViewById(R.id.inputTextAge)
finishButton=findViewById(R.id.finishButton)
val extras = intent.extras
var name = ""
if (extras != null){
name=extras.getString("PERSON_NAME","")
}
finishButton.setOnClickListener {
val age = finishButton.text.toString().toInt()
val intent = Intent(this,thirdActivity3::class.java)
intent.putExtra("NAME",name)
intent.putExtra("AGE",age)
startActivity(intent)
}
}
}
i am trying to make wizard for learning but my code have some problems. i have 3 activitys in kotling but when i go second activity to third it's stopping but its workd when i going first to second
2020-11-27 18:50:41.472 19343-19343/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 19343
java.lang.NumberFormatException: For input string: "Finish"
at java.lang.Integer.parseInt(Integer.java:615)
at java.lang.Integer.parseInt(Integer.java:650)
at com.example.myapplication.secondActivity2$onCreate$1.onClick(secondActivity2.kt:33)
at android.view.View.performClick(View.java:7125)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access$3500(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
this is from logcat
Looking at the error message, it looks like your problem is this line:
val age = finishButton.text.toString().toInt()
The error is saying that you're trying to parse the string "Finish" as a number. It makes sense from this line that you're doing that. You have a button named "Finish". You get the text from the button and then call toInt() on that text, and you get this error.
What do you expect this line to do? Why do you expect querying a button's text to return an integer that represents age?
Second and third buttons work only if I click the first button first. If I click on the second or third button before trying first button then the buttons do not work.
Can you please help me to find out my mistakes? IDE: Android Studio, Language: Kotlin.
Codes are here:
package com.example.habiganjkotlin
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
info_button.setOnClickListener {
val intent = Intent(this, habiganjinfo::class.java)
// start your next activity
startActivity(intent)
news_button.setOnClickListener {
val intent = Intent(this, habiganjnews::class.java)
// start your next activity
startActivity(intent)
corona_button.setOnClickListener {
val intent = Intent(this, corona::class.java)
// start your next activity
startActivity(intent)
} } } } }
The problem of your code is that you have put button 2 and button 3 in button1.setOnClickListener. If these three buttons are independent and you can choose any of them, put them in three seperate setOnClickListener. I mean:
Button1.setOnClickListener{...}
Button2.setOnClickListener{...}
But you have written:
Button1.setOnClickListener{...
Button2.setOnClickListener{...}}
And this is wrong.
When you press the button to open a separate input window, there is a function to display the results toast.
class MainActivity : AppCompatActivity() {
val disposable = CompositeDisposable()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
val f = TestPopup()
usingRxJava(f)
//usingLiveData(f)
}
}
private fun usingRxJava(f: TestPopup) {
val subject = SingleSubject.create<String>()
f.show(supportFragmentManager, "TAG")
button.post {
f.dialog.setOnDismissListener {
val str = f.arguments?.getString(TestPopup.TEST_KEY) ?: ""
subject.onSuccess(str)
}
}
subject.subscribe({
Toast.makeText(this, "Accept : $it", Toast.LENGTH_SHORT).show()
}, {
}).addTo(disposable)
}
private fun usingLiveData(f: TestPopup) {
val liveData = MutableLiveData<String>()
f.show(supportFragmentManager, "TAG")
button.post {
f.dialog.setOnDismissListener {
val str = f.arguments?.getString(TestPopup.TEST_KEY) ?: ""
liveData.postValue(str)
}
}
liveData.observe(this, Observer {
Toast.makeText(this, "Accept : $it", Toast.LENGTH_SHORT).show()
})
}
override fun onDestroy() {
disposable.dispose()
super.onDestroy()
}
}
DialogFragment
class TestPopup : DialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.dialog_test, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
button_test.setOnClickListener {
val arg = Bundle()
arg.putString(TEST_KEY, edit_test.text.toString())
arguments = arg
dismiss()
}
}
companion object {
const val TEST_KEY = "KEY"
}
}
(Sample Project Url : https://github.com/heukhyeon/DialogObserverPattern )
This sample code works in normal cases. However, the toast does not float after the following procedure.
Developer Option - Dont'keep activities enable
Open TestPopup, and enter your text. (Do not press OK button)
Press the home button to move the app to the background
The app is killed by the system.
Reactivate the app (Like clicking on an app in the apps list)
In this case, the text I entered remains on the screen, but nothing happens when I press the OK button.
Of course I know this happens because at the end of the activity the observe relationship between the activity and the Dialog is over.
Most of the code uses the implementation of the callback interface for that Dialog in the Activity to handle that case.
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
button_test.setOnClickListener {
val input = edit_test.text.toString()
(activity as MyListener).inputComplete(input)
dismiss()
}
}
class MainActivity : AppCompatActivity(), TestPopup.MyListener {
override fun inputComplete(input: String) {
Toast.makeText(this, "Accept : $input", Toast.LENGTH_SHORT).show()
}
}
But I think it's a way that doesn't match the Observer pattern, and I want to implement it using the Observer pattern as much as possible.
I'm thinking of getting a Fragment from the FragmentManager and subscribing again at onCreate, but I think there's a better way.
Can someone help me?
Your understanding of the problem is correct, except that the problem happens with any configuration changes, including screen rotation. You can reproduce issue without using the developer mode. Try this for example:
Open TestPopup, and enter your text. (Do not press OK button)
Rotate screen
See toast message not popping up.
Also note that your "observer pattern" implementation is not a proper observer pattern. Observer pattern has a subject and an observer. In your implementation, the activity is acting as both the subject and the observer. The dialog is not taking any part in this observer pattern, and using .setOnDismissListener is just another form of a listener pattern.
In order to implement observer pattern between the Fragment(the subject) and the Activity(the observer), the Activity needs to get the reference of the Fragment using the FragmentManager as you suggested. I suggest to use view model and establish observer pattern between view layer and view model layer instead.
RxJava example:
//MainViewModel.kt
class MainViewModel: ViewModel() {
val dialogText = PublishProcessor.create<String>()
fun postNewDialogText(text: String) {
dialogText.onNext(text)
}
}
// Activity
val disposable = CompositeDisposable()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
viewModel.dialogText.subscribe {
Toast.makeText(this, "Accept : $it", Toast.LENGTH_SHORT).show()
}.addTo(disposable)
button.setOnClickListener {
TestPopup().show(supportFragmentManager, "TAG")
// usingRxJava(f)
// usingLiveData(f)
}
}
override fun onDestroy() {
disposable.dispose()
super.onDestroy()
}
// Dialog Fragment
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
// Important!! use activity when getting the viewmodel.
val viewModel = ViewModelProviders.of(requireActivity()).get(MainViewModel::class.java)
button_test.setOnClickListener {
viewModel.postNewDialogText(edit_test.text.toString())
dismiss()
}
}