taycaldwell / riot-api-java

Riot Games API Java Library
http://taycaldwell.github.io/riot-api-java/
Apache License 2.0
190 stars 73 forks source link

Android Problem with join #49

Closed devingDev closed 8 years ago

devingDev commented 8 years ago

Hello I've been trying to use your Creation but I failed to succeed. I could not even compile it, I don't really know why, didn't know what the error messages meant but there was something wrong with Java I think ( prob because it used jdk8 and not jdk 7 like it is in android studio).

Then I found that there is a Android Version ( https://github.com/rithms/riot-api-java/releases/download/v3.8.2-android/riot-api-java-android.jar ) of this and took that. I'm using minSDK 16 and compileSDK 23. And path to Java: C:\Program Files\Java\jdk1.7.0_79 But now everytime I compile I get this Error:

E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1 Process: amar.testriotapijar, PID: 24307 java.lang.RuntimeException: An error occured while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:304) at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355) at java.util.concurrent.FutureTask.setException(FutureTask.java:222) at java.util.concurrent.FutureTask.run(FutureTask.java:242) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:818) Caused by: java.lang.NoSuchMethodError: No static method join(Ljava/lang/CharSequence;[Ljava/lang/CharSequence;)Ljava/lang/String; in class Ljava/lang/String; or its super classes (declaration of 'java.lang.String' appears in /system/framework/core-libart.jar) at net.rithms.riot.api.RiotApi.getSummonersByName(RiotApi.java:1084) at net.rithms.riot.api.RiotApi.getSummonersByName(RiotApi.java:1099) at amar.testriotapijar.MainActivity$FetchSummonerTask.doInBackground(MainActivity.java:91) at amar.testriotapijar.MainActivity$FetchSummonerTask.doInBackground(MainActivity.java:82) at android.os.AsyncTask$2.call(AsyncTask.java:292) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)  at java.lang.Thread.run(Thread.java:818) 

Oh and my Source is this:

`package amar.testriotapijar;

import android.os.AsyncTask; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.widget.Button; import android.widget.TextView;

import net.rithms.riot.api.RiotApi; import net.rithms.riot.api.RiotApiException; import net.rithms.riot.constant.Region; import net.rithms.riot.dto.Summoner.Summoner;

import java.util.Map;

public class MainActivity extends AppCompatActivity { int id =0; TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); final Button button = (Button) findViewById(R.id.button1); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { FetchSummonerTask summonerTask = new FetchSummonerTask(); summonerTask.execute("summoner1"); } }); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", new View.OnClickListener() { @Override public void onClick(View v) {

                        }
                    }).show();
        }
    });
}

private int getIDOfSummoner(String summName) throws RiotApiException{

    return 0;
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

public class FetchSummonerTask extends AsyncTask<String, Void, Summoner> {

    @Override
    protected Summoner doInBackground(String... params) {

        RiotApi api = new RiotApi(
                "apikeyhiddenforreasons");
        try {
            api.setRegion(Region.EUW);
            Map<String, Summoner> summoners = api.getSummonersByName(params[0]);
            if(summoners != null) {
                return summoners.get(params[0].replaceAll("\\s+", "").toLowerCase());
            }
        } catch (RiotApiException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(Summoner result) {
        super.onPostExecute(result);
        if(result != null) {
            TextView dis = (TextView) findViewById(R.id.tv);
            dis.setText(String.valueOf((result.getSummonerLevel())));
        }
    }
}

} `

taycaldwell commented 8 years ago

This error is caused by the use of the Java 8 method String.join() in the source code. Android hates Java 8 with all it's heart.

This is a known issue with the version you are using, and has been fixed. No Java 8 methods are included in the latest release of the library, and everything should play nicely with Android.

I have removed the bugged riot-api-java-v3.8.2 (Android) version from releases to avoid further confusion.

I could not even compile it, I don't really know why, didn't know what the error messages meant but there was something wrong with Java I think ( prob because it used jdk8 and not jdk 7 like it is in android studio).

Please download and use the latest release, v3.9.0, and comment here with any issues you have using that version.

Sorry for the inconvenience.

devingDev commented 8 years ago

Thank you it's really working now :D I probably downloaded the other File first from the Github page index.html (its a dropbox download and says 22 days ago) which is even older I think than the 3.8.2. So maybe you update that site too because that was the first site i got when i searched for this in google. And again thanks. I wouldn't have tried using the 3.9.0 :D Maybe add Android support in the description :package:

Maybe two questions I dont get ^^

return summoners.get(params[0].replaceAll("\s+", "").toLowerCase());

Why do you have to do it like that and not:

summoner = summoners.get(params[0]) ?

And when does the call to the RiotServer happen?

Here: Map<String, Summoner> summoners = api.getSummonersByName(params[0]);

or here:

return summoners.get(params[0].replaceAll("\s+", "").toLowerCase()); ?

taycaldwell commented 8 years ago

Hey krasfas,

Thanks for bringing to my attention that you found the library through riot-api-java.com and mentioning the download link on the site is still directing to dropbox (where we used to host the latest JAR). I will be sure to update the page and apply the feedback you have given.

return summoners.get(params[0].replaceAll("\s+", "").toLowerCase());

Why do you have to do it like that and not:

summoner = summoners.get(params[0]) ?

The Riot Games API returns summoner information as a map, where the key values are the summoner names in all lower case and stripped of spaces.

For example if you made a request to the Riot Games API for the following summoner names: RHYTHMS, Rithms, Tryn damere, RY z e,

you would receive the following data:

{
   "rhythms": {
      "id": 32236660,
      "name": "Rhythms",
      "profileIconId": 774,
      "revisionDate": 1453818380000,
      "summonerLevel": 30
   },
   "rithms": {
      "id": 35364656,
      "name": "Rithms",
      "profileIconId": 871,
      "revisionDate": 1454456414000,
      "summonerLevel": 30
   },
   "ryze": {
      "id": 329,
      "name": "Ryze",
      "profileIconId": 0,
      "revisionDate": 1454485335000,
      "summonerLevel": 30
   },
   "tryndamere": {
      "id": 133,
      "name": "Tryndamere",
      "profileIconId": 909,
      "revisionDate": 1451787512000,
      "summonerLevel": 30
   }
}

Similarly, when using the library and making a request such as:

Map<String, Summoner> summoners = api.getSummonersByName("RITHMS, TRYN DA mere");

You will have to access the Summoner objects of the map using the summoner name, all lowercase, stripped of spaces since the keys are case sensitive:

Summoner summoner = summoners.get("tryndamere");

Since the Android application example is taking in user input, and using that user input as a key to access the summoner object in the map, stripping the spaces and making all characters lower case with params[0].replaceAll("\s+", "").toLowerCase() makes sure you are using the correct key, regardless if the user searches for "T R Y N DA MERE" or "Tryndamere" rather than just "tryndamere".

And when does the call to the RiotServer happen?

Here: Map summoners = api.getSummonersByName(params[0]);

or here:

return summoners.get(params[0].replaceAll("\s+", "").toLowerCase());

The library makes calls to the API when the method is called, so this line is where the call is happening:

Map summoners = api.getSummonersByName(params[0]);

The following line is just retrieving the summoner from the map:

return summoners.get(params[0].replaceAll("\s+", "").toLowerCase());

This Android example is a bit outdated. If you are only interested in querying for one summoner at a time, you can use the following lines of code instead:

@Override
    protected Summoner doInBackground(String... params) {

        RiotApi api = new RiotApi(
                "apikeyhiddenforreasons");
        try {
            api.setRegion(Region.EUW);
            Summoner summoner = api.getSummonerByName(params[0]);
            return summoner;
        } catch (RiotApiException e) {
            e.printStackTrace();
        }

        return null;
    }

Note this example is using getSummonerByName() rather than getSummonersByName(). Because only one summoner is being requested, the library returns a single Summoner object rather than a Map with one entry.

Hope that makes sense.