startActivity skips onCreate() - android

I have a simple case of Activity1 -> Activity2.
In the past when I've used startActivity(Intent(this, Activity2::class.java)) there have been no issues and the onCreate() method of Activity2 would be called.
In my current case this is not happening. I have logs in the onCreate() method and they are never hit. But if I create a onStart() method it enters there. However, never in my logs for the lifetime of the application does onCreate() of Activity2 ever get hit. How is this possible. onCreate is a requirement before onStart I thought.
Here is the actual code I'm referencing above.
class Activity1 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Timber.d("onCreate")
setContentView(R.layout.activity_splash)
startActivity(Activity2.getIntent(this))
}
}
class Activity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
Timber.d("onCreate") // Never gets touched
}
override fun onStart() {
super.onStart()
Timber.d("onStart"); // Is hit with no problems.
}
companion object {
fun getIntent(#NonNull context: Context) : Intent {
return Intent(context, Activity2::class.java)
}
}
}

You overrode the wrong onCreate - you do not want to use the PersistableBundle version. Change your onCreate to only take the savedInstanceState: Bundle? parameter:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Timber.d("onCreate") // Now it'll be called
}

Related

How to execute the same function in the onCreate method of all activities?

What is the problem?
I want to add this custom window callback in each activity already implemented in the app, currently I need to manually modify the code of the onCreate method of each activity or make it inherit a class that already has onCreate in the desired way, but I need that this process could be performed without modifying the app's existing code, just adding some initialization.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
window.callback = CustomCallback(window.callback, this)
}
Inside you app Application Class (you'll need to create one, if not done yet), on "onCreate" method, call
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
//Code here will run for every activity
}
}
You need a BaseActivity
class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//your code
}
All of your activities need to extends BaseActivity
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
}
}

Android onCreate is called twice after backing out

I have a simple MainActivity and if the app is completely killed it looks like onCreate() is called once. If however I back out of the app so it still appears in the background, when I re-open it I get every log message twice. The weirdest part is if I generate a random number it is always the same in the 2 log messages.
I've tried adding android:LaunchMode="singleTop" (also singleInstance singleTask) in the activity and application tags of the Manifest.
class MainActivity : AppCompatActivity() {
private val binding: ActivityMainBinding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val view = binding.root
setContentView(view)
setupViews()
val data: Uri? = intent?.data
DataHolder.getInstance().setItem(data)
Timber.plant(Timber.DebugTree())
setupInjection()
Timber.d("review nanoTime = ${System.nanoTime()}")
Timber.d("review savedInstance = $savedInstanceState")
Timber.d("review random = ${Random.nextInt()}")
}
override fun onPause() {
Timber.d("review onPause()")
super.onPause()
}
override fun onStop() {
Timber.d("review onStop()")
super.onStop()
}
override fun onDestroy() {
Timber.d("review onDestroy()")
super.onDestroy()
finish()
}
override fun onStart() {
Timber.d("review onStart()")
super.onStart()
}
override fun onRestart() {
Timber.d("review onRestart()")
super.onRestart()
}
override fun onResume() {
Timber.d("review onResume()")
super.onResume()
}
private fun setupInjection() {
val appInjector = InjectorImpl(
firebaseAuth = FirebaseAuth.getInstance()
)
Injector.initialize(appInjector)
}
private fun setupViews() = binding.apply {
val navController = findNavController(R.id.nav_host_fragment)
navView.setupWithNavController(navController)
navView.setOnItemSelectedListener { item ->
when (item.itemId){
R.id.navigation_item_calculator -> {
navController.navigate(BuilderFragmentDirections.actionBuilderToCalculator())
}
R.id.navigation_item_builder -> {
navController.navigate(CalculatorFragmentDirections.actionCalculatorToBuilder())
}
}
true
}
navView.setOnItemReselectedListener { }
}
}
Here is a table of the log trace I get when I run the app on my phone from Android studio. Since the random numbers are the same I feel like this is actually a Logging bug in Android studio and the app isn't actually opened twice.
Realized my problem was with my logging library I used.
Timber was planting a new tree but wasn't uprooting old ones from being backed out so there were 2 instances of them. I fixed by putting a Timber.uprootAll() just before Timber.plant(Timber.DebugTree())

Uninitialized exception while initializing "late init" property

I am not really sure if my case is just not possible with late init properties. But let me just ask :)
I have an applicationController which is used in nearly every activity - so i created a BaseActivity
The problem now is that when I want to get dependencies from the application controller in the child activity, I get an Uninitialized Exception.
Thanks for your help!
Because you override wrong method in BaseActivity, that why your app crash.
Solution: Change your code to
abstract class BaseActivity : AppCompatActivity() {
lateinit var applicationController: ApplicationController
// [IMPORTANT] Remove or comment-out this method
// override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
// super.onCreate(savedInstanceState, persistentState)
// applicationController = ApplicationController.getInstance(applicationContext)
// }
// Override this method
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
applicationController = ApplicationController.getInstance(applicationContext)
}
}
Explanation: This section will explain why the code is not working.
kotlin.UninitializedPropertyAccessException
This is a sub-class of RuntimeException, the app will throw this
exception when you access an object by calling properties or methods
on its own before initializing.
When LoginScreen activity is created, Android will call its onCreate method.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login_screen)
emailMatcher = applicationController.getEmailMatcher()
passwordMatcher = applicationController.getPasswordMatcher()
}
The first line super.onCreate(savedInstanceState) will call onCreate method of its parent, in this case onCreate (bundle) in BaseActivity activity will be called.
Unfortunately, in BaseActivity activity, you override and put the initial code for applicationController in another method onCreate(bundle, persistentState) which quite similar to onCreate (bundle). The difference between them is number of params. As a result, at this time applicationController is still not initialized.
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
applicationController = ApplicationController.getInstance(applicationContext)
}
Until the app reach this line
emailMatcher = applicationController.getEmailMatcher()
Because you call getEmailMatcher method on an uninitialized object applicationController, so the app throws kotlin.UninitializedPropertyAccessException and make your app crash.

Simple Kotlin Project does not show any UI

I have a very simple Android Project in Kotlin. Just to dig in Kodein. I can not see the two TextViews in the main_layout?
I have used MVP pattern for the only MainActivity I have there..
The app starts without a crash and is show a blank white screen.
Any hints?
BaseActivity:
abstract class BaseActivity<V : BasePresenter.View> : AppCompatActivity(), BasePresenter.View {
protected abstract val layoutResourceId : Int
protected abstract val presenter : BasePresenter<V>
val kodeinMu = LazyKodein(appKodein)
protected abstract fun initUI()
protected abstract fun initPresenter()
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
setContentView(layoutResourceId)
initUI()
initPresenter()
}
override fun onPause() {
super.onPause()
presenter.pause()
}
override fun onStop() {
super.onStop()
presenter.stop()
}
override fun onDestroy() {
super.onDestroy()
presenter.destroy()
}
protected fun toast(s: String) {
System.out.println("TAG $s")
}
}
I have read that it is because of API 28 you only can see on API_28 devices or emulators. Either emulator or on real device were also blanked out.
You override the wrong onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) in you activity:
use this : onCreate(savedInstanceState: Bundle?)

onCreate in abstract parent activity no called in kotlin

I declared a child of MapActivity:
class RecordingActivity : MapActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("RecirdingActivity", "InitializeMap") //called
}
override fun getView(): Int {
return R.layout.activity_recording
}
}
I make a call to start this activity from my main activity:
fab.setOnClickListener {
Log.d("MainActivity", "fabClick") //called
startActivity(intentFor<RecordingActivity>())
}
and I have the abstract activity:
abstract class MapActivity: AppCompatActivity(), OnMapReadyCallback {
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
setContentView(getView())
initializeMap()
Log.d("MapActivity", "InitializeMap")//not called
}
}
and onCreate method of this activity is never called
I traced it with a debugger and I had the same result.
What am I doing wrong?
there seems to be two solutions:
maybe the onCreate you actually want to override in MapActivity has the signature onCreate(android.os.Bundle):
abstract class MapActivity: AppCompatActivity(), OnMapReadyCallback {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(getView())
initializeMap()
Log.d("MapActivity", "InitializeMap")
}
}
the documentation of the onCreate(android.os.Bundle, android.os.PersistableBundle) method that is being overridden in MapActivity suggests that persistableMode for the activity in the AndroidManifest.xml needs to be set to persistAcrossReboots for it to be called...but MapActivity is abstract, so you would need to set the attribute for its subclasses instead. in this case that would be RecordingActivity.
<?xml version="1.0" encoding="utf-8"?>
<manifest>
...
<application>
...
<activity
android:name=".RecordingActivity"
android:persistableMode="persistAcrossReboots"/>
...
</application>
...
</manifest>
Simple answer: method onCreate(savedInstanceState: Bundle?) and onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) is not the same.
You need to override the same method, probably the first one.

Categories

Resources