Apurva Jha Apurva Jha - 3 months ago 28
Java Question

Header not getting set properly in android-Retrofit

I'm building an app for sending access-token to the server using Retrofit in android. I don't get any error what I think should set the header correctly is not working so.

The header that I want:

"Authorization: Bearer facebook <user_access_token>"


is the token that I get. Not written here for security purposes.

I am using android Retrofit for the purpose with the files as follows:

MainActivity.java

package com.example.apurva.myapplication;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.os.StrictMode;




public class MainActivity extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

UserService userService;
String token = "Bearer facebook <user_access_token>";
userService = ServiceGenerator.createService(UserService.class, UserService.BASE_URL, token);
User user = userService.me();

}

@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);
}
}


UserService.java

package com.example.apurva.myapplication;

import com.squareup.okhttp.OkHttpClient;

import retrofit.Callback;
import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
import retrofit.client.OkClient;
import retrofit.http.POST;

/**
* Created by apurva on 4/8/15.
*/
public interface UserService {

public static final String BASE_URL = "http://10.0.2.2:8000/auth";

@POST("/convert-token")
User me();

}


ServiceGenerator.java

package com.example.apurva.myapplication;

import com.squareup.okhttp.OkHttpClient;
import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
import retrofit.client.OkClient;

/**
* Created by apurva on 4/8/15.
*/
public class ServiceGenerator {
private ServiceGenerator() {
}

public static <S> S createService(Class<S> serviceClass, String baseUrl, final String token) {
RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint(baseUrl)
.setClient(new OkClient(new OkHttpClient()));

if (token != null) {
builder.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
request.addHeader("Accept", "application/json");
request.addHeader("Authorization", token);
}
});
}

RestAdapter adapter = builder.build();
return adapter.create(serviceClass);
}
}


I would like to mention that there are no errors. I have already set network activity in the main thread by using StrictMode so that is not an issue as well just it does not give the desired result as the user in not getting added in the backend.

I would also like to tel you that I've already checked my back end with cURL and it works fine so there is no issue there as well.

I get runtime error:



Process: com.example.apurva.myapplication, PID: 7140
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.apurva.myapplication/com.example.apurva.myapplication.MainActivity}: retrofit.RetrofitError: 405 METHOD NOT ALLOWED
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
at android.app.ActivityThread.access$800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
Caused by: retrofit.RetrofitError: 405 METHOD NOT ALLOWED
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:388)
at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
at $Proxy0.me(Native Method)
at com.example.apurva.myapplication.MainActivity.onCreate(MainActivity.java:24)
at android.app.Activity.performCreate(Activity.java:5231)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5001)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)




Answer

Your code is ok. You should add logging to your Retrofit.

// Simple add .setLogLevel(RestAdapter.LogLevel.FULL)
RestAdapter.Builder builder = new RestAdapter.Builder()
                    .setLogLevel(RestAdapter.LogLevel.FULL)
                    .setEndpoint(baseUrl)
                    .setClient(new OkClient(new OkHttpClient()));

I'm sure after this you will see in console:

---> HTTP POST http://10.0.2.2:8000/auth/convert-token
Accept: application/json
Authorization: Bearer facebook <user_access_token>
---> END HTTP (no body)

That means your header is set correctly.

"HTTP 405 METHOD NOT ALLOWED" may say that POST method is not expected for this resource. And maybe GET request will help you:

 @GET("/convert-token")
 User me();