How do I properly access my MainActivity from outside its class? - android

I have a function of which I call from MainActivity
class MainActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
doSomethingFunction(this)
}
...
doSomethingFunction(activity: AppCompatActivity)
{
var button = activity.findViewById<Button>(R.id.button)
// if I try do something with button the app crashes eg
button.text = "Text"
}
Which leads me to believe somehow I must not be accessing activity from MainActivity and activity.findViewById<Button>(R.id.button) didn't actually return my buttons id thats why its crashing. I tried to extend doSomethingFunction(activity: MainActivity) but it crashes the same.
How do I properly pass "MainActivity" to doSomethingFunction so that I can do stuff with "activity"

you don't have a setContentView so yes, it will crash, because there's no layout associated with this activity.
you have to use setContentView(R.layout.yourLayoutHere) in order for you to be able to access xml components.
class MainActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.something)
doSomethingFunction(this)
}

a_local_nobody answered my question correctly. I am just posting so that others may benefit. The are two reasons I was facing that error
Reason 1
Just as my code denotes I was calling doSomethingFunction(this) before setContentView thats why there was no setContentView in my sample code. So I couldn't access members in MainActivity well
This lead me to believe in my own project I wasn't initialising my button in time. So After investigations the culprit is in the xml of which a_local_nobody encouraged me to post. I couldn't do that because it was a complex project and I didn't know which part of the xml.
Reason 2
I was using drawer layout which was in turn loading a layout with my button
<androidx.drawerlayout.widget.DrawerLayout
app:headerLayout="#layout/layout_with_button">
This was causing a delay and at run time the button would be null so the app was crashing.
I put the button as a child of Drawer layout and the app runs fine. I deleted app:headerLayout="#layout/layout_with_button"
<androidx.drawerlayout.widget.DrawerLayout>
<Button/>
</androidx.drawerlayout.widget.DrawerLayout>

Related

How do I keep the screen on in any activity or fragment in my App by using kotlin?

I wanted to keep the light of my app's screen always on when I go to a certain activity or fragment, but I can't do that.
You should use this concept WakeLock or Keep Screen On
There are two things
1)If you need to make activity on keep on you can use Keep screen on. It does not require any special permission. You can do this in activity or xml.
Activity:
class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
//Make sure call this function to clear flags when you dont need this in between .
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_parent"
android:keepScreenOn="true"></RelativeLayout>
Second way - if you need to do some CPU running .
Example like a game app.
You need to declare permission in manifest.
And follow this example. Its a straight forward way.

How can I use button in one activity to do something in second activity?

I got a question. I have two activities in my app. In first one, when I click the button, I need something to happen in the second one. How can I do it? If that button would be in the second activity I would just do it by:
button.setOnClickListener {}
But how can I do it when button is in the other activity? It's worth adding that code, that tells what should happen, must be in that second activity, just like it was in that "setOnClickListener". Sorry, I'm starting with Android development.
You could communicate between two activities via broadcast or intent.
But it make logic more complex.
So I suggest use two fragments instead two activities.
If you use two fragment in one activity, you can easy communicate between two fragments.
You can look more detailed information about fragment from this URL.
https://developer.android.com/guide/fragments
To achieve the intended flow you may try the below approach,
Start activity 2 on button click from activity 1.
On activity 2 place your code in onCreate so, once activity 2 loads up your code will fire up.
Activity 1:
button.setOnClickListener{
val intent = Intent(this, second::class.java)
startActivity(intent)
}
Activity 2:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
CallDefinedFunctionHere();
}
You cannot be sure that both activities are present at the same moment since the system might destroy inactive one therefore you cannot trigger any code from activity A inside activity B.
What you can do you can start activity B with an intent and some parameters describing what should happen inside activity B.
or
You can communicate by writing something down to a persistent storage (like SharedPreferences) and then when the other activity is resumed (active again) reading it, reacting to it and then removing it from the storage (to make sure you do not handle it twice).
You can pass data in the intent that opens the second activity.
// In first activity:
buttonX.setOnClickListner {
val intent = Intent(MySecondActivity::class.java).apply {
putExtra("wasFromButtonX", true)
}
startActivity(intent)
}
// In second activity:
fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val wasLaunchedFromButtonX = intent.getBooleanExtra("wasFromButtonX", false)
// Above line uses false as default, so it will only be true if you explicitly
// put the extra in the Intent that started this Activity.
if (wasLaunchedFromButtonX) {
// do alternate setup here
}
}
How to pass information between Activities is explained in the introductory documentation here.
Create a function in class where 2nd activity are defined like this.
public void refresh(){}
Now Call that in your 1st activity where you want to call 1st after any action.
button.setOnClickListener {((MainActivity) Objects.requireNonNull(getActivity())).refresh();}

java.lang.RuntimeException: Unable to start activity ComponentInfo{}: kotlin.KotlinNullPointerException

I've created a DialogBox myDialog and initialised it in Settings.kt activity and I am getting the above error when I am initialising the themeRadioGroup, although I've used a non-null assertion operator(!!).
What I want to do is to change the theme of the app using radio buttons(light or dark). And those two radio buttons are in a dialog box i.e. myDialog and Settings.kt is the activity of which I want to change theme, so that's why I want to access the radio group from myDialog.
Settings.kt Activity
class Settings : AppCompatActivity() {
private lateinit var themeRadioGroup : RadioGroup
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)
val myDialog = Dialog(this)
myDialog.setContentView(R.layout.app_info_popup)
themeRadioGroup = myDialog.findViewById(R.id.theme_radio_group)!!
//...
}
The !! is the only way you can get a KotlinNullPointerException. The exception means your assertion that the item is non-null is wrong. In this case, it means a view with that ID does not exist in the dialog layout you have set.
Maybe the view you are looking for is in the activity layout, in which case you should call this.findViewById instead of myDialog.findViewById.
Otherwise, check your dialog layout closely to make sure it is there. If you have multiple versions of the layout for different configurations, make sure they all have a view with that ID.
You might want to look into view binding, which is designed to avoid this kind of problem.

Android WebView becomes not responsive after finishing previous activity 🤔

I've bumped into a strange issue - WebView becomes unresponsive when I finish the activity that started the activity with the WebView BUT it doesn't happen on the first launch, only on the consecutive ones and it also happens on Android 6 and 7, newer Android versions seem to handle that gently.
The full project which reproduces this can be found here
I have two activities Launcher
class LauncherActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startActivity(Intent(this, MainActivity::class.java))
finish()
}
}
And MainActivity with the WebView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val webView = findViewById<WebView>(R.id.oauthWebView)
webView.loadUrl("https://semantic-ui.com/examples/login.html")
}
}
When I start the app the first time everything seems okay, but the second time when I open it,
WebView becomes unresponsive, the keyboard is not showing and it happens right after Launcher onDestroy
If I'm not calling finish in the LauncherActivity everything is fine.
It looks like finishing LauncherActivity has some impact on WebView loading or some other process that's happening under the hood.
It's pretty weird, Logcat is not very helpful either.
Maybe any of you can provide some hint what might be the reason for such behaviour?
Side note:
I'm not looking for answers on how to architect my navigation better, I know it can be done differently - I'm curious why WebView is behaving so weird.
Can you try this?
val webView = findViewById<WebView>(R.id.oauthWebView)
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("https://semantic-ui.com/examples/login.html")

Start activity to another intent is not working

I made a new project using navigation drawer that android gives me as builtin and then i added my menus in the navigation Drawer and then made another activity that is empty activity and made a button over there of getStarted and on the click listening i made an intent of the mainActivity that has the navigation drawer and then assigned this to the getstarted button to startActivity(mainIntent) but its not working, I have done many R&D but didn't work at all and i am getting following errors.
I have tried all the discussion over here
but nothing is working in my case
class WelcomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_welcome)
getStartedBtn.setOnClickListener {
val main = Intent(this,MainActivity::class.java)
startActivity(main)
}
}
I want to be routed to the main activity.In main activity I have used builtin toolbar or navigation drawer.
To access this from an outer scope (a class, or extension function, or labeled function literal with receiver) we write this#label where #label is a label on the scope this is meant to be from:
You should specify your scope. For more information you can check this link.
val main = Intent(this#WelcomeActivity, MainActivity::class.java)
startActivity(main)
Hope this works!
Try to change val main = Intent(this,MainActivity::class.java) to val main = Intent(WelcomeActivity.this,MainActivity::class.java)
Also make sure that getStartedBtn is correctly imported from xml file.
Do you imported getStartedBtn correctly and try to change the val main = Intent(this,MainActivity::class.java) to val main = Intent(applicatonContext,MainActivity::class.java) it thought this will help if you still facing any problem please post the error.

Categories

Resources