I am creating an app using soundcloud api but I am getting error while parsing json object, I am new in this things so don't know what I am doing wrong here
Here is my interface
ScService.java
public interface SCService
{
#GET("/resolve.json?url=https://m.soundcloud.com/kshmr/sets/materia&client_id=iZIs9mchVcX5lhVRyQGGAYlNPVldzAoX")
Call<Track> getTrack();
}
Here is my model class
Track.java
public class Track
{
#SerializedName("title")
private String mTitle;
#SerializedName("stream_url")
private String mStreamUrl;
public String getTitle()
{
return mTitle;
}
public String getStreamUrl()
{
return mStreamUrl;
}
}
MainActivity.class
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Config.API_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
SCService Scservice = retrofit.create(SCService.class);
Call<Track> call = Scservice.getTrack();
call.enqueue(new Callback<Track>(){
#Override
public void onResponse(Call<Track> call, Response<Track> response)
{
// TODO: Implement this method
if(response.isSuccessful())
{
//String track = response.body().toString();
//Log.e("jsonres",track);
//gson = new GsonBuilder().create();
gson = new Gson();
Track track = gson.fromJson(response.body().toString(), Track.class);
}
#Override
public void onFailure(Call p1, Throwable p2)
{
// TODO: Implement this method
}
});
}
Here is the JSON response from api callcall
enter code here
{"kind":"track","id":399448641,"created_at":"2018/02/14 11:40:02 +0000","user_id":319295181,"duration":188726,"commentable":true,"state":"finished","original_content_size":33279566,"last_modified":"2018/03/10 17:33:18 +0000","sharing":"public","tag_list":"KSHMR \"House of Cards\" \"Sidnie Tipton\" Dharma \"Spinnin' \"","permalink":"houseofcards-mixmaster-05b","streamable":true,"embeddable_by":"all","purchase_url":"http://www.spinninrecords.com/releases/house-of-cards","purchase_title":"Download/Stream","label_id":null,"genre":"Dance & EDM","title":"KSHMR - House of Cards (Ft. Sidnie Tipton)","description":"KSHMR and Sidnie Tipton team up again, this time for the bittersweet sound of \"House of Cards\" \n\nDownload / Stream here: https://www.spinninrecords.com/releases/house-of-cards/","label_name":null,"release":null,"track_type":null,"key_signature":null,"isrc":null,"video_url":null,"bpm":null,"release_year":null,"release_month":null,"release_day":null,"original_format":"wav","license":"all-rights-reserved","uri":"https://api.soundcloud.com/tracks/399448641","user":{"id":319295181,"kind":"user","permalink":"dharmaworldwide","username":"Dharma Worldwide","last_modified":"2018/03/09 12:08:27 +0000","uri":"https://api.soundcloud.com/users/319295181","permalink_url":"http://soundcloud.com/dharmaworldwide","avatar_url":"https://i1.sndcdn.com/avatars-000324744374-jdrkyv-large.jpg"},"permalink_url":"https://soundcloud.com/dharmaworldwide/houseofcards-mixmaster-05b","artwork_url":"https://i1.sndcdn.com/artworks-000302088414-recq7g-large.jpg","stream_url":"https://api.soundcloud.com/tracks/399448641/stream","download_url":"https://api.soundcloud.com/tracks/399448641/download","playback_count":135077,"download_count":0,"favoritings_count":7351,"reposts_count":1354,"comment_count":120,"downloadable":false,"waveform_url":"https://w1.sndcdn.com/0Bcy6WpC8dzY_m.png","attachments_uri":"https://api.soundcloud.com/tracks/399448641/attachments","policy":"ALLOW","monetization_model":"NOT_APPLICABLE"}
I can't use gson.fromJson(...) method, how could I fix this?
Ps-I have pretty much changed my code.
You should do:
EDIT:
ScService.java
public interface SCService
{
#GET("users/17586135/tracks?client_id=iZIs9mchVcX5lhVRyQGGAYlNPVldzAoX")
Call<Track> getTrack();
}
MainActivity.class
Call<Track> call = Scservice.getTracks();
call.enqueue(new Callback<Track>(){
#Override
public void onResponse(Call call, Response<Track> response)
{
// Get the result
Track track = response.body();
}
#Override
public void onFailure(Call p1, Throwable p2)
{
// TODO: Implement this method
}
});
}
More here
The Gson object should be used in this way:
gson = new GsonBuilder().create();
Track track = gson.fromJson(response.body().toString(),Track.class);
Related
I get a result by using okhttp3 get method.
And Now, I want to return the result to MainActivity.
I tried using intent, but I'm failed.
Also I read this okhttp3 how to return value from async GET call. But I confused about where I have to write that code.
public interface GetLastIdCallback {
void lastId(String id);
}
my MainActivity:
getMaskInfo info = new getMaskInfo(this);
info.requestGet(latitude, longitude);
getMaskInfo Activity (I want to return JSONObject or JSONArray):
package com.example.buymaskapp;
public class getMaskInfo {
OkHttpClient client = new OkHttpClient();
public static Context mContext;
public getMaskInfo(Context context){
mContext = context;
}
public void requestGet(double lat, double lng){
String url = "https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/storesByGeo/json";
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
urlBuilder.addEncodedQueryParameter("lat", Double.toString(lat));
urlBuilder.addEncodedQueryParameter("lng", Double.toString(lng));
urlBuilder.addEncodedQueryParameter("m", "1000");
String requestUrl = urlBuilder.build().toString();
Request request = new Request.Builder().url(requestUrl).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Log.d("error", "Connect Server Error is " + e.toString());
}
#Override
public void onResponse(Call call, Response response) throws IOException {
try{
JSONObject jsonObject = new JSONObject(response.body().string());
JSONArray totalStore = jsonObject.getJSONArray("stores");
System.out.println(jsonObject);
}catch (JSONException e){
//
}
}
});
}
}
Instead of returning void from requestGet() method, return a LiveData
public LiveData<JSONObject> requestGet(double lat, double lng) {
LiveData<JSONObject> result = MutableLiveData<JSONObject>();
/* reqeust builder & url builder code here */
client.newCall(request).enqueue(new Callback() {
/* override other methods here */
public void onResponse(Call call, Response response) throws IOException {
try{
JSONObject jsonObject = new JSONObject(response.body().string());
((MutableLiveData) result).postValue(jsonObject);
}catch (JSONException e){
/* catch and do something */
}
}
});
return result;
}
Observe the livedata in mainactivity
info.requestGet(latitude, longitude).observe(getViewLifeCycleOwner, new Observer() {
#Override
public void onCanged(JSONObject result) {
/* code to use result */
}
});
Otherwise, you can also implement interface on mainactivity and use its instance in getMaskInfo or in requestGet method to send back data.
Create a callback in MainActivity:
public void onResult(JSONArray stores)
or whatever you want to return from the call. Since you now know that your mContext is actually MainActivity, you can make a cast and call that method
((MainActivity)mContext).onResult(totalStore).
If you need to use getMaskInfo with other activities as well, you can put method onResult into an interface, make MainActivity implement that interface and pass the interface as an argument to getMaskInfo.
Interface class
public interface GetLastIdCallback {
void lastId(String id);
void getJSONCallback(JSONObject object);
}
Update the onResponse function
#Override
public void onResponse(Call call, Response response) throws IOException {
try{
JSONObject jsonObject = new JSONObject(response.body().string());
JSONArray totalStore = jsonObject.getJSONArray("stores");
System.out.println(jsonObject);
((GetLastIdCallback )(mContext)).getJSONCallback(jsonObject); //Return here
}catch (JSONException e){
//
}
}
});
Calling activity must implement GetLastIdCallback interface
public class Main2Activity extends AppCompatActivity implements GetLastIdCallback{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
}
#Override
public void lastId(String id) {
}
#Override
public void getJSONCallback(JSONObject object) {
//Here you can use response according to your requirements
}
}
In MainActivityViewModel class i have one Getter method that returns an instance of CurrentWeather (pojo class) and this method needs response from OnResponse method but I get null for first time.
The first methods invoke from MainActivity, viewModel is not null but the currentWeather instance is.
MainActivityViewModel viewModel = ViewModelProviders.of(this).get(MainActivityViewModel.class);
currentWeather = viewModel.getCurrentWeather();
I don't know if I can ask to wait for a moment before return currentWeather in first method or not.
public class MainActivityViewModel extends ViewModel implements Callback<ResponseBody> {
private CurrentWeather currentWeather;
public CurrentWeather getCurrentWeather() {
if (currentWeather == null) {
createCurrentWeather("London");
}
return currentWeather;
}
public void createCurrentWeather(String city) {
RetrofitApiManager.getInstance().getCurrentWeatherApi(this, city);
}
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
ResponseBody body = response.body();
try {
String serverResponde = body.string();
Timber.e(serverResponde);
Gson gson = new Gson();
currentWeather = gson.fromJson(serverResponde, CurrentWeather.class);
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
}
It's because it takes a while before a response is returned.
Usually, you need a LiveData object to get results from background tasks.
In your MainActivityViewModel, add the following:
private MutableLiveData currentWeatherData = new MutableLiveData<CurrentWeather>();
public LiveData<CurrentWeather> getCurrentWeatherData() {
return currentWeatherData;
}
When you get response, update your LiveData
currentWeather = gson.fromJson(serverResponde, CurrentWeather.class);
currentWeatherData.postValue(currentWeather);
In your activity, you need to observe this LiveData.
viewModel.getCurrentWeatherData().observe(this, new Observer<CurrentWeather>() {
#Override
public void onChanged(CurrentWeather c) {
// Do whatever you want with c.
}
});
I am new to RxJava. I want to fetch data from the JSON API. Assume there are two APIs, API 1 and API 2. We fetch a JSON object "mediaId" from API 1. Now, I want to fetch JSON from API 2 with "mediaId". How can I achieve this using RxJava, along with retrofit in Android?
public void gettdata(final Listerner listerner){
postitemses= new ArrayList<>();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.mytrendin.com")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
APiService networkAPI = retrofit.create(APiService.class);
Observable<List<Postitems>> observable = networkAPI.getFriendObservable()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread());
observable.subscribe(new Observer<List<Postitems>>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
listerner.onFailure("oops... Something went wrong");
}
#Override
public void onNext(List<Postitems> postitemsList1) {
Postitems postitems;
for (int i=0;i<postitemsList1.size();i++){
postitems = new Postitems();
int id = postitemsList1.get(i).getId();
String title = postitemsList1.get(i).getTitle().getRendered();
String shortdesc= postitemsList1.get(i).getExcerpt().getRendered();
String mediaid= postitemsList1.get(i).getFeatured_media();
String authorid= postitemsList1.get(i).getAuthor();
String date = postitemsList1.get(i).getDate();
String slug = postitemsList1.get(i).getSlug();
Log.i("Hello-slug",""+slug);
String[] mediaurl= mydata(mediaid);
Log.i("Hello-mediaurl",""+mediaurl);
postitems.setId(id);
postitems.setDate(date);
postitems.setSlug(""+slug);
postitems.setPostExcerpt(shortdesc);
postitems.setPostTitle(title);
postitemses.add(postitems);
}
listerner.showpostitems(postitemses);
}
});
}
public String[] mydata(String mediaid){
final String[] mediaurl = new String[1];
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://www.mytrendin.com")
.build();
APiService aPiService = retrofit.create(APiService.class);
Call<Postitems> call = aPiService.getmediaurl(mediaid);
call.enqueue(new Callback<Postitems>() {
#Override
public void onResponse(Call<Postitems> call, Response<Postitems> response) {
Postitems postitemsList1 = response.body();
mediaurl[0] =postitemsList1.getGuid().getRendered();
// mediaurl[0][0] =postitemsList1.get(0).getGuid().getRendered();
}
#Override
public void onFailure(Call<Postitems> call, Throwable t) {
}
});
return mediaurl;
}
error occured
https://www.mytrendin.com
05-09 03:42:09.227 15315-15315/? D/AndroidRuntime: Shutting down VM
--------- beginning of crash
05-09 03:42:09.228 15315-15315/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mytrendin.mytrendin, PID: 15315
java.lang.NullPointerException: Attempt to invoke virtual method .mytrendin.dashboard.utils.Po stitems$Guid (ZygoteInit.java:755)
Sure you can use the merge operator along with the IO scheduler.By definition,merge can combine multiple Observables into one by merging their emissions.here is an example,
Observable<Integer> odds = Observable.just(1, 3, 5).subscribeOn(someScheduler);
Observable<Integer> evens = Observable.just(2, 4, 6);
Observable.merge(odds, evens)
.subscribe(new Subscriber<Integer>() {
#Override
public void onNext(Integer item) {
System.out.println("Next: " + item);
}
#Override
public void onError(Throwable error) {
System.err.println("Error: " + error.getMessage());
}
#Override
public void onCompleted() {
System.out.println("Sequence complete.");
}
});
Output :
Next: 1
Next: 3
Next: 5
Next: 2
Next: 4
Next: 6
Sequence complete.
Something like this in your case,
public Observable<Data> getMergedData() {
return Observable.merge(
networkRepository.getData().subscribeOn(Schedulers.io()),
networkRepository.getData().subscribeOn(Schedulers.io())
);
}
Alright there is another way to solve this, first create a observable for both API, then subscribe and observe changes from your first API subscription.Next create a PublishSubject instance. Which is useful because,once an Observer has subscribed, emits all subsequently observed items to the subscriber.For example publish string values from the api response.
private PublishSubject<String> subject = PublishSubject.create();
subject.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()).filter((s) -> s.size() > 0).subscribe(new Observer<String>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(String str) {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
Then to trigger the observable call onNext from the subject.
subject.onNext("some data from api");
Advantages, very flexible to changes to anywhere in your class scope.
Hope this helps.
for the below snippet
call.enqueue(new Callback<Postitems>() {
#Override
public void onResponse(Call<Postitems> call, Response<Postitems> response) {
Postitems postitemsList1 = response.body();
mediaurl[0] =postitemsList1.getGuid().getRendered();
// mediaurl[0][0] =postitemsList1.get(0).getGuid().getRendered();
//use the concept of publish subject here, which i detailed in answer, example
subject.onNext(postitemsList1.getGuid().getRendered());
//the string data will be passed to the above observable for the subject instance.
}
#Override
public void onFailure(Call<Postitems> call, Throwable t) {
}
});
I'm novice on using Retrofit, I want to post data as an json data with object format to server and get response from that, I tested my restful url with fake data and that work fine without any problem, but when i post data from android i get null. what i want to do? i want to post data to server and get response with this format:
public class UserLoginInformation {
private String username;
private String userUniqueId;
}
My interface:
public interface SignalRetrofitServiceProviders {
#POST("joinUserToApplication")
Call<List<UserLoginInformation>> joinUserToApplication(#Body Object data);
}
post data:
private void joinUserToApplication(String data) {
AlachiqRestFullProvider signalProvider = new AlachiqRestFullProvider();
SignalRetrofitServiceProviders signalRetrofitServiceProviders = signalProvider.getServices();
Call<List<UserLoginInformation>> call = signalRetrofitServiceProviders.joinUserToApplication(data);
call.enqueue(new Callback<List<UserLoginInformation>>() {
#Override
public void onResponse(Call<List<UserLoginInformation>> call, Response<List<UserLoginInformation>> response) {
List<UserLoginInformation> result = response.body();
final String r = new Gson().toJson(result);
}
#Override
public void onFailure(Call<List<UserLoginInformation>> call, Throwable t) {
t.printStackTrace();
Log.e("onFailure ", t.getMessage());
}
});
}
RestFull provider:
public class AlachiqRestFullProvider {
private SignalRetrofitServiceProviders signalRetrofitServiceProviders;
public AlachiqRestFullProvider() {
OkHttpClient httpClient = new OkHttpClient();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ClientSettings.ALACHIQ_WEB_BASE_URL)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
signalRetrofitServiceProviders = retrofit.create(SignalRetrofitServiceProviders.class);
}
public SignalRetrofitServiceProviders getServices() {
return signalRetrofitServiceProviders;
}
}
data for post:
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("mobileNumber", mobileNumber);
jsonObject.put("userUniqueId", uuid);
jsonObject.put("userPhoneNumbers", phoneContacts);
startService(
new Intent(context, AlachiqRestFullWebServiceProvider.class)
.putExtra("request_type", "joinUserToApplication")
.putExtra("data", jsonObject.toString()));
} catch (JSONException e) {
e.printStackTrace();
}
server response data like with this format:
{"username":"mahdi","userUniqueId":"fwcrwcrwr23234c24"}
server side application to get data is:
Route.post('joinUserToApplication', function *(request, response) {
console.log(request._raw);
response.send({username: "mahdi", userUniqueId: "fwcrwcrwr23234c24"});
});
The POST body that is being serialized is a generic Object.
Create a POJO with the fields that you require and use a deserializer that retrofit understands
public interface SignalRetrofitServiceProviders {
#POST("joinUserToApplication")
Call<List<UserLoginInformation>> joinUserToApplication(#Body UserLoginInformation data);
}
Please note the parameter of the function is not changed to UserLoginInformation
http://square.github.io/retrofit/#restadapter-configuration
I'm using Retrofit 1.9.0 in Android Studio to get a response from my REST API.
The method I want to do is GET, on this URL: http://dotfreeride.com/api/rest/adventures.php
I successfully retrieved the response for another API but that had only 1 object, this has 3 big objects.
My IApiMethods interface is like this:
#GET("/adventures.php")
JSONObject getAdventures(
Callback<AdventuresApi> cb
);
My AdventuresApi (Model class) is like this:
public class AdventuresApi {
public String adventure_id;
public String trimaps_context;
public String name;
public String video_url;
public List<ArrayPoi> array_poi;
public class ArrayPoi {
String poi_id;
String name;
String lat;
String lng;
String video_url;
}
}
My Retrofit call in the Activity is like this:
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_URL)
.build();
IApiMethods methods = restAdapter.create(IApiMethods.class);
Callback callback = new Callback() {
#Override
public void success(Object o, Response response) {
}
#Override
public void failure(RetrofitError error) {
Log.e("JSON", "NO DATA!");
}
};
methods.getAdventures(callback);
I don't really know how to get the objects, I want to get the name of the object (Example: where trimaps_context is "verb", I need the name "Powder Hound")
For a single object I successfully did it like this in onResponse(Object o, Response response):
(ProfileApi) profileData = (ProfileApi) o;
Log.e("JSON", profileData.name + " " + profileData.email);
1) You are trying to combine both synchronous and asynchronous call. If you want to perform a request asynchronously you have to define it like this:
#GET("/adventures.php")
void getAdventures(
Callback<List<AdventuresApi>> cb
);
2) Do not create RestAdapter instance everytime you call request. It's really heavyweight operation. Use singleton pattern. You can then simply call:
ApiManager.getAdapter().getAdventures(...);
3) Object mapping is provided by parametrized Callback class:
ApiManager.getAdapter().getAdventures(
new Callback<List<AdventuresApi>>() {
#Override
public void success(List<AdventuresApi> adventures, Response response) {
// here you can access the adventures list
}
#Override
public void failure(RetrofitError error) {
// handle error
}
});