0
votes

I'm trying to build an application that converts currency. I use a public API to access the currency exchange functionality. When I debug my code, I'm unable to view the JSON received object because of this network security error. I checked other posts on here and tried to fix it by including android:usesCleartextTraffic="true" and uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" in AndriodManifest.xml file. This is an image of the debugging output: image

Here are my code files.

AndriodManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.currencyconversion">

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.CurrencyConversion"
        android:usesCleartextTraffic="true"
        >
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

MainActivity.java:

package com.example.currencyconversion;

import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;

import com.example.currencyconversion.Retrofit.RetrofitBuilder;
import com.example.currencyconversion.Retrofit.RetrofitInterface;
import com.google.gson.JsonObject;

public class MainActivity extends AppCompatActivity {

    Button button;
    EditText currencyToBeConverted;
    EditText currencyConverted;
    Spinner convertToDropdown;
    Spinner convertFromDropdown;

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

        // Initialization
        currencyConverted =(EditText) findViewById(R.id.currency_converted);
        currencyToBeConverted =(EditText) findViewById(R.id.currency_to_be_converted);
        convertToDropdown = (Spinner) findViewById(R.id.convert_to);
        convertFromDropdown = (Spinner) findViewById(R.id.convert_from);
        button = (Button) findViewById(R.id.button);

       // Adding Functionality
        String[] downDownList = {"USD", "AED", "EUR", "GBP"};
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.support_simple_spinner_dropdown_item, downDownList);
        convertToDropdown.setAdapter(adapter);
        convertFromDropdown.setAdapter(adapter);


        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                //API Call
                RetrofitInterface retrofitInterface = RetrofitBuilder.getRetrofitInstance().create(RetrofitInterface.class);
                //Call<JsonObject> call = retrofitInterface.getExchangeCurrency(convertFromDropdown.getSelectedItem().toString());
                Call<JsonObject> call = retrofitInterface.getExchangeCurrency("AED");
                call.enqueue(new Callback<JsonObject>() {
                    @Override
                    public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
                        Log.d("response", String.valueOf(response.body())); //HERE IS WHERE I DEBUG


                        /*JsonObject res = response.body();
                        JsonObject rates = res.getAsJsonObject("conversion_rates");
                        double currency = Double.valueOf(currencyToBeConverted.getText().toString());
                        double multiplier = Double.valueOf(rates.get(convertToDropdown.getSelectedItem().toString()).toString());
                        double result = currency * multiplier;
                        currencyConverted.setText(String.valueOf(result));*/

                    }

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

                    }
                });
            }
        });


    }

RetrofitBuilder.java:

package com.example.currencyconversion.Retrofit;

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

public class RetrofitBuilder {
    public static Retrofit retrofit;
    public static Retrofit getRetrofitInstance() {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl("https://v6.exchangerate-api.com/")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }

        return retrofit;
    }
}

RetrofitInterface.java:

package com.example.currencyconversion.Retrofit;

import com.google.gson.JsonObject;

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;

public interface RetrofitInterface {
    @GET("v6/4API-KEY/latest/{currency}")
    Call<JsonObject> getExchangeCurrency(@Path("currency") String currency);
}
1
The message in your title is not an error.CommonsWare

1 Answers

0
votes
  1. Using the clearTextTraffic attribute only affects the httprotocol. So if you’re consuming an api where the base url isn’t over a secure http, protocol. (https) you use that attribute
  2. Have you declared the uses permission internet in your android manifest file ?
  3. You can create a network_config.xml file to set certain internet configurations

Have you looked at the JSON response body of the GET request you are calling ? What is the hierarchy like, you have to follow the hierarchy

Is it an array of objects, an object in an object where the key,value pairs are ?

Could you also post your jsonObject class. Have you made sure that the variables in that class have the exact naming convention as the keys in the api.

For example;

If the response had an object with this key,value pair

name:”Eimanalw”

In your jsonObject class have you named the variable Name instead of name

Finally, if you did change the character and named it Name did you use the

@Serializable(“name”)  //annotation
String Name;