Android COMPILE_SDK_VERSION, MIN_SDK_VERSION, TARGET_SDK_VERSION

Hi,

Could any one explain why for test project we have below settings:
cocos2d-x-3.16/tests/cpp-tests/proj.android-studio/gradle.properties
PROP_COMPILE_SDK_VERSION=14
PROP_MIN_SDK_VERSION=10
PROP_TARGET_SDK_VERSION=22
PROP_APP_PLATFORM=10
PROP_APP_ABI=armeabi
Do I understand it correctly that with current setting it may crash when user will run app on i.e. android device API=13. (Because we support API 10 and compile SDK with 14)

Why to not set it to one value to avoid problems? In may case I would like run on API=15 and above
PROP_COMPILE_SDK_VERSION=15
PROP_MIN_SDK_VERSION=15
PROP_TARGET_SDK_VERSION=15
PROP_APP_PLATFORM=15

Regards,
CHP

This is easy to answer, with a blog post from the Googler Ian Lake.

To answer your question in short: API 13 shouldn’t crash, because minSDK is 10. But only the minSDK doesn’t do anything except setting a filter for the play store. The app can be downloaded from API10 (and above). You as a developer needs to ensure, that your minSDK is the real one - don’t use API11+ calls without an API-Level check.

The target marks the android.jar, which is used at compile time as the interface for your calls. This means, you can’t use API23 (and above) without using reflections. It also means, that in API23+ the app will run a “compat-mode” (which should be avoided -> see blog post).

Any other questions?

@mars3142

Thank you for answer.

According above post optimal settings are following:
minSdkVersion (lowest possible) <= targetSdkVersion == compileSdkVersion (latest SDK)
Why we have in cpp-tests 10, 14, 22 instead of 10, 25, 25?

What about PROP_APP_PLATFORM=10? PROP_APP_PLATFORM should be equal to minSdkVersion?

Regards,
CHG

1 Like

Really good question. I would think it’s because the cocos2d-x (and contributors) aren’t Android devs in the main time, so the didn’t know it - and it works with the current setup. I run the lint checks and they’re some that they should fix. I’m not in that position to publish a game yet, but as time is nearby, I need check it in detail.

My problem will be the iOS part, because I’m not a iOS dev. So I will give it to some colleagues to check it. Maybe there are also some issues within the build configuration.

But to answer your question *Why is the Android build isn’t setup as expected", we can ask @slackmoehrle.

You can ask me and I am in return going to ask @zhangxm to read this thread.

1 Like

@mars3142 can not open the link you pasted.

Yep, i am not Android devs, that’s what i about until know about these flags. An Android native app includes two parts of codes, C++ and Java. Both these two types of languages need a version to compile codes:

  • using which version of header files to compile C++ codes
  • using which version of Android SDK to compile Java codes

Before Android Studio, there is only one parameter to set the version for both C++ and Java, that’s --app-abi. In Android Studio, there is separated parameter for each language:

  • PROP_COMPILE_SDK_VERSION is set to compileSdkVersion to set the API level to compile java codes
  • PROP_APP_PLATFORM is appended to APP_PLATFORM=android- to set the version to compile C++ codes
  • PROP_TARGET_SDK_VERSION is set to targetSdkVersion says the version that you have tested, and ask Android OS to do some operation to make compatibility.

This is one point, but this is also the hard limit of the minSDK, because if you compile your c++ against 10, your min API level has to be also 10.

The comment of @CrazyHappyGame is correct. I would always prefer target to be the lastest (right now 26), compile also 26 and minSDK depending on you own preferences. I would always use 19 (because if you see the Android dashboard from Google, you will see, that minSDK 19 will be a sum of 94% usage of the play store). I don’t know other statistics, to chose another minSDK.

PS: If you give me your email (via PM), I can send you the article as pdf.

Yep, it is 10. PROP_COMPILE_SDK_VERSION = 14 is because in AndroidManefest.xml we uses properties that are not in API level 10, and Android Studio 2.3.3 seems to support API level 14+.

If you Java codes uses API that only in latest version, then your app will crash on devices with lower Android OS version.

Isn’t it a public doc? Or can you upload it in forum?

It’s not bad to use the latest compileSDK, because it’s daily business for an Android dev. Unused properties will be ignored in AndroidManifest.xml.

That’s partial wrong. The target is only the interface which is used at compile time - you can compare it to header-files in c++. Gradle will use the android.jar with the version you chose as target. The app will always be usable in older versions. But if you use newer Java-APIs you (as developer) has to build API-bridges (e.g. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { }) and this will be compile with target 26 and will be ignored on runtime in lower versions.

A good example are runtime permissions since API 23. Everytime you save a file to /sdcard, you had to check, if the app has permission for that. Because most of the game devs/companies are lazy, the set target to 22, so they can ignore it, but this is bad behavior and shouldn’t be done that way. A user will be forced to approve the permission at install time instead of runtime. I know many users, who won’t install games with the “old permission model”, because the have no control over the permission.

It’s a post on medium (public blog page), so I thing it will be fine to upload a “copy” here. If you have any questions about it, feel free to ask.

ian_lake.pdf (266.7 KB)

It will cause compiling error that some property missed. You can set it to 10 to have a try.

If the codes handle it like this, then there is not problem, but it is better that it will trigger compile error for it automatically, that’s why we set it to low API. We should make sure that engine codes will not forget to handle it.

Thanks for uploading the doc, will you please also paste the link of the blog? Thanks.

Correct, this will be done in the ./gradlew build call (task lint). A not checked API call, will be a failure and the build won’t be successful. A ./gradlew assemble" will not be the right choice (this was used in your legacy cocos command). If it will be fail in API 10, you need to annotate it with targetAPI within the AndroidManifest.

The link is still https://medium.com/google-developers/picking-your-compilesdkversion-minsdkversion-targetsdkversion-a098a0341ebd

PS: Long time ago I opened an issue -> https://github.com/cocos2d/cocos2d-x/issues/17942 - This is about the lint errors. Someone should check them for the 3.17 release, if possible. So you can be sure everything works fine. If needed, give my a ping and I can check it shortly before the next release.

PPS: Why will you stick on minSDK on 10? Is there a really need? As you mentioned before, the Android Studio 2.+ uses 14 as minimum and you canceled Eclipse support, so why don’t you raise the minSDK to 14?

Guys,

I just released my app with cocos2d-x 3.16, ndk14
PROP_COMPILE_SDK_VERSION=25
PROP_MIN_SDK_VERSION=15
PROP_TARGET_SDK_VERSION=25
PROP_APP_PLATFORM=15

And have 10x more crashes in google play… (Works fine on all my Android devices.). Please help me!!!

at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3319)
at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3415)
at android.app.ActivityThread.access$1100 (ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1821)
at android.os.Handler.dispatchMessage (Handler.java:102)
at android.os.Looper.loop (Looper.java:148)
at android.app.ActivityThread.main (ActivityThread.java:7325)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1120)
Caused by: java.lang.NullPointerException:
at org.cocos2dx.cpp.AppActivity.onCreate (AppActivity.java:110)
at android.app.Activity.performCreate (Activity.java:6904)
at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1136)
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3266)

Another:
java.lang.RuntimeException:
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2429)
at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2493)
at android.app.ActivityThread.access$800 (ActivityThread.java:166)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1283)
at android.os.Handler.dispatchMessage (Handler.java:102)
at android.os.Looper.loop (Looper.java:136)
at android.app.ActivityThread.main (ActivityThread.java:5584)
at java.lang.reflect.Method.invokeNative (Native Method)
at java.lang.reflect.Method.invoke (Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1268)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1084)
at dalvik.system.NativeStart.main (Native Method)
Caused by: java.lang.NullPointerException:
at org.cocos2dx.cpp.AppActivity.onCreate (AppActivity.java:110)
at android.app.Activity.performCreate (Activity.java:5442)
at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1094)
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2393)

At first your settings (min, target, compile) seems to be fine. What’s this line of code, because it’s your custom Activity and there is the culprit.

The crashes are on which Android versions?

@zhangxm @slackmoehrle do I understand it correctly that right now we have to override onCreate ? Please check https://github.com/cocos2d/cocos2d-x/pull/18271/files
So if you create new project it is fine. If you have app created before 3.16 than you have to add manually:

 protected void onCreate(Bundle savedInstanceState) {
          super.setEnableVirtualButton(false);
          super.onCreate(savedInstanceState);
 +        // Workaround in https://stackoverflow.com/questions/16283079/re-launch-of-activity-on-home-button-but-only-the-first-time/16447508
 +        if (!isTaskRoot()) {
 +            // Android launched another instance of the root activity into an existing task
 +            //  so just quietly finish and go away, dropping the user back into the activity
 +            //  at the top of the stack (ie: the last state of this task)
 +            // Don't need to finish it again since it's finished in super.onCreate .
 +            return;
 +        }

Regards,
Chp

@dumganhar James could you check above ?

Regards,
Chp

1 Like

The codes are added to fix issues mentioned in the PR. You should add it manually if the project is created before v3.16. It doesn’t break compatibility.

If your Game Activity has override onCreate method, it’s necessary to add if (!isTaskRoot()) { return; } code after super.onCreate.

What do you think about adding some information about that to release notes?

So the general consensus is:

PROP_COMPILE_SDK_VERSION=26
PROP_MIN_SDK_VERSION=15
PROP_TARGET_SDK_VERSION=26
PROP_APP_PLATFORM=15

Should work with no problem? I’m in the same boat, and these are the values I came up with as well. I’m using cocos2d-x v3.15, and just want to make sure nothing will break, for example the runtime permissions that @mars3142 mentioned, or the crash that @CrazyHappyGame was seeing?

Thanks!

1 Like