1

Could you guys give me a little push here. I'm stuck trying to run the yelp api inside the onPerformSyn. How can I possible do this.? I'm getting the error below. "No empty constructor" I'm using this post to try to create the constructor but it doesn't work for me.
Please help is appreciated.

Note: After the Yelp response I'll be storing the data into SQLite (Scheme Library) so that is not the end of the code.

public class SyncAdapter extends AbstractThreadedSyncAdapter{
    public final String LOG_TAG = SyncAdapter.class.getSimpleName();
    public static final int SYNC_INTERVAL = 4;//60 * 180;
    public static final int SYNC_FLEXTIME = SYNC_INTERVAL/3;
    private static final long DAY_IN_MILLIS = 1000;//1000 * 60 * 60 * 24;
    private static final int WEATHER_NOTIFICATION_ID = 3004;

    private GoogleApiClient mGoogleApiClient;
    private YelpAPI yelpAPI;
    private Location mLastLocation;

    public SyncAdapter(Context context, boolean autoInitialize) {
        super(context, autoInitialize);

//        YelpAPIFactory apiFactory = new YelpAPIFactory(BuildConfig.YELP_CONSUMER_KEY, BuildConfig.YELP_CONSUMER_SECRET, BuildConfig.YELP_TOKEN, BuildConfig.YELP_TOKEN_SECRET);
//        yelpAPI = apiFactory.createAPI();
    }


    @Override
    public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {


        class YelpApi2 extends DefaultApi10a {

            @Override
            public String getAccessTokenEndpoint() {
                return null;
            }

            @Override
            public String getAuthorizationUrl(Token arg0) {
                return null;
            }

            @Override
            public String getRequestTokenEndpoint() {
                return null;
            }

        }

        class Yelp {
            OAuthService service;
            Token accessToken;
            public Yelp(String consumerKey, String consumerSecret,     String token, String tokenSecret) {
                this.service = new    ServiceBuilder().provider(YelpApi2.class).apiKey(consumerKey).apiSecret(consumerSecret).build();
                this.accessToken = new Token(token, tokenSecret);
            }

            public String search(String term, double latitude, double longitude) {
                OAuthRequest request = new OAuthRequest(Verb.GET, "http://api.yelp.com/v2/search");
                request.addQuerystringParameter("term", term);
                request.addQuerystringParameter("ll", latitude + "," + longitude);
                this.service.signRequest(this.accessToken, request);
                Response response = request.send();
                return response.getBody();
            }

        }



            Yelp yelp = new Yelp(BuildConfig.YELP_CONSUMER_KEY, BuildConfig.YELP_CONSUMER_SECRET, BuildConfig.YELP_TOKEN, BuildConfig.YELP_TOKEN_SECRET);
            String response = yelp.search("church", 30.361471, -87.164326);

            System.out.println(response);
            }

I followed this tut, but I didn't do the .jar part, i couldn't import it, instead I used this line in the gradle.

        compile 'com.yelp.clientlib:yelp-android:2.0.0'

Error I'm getting
=========================================

    FATAL EXCEPTION: SyncAdapterThread-1
    Process: mem.edu.joshua, PID: 14149
    org.scribe.exceptions.OAuthException: Error while creating the Api object
    at org.scribe.builder.ServiceBuilder.createApi(ServiceBuilder.java:59)
    at org.scribe.builder.ServiceBuilder.provider(ServiceBuilder.java:45)
    at mem.edu.joshua.sync.SyncAdapter$1Yelp.<init>(SyncAdapter.java:99)
    at mem.edu.joshua.sync.SyncAdapter.onPerformSync(SyncAdapter.java:116)
    at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:259)

    Caused by: java.lang.InstantiationException: can't instantiate class mem.edu.joshua.sync.SyncAdapter$1YelpApi2; no empty constructor
    at java.lang.Class.newInstanceImpl(Native Method)
    at java.lang.Class.newInstance(Class.java:1208)


  [1]: http://stackoverflow.com/questions/11859403/no-empty-constructor-when-create-a-service
  [2]: https://thysmichels.com/2011/12/30/yelp-api-example/#comment-18031
Erik
  • 57
  • 1
  • 9
  • Have you tried just adding an empty constructor to your SyncAdapter? Like so: public SyncAdapter() {} – Tim Kranen Aug 08 '16 at 22:13
  • Tim, I just tried. Not sure if you noticed the SyncAdapter constructor is there already, but if I try the way you say 'empty' it gives me an error asking for super(), if I do super() then it's asking for something to go inside the brackets with the error 'cannot resolve method super()' . So I have to add the Context and Boolean just as it is right now. – Erik Aug 09 '16 at 01:42
  • So after looking into it again, I realized its not actually your SyncAdapter. But your implementation of the YelpApi2 class. The exception that popped up in your case appears (in my experience) if your class (or super class) require a default 'no args' constructor. Try adding an empty constructor to your YelpApi2 class; public (or private) YelpApi2() {}; – Tim Kranen Aug 09 '16 at 17:40
  • Hi Tim. I remember I tried it already since that is where the error is pointing to, but anyway I went back and tried again and I'm still getting the error. You have become my best option in trying to solve this, I appreciate it. – Erik Aug 10 '16 at 01:55
  • So, the problem (I think) lies in the fact that the ServiceBuilder uses reflection to instantiate the YelpApi2 class. Right now you defined your class in a local scope, which seems a bit weird to me. Could you try extracting the method to its own class? It could be an inner class (i.e. private class YelpApi2 outside the method), and also add that empty constructor. I wouldn't recommend defining your classes within methods. In some cases this can be useful but not here. Check this out too: http://stackoverflow.com/questions/17485297/how-to-instantiate-inner-class-with-reflection-in-java – Tim Kranen Aug 10 '16 at 18:11
  • 1
    Better yet is to extract the Yelp class totally and give it its own .java file. I think simply changing it to a class scoped class won't help either. It'll still crash when trying to instantiate it trough reflection. So you need: 1) A no args constructor. 2) The classes defined in a seperate file. – Tim Kranen Aug 10 '16 at 18:12
  • It worked ! it worked ! I'm so happy : ) Thank you so much Tim, I never imagine that was causing the issue. I just put them in a separate .java file and it's running fine. You are the best ! – Erik Aug 10 '16 at 19:17
  • Let me post this as answer so this question can get closed! – Tim Kranen Aug 10 '16 at 20:40

1 Answers1

1

The problems was that the ServiceBuilder was trying to instantiate the class trough reflection. This will cause problems when using a local or inner class, since these classed require an extra 'invisible' parameter. (Related question: How to instantiate inner class with reflection in Java?)

So the solution is to extract the Yelp class and the YelpApi2 class into their own file.

Community
  • 1
  • 1
Tim Kranen
  • 4,202
  • 4
  • 26
  • 49