Click here to Skip to main content
15,867,308 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I am building a weather displaying android application with the api of openweather.org api key.

I have written some basic logic to display the weather details of a related city when the user searches the city

So the error i am facing is as displayed as follows,

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.openweather, PID: 2966
    java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.openweather-SX-bmUO1B6_TZYTWtbjZGQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.openweather-SX-bmUO1B6_TZYTWtbjZGQ==/lib/arm64, /system/lib64]]] couldn't find "libkeys.so"
        at java.lang.Runtime.loadLibrary0(Runtime.java:1067)
        at java.lang.Runtime.loadLibrary0(Runtime.java:1007)
        at java.lang.System.loadLibrary(System.java:1667)
        at com.example.openweather.Retrofit.ApiClient.<clinit>(ApiClient.java:10)
        at com.example.openweather.Retrofit.ApiClient.getClient(ApiClient.java:21)
        at com.example.openweather.MainActivity.getWeatherData(MainActivity.java:52)
        at com.example.openweather.MainActivity.access$000(MainActivity.java:19)
        at com.example.openweather.MainActivity$1.onClick(MainActivity.java:44)
        at android.view.View.performClick(View.java:7870)
        at android.view.View.performClickInternal(View.java:7839)
        at android.view.View.access$3600(View.java:886)
        at android.view.View$PerformClick.run(View.java:29363)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:7948)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)



So I have 4 classes and an interface to this project which are as follows,

The Main Activity

package com.example.openweather;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.openweather.Retrofit.ApiClient;
import com.example.openweather.Retrofit.ApiInterface;
import com.example.openweather.Retrofit.Example;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends AppCompatActivity {

    ImageView search;
    TextView tempText,
            descText,
            humidityText;
    EditText textField;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        search = findViewById(R.id.search);
        tempText = findViewById(R.id.tempText);
        descText = findViewById(R.id.descText);
        humidityText = findViewById(R.id.humidityText);
        textField = findViewById(R.id.textField);


        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {


                getWeatherData(textField.getText().toString().trim());

            }
        });
    }

    private void getWeatherData(String name) {

        ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);

        Call<Example> call = apiInterface.getWeatherData(name);

        call.enqueue(new Callback<Example>() {
            @Override
            public void onResponse(Call<Example> call, Response<Example> response) {

                try {
                    tempText.setText("Temp" + " " + response.body().getMain().getTemp() + " C");
                    descText.setText("Feels Like" + " " + response.body().getMain().getFeels_like());
                    humidityText.setText("Humidity" + " " + response.body().getMain().getHumidity());
                } catch (Exception e) {
                    e.printStackTrace();
                }


            }

            @Override
            public void onFailure(Call<Example> call, Throwable t) {

            }
        });

    }


    @Override
    public void onBackPressed() {
        super.onBackPressed();
    }
}



The ApiInterface

package com.example.openweather.Retrofit;

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;

public interface ApiInterface {

    @GET("https://api.openweathermap.org/data/2.5/weather?appid=1ebf50976c7bdea4db9a208956569a84&units=metric")
    Call<Example> getWeatherData(@Query("q") String name);
}


The ApiClient Java Class

package com.example.openweather.Retrofit;

import android.util.Base64;

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class ApiClient {
    static {
        System.loadLibrary("keys");
    }

    public native static  String getApi();

    private static Retrofit retrofit = null;

    public static String APIKEY = new String(Base64.decode(getApi(), Base64.DEFAULT));

    public static  Retrofit getClient(){

        if (retrofit == null){

            retrofit = new Retrofit.Builder()
                    .baseUrl("https://api.openweathermap.org/data/2.5/")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

        }


        return retrofit;

    }
}


The Example Java Class (Example.java)

package com.example.openweather.Retrofit;

import com.google.gson.annotations.SerializedName;

public class Example {
    @SerializedName("main")
    private Main main;


    public Main getMain() {
        return main;
    }

    public void setMain(Main main) {
        this.main = main;
    }
}


The Main Java Class (Main.java)

package com.example.openweather.Retrofit;

import com.google.gson.annotations.SerializedName;

public class Main {
    @SerializedName("temp")
    String temp;

    @SerializedName("humidity")
    String humidity;

    @SerializedName("feels_like")
    String feels_like;


    public String getTemp() {
        return temp;
    }

    public void setTemp(String temp) {
        this.temp = temp;
    }

    public String getHumidity() {
        return humidity;
    }

    public void setHumidity(String humidity) {
        this.humidity = humidity;
    }

    public String getFeels_like() {
        return feels_like;
    }

    public void setFeels_like(String feels_like) {
        this.feels_like = feels_like;
    }

}


The Module Build Gradle

plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
        applicationId "com.example.openweather"
        minSdkVersion 16
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    implementation 'com.squareup.retrofit2:retrofit:2.6.1'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
}



I have tried some ways to overcome the issue but have failed.

Hope to get a solituon for this

What I have tried:

Have tried different solutions by removing the retrofit dependencies and readding them back to project and altering the api key and so on, but nothing seems to be working
Posted
Updated 15-Jan-21 7:11am
v3
Comments
Richard MacCutchan 14-Jan-21 4:28am    
The message is clear: it cannot find the native library named libkeys.so.
AasifAha 14-Jan-21 7:54am    
I am launching this project in my physical device and I tried launching it with a android studio emulator as well both the cases I get the same error
David Crow 14-Jan-21 12:37pm    
I'm not sure what the statement in question does (probably because I know nothing of JNI or the NDK), but I was able to mock up a simple test that retrieves the current weather in my area:
StringBuilder sb = new StringBuilder();

try
{
    URL url = new URL("https://api.openweathermap.org/data/2.5/weather?zip=74103&appid=1ebf50976c7bdea4db9a208956569a84&units=metric");
    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
    if (connection.getResponseCode() == HttpsURLConnection.HTTP_OK)
    {
        String strLine;

        BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        while ((strLine = reader.readLine()) != null)
            sb.append(strLine);

        reader.close();
        connection.disconnect();

        JSONObject object = new JSONObject(sb.toString());

        JSONObject coords = object.getJSONObject("coord");
        double latitude = coords.getDouble("lat");
        Log.d("Test2", "latitude = " + latitude);
        double longitude = coords.getDouble("lon");
        Log.d("Test2", "longitude = " + longitude);

        JSONObject main = object.getJSONObject("main");
        double temp = main.getDouble("temp");
        Log.d("Test2", "temp = " + temp);
        double feels_like = main.getDouble("feels_like");
        Log.d("Test2", "feels_like = " + feels_like);
        int humidity = main.getInt("humidity");
        Log.d("Test2", "humidity = " + humidity);

        JSONObject wind = object.getJSONObject("wind");
        double speed = wind.getDouble("speed");
        Log.d("Test2", "wind speed = " + speed);
        int dir = wind.getInt("deg");
        Log.d("Test2", "wind from = " + dir);
    }
}
catch(Exception e)
{
    Log.e("Test2", e.getMessage());
}
It's probably comparing apples to oranges, but it at least shows you that their API works.

1 solution

In your ApiClient.java source you have the following:
Java
static {
    System.loadLibrary("keys");
}

and the error message is saying that it cannot find that (64-bit) library. It is possible that your system either does not have a 64-bit library, or the library that you are trying to load is not present. Check your target system to see whether that library exists, and which version it is.
 
Share this answer
 
Comments
AasifAha 14-Jan-21 7:56am    
System? what system are you referring here, is it the device which the application getting launched or the PC that I am using to develop the app,

In terms of PC not an issue, my OS is a 64BIT processing os, and the mobile phone also has a 64BIT Architecture (Galaxy A20s)
Richard MacCutchan 14-Jan-21 8:02am    
The issue remains to be that this library does not exist either on your device or in the emulator. That suggests that there is no such library. What are you trying to do with it, and where did you find the information on using it?
AasifAha 14-Jan-21 8:50am    
I am following a YouTube tutorial which shows on how to create a weather app based on city (User searches for the city by name).

The error is thrown when i type in some city name and click on the search button

Link - https://youtu.be/SrVY2la7lCI

GIT HUB - https://github.com/daniyalahmedkhan/WeatherApp/tree/master/app/src/main
Richard MacCutchan 14-Jan-21 9:13am    
Then you need to talk to the person who created the video. They are more likely to know why they are trying to load this library.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900