How to build your first extension. A complete guide for the newbies

They are imports that let you use other packages in your project. Somewhere, there’s a .java file with the package name “com.google.appinventor.components.common.ComponentCategory”, and you’re importing the public methods and fields of that file into yours.
This is where the directory structure @Shreyash was talking about comes in handy. You can expect the file (in this case, ComponentCategory.java) to exist in com/google/appinventor/components/common/
And you would be right in assuming so: appinventor-sources/ComponentCategory.java at master · mit-cml/appinventor-sources · GitHub

If you click on the link, you’ll see there are other .java files in the folder alongside ComponentCategory.java. Suppose you wish to import all of them into your file, you’d use something called a wildcard import. That’s what these lines are:

You’re effectively importing all files inside com/google/appinventor/components/annotations and com/google/appinventor/components/runtime. More on wildcard imports here: Everything You Need to Know about Java Packages and Import Statements

Similarly, these files are present in android/content/Context and android/util/Log. But you won’t find their source code (.java files) in the App Inventor repository. This is because they’re provided by Android and are not specific to App Inventor. (Also note the importance of picking the right package name here. Since the package name in the case above starts with android, we can assume it’s part of Android’s standard library. And the others have com.google.appinventor, which indicates these files are part of App Inventor’s library. (You might wonder why it isn’t com.mit.appinventor, and that’s because these files were originally written by Google. It’s hard to rename packages without breaking compatibility, especially with third-party code, which is why the original package names have probably been retained))

But the source for these Android files surely must exist somewhere… the compiler can’t fetch code from thin air. You’re right, and Java solves this problem by letting us build .jar files. .jars are packaged .java files. They contain executable code (bytecode, if I’m being pedantic) generated from your source code. Google provides one such .jar for the Android library which App Inventor uses in its components. You can find it here: appinventor-sources/android.jar at master · mit-cml/appinventor-sources · GitHub
Further reading on bytecode and libraries if you’re interested:
Java bytecode:
JAR File Overview
Java bytecode - Wikipedia

Some of these imports are essential for your extension to work, while some are optional and depend on what you wish to do with your project. For example, if I were to make a Twitter extension, I’d first look for a .jar supplied by Twitter that contains the endpoints I can use (say, TwitterAPI.sendTweet(…)).
I then download this .jar and add it to my extension. (This is not possible with the online IDEs, by the way. You have to use the extension template or AI repository to include libraries in your project that App Inventor doesn’t already provide). Finally, I import the Twitter packages into my project using the import keyword.

Tip: Avoid wildcard imports as it makes it harder to track where certain parts of your code are coming from. It’s rare that you would want to include all files in a folder. Use it only when needed. java - Using the wildcard when importing packages - Code Review Stack Exchange

12 Likes

And if you’re interested to know why Java uses such a system instead of making all code available everywhere, or placing all functions and variables in a single file/folder, I suggest reading up on Object Oriented Programming and its core principles. Java is an Object Oriented language, and as such sticks to the four fundamental principles laid out here: What are four basic principles of Object Oriented Programming?

9 Likes

Very well explained, thank you @Vishwas! I’ve been reading it many times too understand everything. Now I see why users asked in many occasions if they can import third party libraries.

Is it right to say that all these files are stored somewhere in the online IDE (AppyBuilder or Kodular) and that’s why we can import them but not the third party ones, that’s why we can’t use those?

Also, which ones are “mandatory” or required to use for any type of extension? Example: I just want to make the typical a + b and return the result. Do I need all of these imports shown in the example?

7 Likes

Yes. That is correct.

You will need to import the annotations for every extension. They’re used to expose your Java code as blocks. That’s one required import you’ll find in ALL extensions.
import com.google.appinventor.components.annotations.*;

You’ll also need the ComponentCategory import to tell the system which category to place your extension in.

And it’s generally a good idea to import all files in the runtime folder because your extension will almost always use some functionality already defined in other App Inventor components. (the runtime folder is where you can find the source code for all AI components. If you were making your extension using the AI repository, it’s where you would be placing your extension’s Java file) If you know about “inheritance” in object oriented programming, you’ll see that all extensions “extend” AndroidNonVisibleComponent, which is a file defined in com/google/appinventor/components/runtime.

So, at the least, you’ll need:

9 Likes

@Italo all files are stored into database

3 Likes

Perfect, this is very informative so far.

Very convenient! Long time ago I tried learning how to make extensions but the online IDE’s were not existent yet, so It was a lot more complicated. Is there any difference between the AppyBuilder and the Kodular IDE’s? I know the Kodular one is not available at the moment.
Any plans on unifying them? Any advantages of using one vs the other?

2 Likes

And to take it one step further, is it possible to import third party libraries in the future?

1 Like

I was actually typing a question about that too.
Specifically, what are the steps necessary to do this? :

And I know I’m making a lot of questions, please don’t feel obligated to reply. It can be replied another day or by anyone else. This is going very well by the way.

1 Like

I don’t think so. Both offer pretty much the same functionality. We don’t have any plans to merge them as of now.

We have plans to add this as a paid feature alongside other perks. It’s still a work in progress, though.

To summarise, you have to get the .jar file from the provider, place it in the lib folder of the repository, and add a few lines in the main build.xml file. You should then use the @UsesLibraries() annotation to list the .jar files you’re using in your extension. This is fairly advanced, and I’d recommend looking into this after you’ve got a good idea of how App Inventor components and extensions work behind the scenes.

I’d also suggest glancing over my go-to guide for extensions development. It may be a bit daunting at first, but it does a great job explaining how the App Inventor system works and how you should go about making your own extensions:
https://docs.google.com/document/d/1xk9dMfczvjbbwD-wMsr-ffqkTlE3ga0ocCE1KOb2wvw/pub

6 Likes

Hi @Vishwas

Sometimes I have to use that annotation and sometimes not.It’s quite confusing for me and it increase aix size also.
Can you please tell me when to use that annotation and when not?

1 Like

I am already bad at koding in kodular how would i code an extension :slight_smile:

But its a good choice to make HTML

2 Likes

Hello, after a few months of koding in :kodular:, I find it interesting. But I have no clue about extension after creating a new project in AppyBuilder Code Editor
I went speechless.
My thought: What???
So, is there any tutorial of this?

See here:

3 Likes

Thx for your quick reply!

1 Like

Why i can’t get confirmation email.