nov
May 4, 2016, 2:00pm
#1
I try to add Splash Screen to my Cocos2dx Android app, which I ported from iOS.
Because:
It takes so much time, before the App starts (around 17 seconds).
It shows black screen during waiting.
I tried to add Splash Sreen Java way, but it displays image for a few seconds only and then switches back again to black screen for the rest of start up time.
I have this code there.
styles.xml
<resources>
<!-- Base application theme. -->
<!-- <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> -->
<!-- Customize your theme here. -->
<!-- </style> -->
<style name="SplashTheme" parent="android:style/Theme"> <!-- Theme.AppCompat.NoActionBar @android:style/Theme.NoTitleBar.Fullscreen -->
<item name="android:windowBackground">@drawable/background_splash</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
</resources>
SplashActivity.Java
package com.bignerdranch.android.splash;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class SplashActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
}
}
drawable/background_splash.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@color/gray"/>
<item>
<bitmap
android:gravity="center"
android:src="@mipmap/ic_launcher"/>
</item>
</layer-list>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.de.test"
android:installLocation="auto">
<uses-feature android:glEsVersion="0x00020000" />
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@drawable/icon">
<!-- Tell Cocos2dxActivity the name of our .so -->
<meta-data android:name="android.app.lib_name"
android:value="cocos2dcpp" />
<!-- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" portrait -->
<activity
android:name="org.cocos2dx.cpp.AppActivity"
android:launchMode="singleTop"
android:screenOrientation="sensorPortrait"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
</manifest>
How to improve it, to show Splash Screen during whole Cocos2dx App loading (instead of black screen)?
How to improve start up time?
I think there is an example in the cpptests where it shows how to load resource using async.
Have a look, maybe it will help you out.
I had the same problem. See my thread about it here . There’s no perfect solution but you can pick one which works for you.
1 Like
Levis
May 6, 2016, 10:05am
#4
You can do it modifying your .java in src folder
this is my sample of appactivity, I use the Dialog
package your bundle id;
import your bundle;
import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
public class AppName extends Cocos2dxActivity {
public static Dialog loader_dialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loader_dialog = new Dialog(this,R.style.Loader);
loader_dialog.setContentView(R.layout.loader);
loader_dialog.show();
}
public static void dismissLoader() {
loader_dialog.dismiss();
}
}
in the android manifest xml:
<activity
android:name="your bundle id"
android:label="@string/app_name"
android:launchMode="singleTop"
android:screenOrientation="sensorPortrait"
android:configChanges="orientation"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
and finally the most important the styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Loader" parent="android:Theme.Black.NoTitleBar.Fullscreen">
<item name="android:windowAnimationStyle">@style/LoaderAnimation</item>
</style>
<style name="LoaderAnimation">
<item name="android:windowEnterAnimation">@android:anim/fade_in</item>
<item name="android:windowExitAnimation">@android:anim/fade_out</item>
</style>
</resources>
I’ve also added a fade in / out
No black screen in this way
nov
May 6, 2016, 10:33am
#5
Thanks guys! I just improved the code to start in 4-5 seconds, started to use spread sheets for this app! But it still displays, with current code, as written at the top of this forum thread, not yet modified it: first logo for a second then it shows black screen for about 3 - 4 seconds until app starts.
I will try to test Levis and or others solution too now. Will report back.
1 Like
Levis
May 6, 2016, 10:46am
#6
@nov with my solution I don’t have any glitch or black screen, last year I’ve worked to resolve this, maybe you can find also useful my first post on native splashscreen:
I need some help on creating a native splashscreen.
I mean the splash that use the png in drawable path.
In AndroidManifest.xml we have:
android:icon="@drawable/icon"
and it works.
But the default theme:
android:theme="@android :style/Theme.NoTitleBar.Fullscreen">
Doesn’t have the style:
<item name="android:windowBackground">@drawable/splash</item>
So what is the right way to proceed?
I have created styles.xml in res/values, with the following code:
<?xml version="1.0" encoding="utf-8"…
nov
May 6, 2016, 10:53am
#7
How R is defined, please?
I am getting:
/testproject/proj.android-studio/app/src/org/cocos2dx/cpp/AppActivity.java:38: error: package R does not exist
loader_dialog = new Dialog(this,R.style.Loader);
^
/testproject/proj.android-studio/app/src/org/cocos2dx/cpp/AppActivity.java:39: error: package R does not exist
loader_dialog.setContentView(R.layout.loader);
I am not yet very familiar with Android code, although I know Java, I am staring to get to used to Android.
Levis
May 6, 2016, 11:01am
#8
R.java is autogenerated on build, these are the resources (drawable, layout, styles etc)
maybe I forgot to add in import line when I rewrote “your bundle”:
import com.bundle.appname.R;
nov
May 6, 2016, 11:07am
#9
Ok. Thanks. Seems to be a little better, but now getting this.
/testproject/proj.android-studio/app/src/org/cocos2dx/cpp/AppActivity.java:40: error: cannot find symbol
loader_dialog.setContentView(R.layout.loader);
^
symbol: variable loader
location: class layout
1 error
Levis
May 6, 2016, 11:29am
#10
You’re right, sorry forgot to add this:
layout/loader.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/splash"
android:orientation="vertical">
</LinearLayout>
Next time I’ll promise to create a repo with all files
nov
May 6, 2016, 11:47am
#11
Ok. Thanks. It compiles!
But now it seems the logo stays there forever, not sure what I am not doing right?
You can call dismissLoader here, in your c++ code, for the logo don’t stay forever, you close it when you enter in your application :
void EcranChargement::onEnter()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include “platform/android/jni/JniHelper.h”
#include < jni.h>
JniMethodInfo methodInfo;
if (JniHelper::getStaticMethodInfo(methodInfo, “org/cocos2dx/cpp/AppActivity”, “dismissLoader”, “()V”)) {
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
#endif
Layer::onEnter();
scheduleOnce(CC_SCHEDULE_SELECTOR(EcranChargement::RunGameScreen), 1.0f);
}
Levis
May 9, 2016, 11:00am
#13
Yes @versailles is right.
You can call dismissLoader everywhere you decide in your code with JNI helper.
In some apps I call after loading data and if you want you can also add a static delay if you need some more time or whatever else:
// Remove Splashscreen when all important data is loaded
void Start::dismissLoader() {
CCLOG("[Start] dismissLoader");
#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
this->runAction(Sequence::create(
DelayTime::create(1.0f),
CallFunc::create([&]() {
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, "your activity", "dismissLoader", "()V")) {
t.env->CallStaticVoidMethod(t.classID, t.methodID);
}
}),
nullptr));
#endif
}
nov
May 9, 2016, 12:38pm
#14
Thanks guys! It works perfectly!
Only issue I have now is that my screenshot is whole Android screen height size height.
But it gets cut because of bottom toolbar displayed there.
Is there anything to do with it, please?
loader.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:baselineAligned="false"
android:measureWithLargestChild="false"
android:background="@drawable/background_splash">
</LinearLayout>
background_splash.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@color/white"/>
<item>
<bitmap
android:gravity="center"
android:src="@mipmap/screen"/>
</item>
</layer-list>
Levis
May 9, 2016, 1:15pm
#15
Sorry I didn’t undertand, can u post a screenshot?
nov
May 9, 2016, 1:29pm
#16
At the bottom of the screen is navigation bar. Which makes the splash screen image to not fit. Image is cut at the bottom and at the top.
nov
May 10, 2016, 6:39am
#17
Ok. I fixed it by setting full screen to loader dialog and cocos2dx view according to this article and this cocos2dx thread.
http://developer.sonymobile.com/knowledge-base/tutorials/legal/how-to-provide-your-app-users-with-maximum-screen-estate-tutorial/
You do this by adding code from https://developer.android.com/training/system-ui/immersive.html in your main java activity class. This applies to cocos2d-x 2.x so not sure how to add it for 3.x yet. Your activity class would then look like this for example:
public class YourApp extends Cocos2dxActivity
{
private Cocos2dxGLSurfaceView glSurfaceView;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
public Cocos2dxGLSurfaceVi…
public class AppActivity extends Cocos2dxActivity {
public static Dialog loader_dialog;
private Cocos2dxGLSurfaceView glSurfaceView;
private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
| View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loader_dialog = new Dialog(this,R.style.Loader);
loader_dialog.setContentView(R.layout.loader);
if (android.os.Build.VERSION.SDK_INT >= 11) {
loader_dialog.getWindow().getDecorView().setSystemUiVisibility(mSystemUiVisibility);
}
loader_dialog.show();
}
public static void dismissLoader() {
loader_dialog.dismiss();
}
public Cocos2dxGLSurfaceView onCreateView()
{
glSurfaceView = new Cocos2dxGLSurfaceView(this);
this.hideSystemUI();
// create stencil buffer
glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8);
return glSurfaceView;
}
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus)
{
this.hideSystemUI();
}
}
private void hideSystemUI()
{
if (android.os.Build.VERSION.SDK_INT >= 11) {
// Set the IMMERSIVE flag.
// Set the content to appear under the system bars so that the content
// doesn't resize when the system bars hide and show.
glSurfaceView.setSystemUiVisibility(mSystemUiVisibility);
}
}
static
{
System.loadLibrary("cocos2dcpp");
}
}
Now I will have to find out how to compile release version of the app and how to upload it to the Google Play?
Levis
May 10, 2016, 7:43am
#18
Nice!
In this way you setup the immersive mode, that is my preferred
For compiling you can use:
cocos run -p android -j 4 -s projFolder -m release
Cocos will generate the apk that you can upload to Google Play
nov
May 10, 2016, 12:48pm
#19
Thanks. I try to use this command, since I use Android Studio:
cocos compile -p android --android-studio -m release --ndk-mode release
What -j 4
means in your command?
I try to minimize APK file size.
How to remove not needed files eg. iOS startup screens from APK generation?
Levis
May 10, 2016, 2:01pm
#20
-j, --jobs number of jobs at once 4 Use N jobs at once. It's only take effect with target android & linux.
You don’t need to remove iOS stuff, they are in another dir.