Getting multiple errors while writing an extension

Getting multiple errors while writing an extension

While writing an extension that uses API to get a random joke from internet in json format, and then parsing that json to obtain the desired result, I am getting multiple errors.

I am attaching all the code and logs. If you can, please help me get a solution.

Code:

 package com.aariz.expressjokes;

        import android.app.Activity;
        import android.content.Context;
        import com.google.appinventor.components.annotations.*;
        import com.google.appinventor.components.common.ComponentCategory;
        import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
        import com.google.appinventor.components.runtime.ComponentContainer;
        import com.google.appinventor.components.runtime.EventDispatcher;
        
        import org.json.JSONArray;
        import org.json.JSONException;
        import org.json.JSONObject;
        
        import java.io.IOException;
        
        import okhttp3.Call;
        import okhttp3.Callback;
        import okhttp3.OkHttpClient;
        import okhttp3.Request;
        import okhttp3.Response;
        
        @DesignerComponent(
                version = 1,
                description = "Introducing the ExpressJokes extension! Be no more worried to entertain your users. Simply use the extension to get a new, randomly selected joke delivered straight to your app. Whether you're looking to make your users laugh or just need a quick pick-me-up for our admin panel, this extension has you covered. Give it a try and bring some joy to your day!",
                category = ComponentCategory.EXTENSION,
                nonVisible = true,
                iconName = "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhL5ve5hVzd7Oa5HY0FjGcXg8ybTBPqu0rDxrGJmltzDh9QK5kXlQpiMDoFarZNp0LWlKcHt_O9YhAo-Bd7pHYbivQ8_ji4O-fzr9ioyF4FCe9tDWUaAzW6x1SoKq4dCMm7D2FX7gfjWtdOJjsIA8WHm41mmvSTnl08oAOfGpoW2jV3bxQq9ntSC4B/s320/expressJoke.jpg")
        
        @SimpleObject(external = true)
        //Libraries
        @UsesLibraries(libraries = "okhttp-3.9.0.jar")
        //Permissions
        @UsesPermissions(permissionNames = "android.permission.INTERNET")
        
        public class ExpressJokes extends AndroidNonvisibleComponent {
        
            //Activity and Context
            private Context context;
            private Activity activity;
        
            public String apiresponse,joke;
        
            public ExpressJokes(ComponentContainer container){
                super(container.$form());
                this.activity = container.$context();
                this.context = container.$context();
            }
        
            @SimpleFunction(description = "Get a new, randomly selected joke delivered")
            public void getJoke(){
                OkHttpClient client = new OkHttpClient();
                Request request = new Request.Builder()
                        .url("https://jokes-by-api-ninjas.p.rapidapi.com/v1/jokes")
                        .get()
                        .addHeader("X-RapidAPI-Key", "...")
                        .addHeader("X-RapidAPI-Host", "jokes-by-api-ninjas.p.rapidapi.com")
                        .build();
                client.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        return "Something went wrong!";
                    }
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        if(response.isSuccessful()){
                            apiresponse = response.body().string();
                            context.this.runOnUiThread(new Runnable() {
                                @Override
                                public String run() {
                                    try {
                                        JSONArray jsonArray = new JSONArray(apiresponse);
                                        JSONObject jsonObject = jsonArray.getJSONObject(0);
                                        joke = jsonObject.getString("joke");
                                        return joke;
                                    } catch (JSONException e) {
                                        return "Something went wrong!";
                                    }
                                }
                            });
                        }
                    }
                });
            }
        }

`

Issues:

Started Compiling Project ExpressJokes
        Buildfile: /compiler/android/build.xml
        
        javac:
        [mkdir] Created dir: /compiler/android/build/PIPMP/classes
        [javac] Compiling 1 source file to /compiler/android/build/PIPMP/classes
        [javac] warning: [options] bootstrap class path not set in conjunction with -source 1.7
        [javac] Note: Wrote file file:/compiler/android/build/PIPMP/classes/simple_components.json
        [javac] Note: Wrote file file:/compiler/android/build/PIPMP/classes/simple_components.txt
        [javac] Note: Wrote file file:/compiler/android/build/PIPMP/classes/simple_components_build_info.json
        [javac] Note: Wrote file file:/compiler/android/build/PIPMP/classes/AutogeneratedOdeMessages.java
        [javac] Note: Wrote file file:/compiler/android/build/PIPMP/classes/ComponentsTranslation.java
        [javac] /compiler/android/src/PIPMP/com/aariz/expressjokes/ExpressJokes.java:59: error: is not abstract and does not override abstract method onFailure(Call,IOException) in Callback
        [javac] client.newCall(request).enqueue(new Callback() {
        [javac] ^
        [javac] /compiler/android/src/PIPMP/com/aariz/expressjokes/ExpressJokes.java:61: error: onFailure(Call,IOException) in cannot implement onFailure(Call,IOException) in Callback
        [javac] public String onFailure(Call call, IOException e) {
        [javac] ^
        [javac] return type String is not compatible with void
        [javac] /compiler/android/src/PIPMP/com/aariz/expressjokes/ExpressJokes.java:60: error: method does not override or implement a method from a supertype
        [javac] @Override
        [javac] ^
        [javac] /compiler/android/src/PIPMP/com/aariz/expressjokes/ExpressJokes.java:68: error: is not abstract and does not override abstract method run() in Runnable
        [javac] context.this.runOnUiThread(new Runnable() {
        [javac] ^
        [javac] /compiler/android/src/PIPMP/com/aariz/expressjokes/ExpressJokes.java:70: error: run() in cannot implement run() in Runnable
        [javac] public String run() {
        [javac] ^
        [javac] return type String is not compatible with void
        [javac] /compiler/android/src/PIPMP/com/aariz/expressjokes/ExpressJokes.java:69: error: method does not override or implement a method from a supertype
        [javac] @Override
        [javac] ^
        [javac] /compiler/android/src/PIPMP/com/aariz/expressjokes/ExpressJokes.java:68: error: cannot find symbol
        [javac] context.this.runOnUiThread(new Runnable() {
        [javac] ^
        [javac] symbol: class context
        [javac] 7 errors

Please help if you know how to solve this issue. I am using this API to get joke from the internet.

Thank you very much!

There are some Java concepts that you need to clear up. Look at your getJoke function.

First of all, you should rename the function according to the naming conventions to GetJoke.

Second, you don’t have to import activity and context. They are replaceable with the variable form, because Form implements activity and context. Do not use context.this, use form.

On top of this, you need to understand when to return a value. A void function does not return a value, it only does something. If you want to return a value, use String; however in this context, you are running something using the Internet, so you should rather call an event.

With all of those cleared up, I rewrote your code. You also have to add the JSON library found here which you forgot. (json-20220924.jar)

You must also replace the ellipsis in the line .addHeader("X-RapidAPI-Key", "...") with your own Rapid API key.

package com.gordonlu.expressjokes;

import android.app.Activity;
import android.content.Context;
import com.google.appinventor.components.annotations.*;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.ComponentContainer;
import com.google.appinventor.components.runtime.EventDispatcher;
        
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
        
import java.io.IOException;
        
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
        
@DesignerComponent(
    version = 1,
    description = "Introducing the ExpressJokes extension! Be no more worried to entertain your users. Simply use the extension to get a new, randomly selected joke delivered straight to your app. Whether you're looking to make your users laugh or just need a quick pick-me-up for our admin panel, this extension has you covered. Give it a try and bring some joy to your day!",
    category = ComponentCategory.EXTENSION,
    nonVisible = true,
    iconName = "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhL5ve5hVzd7Oa5HY0FjGcXg8ybTBPqu0rDxrGJmltzDh9QK5kXlQpiMDoFarZNp0LWlKcHt_O9YhAo-Bd7pHYbivQ8_ji4O-fzr9ioyF4FCe9tDWUaAzW6x1SoKq4dCMm7D2FX7gfjWtdOJjsIA8WHm41mmvSTnl08oAOfGpoW2jV3bxQq9ntSC4B/s320/expressJoke.jpg")
    
@SimpleObject(external = true)
@UsesLibraries(libraries = "okhttp-3.9.0.jar,json-20220924.jar")
@UsesPermissions(permissionNames = "android.permission.INTERNET")
        
public class ExpressJokes extends AndroidNonvisibleComponent {
        
    public String apiresponse;
    public String joke;
        
    public ExpressJokes(ComponentContainer container){
        super(container.$form());
    }
        
    @SimpleFunction(description = "Get a new, randomly selected joke delivered")
    public void GetJoke(){
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("https://jokes-by-api-ninjas.p.rapidapi.com/v1/jokes")
                .get()
                .addHeader("X-RapidAPI-Key", "...")
                .addHeader("X-RapidAPI-Host", "jokes-by-api-ninjas.p.rapidapi.com")
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
                Error(e.getMessage());
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if(response.isSuccessful()){
                    apiresponse = response.body().string();
                    form.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                JSONArray jsonArray = new JSONArray(apiresponse);
                                JSONObject jsonObject = jsonArray.getJSONObject(0);
                                joke = jsonObject.getString("joke");
                                GotJoke(joke);
                            } catch (JSONException e) {
                                e.printStackTrace();
                                Error(e.getMessage());
                            }
                        }
                    });
                }
            }
        });
    }

    @SimpleEvent(description = "This event is fired when an error has occurred.")
    public void Error(String error) {
        EventDispatcher.dispatchEvent(this, "Error", error);
    }

    @SimpleEvent(description = "This event is fired when the extension has successfully retrieved the joke.")
    public void GotJoke(String joke) {
        EventDispatcher.dispatchEvent(this, "GotJoke", joke);
    }
}

3 Likes

Thank you very much for your help brother. I would never forget this kind act of yours.
But brother can you please share the .aia of the app you've attached the screenshot of, because, I am getting runtime errors.

Here's the screenshot:

Therefore it would be highly appreciated if you do share your project to help me resolve, also I am a beginner so forgive me of any silly mistakes and guide me.

Here's the .aia file of my app incase you may want to have a look:

https://drive.google.com/uc?export=download&id=1sKR6rhLwir-iWNztX27r_4M8ADXeMaru

Thank you very much!

Make sure you are using the JAR file provided in Maven.

https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp/3.9.0

Questionably, your project worked for me with the extension that you have provided.

But it doesn’t work at my end. I even tried using the app in my other phone. Here’s the screenshot of the app on a different phone:



What should I do now?

Praise be to God that I was finally able to get off with this error. Also thank you very much @Gordon_Lu for you help and guide. I found this stackoverflow question (https://stackoverflow.com/questions/36995096/java-lang-noclassdeffounderror-failed-resolution-of-lokio-buffer) and after adding

okio-1.13.0.jar

to

@UsesLibraries(libraries = "okhttp-3.9.0.jar, okio-1.13.0.jar, json-20220924.jar")

My code, it worked perfectly!

1 Like