Android Studio & Old Projects

Before I give you the gritty (dirty) details, you need to understand some things about the ABC company and the Fruit Company.

They don’t care. You are dirt under their shoes. The only reason the ABC company lets you play in their store is because the Fruit company does. The only reason the Fruit Company does is because developers showed Jobs they could do it without the Apples&Oranges Company’s help.

Updating Old Projects

I got a notice from the ABC company that I had to update my app regarding my usage of the App user’s data. My app does NOT collect any data, therefore it is not used. I say so on my web page. That is not good enough for ABC and I must update my app, or it will be removed from the store. It is a free app, and I derive no revenues from it. It is my opinion that ABC got caught illegally using data and is now punishing developers for their misdeeds. I bet they hope developer outcry will force law changes.

So, I loaded up Android Studio 2022, allowed it to import and update the app. It failed. Miserably failed. No notices about what it did not do. No suggestions on fixing the bad import. Android Studio crashed several times. Builds failed. Crashes happened. Infinite loops occurred.

So I wiped Android Studio off the system and re-downloaded it. I then started with a C++ project. That downloaded and created a project and crashed trying to build the project. Then tried building a default project. That worked to some extent.

Wiped AS 2022 again and tried creating a default Java project with the recommended Kotlin gradle files. That failed with an interesting error. Many, many, many duplicate classes. What? I have no classes.

Several hours of using the ABC search engine finally landed me on this solution from Stack Overflow references.

In “build.gradle.kts” (:app) in the dependencies section add constraints:

dependencies {
  ...
    constraints {
        implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0") {
            because("kotlin-stdlib-jdk7 is now a part of kotlin-stdlib")
        }
        implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0") {
            because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib")
        }
    }

}

Once you do this, you can get to the place of doing a build. Once that build correctly starts, AS 2022 will finally download the correct sdklib files, and the build will finish. Once that happens, you can remove the constraints, since the new sdklib fixes the attempted usage of both old libs. Another AS-2022 miracle that breaks all rules of building code. And that is due to AS having to support Java.

Java: May The Farce Be With You

Java was originally conceived to be a universal interpreted language (using state of the art classes) to be run on embedded devices. Unfortunately, the actual implementation of Java precludes this use.

Another interesting fact about Java is the lack of global variables. That is classically solved by creating a static Global Java class with static variables in it. Nasty work around.

Java has one more interesting feature: No class is guaranteed to be in memory. JVM will delete classes as it sees fit. Your code is not guaranteed to run. Get over it. Pragmatically, if that happens much, the Android system fails and is never used. So ABC has, for the most part, fixed that issue. Judicious use of static variables keeps components of classes in memory for future use even if the class is deleted and brought back into play. You should treat all classes as singletons and make sure static variables work for all patterns of duplicated or disabled and re-enabled classes.

Today’s smartphones have the clock speed and around 4 times the computing power of the original 1990’s Cray Supercomputers. Even with all that power, Java runs like molasses.

And the build system is not much better. In AS, the Java Virtual Machine Engine is always running and tries to automagically link to the correct sdks. Based on AS history, that has proven impossible to do without lots of mistakes.

ABC has gotten around some of Java’s issues (speed being the major one) by using JNI (Java Native Interface (to “C”)) as much as possible. From what I can tell, there are NO API’s in Java that are solely Java implementations. Every single one I have stepped into has gone into JNI as soon as possible.

The other steps taken to speed Java up is pre-compiling apps into ByteCode and binding libraries for quick access. The amount of hoops that ABC has to go through for Java to work with any speed at all is astounding. And, between API based builds, ABC often breaks minor internet systems like UDP. Oh, well.

AS 2022 Builds And NDK.

To be fair, I was on Android Studio 2.3 the last time I worked on my Android Applications. You can download AS 2.3, and it will run on the latest OS’s, but it will not build an application. It seems ABC has turned off some servers critical to allowing AS to finish a build. Still, it is a useful tool to have.

The reason AS 2.3 is useful to have it that it lets you open a project that will not build. If you try to open a project on AS2022 that will not build, you get a failure, depending upon the severity of the errors. That is right, you get a failure to open. You can’t open enough in the AS 2022 to fix your project so it can build. This may be due to unavailable servers the older code is referring to (which I had no idea were required to do development builds.)

I tried revisiting the C++ application after I finally got the standard Kotlin build to compile, and the right sdklib for kotlin was downloaded. This library is required even though you may be building in native Java. (Hint: Kotlin is a pre-processor language that interprets into Java that is then interpreted by the JVM and runs on your phone. Chances are Kotlin is just a little bit slower in speed tests than Java.)

Well, the revisit of the C++ application failed. I was getting NDK errors. It turned out that the build download system is fully broken. The NDK library 25.1 license exists *somewhere*, and the directory exists, but the NDK was never downloaded. The build system says it was fixing the NDK by downloading it, but it never downloaded it, even after multiple tries.

That part of the AS build is broken. I finally reopened the sdk, selected the broken NDK (which was not selected), unselected it, selected it again, and applied. Magically the download started. After the download finished, I was able to do a build of the C++ code and have it work (I think. Very large program.).

The irony of the situation is the 25.2 NDK was selected and correctly downloaded, but the build system refused to use it. I could not find the license file(s), no matter how much ABC searches I did, so I could not remove the offending license which caused the directory to be created. If I deleted the 25.1 directory, it recreated it as empty and complained that the build could not complete due to NDK licensing issues.

CMakeLists.txt Hint

The default CMakeLists.txt is ok, but useless except for a tiny project where you have only one file to compile. That is a waste of time. Here is part of a CMakeLists.txt file which will compile any files in the same directory as the CMakeLists.txt file, and any files in any directories below the CMakeLists.txt directory. Insert about 3 lines and change one line in your CMakeLists.txt to be able to add arbitrary files to your NDK build.

#This cpp_android names the library to be included in the 
# static {
#    System.LoadLibrary("cpp_android");
#  }
#I created a Java class called Jni and put the above lines in it
# and the references to my c function calls.
# build script scope).
project("cpp_android")

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
#
# In this top level CMakeLists.txt, ${CMAKE_PROJECT_NAME} is used to define
# the target library name; in the sub-module's CMakeLists.txt, ${PROJECT_NAME}
# is preferred for the same purpose.
#
# In order to load a library into your app from Java/Kotlin, you must call
# System.loadLibrary() and pass the name of the library defined here;
# for GameActivity/NativeActivity derived applications, the same library name must be
# used in the AndroidManifest.xml file.
#
# !!!! Following 3 lines create the list of directories and files
#      for the build system CMake triggers.  This assumes your
# current NDK build directory is named "cpp"
file(GLOB_RECURSE cpp_srcs_c "../cpp/*.c")
file(GLOB_RECURSE cpp_srcs_cpp "../cpp/*.cpp")
set(cpp_srcs ${cpp_srcs_c} ${cpp_srcs_cpp})
#
# the ${cpp_srcs} replaces the native-lib.cpp in the example
# in this case, I commented it out with at # in front of native-lib.cpp
add_library(${CMAKE_PROJECT_NAME} SHARED
        # List C/C++ source files with relative paths to this CMakeLists.txt.
        ${cpp_srcs})
        #native-lib.cpp)

Moving Your Project? Gotcha!

Another problem I had was trying to move my project to another directory. That failed because something in the build system pointed back to the original directory the project was in. No amount of cleaning fixed the problem.

I finally found the answer to moving a project under Android Studio 2022 by piecing together several StackOverflow posts. Some of the steps may be overkill, but after an hour or two of frustration, you don’t mind the extra steps. Note that on Mac and Linux, .idea is a hidden directory in your project directory (or maybe your home directory). Once you find that directory, you are good to go.

// if you want to move the project, follow these steps
// 1. clean the project
// 2. close the project
// 3. move the project. rename if you wish
// 4. under the .idea/modules/app/ folder delete the .iml file there
// 5. under the .idea/modules/app/ folder delete the .cxx folder (contains CMakeLists.txt generated files)
// 6. re-open the project and build
// if you don't do all the above,you will get a CMakeLists.txt reference to 
// the previous build directory. Very Puzzling!

Changing the project prefix (i.e. the com.example. )

There is a plugin for Android Studio that does this for you. It is called “Android Package Renamer.” Download that plugin and let it do the work for you.

Android Studio Thoughts

Android Studio sucks. It is extremely SLOW. Gradle bragged it only took 1 minute to do a build.

It fails to build default projects that the AS GUI creates right out of the chute. I pity the poor fool trying to do a build the first time. I saw an estimate of 6 months to come up to speed on Android development using AS. I believe it, only because the AS system is in such poor shape, and it is not getting better based on my current experiences.

I have to say that VSCode has spoiled me. I know that VSCode is a memory hog, but I don’t care. Time is an on-going expensive cost, memory is a one time cost. You only have a certain number of weekends left in your life. More memory can be purchased. Not weekends.

The Fruit Company’s build system is not much better. You are overwhelmed by its complexity, but based on my previous experiences, at least it can build its default projects. Once you understand that Objective C is a pre-compiler language that translates to C, it becomes easier to understand.

I have use Microsoft’s IDE since 1980’s, as well as Eclipse, a dozen text editors, 14+ programming languages, and about that many assembler languages. Several more IDE’s are thrown into the mix.

With all of that, so far, the best IDE experience I have had is PSOC Creator. Slow, yes. Annoying, yes. But it works! It saved time and kept complexity managed so I could get work done first. As I used it, I was able to uncover complexities when I needed them. I was not slapped in the face with things I did not need to know.

Enabling XLint for Java Compiles

Unfortunately, this bit of information is just barely out there and assumes you know their compile system inside and out. If you get a suggestion to enable XLint, then do the following.

Inside “build.gradle.kts” (:app) add the following lines at the bottom of the file:

afterEvaluate {
    tasks.withType(JavaCompile::class) {
        options.compilerArgs.add("-Xlint:unchecked")
        options.compilerArgs.add("-Xlint:deprecation")
    }
}

Using those lines will give you the extra information you are looking for. Most of the time you can ignore these warnings, but at some point in the future, you will have to deal with the issues raised.

In my opinion, changing API’s to make old ones obsolete is usually stupid. I believe it is usually done to make some developer at ABC feel important. I was once like that. I wanted to feel important.

App Signing and Danger Ahead

I understand the thinking behind signing apps. I disagree with the implementation.

The Fruit Company requires you to be online to run their apps, unless you can wait several (feels like) minutes for an app to open. The bottom line on this is they know which apps you are using. And so do all of the 3 letter agencies out there. Some apps are illegal to use in some parts of the world, such as VPN apps in the CCP controlled territories. Signing apps alert governments that you are using something they may have declared to be illegal.

The ABC company requires you let them sign the app. That means they (or a government agency) can slip in spyware inside the app without your knowledge, or the end user’s knowledge. Therefore, you are unable to trust any modern app delivered by ABC play store, as it may contain a Trojan Horse slipped in by the ABC company itself, or by a malicious actor intercepting and modifying the download in real time with a new signing key. (Or a government, or an ISP, or …)

This is easily possible due to the nature of Java, which automagically links in the code and uses it with virtually no security checks. It turns out Java’s main strength is the source of many security headaches today.

Fini

If you need to deliver virus free, Trojan Horse free, apps to your customers, use “side loading” for Android and sign the apps yourself. (Assuming libraries provided by ABC are not compromised.)

For IOS, use annual keys or Enterprise permanent keys (with the caveat that others know when that app is being executed).

Unsigned Apps: For Windows or Mac, you can have them enable “developer” mode on their machine and run unsigned apps. Otherwise warn them of the consequences of using signed apps.

Enjoy!

Add a Comment

Your email address will not be published. Required fields are marked *