I am using Facebook Login for my app that uses firebase. When user logs in, the app is supposed to pull info from Facebook such as name, email, gender, location, bio, ect. This worked fine before I updated to Android Studio 2.2. Now after the update I’m getting the error
Attempt to invoke virtual method ‘java.lang.String org.json.JSONObject.getString(java.lang.String)’ on a null object reference.
The account is saved to firebase but after login the app crashes. I can’t tell if this is anise with the emulator(Nexus 6 API 23), or if something happened to my code.
Logcat
10-27 08:23:07.965 15474-15474/com.rograb.workorderapp D/LOGIN DEBUG:facebook:onSuccess:com.facebook.login.LoginResult@47060b7
10-27 08:23:07.965 15474-15474/com.rograb.workorderapp D/LOGIN DEBUG: handleFacebookAccessToken:{AccessToken token:ACCESS_TOKEN_REMOVED permissions:[public_profile, contact_email, user_friends, user_likes, email, user_location]}
10-27 08:23:07.967 15474-15487/com.rograb.workorderapp W/DynamiteModule: Local module descriptor class for com.google.firebase.auth not found.
10-27 08:23:07.971 15474-16534/com.rograb.workorderapp V/FA: Activity resumed, time: 1301956
10-27 08:23:07.973 15474-15487/com.rograb.workorderapp W/DynamiteModule: Local module descriptor class for com.google.firebase.auth not found.
10-27 08:23:07.986 15474-15533/com.rograb.workorderapp E/Surface: getSlotFromBufferLocked: unknown buffer: 0xb2c3e080
10-27 08:23:08.366 15474-15474/com.rograb.workorderapp D/AndroidRuntime: Shutting down VM
10-27 08:23:08.366 15474-15474/com.rograb.workorderapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.rograb.workorderapp, PID: 15474
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String org.json.JSONObject.getString(java.lang.String)' on a null object reference
at com.rograb.workorderapp.models.UserModel.fromJSON(UserModel.java:117)
at com.rograb.workorderapp.activities.LoginActivity$2$1.onCompleted(LoginActivity.java:106)
at com.facebook.GraphRequest$1.onCompleted(GraphRequest.java:304)
at com.facebook.GraphRequest$5.run(GraphRequest.java:1383)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
10-27 08:23:11.904 15474-15474/com.rograb.workorderapp I/Process: Sending signal. PID: 15474 SIG: 9
UserModel
public class UserModel {
private String id;
private String name;
private String email;
private String gender;
private String locationId;
private String locationName;
private String bio;
private String languages;
private ArrayList<TripModel> favorites = new ArrayList<>();
private HashMap<String, Object> timestampJoined;
public UserModel() {
}
public UserModel(String name, String email, HashMap<String, Object> timestampJoined) {
this.name = name;
this.email = email;
this.timestampJoined = timestampJoined;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getLocationId() {
return locationId;
}
public void setLocationId(String locationId) {
this.locationId = locationId;
}
public String getLocationName() {
return locationName;
}
public void setLocationName(String locationName) {
this.locationName = locationName;
}
public String getBio() {
return bio;
}
public void setBio(String bio) {
this.bio = bio;
}
public String getLanguages() {
return languages;
}
public void setLanguages(String languages) {
this.languages = languages;
}
public HashMap<String, Object> getTimestampJoined() {
return timestampJoined;
}
public void setTimestampJoined(HashMap<String, Object> timestampJoined) {
this.timestampJoined = timestampJoined;
}
public ArrayList<TripModel> getFavorites() {
return favorites;
}
public void setFavorites(ArrayList<TripModel> favorites) {
this.favorites = favorites;
}
public static UserModel fromJSON(JSONObject jsonObject){
UserModel user = new UserModel();
try {
user.id = jsonObject.getString("id");
user.name = jsonObject.getString("name");
user.email = jsonObject.getString("email");
user.gender = jsonObject.getString("gender");
user.locationId = jsonObject.getJSONObject("location").getString("id");
user.locationName = jsonObject.getJSONObject("location").getString("name");
user.languages = "";
} catch (JSONException e) {
e.printStackTrace();
}
return user;
}
}
LoginActivity
public class LoginActivity extends AppCompatActivity {
private static final String TAG = "LOGIN DEBUG";
@BindView(R.id.btnFacebookLogin)
LoginButton btnFacebookLogin;
CallbackManager callbackManager;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
UserModel userModel = new UserModel();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
final WorkOrderApplication app = (WorkOrderApplication) getApplicationContext();
// Initialize Firebase Auth
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
if (user.getEmail() == null || user.getEmail().equals(""))
user.updateEmail(userModel.getEmail());
if (user.getUid() != null) {
setAuthenticatedUserFacebook(firebaseAuth);
onLoginSuccess();
}
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
}
};
// Initialize Facebook Login button
callbackManager = CallbackManager.Factory.create();
btnFacebookLogin.setReadPermissions(Arrays.asList("public_profile", "email", "user_location", "user_friends", "user_likes"));
btnFacebookLogin.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
Log.d(TAG, "facebook:onSuccess:" + loginResult);
handleFacebookAccessToken(loginResult.getAccessToken());
// App code
GraphRequest request = GraphRequest.newMeRequest(
loginResult.getAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
@Override
public void onCompleted(JSONObject object, GraphResponse response) {
userModel = UserModel.fromJSON(object);
app.setUserInfo(userModel);
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "id,name,email,gender,location,bio,languages");
request.setParameters(parameters);
request.executeAsync();
}
@Override
public void onCancel() {
Log.d(TAG, "facebook:onCancel");
}
@Override
public void onError(FacebookException error) {
Log.d(TAG, "facebook:onError", error);
}
});
}
private void setAuthenticatedUserFacebook(FirebaseAuth firebaseAuth) {
final String userEncondedEmail = Utilities.encodeEmail(firebaseAuth.getCurrentUser().getEmail());
String userName = firebaseAuth.getCurrentUser().getDisplayName();
HashMap<String, Object> timestampJoined = new HashMap<>();
timestampJoined.put(Constants.FIREBASE_PROPERTY_TIMESTAMP, ServerValue.TIMESTAMP);
final WorkOrderApplication app = (WorkOrderApplication) getApplicationContext();
//Save user in firebase
final UserModel user = new UserModel(userName, userEncondedEmail, timestampJoined);
app.getUsersReference().child(userEncondedEmail).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() == null) {
app.getUsersReference().child(userEncondedEmail).setValue(user);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
callbackManager.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
}
@Override
public void onStop() {
super.onStop();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
}
public void onLoginSuccess() {
Intent i = new Intent(this, JobListActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
finish();
}
private void handleFacebookAccessToken(AccessToken token) {
Log.d(TAG, "handleFacebookAccessToken:" + token);
AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Log.w(TAG, "signInWithCredential", task.getException());
Toast.makeText(LoginActivity.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
} else {
onLoginSuccess();
}
}
});
}
}
build.gradle
android {
compileSdkVersion 24
buildToolsVersion "24.0.0"
defaultConfig {
applicationId "com.rograb.workorderapp"
minSdkVersion 16
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
repositories {
mavenCentral()
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:24.0.0'
testCompile 'junit:junit:4.12'
apt 'com.jakewharton:butterknife-compiler:8.2.1'
apt 'org.parceler:parceler:1.1.1'
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support:design:24.2.0'
compile 'com.android.support:cardview-v7:24.2.0'
compile 'com.android.support:recyclerview-v7:24.2.0'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.google.firebase:firebase-auth:9.4.0'
compile 'com.facebook.android:facebook-android-sdk:[4,5)'
compile 'com.jakewharton:butterknife:8.2.1'
compile 'org.parceler:parceler-api:1.1.1'
compile 'com.google.firebase:firebase-database:9.4.0'
compile 'com.firebaseui:firebase-ui-database:0.5.1'
compile 'com.google.android.gms:play-services-location:9.4.0'
compile 'com.google.android.gms:play-services-maps:9.4.0'
compile 'com.google.android.gms:play-services-places:9.4.0'
compile 'com.firebase:geofire-android:2.1.0'
compile 'com.github.qiugang:EditTag:v1.2.3'
compile 'com.astuetz:pagerslidingtabstrip:1.0.1'
compile 'com.android.support:support-v4:24.2.0'
}
apply plugin: 'com.google.gms.google-services'
ProfileActivity
public class ProfileActivity extends AppCompatActivity implements OnMapReadyCallback {
WorkOrderApplication app;
private GoogleMap mMap;
@BindView(R.id.ivProfile)
ProfilePictureView ivProfile;
@BindView(R.id.tvBio)
TextView tvBio;
@BindView(R.id.tvEmail)
TextView tvEmail;
@BindView(R.id.app_bar)
AppBarLayout appBar;
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.tvUserName)
TextView tvUserName;
@BindView(R.id.tvLocationName)
TextView tvLocationName;
@BindView(R.id.toolbar_layout)
CollapsingToolbarLayout collapsingToolbarLayout;
@BindView(R.id.tvLanguages)
TextView tvLanguages;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
app = (WorkOrderApplication) getApplicationContext();
}
@Override
public void onBackPressed() {
finish();
overridePendingTransition(R.anim.left_in, R.anim.right_out);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
setUserInformation();
}
private void setUserInformation() {
UserModel user = app.getUserInfo();
ivProfile.setProfileId(user.getId());
tvUserName.setText(user.getName());
tvLocationName.setText(user.getLocationName());
tvBio.setText(user.getBio());
if (user.getBio().equals(Constants.EMPTY_STRING)) {
tvBio.setVisibility(View.GONE);
}
tvEmail.setText(user.getEmail());
//tvLanguages.setText(user.getLanguages());
//Set marker in User location
LatLng userLatLong = getUserLatLong(user.getLocationName());
mMap.addMarker(new MarkerOptions()
.position(userLatLong)
.icon(BitmapDescriptorFactory.fromBitmap(Utilities.writeTextOnDrawable(this, R.drawable.user_marker, "")))
.title(user.getLocationName()));
mMap.moveCamera(CameraUpdateFactory.newLatLng(userLatLong));
mMap.animateCamera(CameraUpdateFactory.zoomTo(5.0f));
//Collapsing Toolbar options
collapsingToolbarLayout.setExpandedTitleColor(Color.TRANSPARENT);
//collapsingToolbarLayout.setTitle(user.getName());
collapsingToolbarLayout.setTitle(" ");
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBar.getLayoutParams();
AppBarLayout.Behavior behavior = new AppBarLayout.Behavior();
behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
@Override
public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
return false;
}
});
params.setBehavior(behavior);
}
private LatLng getUserLatLong(String locationName) {
LatLng userLatLong = null;
if (Geocoder.isPresent()) {
try {
Geocoder gc = new Geocoder(this);
List<Address> addresses = gc.getFromLocationName(locationName, 1); // get the found Address Objects
for (Address a : addresses) {
if (a.hasLatitude() && a.hasLongitude()) {
userLatLong = new LatLng(a.getLatitude(), a.getLongitude());
}
}
} catch (IOException e) {
Log.e("Geocoder Error", e.toString());
}
}
return userLatLong;
}
}
2
Answers
The problem was that Facebook updated their permissions and I was required to submit for review to get the user_location. this was giving me the AccessToken token:ACCESS_TOKEN_REMOVED Error.This is why it worked to begin with and then stopped out of nowhere.
The exception indicates that you are trying to dereference something that is null.
Judging by the code, I would imagine it is that your JSON object does not have a “location” in it, and so this line fails:
The stacktrace is very useful here.
This tells you your code broke at line 117.
Most editors have a “jump to line” feature, or line numbering.
In Eclipse, you can use Ctrl-L.
Here’s an interesting tip:
In Eclipse, you can open up a new “Java Stack Trace” console.
Copy the stack trace from your log, and paste it into the Java Stack Trace console.
Then, you can just click on the stacktrace text and it will take you straight to the offending line!