英文:
Storing access token in SharedPreferences returns null object reference error
问题
I am trying to store the access token I recieve from my oAuth2 server after logging in, but when I try to store it I get an error "java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.dentdevils.helper.retrofit.oauth2.PreferenceClass.setToken(java.lang.String)' on a null object reference" and I'm unsure why.
Here are my classes:
PreferenceClass.java
package com.example.dentdevils.helper.retrofit.oauth2;
import android.content.Context;
import android.content.SharedPreferences;
public class PreferenceClass {
public static final String PREFERENCE = "accessTokenPref";
private SharedPreferences sharedPreferences;
public PreferenceClass(Context context) {
sharedPreferences = context.getSharedPreferences(PREFERENCE, Context.MODE_PRIVATE);
}
public String getToken() {
String token = sharedPreferences.getString("token", "");
return token;
}
public void setToken(String token) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("token", token);
editor.commit();
}
public void clearToken() {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.remove("token");
editor.commit();
}
}
MainActivity.java
package com.example.dentdevils;
import ...
public class MainActivity extends AppCompatActivity {
...
private PreferenceClass preferenceClass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
...
preferenceClass = new PreferenceClass(this);
...
btnLogin.setOnClickListener(v -> getAccessToken());
}
public void getAccessToken() {
progressDialog.show();
AccessToken accessToken = new AccessToken();
accessToken.setClient_id("client");
accessToken.setClient_secret("client");
accessToken.setGrant_type("client_credentials");
OauthService oauthService = cOauthService.createService(OauthService.class, inputEmail.getText().toString(), inputPassword.getText().toString());
Call<AccessTokenResponse> call = oauthService.fetchAccessToken(accessToken);
call.enqueue(new Callback<AccessTokenResponse>() {
@Override
public void onResponse(Call<AccessTokenResponse> call, retrofit2.Response<AccessTokenResponse> response) {
if (response.isSuccessful()) {
String a = response.body().getAccess_token();
preferenceClass.setToken(a);
progressDialog.dismiss();
Intent i = new Intent(getApplicationContext(), HomeActivity.class);
startActivity(i);
} else {
progressDialog.dismiss();
Toast.makeText(MainActivity.this, "There was an error, please try again!", Toast.LENGTH_LONG).show();
}
}
@Override
public void onFailure(Call<AccessTokenResponse> call, Throwable t) {
Log.d("Error", t.getMessage());
}
});
}
...
}
Is there anything blatantly obvious as to why this does not work and it does not store my access token in SharedPreferences? I know the access token gets returned as I can log it and it appears.
The full logcat output can be seen below:
2020-08-25 16:22:20.724 7197-7197/com.example.dentdevils E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.dentdevils, PID: 7197
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.dentdevils.helper.retrofit.oauth2.PreferenceClass.setToken(java.lang.String)' on a null object reference
at com.example.dentdevils.MainActivity$1.onResponse(MainActivity.java:76)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1.lambda$onResponse$0$DefaultCallAdapterFactory$ExecutorCallbackCall$1(DefaultCallAdapterFactory.java:89)
at retrofit2.-$$Lambda$DefaultCallAdapterFactory$ExecutorCallbackCall$1$3wC8FyV4pyjrzrYL5U0mlYiviZw.run(Unknown Source:6)
at android.os.Handler.handleCallback(Handler.java:888)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
英文:
I am trying to store the access token I recieve from my oAuth2 server after logging in, but when I try to store it I get an error java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.dentdevils.helper.retrofit.oauth2.PreferenceClass.setToken(java.lang.String)' on a null object reference
and I'm unsure why.
Here are my classes:
PreferenceClass.java
package com.example.dentdevils.helper.retrofit.oauth2;
import android.content.Context;
import android.content.SharedPreferences;
public class PreferenceClass {
public static final String PREFERENCE = "accessTokenPref";
private SharedPreferences sharedPreferences;
public PreferenceClass(Context context) {
sharedPreferences = context.getSharedPreferences(PREFERENCE, Context.MODE_PRIVATE);
}
public String getToken() {
String token = sharedPreferences.getString("token", "");
return token;
}
public void setToken(String token) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("token", token);
editor.commit();
}
public void clearToken() {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.remove("token");
editor.commit();
}
}
MainActivity.Java
package com.example.dentdevils;
import android.Manifest;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.example.dentdevils.helper.retrofit.oauth2.PreferenceClass;
import com.example.dentdevils.helper.retrofit.oauth2.client.cOauthService;
import com.example.dentdevils.helper.retrofit.oauth2.request.AccessToken;
import com.example.dentdevils.helper.retrofit.oauth2.response.AccessTokenResponse;
import com.example.dentdevils.helper.retrofit.oauth2.service.OauthService;
import com.example.dentdevils.ui.HomeActivity;
import retrofit2.Call;
import retrofit2.Callback;
public class MainActivity extends AppCompatActivity {
SharedPreferences sharedPreferences;
public static final String mypreference = "mypref";
public static final String email = "emailKey";
public static final String access = "accessKey";
public static final int MY_PERMISSIONS_REQUEST_CAMERA = 99;
private static final String TAG = MainActivity.class.getSimpleName();
private Button btnLogin;
private EditText inputEmail;
private EditText inputPassword;
private ProgressDialog progressDialog;
private PreferenceClass preferenceClass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
checkCameraPermission();
sharedPreferences = getSharedPreferences(mypreference,
Context.MODE_PRIVATE);
inputEmail = findViewById(R.id.email);
inputPassword = findViewById(R.id.txtEditPassword);
btnLogin = findViewById(R.id.btnLogin);
progressDialog = new ProgressDialog(this);
progressDialog.setCancelable(false);
btnLogin.setOnClickListener(v -> getAccessToken());
}
public void getAccessToken() {
progressDialog.show();
AccessToken accessToken = new AccessToken();
accessToken.setClient_id("client");
accessToken.setClient_secret("client");
accessToken.setGrant_type("client_credentials");
OauthService oauthService = cOauthService.createService(OauthService.class, inputEmail.getText().toString(), inputPassword.getText().toString());
Call<AccessTokenResponse> call = oauthService.fetchAccessToken(accessToken);
call.enqueue(new Callback<AccessTokenResponse>() {
@Override
public void onResponse(Call<AccessTokenResponse> call, retrofit2.Response<AccessTokenResponse> response) {
if (response.isSuccessful()) {
String a = response.body().getAccess_token();
preferenceClass.setToken(a);
progressDialog.dismiss();
Intent i = new Intent(getApplicationContext(), HomeActivity.class);
startActivity(i);
} else {
progressDialog.dismiss();
Toast.makeText(MainActivity.this, "There was an error, please try again!", Toast.LENGTH_LONG).show();
}
}
@Override
public void onFailure(Call<AccessTokenResponse> call, Throwable t) {
Log.d("Error", t.getMessage());
}
});
}
public boolean checkCameraPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
new AlertDialog.Builder(this)
.setTitle("Permission Required!")
.setMessage("This app requires the camera permission to be able to capture images of car damage. Please grant the app access to the camera by going into your Settings > Apps > Apps > Dent Devils > Permissions > Camera, then press Allow.")
.setPositiveButton("", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, MY_PERMISSIONS_REQUEST_CAMERA);
}
})
.create()
.show();
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, MY_PERMISSIONS_REQUEST_CAMERA);
}
return false;
} else {
return true;
}
}
}
Is there anything blatantly obvious as to why this does not work and it does not store my access token in SharedPreferences? I know the access token gets returned as I can log it and it appears.
The full logcat output can be seen below:
2020-08-25 16:22:20.724 7197-7197/com.example.dentdevils E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.dentdevils, PID: 7197
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.dentdevils.helper.retrofit.oauth2.PreferenceClass.setToken(java.lang.String)' on a null object reference
at com.example.dentdevils.MainActivity$1.onResponse(MainActivity.java:76)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1.lambda$onResponse$0$DefaultCallAdapterFactory$ExecutorCallbackCall$1(DefaultCallAdapterFactory.java:89)
at retrofit2.-$$Lambda$DefaultCallAdapterFactory$ExecutorCallbackCall$1$3wC8FyV4pyjrzrYL5U0mlYiviZw.run(Unknown Source:6)
at android.os.Handler.handleCallback(Handler.java:888)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
答案1
得分: 0
在 MainActivity
中从未给 preferenceClass
赋值。
在你的 onCreate
中添加类似以下的代码:
preferenceClass = new PreferenceClass(this);
英文:
You never assign a value to preferenceClass
in MainActivity
.
Add something like this to your onCreate
:
preferenceClass = new PreferenceClass(this);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论