James Robert Singleton James Robert Singleton - 3 months ago 17
Java Question

OkHttp Request in Separate Class

So I currently have my OkHttp requests in my MainActivity in order to test that they actually worked. However, I need to move them to a separate class so that I can use the requests to populate my Navagation Drawer menu items. Furthermore, in my MainActivity, I do oAuth of invalidating a token and requesting it and that token needs to be used in my requests. I am a bit lost as I am calling the new class in my MainActivity as

apiRequest.run();
This is what I get back in the run console.

I/System.out: ya29.CjBIAx67rM70-CKu9Wc5fUSLzt9rIqt4bRubpl4hB9UjwqeRatoZppbMmNDl_SPcFWA
E/AuthApp: ya29.CjBIAx67rM70-CKu9Wc5fUSLzt9rIqt4bRubpl4hB9UjwqeRatoZppbMmNDl_SPcFWA
W/System.err: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String android.content.SharedPreferences.getString(java.lang.String, java.lang.String)' on a null object reference
W/System.err: at com.example.jamessingleton.chffrapi.AuthPreferences.getToken(AuthPreferences.java:43)
W/System.err: at com.example.jamessingleton.chffrapi.APIRequests.run(APIRequests.java:34)
W/System.err: at com.example.jamessingleton.chffrapi.MainActivity$1.onClick(MainActivity.java:90)
W/System.err: at com.google.android.gms.common.SignInButton.onClick(Unknown Source)
W/System.err: at android.view.View.performClick(View.java:5697)
W/System.err: at android.widget.TextView.performClick(TextView.java:10814)
W/System.err: at android.view.View$PerformClick.run(View.java:22526)
W/System.err: at android.os.Handler.handleCallback(Handler.java:739)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:95)
W/System.err: at android.os.Looper.loop(Looper.java:158)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7224)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)


Here is my MainActivity where I am implementing it.

Context mContext = MainActivity.this;
private AccountManager mAccountManager;
private AuthPreferences authPreferences;
private APIRequests apiRequests;
EditText emailText;
TextView responseView;
ProgressBar progressBar;

static final String API_URL = "https://api.comma.ai/v1/auth/?access_token=";
static final String ChffrMe_URL = "https://api.comma.ai/v1/me/";
static final String SCOPE = "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.me";
private static final int AUTHORIZATION_CODE = 1993;
private static final int ACCOUNT_CODE = 1601;
String commatoken;
String commaMyInfo;
private final OkHttpClient client = new OkHttpClient();



@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
responseView = (TextView) findViewById(R.id.responseView);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
mAccountManager = AccountManager.get(this);
authPreferences = new AuthPreferences(this);
apiRequests = new APIRequests();
final Context context = this;
invalidateToken();
requestToken();
SignInButton signInButton = (SignInButton) findViewById(R.id.sign_in_button);
signInButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (authPreferences.getUser() != null && authPreferences.getToken() != null) {
System.out.println(authPreferences.getToken());
doCoolAuthenticatedStuff();
// Intent intent = new Intent(context, NavDrawerActivity.class);
// startActivity(intent);
try {
apiRequests.run();
} catch (Exception e) {
e.printStackTrace();
}
// try {
// run();
// } catch (Exception e) {
// e.printStackTrace();
// }
//new RetrieveFeedTask().execute();
} else {
chooseAccount();
}
}
});


And here is my APIRequests.java

public class APIRequests {
private final OkHttpClient client = new OkHttpClient();
static final String API_URL = "https://api.comma.ai/v1/auth/?access_token=";
static final String ChffrMe_URL = "https://api.comma.ai/v1/me/";
private AuthPreferences authPreferences = new AuthPreferences(this);
String commatoken;
String commaMyInfo;
private MainActivity mActivity;

public void run() throws Exception {
Request request = new Request.Builder()
.url(API_URL + authPreferences.getToken())
.build();

client.newCall(request).enqueue(new Callback() {
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}


public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

Headers responseHeaders = response.headers();
for (int i = 0, size = responseHeaders.size(); i < size; i++) {
System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
}
try
{
String token = response.body().string();
JSONObject json = new JSONObject(token);
commatoken = json.getString("access_token");
} catch (JSONException e)
{

}
// commatoken = response.body().string();
// System.out.println(commatoken);

if(response.isSuccessful())
{
final Request dataRequest = new Request.Builder()
.header("content-type", "application/x-www-form-urlencoded")
.header("authorization", "JWT "+ commatoken)
.url(ChffrMe_URL).build();

client.newCall(dataRequest).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}

@Override
public void onResponse(Call call, Response responseMe) throws IOException {
if (!responseMe.isSuccessful()) throw new IOException("Unexpected code " + responseMe);

Headers responseHeaders = responseMe.headers();
for (int i = 0, size = responseHeaders.size(); i < size; i++) {
System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
}
try
{
String myInfo = responseMe.body().string();
JSONObject json = new JSONObject(myInfo);
commaMyInfo = json.getString("points");
System.out.println(commaMyInfo);
} catch (JSONException e)
{

}
// runOnUiThread(new Runnable() {
// @Override
// public void run() {
// responseView.setText("Comma Points: " +commaMyInfo);
// }
// });

}
});
}
}

});
}
}


Not sure why it isn't liking my apiRequests.run();

Here is the AuthPreferences

public class AuthPreferences {
private static final String KEY_USER = "user";
private static final String KEY_TOKEN = "token";

private SharedPreferences preferences;

public AuthPreferences(Context context) {
preferences = context
.getSharedPreferences("auth", Context.MODE_PRIVATE);
}

public AuthPreferences(APIRequests apiRequests) {

}

public void setUser(String user) {
Editor editor = preferences.edit();
editor.putString(KEY_USER, user);
editor.commit();
}

public void setToken(String password) {
Editor editor = preferences.edit();
editor.putString(KEY_TOKEN, password);
editor.commit();
}

public String getUser() {
return preferences.getString(KEY_USER, null);
}

public String getToken() {
return preferences.getString(KEY_TOKEN, null);

}
}

Answer

Your AuthPreferences class has two constructors. One sets a preferences field. The other does not. You crash when you use the constructor that does not set the preferences field, as then that field is null when you try using it.

I recommend getting rid of the second constructor. Then, add a constructor to APIRequests that takes an AuthPreferences as a parameter, and use that to populate the authPreferences field (rather than creating a new, flawed instance of AuthPreferences). Then, in the activity, replace apiRequests = new APIRequests(); with apiRequests = new APIRequests(authPreferences);, to meet the requirements of your new constructor.