4

I followed Android's Build your first app guide. Next, I'm trying to add a launcher splash screen by following a number of tutorials (this being one of them). When I run the app in the emulator it loads so fast that I can't tell if the splash screen works. Is there a way to temporarily slow down the emulator to check the splash screen? Also the app crashes when the Send button is clicked which doesn't make sense because the sendMessage function exists in the MainActivity.

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.myfirstapp, PID: 9242
    java.lang.IllegalStateException: Could not find method sendMessage(View) in a parent or ancestor Context for android:onClick attribute defined on view class androidx.appcompat.widget.AppCompatButton with id 'button'
        at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.resolveMethod(AppCompatViewInflater.java:436)
        at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:393)
        at android.view.View.performClick(View.java:7125)
        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)

I'm honestly not sure what is wrong or if the app is just so small that a splash screen won't show. I'm also not sure the best way to share my project here. So below is all of the code.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myfirstapp">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".SplashActivity"
            android:theme="@style/SplashTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".DisplayMessageActivity"
                  android:parentActivityName=".MainActivity">
            <!-- For API 15 -->
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value=".MainActivity" />
        </activity>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
            </intent-filter>
        </activity>
    </application>
</manifest>

MainActivity.kt

package com.example.myfirstapp

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.EditText

const val EXTRA_MESSAGE = "come.example.myfirstapp.MESSAGE"

class MainActivity : AppCompatActivity()
{
    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    //Called when user taps Send button
    fun sendMessage(view: View)
    {
        val editText = findViewById<EditText>(R.id.editTextTextPersonName)
        val message = editText.text.toString()
        val intent = Intent(this, DisplayMessageActivity::class.java).apply {putExtra(EXTRA_MESSAGE, message)}
        startActivity(intent)
    }
}

DisplayMessageActivity

package com.example.myfirstapp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView

class DisplayMessageActivity : AppCompatActivity()
{
    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_display_message)

        //Get the Intent that started this activity and extract the string
        val message = intent.getStringExtra(EXTRA_MESSAGE)

        //Capture the layout's TextView and set the string as its text
        val text = findViewById<TextView>(R.id.textView).apply {text = message}
    }
}

SplashActivity

package com.example.myfirstapp

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class SplashActivity : AppCompatActivity()
{
    override fun onCreate(savedIntanceState: Bundle?)
    {
        setTheme(R.style.AppTheme)
        super.onCreate(savedIntanceState)
        setContentView(R.layout.activity_main)
    }
}

drawable splash_background.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:opacity="opaque">
    <item android:drawable="@color/colorPrimary" />
    <item>
        <bitmap android:gravity="center" android:src="@mipmap/ic_launcher" />
    </item>
</layer-list>

values styles.xml

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <!-- Splash Screen theme. -->
    <style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
        <item name="android:windowBackground">@drawable/splash_background</item>
    </style>
</resources>

Edit - updated error after help from S T

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Tom
  • 717
  • 2
  • 6
  • 23
  • check this. https://stackoverflow.com/a/38367699/10778405 – S T Jul 03 '20 at 01:03
  • I installed it for API v 29. There wasn't one for v 30. The error is gone now, but I have no idea if the splash screen actually works before it loads so fast. Are there any errors with my code? Is there a way to slow down the emulator to see the splash screen? – Tom Jul 03 '20 at 01:35

3 Answers3

3

If you want to add a tutorial for the first launch there is well explained how to create an introduction with slides: https://www.androidhive.info/2016/05/android-build-intro-slider-app/

If you want just a simple splash screen that appears each time the app is started see this: https://android.jlelse.eu/the-complete-android-splash-screen-guide-c7db82bce565

sixpain
  • 342
  • 1
  • 5
  • 13
  • Thanks @sixpain for both of these links. The second link tutorials (option 1 or 2) is what I am looking for I think. In Option 2 I don't understand where `UserDb` comes from on line 11 of SplashActivity.kt. Do you know where that is declared or why it is needed? My app is so simple that is starts so stinking fast that I can't tell if it is actually working. I'm interested in your first link as well, but after I get this launching loader screen figured out. – Tom Jul 05 '20 at 06:23
  • One more question about Option 2 in your second link: "All you have to do in this step is to create a new splash Activity and assign the launcher theme to it in your AndroidManifest.xml file" does not make sense to me. I created a new empty activity, but not sure how to reference the theme correctly in the manifest. Option 1 says to update `android:theme="@style/AppTheme.Launcher"`, but I don't understand how to do the same for the new activity in Option 2. Thanks. – Tom Jul 05 '20 at 06:30
  • My bad, i linked an advanced tutorial. In particular UserDB is the Database of the application used in that example, so you don't need this for a basic application. Try to see this, it's quite easy: https://android.jlelse.eu/launch-screen-in-android-the-right-way-aca7e8c31f52. – sixpain Jul 05 '20 at 13:29
  • Regarding your second question, in the manifest when you declare an activity, you can set the propriety android:theme="" for each of them. I link you an example of my application: https://github.com/MicheleSalvatori/FiscalCode/blob/master/app/src/main/AndroidManifest.xml There you can see the declaration in the manifest of my my splash activity. There you can set the xml properties, in particular see the android:theme setted as the style that i defined. You can make this for every activity just adding under the property android:theme – sixpain Jul 05 '20 at 13:34
  • Thanks @sixpain. This basic tutorial doesn't work either. Using the exact code in the tutorial, `.activities.MainActivity` is undefined in manifest. I thought it should be `.MainActivity` instead. While it compiles, the app crashes immediately w/ error `java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.splashscreen/com.example.splashscreen.MainActivity}: android.content.res.Resources$NotFoundException: Drawable com.example.splashscreen:drawable/splash with resource ID #0x7f06006d`. It seems like all tutorials are ~5 yrs old and outdated enough to not work anymore. – Tom Jul 05 '20 at 22:01
  • Nope, i used this to design my splash screen and it's correct. The error is caused by the drawable not found. In your application you don't have the drawable "splash" but you are trying to refer to it. First, you need to create a drawable for the splash screen so create a new XML file under drawable folder called "splash.xml" and paste this inside https://gist.githubusercontent.com/pallocchi/35b82e753ef9506965d0b7705e80b57a/raw/09d49df7e02005b5739958eddb954d0665e0b533/splash.xml Also, ".activities.MainActivity" is due to the fact that he have a folder "activities" containing MainActivity – sixpain Jul 06 '20 at 09:02
0

I think that your problem is that you are using the same layout for both activities. Set different layout for SplashActivity.

Nurseyit Tursunkulov
  • 8,012
  • 12
  • 44
  • 78
-1

In splash activity you should use kotlin delay(3000) function. Which waits for 3 seconds. like this:

        lifecycleScope.launchWhenCreated { 
        delay(3000)
    }
Nurseyit Tursunkulov
  • 8,012
  • 12
  • 44
  • 78
  • Thanks for the idea. `lifecycleScope` is not recognized and prompts to create abstract property. I think this might be a little ahead of where I am. If this delay were to work, I'm not confident I have the rest of the code correct as there is an error on Send button click. – Tom Jul 03 '20 at 03:09
  • add this to gradle: implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0-alpha01" – Nurseyit Tursunkulov Jul 04 '20 at 04:25