Adding retrofit into android project - java

I want to try using Retrofit in a new Android project.
I have added the following to my build.gradle:
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.google.code.gson:gson:2.8.0'
I have a POJO called 'Turbine' which looks as follows:
public class Turbine {
String name;
}
I have my Endpoint service class:
import java.util.List;
import greenapps.objects.Turbine;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
public interface GreenAppService {
#GET("turbines/{id}")
Call<List<Turbine>> turbine(#Path("id") String id);
}
In my main activity in android I have the following code (this is where I want to execute the call and get back my Turbine pojo object filled with data from the backend:
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
...
...
...
//Relevant snippet starts here
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.API_V1_ENDPOINT)
.build();
GreenAppService service = retrofit.create(GreenAppService.class);
Call<List<Turbine>> turbine = service.turbine("1");
turbine.enqueue(new Callback<Turbine>() {
#Override
public void onResponse(Call<Turbine> call, Response<Turbine> response) {
}
#Override
public void onFailure(Call<Turbine> call, Throwable t) {
}
});//Relevant snippet ends here
On the turbine.enqueue line I am getting the following error:
I presume the syntax here is wrong somehow, but I don't quite see what is causing the issue.
Also, once this works, how do I get my Turbine object? Is it a case of doing Turbine t = response.body();

Because you defined that you are waiting an Array of Turbine.
turbine.enqueue(new Callback<Turbine>()
to
turbine.enqueue(new Callback<ArrayList<Turbine>>()
also you need to update onResponse and onFailure methods with arraylist.
I strongly suggest you to apply singleton pattern for your GreenAppService object.
UPDATE
Here is an example of singleton pattern.
public final class WebService {
private static GreenAppService sInstance;
public static GreenAppService getInstance() {
if (sInstance == null) {
sInstance = new Retrofit
.Builder()
.baseUrl(Constants.API_V1_ENDPOINT)
.build();
}
return sInstance;
}
}
After that we call like
WebService
.getInstance()
.yourmethod()
.enqueue()

Easy way to add retrofit in your project with just one click. (one-time setup)
Retrofit zip
Extract the file and you will get the “Retrofit” folder inside.
Copy this folder following the Android Studio path
Android\Android Studio\plugins\android\lib\templates\other
Restart your Android Studio.
Select your project in which you want to add retrofit and find an option below.
Project > New > Other> Retrofit
You can see full blog here
https://medium.com/#mestri.vinayak.n/quick-install-retrofit-in-your-android-project-custom-template-a14a6adc77c2

Related

Quarkus Mutiny Web Client Decode JSON safely

I've been getting into Quarkus and trying to utilize the Mutiny Vertx WebClient. My code works but I prefer not to have to rely on unsafe/unchecked assignments which is how I've currently written the code with bodyAsJson method on HttpResponse. Is there a better way, or more standard way to decode JSON from the Mutiny Vertx client? I realize I could just call bodyAsJsonObject and return that, but I need to do processing on the data the comes back from API calls so I need to decode it to a class representing the data shape/structure.
package com.something.app.language;
import com.something.app.model.Language;
import io.micrometer.core.annotation.Timed;
import io.smallrye.mutiny.Uni;
import io.vertx.mutiny.core.Vertx;
import io.vertx.mutiny.ext.web.client.WebClient;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import java.util.List;
#ApplicationScoped
public class LanguageService {
#Inject
Vertx vertx;
private WebClient client;
#PostConstruct
void init() {
this.client = WebClient.create(vertx);
}
#Timed
public Uni<List<Language>> getLanguages() {
return this.client
.get(80, "somehost.com", "/languages")
.timeout(1000)
.send()
.onItem()
.transform(resp -> {
if (resp.statusCode() == 200) {
return resp.bodyAsJson(List.class);
} else {
throw new RuntimeException("");
}
});
}
}
There are several ways. First, Vert.x uses Jackson under the hood, so everything that can be done with Jackson is possible.
You can use resp.bodyAsJson(MyStructure.class), which would create an instance of MyStructure.
If you have a JSON Array, you can map every element to the object class.
Finally, you can implement your own body codec (See https://vertx.io/docs/apidocs/io/vertx/ext/web/codec/BodyCodec.html).

Using Paging Library 3 with LiveData from Java

I want to use Paging Library 3 in conjunction with LiveData from Java. The documentation explains how to use Guava Futures, RxJava Singles and Kotlin Coroutines but not how to use it with LiveData from Java. I can probably The various PagingSource classes provide load, loadSingle and loadFuture.
The load example in Kotlin loads data using retrofit with a coroutine and can thus return a LoadResult object. But with LiveData, I need to make an asynchronous call from retrofit and set the value on LiveData object. There is no separate load utility method for LiveData like there is for RxJava and Guava. So, How can I achieve this using LiveData from Java ?
package org.metabrainz.mobile.data.repository;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.paging.PagingSource;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.metabrainz.mobile.data.sources.Constants;
import org.metabrainz.mobile.data.sources.api.MusicBrainzServiceGenerator;
import org.metabrainz.mobile.data.sources.api.SearchService;
import org.metabrainz.mobile.data.sources.api.entities.mbentity.MBEntity;
import org.metabrainz.mobile.data.sources.api.entities.mbentity.MBEntityType;
import org.metabrainz.mobile.presentation.features.adapters.ResultItem;
import org.metabrainz.mobile.presentation.features.adapters.ResultItemUtils;
import java.util.ArrayList;
import java.util.List;
import kotlin.coroutines.Continuation;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class SearchPagingSource extends PagingSource<Integer, ResultItem> {
#NonNull
private final static SearchService service = MusicBrainzServiceGenerator
.createService(SearchService.class, true);
#NonNull
private MBEntityType entity;
#NonNull
private String searchTerm;
public SearchPagingSource(#NonNull MBEntityType entity, #NonNull String searchTerm) {
this.entity = entity;
this.searchTerm = searchTerm;
}
#NotNull
#Override
public LiveData<LoadResult<Integer, ResultItem>> load(#NotNull LoadParams<Integer> loadParams,
#NotNull Continuation<? super LoadResult<Integer, ResultItem>> continuation) {
Integer pageSize = loadParams.getLoadSize();
Integer offset = loadParams.getKey() == null ? 0 : loadParams.getKey();
MutableLiveData<LoadResult<Integer, ResultItem>> resultsLiveData = new MutableLiveData<>();
service.searchEntity(entity.name, searchTerm, pageSize.toString(),
String.valueOf(offset * pageSize))
.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(#NonNull Call<ResponseBody> call,
#NonNull Response<ResponseBody> response) {
try {
List<ResultItem> data = ResultItemUtils
.getJSONResponseAsResultItemList(response.body().string(), entity);
LoadResult.Page<Integer, ResultItem> loadResult
= new LoadResult.Page<>(data, Math.max(0, offset - pageSize),
offset + pageSize, LoadResult.Page.COUNT_UNDEFINED,
LoadResult.Page.COUNT_UNDEFINED);
resultsLiveData.setValue(loadResult);
} catch (Exception e) {
e.printStackTrace();
LoadResult.Error<Integer, ResultItem> error = new LoadResult.Error<>(e);
resultsLiveData.setValue(error);
}
}
#Override
public void onFailure(#NonNull Call<ResponseBody> call, #NonNull Throwable t) {
}
});
return resultsLiveData;
}
}
This however crashes at runtime
org.metabrainz.android E/AndroidRuntime: FATAL EXCEPTION: main
Process: org.metabrainz.android, PID: 2222
java.lang.ClassCastException: androidx.lifecycle.MutableLiveData cannot be cast to androidx.paging.PagingSource$LoadResult
at androidx.paging.PageFetcherSnapshot.doInitialLoad(PageFetcherSnapshot.kt:302)
at androidx.paging.PageFetcherSnapshot$pageEventFlow$1.invokeSuspend(PageFetcherSnapshot.kt:149)
at androidx.paging.PageFetcherSnapshot$pageEventFlow$1.invoke(Unknown Source:10)
at androidx.paging.CancelableChannelFlowKt$cancelableChannelFlow$1.invokeSuspend(CancelableChannelFlow.kt:35)
at androidx.paging.CancelableChannelFlowKt$cancelableChannelFlow$1.invoke(Unknown Source:10)
at kotlinx.coroutines.flow.ChannelFlowBuilder.collectTo$suspendImpl(Builders.kt:327)
at kotlinx.coroutines.flow.ChannelFlowBuilder.collectTo(Unknown Source:0)
at kotlinx.coroutines.flow.internal.ChannelFlow$collectToFun$1.invokeSuspend(ChannelFlow.kt:33)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoop.processUnconfinedEvent(EventLoop.common.kt:69)
at kotlinx.coroutines.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:321)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:26)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:109)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:158)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:54)
at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
at androidx.lifecycle.BlockRunner.maybeRun(CoroutineLiveData.kt:174)
at androidx.lifecycle.CoroutineLiveData.onActive(CoroutineLiveData.kt:240)
at androidx.lifecycle.LiveData$ObserverWrapper.activeStateChanged(LiveData.java:437)
at androidx.lifecycle.LiveData$LifecycleBoundObserver.onStateChanged(LiveData.java:395)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300)
at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339)
at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145)
at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131)
at androidx.lifecycle.ReportFragment.dispatch(ReportFragment.java:68)
at androidx.lifecycle.ReportFragment.dispatch(ReportFragment.java:144)
at androidx.lifecycle.ReportFragment.onStart(ReportFragment.java:109)
at android.app.Fragment.performStart(Fragment.java:2637)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1312)
at android.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1549)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1611)
at android.app.FragmentManagerImpl.dispatchMoveToState(FragmentManager.java:3039)
at android.app.FragmentManagerImpl.dispatchStart(FragmentManager.java:2996)
at android.app.FragmentController.dispatchStart(FragmentController.java:189)
at android.app.Activity.performStart(Activity.java:7007)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2867)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2986)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1671)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:206)
at android.app.ActivityThread.main(ActivityThread.java:6784)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:852)
I had opened a feature request for shipping a LiveData Paging Source with the Paging Library. I received the following reply from the Google devs.
The Java Guava samples on d.android.com are for Guava + LiveData, in the coroutine equivalent we use: Guava's ListenableFuture as an async primitive that returns a single result (equivalent to a Coroutine or RxJava Single), and LiveData for multiple results / stream of results (equivalent of Kotlin Flow, or RxJava Observable).
I was recommended to write something on the lines of the following code snippet I if I wanted to use LiveData.
abstract class SearchPagingSource extends RxPagingSource<Integer, ResultItem>() {
#NotNull
public abstract LiveData<LoadResult<Integer, ResultItem>> loadLiveData(params: LoadParams<Key>);
#NotNull
#Override
public Single<LoadResult<Integer, ResultItem>> loadSingle(#NotNull LoadParams<Integer> loadParams) {
return loadLiveData(params).toRxJavaSingle(); // You must implement this bit!
}
}
The LiveData used in the above snippet should be a SingleLiveEvent
PS: The Google devs are open to reconsider their position on shipping this in the library itself if more developers request it. The relevant Google Issue tracker ticket is this.

NoSuchMethod when calling AWS Lambda using the AWS Sdk

I've created & deployed one simple GET API in API Gateway and here is the ARN and there is no authentication whatsoever on this function, I can simply call it on my browser
arn:aws:lambda:ap-southeast-1:XXXXXXXXXXXXXX:function:La
and the public url that can be browsed using the browser is:
https://xxxxxxxxx.execute-api.ap-southeast-1.amazonaws.com/v1/lambda/geta
and I'm using Spring boot project and the below code to invoke the API (Following this Doc)
The interface as the lambda service
package com.xxxxxxx.services.interfaces;
import com.amazonaws.services.lambda.invoke.LambdaFunction;
public interface ILambdaGetBalance {
#LambdaFunction(functionName="La")
String getA();
}
The service using that interface to call the lambda function
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.xxxxxxxx.services.interfaces.ILambdaGetBalance;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.lambda.AWSLambda;
import com.amazonaws.services.lambda.AWSLambdaClientBuilder;
import com.amazonaws.services.lambda.invoke.LambdaInvokerFactory;
#Service
public class LambdaService {
#Value("${aws.access-key}")
private String accessKey;
#Value("${aws.secret-key}")
private String secretKey;
#Value("${aws.lambda.region-name}") // this is ap-southeast-1
private String regionName;
public void test() {
AWSCredentials credentials = new BasicAWSCredentials(accessKey,
secretKey);
AWSLambda client = AWSLambdaClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withRegion(regionName)
.build();
final ILambdaGetBalance getBalance = LambdaInvokerFactory.builder()
.lambdaClient(client)
.build(ILambdaGetBalance.class);
getBalance.getA();
}
}
after calling the getA function the system will through the following exception:
java.lang.NoSuchMethodError: com.amazonaws.services.lambda.AWSLambdaClient.beforeClientExecution(Lcom/amazonaws/AmazonWebServiceRequest;)Lcom/amazonaws/AmazonWebServiceRequest;
Any idea why is this happening? What am I missing?
Looks like your aws-java-sdk-lambda and aws-java-sdk-core modules may have incompatible versions. How are you resolving the dependencies for your project? The beforeClientExecution method was added to the AmazonWebServiceClient base class in version 1.11.106 of aws-java-sdk-core - see here: https://github.com/aws/aws-sdk-java/blame/master/aws-java-sdk-core/src/main/java/com/amazonaws/AmazonWebServiceClient.java#L590

Java EE FirebaseApp name [DEFAULT] already exists

I got a problem related to Firebase and Java EE.
I'm currently writing some Java servlets for my project and I'm using Firebase the first time because I wanted to try something new.
My actual problem is the following:
I got a servlet which is responsible for exchanging an iOS device token in an user database. This is necessary for sending Remote Push Notifications to a device.
I've done this like in the google tutorials, but I'm getting the following exception:
java.lang.IllegalStateException: FirebaseApp name [DEFAULT] already exists!
The way I'm accessing the Firebase Database is through the Java SDK.
I do this with the following code:
connect method
// gets called by the servlet to configure Firebase
public static void connect() {
try {
// for authentication purpose
Map<String, Object> auth = new HashMap<>();
auth.put("uid", "my-service-account");
// Setting up the FirebaseOptions object
// constant FIREBASE_DATABASE_URL = "url to my database"
// constant FIREBASE_KEY_PATH = "path to my json key"
options = new FirebaseOptions.Builder()
.setDatabaseUrl(FIREBASE_DATABASE_URL)
.setServiceAccount(new FileInputStream(FIREBASE_KEY_PATH))
.setDatabaseAuthVariableOverride(auth)
.build();
FirebaseApp.initializeApp(options);
// calling the method for exchanging the token
exchangeIosDeviceToken("testmail#example.com", "5bf53173c9ef0a37638f3ddaa59cf2c0687c14ca0dcd47ccf57f9f09bd6368ab");
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}
}
exchangeIosDeviceToken method
public static boolean exchangeIosDeviceToken(String email, String newDeviceToken) {
FirebaseDatabase database = FirebaseDatabase.getInstance();
// getting a reference to my "employee" child
DatabaseReference employeeReference = database.getReference("/employee");
Map<String, Object> employeeUpdates = new HashMap<>();
// updating the device token with child "iosDeviceToken" of "employee"
employeeUpdates.put(email+"/iosDeviceToken", newDeviceToken);
// update the actual children
employeeReference.updateChildren(employeeUpdates);
return true;
}
The funny part is when I'm trying to execute this code in a standalone main class (replacing the connect method, with the main method), the code is working.
Before you're saying things like "there are tons of questions related to this topic"... They are nearly all related to Android and questions related to my problem seldom got answered.
Regards
Solved the problem.
The problem was:
I've called the connect method everytime a request was incoming.
Solution:
Call the connect method only once. (ServletContextListener)
this for the future users, You can check whether the default app is initialized or not like this.
FirebaseApp firebaseApp = null;
List<FirebaseApp> firebaseApps = FirebaseApp.getApps();
if(firebaseApps!=null && !firebaseApps.isEmpty()){
for(FirebaseApp app : firebaseApps){
if(app.getName().equals(FirebaseApp.DEFAULT_APP_NAME))
firebaseApp = app;
}
}
else
firebaseApp = FirebaseApp.initializeApp(options);
This exception appear because you are trying to create the [DEFAULT] FirebaseApp again, simply you can add a validation to check if it exist or not before the initialization, like this:
if(FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME) != null) {
return;
}
My fix to this issue was call FirebaseApp.getInstance().delete();
My solution
package com.zs.configuration;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOpt`enter code here`ions;
import com.google.firebase.auth.FirebaseAuth;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.io.FileInputStream;
#WebListener
public class MyAppServletContextListener
implements ServletContextListener{
#Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContextListener destroyed");
}
//Run this before web application is started
#Override
public void contextInitialized(ServletContextEvent arg0) {
try {
FileInputStream serviceAccount = new FileInputStream(getClass().getClassLoader().getResource("zs.json").getFile());
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://zs.firebaseio.com")
.build();
FirebaseApp firebaseApp = FirebaseApp.initializeApp(options);
FirebaseAuth.getInstance(firebaseApp);
}catch (Exception exc){
System.out.println("Firebase exception "+exc);
}
System.out.println("ServletContextListener started");
}
}
In my Application class
#ServletComponentScan
#SpringBootApplication
public class ZSApplication {
public static void main(String[] args) {
SpringApplication.run(ZSApplication.class, args);
}
}
Summarising all the solutions, very good ones BTW, proposed here: Running code after Spring Boot starts please find below the spring-boot (2.6.3) implementations which works for me.
Beware: Substitute with your app and files names below.
Placing the firebase initialisation method ( FirebaseApp.initializeApp(options)) directly on the main method (as I found on this tutorial: https://www.youtube.com/watch?v=8jK9O0lwem0) it caused the error, just because, debugging I notice, for some reason the call of the method FirebaseApp.initializeApp(options); is done multiple times.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Objects;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import lombok.extern.slf4j.Slf4j;
#Slf4j
#SpringBootApplication
public class YourAppNameApplication {
public static void main(String[] args) {
SpringApplication.run(YourAppNameApplication.class, args);
}
/**
* Initialize the firebase SDK to integrate with the firebase application. Used
* for check the clients UIDs authentications.
*
* #throws IOException in case the firebase configuration JSON file is not
* present on the path.
*/
#EventListener(ApplicationReadyEvent.class)
public void initFirebaseSDK() throws IOException {
ClassLoader classLoader = YourAppNameApplication.class.getClassLoader();
File file = new File(
Objects.requireNonNull(classLoader.getResource("your_file_firebase.json")).getFile());
FileInputStream serviceAccount = new FileInputStream(file.getAbsolutePath());
#SuppressWarnings("deprecation")
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://your_firebase_app_name.firebaseio.com").build();
FirebaseApp.initializeApp(options);
if (!(FirebaseApp.getApps().isEmpty())
&& FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME).getName() != null) {
log.info("Firebase SDK has been initialised with the app name: "
+ FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME).getName());
} else {
log.error(
"Firebase SDK has NOT been initialised. This is a serious error. Please contact the administrator of the app.");
}
}
}

Fatal exception. Using Retrofit2-beta3 cannot retrieve data from apiUrl using retrofit2

Ive been doing this tutorial using Android Studio IDE.
The problem I have is that the tutorial was done with older libraries of gson and retrofit 1.8.0...
I was following along well with retrofit2.0-beta3 until I came upon this error that I cant seem to resolve..
It has something to do with this line...(this line is in my MainActivity.Java under onCreate())
SCService scService = SoundCloud.getService();
scService.getRecentTracks(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()), new Callback<List<Track>>() {
#Override
public void onResponse(Response<List<Track>> tracks) {
Log.d("TAG", "ONRESPONSE() - -- - some else wrong");
// response.isSuccess() is true if the response code is 2xx
if (tracks.isSuccess()) {
Log.d("TAG", "ONRESPONSE()_isSuccess? - -- - some else wrong");
List<Track> track = tracks.body();
loadTracks(track);
} else {
Log.d("TAG", "some else wrong");
}
}
#Override
public void onFailure(Throwable t) {
// handle execution failures like no internet connectivity
Log.d("Error", t.getMessage());
}
});
so I think that the problem starts with scService Interface..
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.http.GET;
import retrofit2.http.Query;
interface SCService {
#GET("tracks?client_id=" + Config.CLIENT_ID)
public void getRecentTracks(#Query("created_at[from]") String date, Callback<List<Track>> cb);
}
Here is my Soundcloud class....
import retrofit2.Retrofit;
import retrofit2.Retrofit;
public class SoundCloud {
private static final Retrofit REST_ADAPTER = new Retrofit.Builder().baseUrl(Config.API_URL).build();
private static final SCService SERVICE = REST_ADAPTER.create(SCService.class);
public static SCService getService() {
return SERVICE;
}
}
This is the Config class didnt think it would be needed...
public class Config {
public static final String CLIENT_ID = "c85f6828ae5eaf5981937ead09ef1b45";
public static final String API_URL = "https://api.soundcloud.com/";
}
I have been at this the whole day, Any help would be much appreciated..
It could be few things, but most likely the problem is that Gson converter is no longer automatically registered with retrofit and thus your code doesn't know how to get you object from Json. I.e. in retrofit2 you need to register Gson like:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://api.nuuneoi.com/base/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
Take a look at this article: Retrofit 2 changes, Custom Gson Object (in the middle of the page)

Categories

Resources