1

I am learning to work with google cloud endpoint. I am trying to connect from my device however, I keep getting an error.

failed to connect to /192.168.1.100 (port 8080) after 20000ms: isConnected failed: ECONNREFUSED (Connection refused)

How do I overcome this issue, I would like to run on a real device?

Get Jokes.class

public class GetJokes extends AsyncTask<Pair<Context, String>, Void, String> {
private static MyApi myApiService = null;
private Context context;

@Override
protected String doInBackground(Pair<Context, String>... params) {
    if (myApiService == null) {  // Only do this once
        MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
            new AndroidJsonFactory(), null)
            // options for running against local devappserver
            // - 10.0.2.2 is localhost's IP address in Android emulator
            // - turn off compression when running against local devappserver
            .setRootUrl("http://10.0.2.2:8080/_ah/api/")
            .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
                @Override
                public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
                    abstractGoogleClientRequest.setDisableGZipContent(true);
                }
            });
        // end options for devappserver

        myApiService = builder.build();
    }

    context = params[0].first;
    String name = params[0].second;

    try {
        return myApiService.sayHi(name).execute().getData();
    } catch (IOException e) {
        return e.getMessage();
    }
}

@Override
protected void onPostExecute(String result) {
    Toast.makeText(context, result, Toast.LENGTH_LONG).show();
    Log.i("Failed to con", result);
}
}

MainActivityFragment.class

public class MainActivityFragment extends Fragment {

public static final String JOKE = "JOKE";

public MainActivityFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.fragment_main, container, false);

    Button tellJokeButton = (Button)root.findViewById(R.id.tellJoke_button);
    tellJokeButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new GetJokes().execute(new Pair<Context, String>(getActivity(), "Manfred"));
        }
    });

    AdView mAdView = (AdView) root.findViewById(R.id.adView);
    // Create an ad request. Check logcat output for the hashed device ID to
    // get test ads on a physical device. e.g.
    // "Use AdRequest.Builder.addTestDevice("ABCDEF012345") to get test ads on this device."
    AdRequest adRequest = new AdRequest.Builder()
            .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
            .build();
    mAdView.loadAd(adRequest);
    return root;
}

public void tellJoke(){

    Intent intent = new Intent(getActivity(), JokeTellerActivity.class);
    //TODO: get jokes from Google Cloud endpoint
    intent.putExtra(JOKE,

        getActivity().getString(R.string.joke)
    );

    startActivity(intent);
}
}

MyEndPoint.class

public class MyEndpoint {

public static List<Joke> mJokes = new ArrayList<>();

/** A simple endpoint method that takes a name and says Hi back */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
    MyBean response = new MyBean();
    response.setData("Hi, " + name);

    return response;
}
}

I've tried running it on several different devices and none of them would connect.

Sam321pbs
  • 301
  • 2
  • 17

2 Answers2

1

I've had the same problem because I'm also doing this project from the Android Nanodegree (Udacity).

I've found the solution in this question. Because the answers there are a bit messy or uncomplete, I'm going to explain in detail what I did to run the local server on my computer and test it with a real device.

1) Add httpAddress = "0.0.0.0" to the appengine block in your build.gradle file of the backend (Google Cloud Endpoint) module, like this:

appengine {
    ...
    httpAddress = "0.0.0.0"
}

According to a comment on the linked question this means that 'will accept from anywhere'.

2) Run your backend module locally (ie. start the web server). This is trivial: select the backend configuration on the drop-down menu and press the green button. You can find more detailed instructions here.

You should now be able to open a browser (on your computer) and navigate to http://localhost:8080/ and see a webpage with 'Hello, Endpoints!' and many other stuff.

3) Find your computer's IP address (on a Mac go to System Preferences -> Network) and then set it as the root url in your Android app code, like this:

MyApi.Builder builder = new MyApi.Builder(
                            AndroidHttp.newCompatibleTransport(),
                            new AndroidJsonFactory(), 
                            null
).setRootUrl("http://192.168.1.36:8080/_ah/api/")

That's all!

Community
  • 1
  • 1
Albert Vila Calvo
  • 15,298
  • 6
  • 62
  • 73
0

So you've setup an AppEngine based cloud endpoint as a local development server on the same machine in which you are running an Android emulator? Be sure you're using the correct IP address (and port) for the endpoint. The local IP address you need is not the one in use by the Android emulator, but the host dev machine. For example:

Local Dev Machine: 192.168.1.100

AppEngine server on dev machine: listening on 8080

Android Emulator running on dev machine: 10.0.2.2

You should be able to access the API explorer on the dev machine via a browser on the Android emulator as well. You can use that to sanity check that your app is using the correct address:

http://192.168.1.100:8080/_ah/api/explorer
Larry Schiefer
  • 15,687
  • 2
  • 27
  • 33
  • I tried a few different local dev machine from what I found in my research and all don't seem to work. However, in the google example there is a comment that says "turn off compression when running against local devappserver", how do I go about doing that? – Sam321pbs Mar 08 '16 at 20:36
  • There should be an API method on the builder or if you get the underlying `HttpRequest` or similar to disable compression. – Larry Schiefer Mar 08 '16 at 21:55