0

我是使用Firebase在Android應用上工作的學生。我一直在嘗試設置Firebase身份驗證,但我一直收到空ptr例外的錯誤。Firebase身份驗證getcurrentUser java.lang.NullPointerException

  1. 用戶被放在LoginActivity.java屏幕使用谷歌,登錄API簽署並得到認證火力地堡

  2. 然後用戶轉到下一個活動MainActivity.java

它看起來像代碼:FirebaseUser user = firebaseAuth.getCurrentUser();MainActivity.java返回空值,我不知道如何避免這個!

下面是我找到的相關跟蹤:

FATAL EXCEPTION: main 
Process: joroze.com.roomifer, PID: 23176 
java.lang.RuntimeException: Unable to start activity ComponentInfo{joroze.com.roomifer/joroze.com.roomifer.MainActivity}: java.lang.NullPointerException 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245) 
    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:5021) 
    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:827) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:643) 
    at dalvik.system.NativeStart.main(Native Method) 
    Caused by: java.lang.NullPointerException 
    at joroze.com.roomifer.MainActivity.onCreate(MainActivity.java:126) 
    at android.app.Activity.performCreate(Activity.java:5426) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1090) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)  
    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:5021)  
    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:827)  
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:643)  
    at dalvik.system.NativeStart.main(Native Method)  

LoginActivity.java

public class LoginActivity extends AppCompatActivity implements 
     GoogleApiClient.OnConnectionFailedListener, 
     View.OnClickListener { 

    private static final String TAG = "SignInActivity"; 
    private static final int RC_SIGN_IN = 9001; 

    // [START declare_auth] 
    private FirebaseAuth mAuth; 
    // [END declare_auth] 

    // [START declare_auth_listener] 
    private FirebaseAuth.AuthStateListener mAuthListener; 
    // [END declare_auth_listener] 


    private GoogleApiClient mGoogleApiClient; 
    private ProgressDialog mProgressDialog; 

    /** 
    * Id to identity READ_CONTACTS permission request. 
    */ 
    private static final int REQUEST_READ_CONTACTS = 0; 

    private DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference(); 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 

     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_login); 


     // Button listeners 
     findViewById(R.id.sign_in_button).setOnClickListener(this); 

     // [START configure_signin] 
     // Configure sign-in to request the user's ID, email address, and basic 
     // profile. ID and basic profile are included in DEFAULT_SIGN_IN. 
     // Configure Google Sign In 
     GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) 
       .requestIdToken(getString(R.string.default_web_client_id)) 
       .requestEmail() 
       .build(); 
     // [END configure_signin] 





     // [START build_client] 
     // Build a GoogleApiClient with access to the Google Sign-In API and the 
     // options specified by gso. 
     mGoogleApiClient = new GoogleApiClient.Builder(this) 
       .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */) 
       .addApi(Auth.GOOGLE_SIGN_IN_API, gso) 
       .build(); 
     // [END build_client] 

     // [START initialize_auth] 
     mAuth = FirebaseAuth.getInstance(); 
     // [END initialize_auth] 

     // [START auth_state_listener] 
     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()); 
       } else { 
        // User is signed out 
        Log.d(TAG, "onAuthStateChanged:signed_out"); 
       } 

      } 
     }; 
     // [END auth_state_listener] 


     // [START customize_button] 
     // Set the dimensions of the sign-in button. 
     SignInButton signInButton = (SignInButton) findViewById(R.id.sign_in_button); 
     signInButton.setSize(SignInButton.SIZE_STANDARD); 
     // [END customize_button] 


    } 

    @Override 
    public void onStart() { 
     super.onStart(); 

     mAuth.addAuthStateListener(mAuthListener); 

     OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient); 
     if (opr.isDone()) { 
      // If the user's cached credentials are valid, the OptionalPendingResult will be "done" 
      // and the GoogleSignInResult will be available instantly. 
      Log.d(TAG, "Got cached sign-in"); 
      GoogleSignInResult result = opr.get(); 
      handleSignInResult(result); 

     } else { 
      // If the user has not previously signed in on this device or the sign-in has expired, 
      // this asynchronous branch will attempt to sign in the user silently. Cross-device 
      // single sign-on will occur in this branch. 
      showProgressDialog(); 
      opr.setResultCallback(new ResultCallback<GoogleSignInResult>() { 
       @Override 
       public void onResult(GoogleSignInResult googleSignInResult) { 
        hideProgressDialog(); 
        handleSignInResult(googleSignInResult); 
       } 
      }); 

     } 
    } 


    // [START onActivityResult] 
    @Override 
    public void onActivityResult(int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 

     // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...); 
     if (requestCode == RC_SIGN_IN) { 
      GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data); 
      handleSignInResult(result); 
     } 
    } 
    // [END onActivityResult] 

    // [START handleSignInResult] 
    private void handleSignInResult(GoogleSignInResult result) { 
     Log.d(TAG, "handleSignInResult:" + result.isSuccess()); 

     if (result.isSuccess()) { 
      // Signed in successfully, show authenticated UI. 
      GoogleSignInAccount acct = result.getSignInAccount(); 
      firebaseAuthWithGoogle(acct); 

      Intent nextActivity = new Intent(this, MainActivity.class); 
      startActivity(nextActivity); 

     } else { 
      Log.d(TAG, "Currently signed out"); 
      // Signed out, show unauthenticated UI. 
     } 
    } 
    // [END handleSignInResult] 

    // [START signIn] 
    private void signIn() { 
     Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient); 
     startActivityForResult(signInIntent, RC_SIGN_IN); 
    } 
    // [END signIn] 


    @Override 
    public void onConnectionFailed(ConnectionResult connectionResult) { 
     // An unresolvable error has occurred and Google APIs (including Sign-In) will not 
     // be available. 
     Log.d(TAG, "onConnectionFailed:" + connectionResult); 
     Toast.makeText(this, "Google Play Services error.", Toast.LENGTH_SHORT).show(); 
    } 


    private void showProgressDialog() { 
     if (mProgressDialog == null) { 
      mProgressDialog = new ProgressDialog(this); 
      mProgressDialog.setMessage("Loading..."); 
      mProgressDialog.setIndeterminate(true); 
     } 

     mProgressDialog.show(); 
    } 

    private void hideProgressDialog() { 
     if (mProgressDialog != null && mProgressDialog.isShowing()) { 
      mProgressDialog.hide(); 
     } 
    } 


    @Override 
    public void onClick(View v) { 
     signIn(); 
    } 


    // [START on_stop_remove_listener] 
    @Override 
    public void onStop() { 
     super.onStop(); 
     if (mAuthListener != null) { 
      mAuth.removeAuthStateListener(mAuthListener); 
     } 
    } 
    // [END on_stop_remove_listener] 

    // [START auth_with_google] 
    private void firebaseAuthWithGoogle(GoogleSignInAccount acct) { 
     Log.d(TAG, "firebaseAuthWithGoogle:" + acct.getId()); 
     // [START_EXCLUDE silent] 
     showProgressDialog(); 
     // [END_EXCLUDE] 

     AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null); 
     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(); 
         } 
         // [START_EXCLUDE] 
         hideProgressDialog(); 
         // [END_EXCLUDE] 
        } 
       }); 
    } 
    // [END auth_with_google] 

} 

MainActivity.java

public class MainActivity extends AppCompatActivity 
      implements NavigationView.OnNavigationItemSelectedListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, CreateGroupDialogFragment.CreateGroupDialogListener { 

     private static final String TAG = "SignInActivity"; 

     FirebaseManageJSON fbmjson = new FirebaseManageJSON(this); 

     private FirebaseAuth mAuth; 
     private FirebaseAuth.AuthStateListener mAuthListener; 

     FirebaseUser mCurrentUser; 

     GoogleApiClient mGoogleApiClient; 

     @Override 
     protected void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.activity_main); 

      mAuth = FirebaseAuth.getInstance(); 

      mAuthListener = new FirebaseAuth.AuthStateListener() { 
       @Override 
       public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { 
        FirebaseUser user = firebaseAuth.getCurrentUser(); 
        if (user != null) { 
         // Currently signed in 
         mCurrentUser = user; 

         clientUser = new User(mCurrentUser.getUid(), mCurrentUser.getDisplayName(), mCurrentUser.getEmail()); 
         writeNewUser(clientUser); 

        } else { 
         signOut(); 
        } 
       } 
      }; 


      // [START configure_signin] 
      // Configure sign-in to request the user's ID, email address, and basic 
      // profile. ID and basic profile are included in DEFAULT_SIGN_IN. 
      GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) 
        .requestEmail() 
        .build(); 
      // [END configure_signin] 

      // [START build_client] 
      // Build a GoogleApiClient with access to the Google Sign-In API and the 
      // options specified by gso. 
      mGoogleApiClient = new GoogleApiClient.Builder(this) 
        .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */) 
        .addApi(Auth.GOOGLE_SIGN_IN_API, gso) 
        .build(); 
      // [END build_client] 

      Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
      setSupportActionBar(toolbar); 

      FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 

      fab.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View view) { 
        showCreateGroupDialog(); 
       } 
      }); 


      DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 


      ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
        this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); 
      drawer.setDrawerListener(toggle); 

      toggle.syncState(); 

      NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); 
      navigationView.setNavigationItemSelectedListener(this); 

      View hView = navigationView.getHeaderView(0); 

      TextView userNameView = (TextView) hView.findViewById(R.id.usernameView); 
      TextView emailView = (TextView) hView.findViewById(R.id.emailView); 
      ImageView profileImageView = (ImageView) hView.findViewById(R.id.profileImageView); 

      if (mCurrentUser.getDisplayName() != null) 
       userNameView.setText(mCurrentUser.getDisplayName()); 

      if (mCurrentUser.getEmail() != null) 
       emailView.setText(mCurrentUser.getEmail()); 

      if (mCurrentUser.getPhotoUrl().toString() != null) 
       Glide.with(this).load(mCurrentUser.getPhotoUrl().toString()).into(profileImageView); 

      drawer.openDrawer(GravityCompat.START); 
     } 

      @Override 
      public void onBackPressed() { 
       DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
       if (drawer.isDrawerOpen(GravityCompat.START)) { 
        drawer.closeDrawer(GravityCompat.START); 
       } else { 
        // User should not need to go to the previous activity this way 
        //super.onBackPressed(); 
       } 
      } 


      @Override 
      public boolean onCreateOptionsMenu (Menu menu){ 
       // Inflate the menu; this adds items to the action bar if it is present. 
       getMenuInflater().inflate(R.menu.main, menu); 

       return true; 
      } 


      @Override 
      public boolean onOptionsItemSelected (MenuItem item){ 

       String message = "Roomifer is awesome!"; 
       Intent share = new Intent(Intent.ACTION_SEND); 
       share.setType("text/plain"); 
       share.putExtra(Intent.EXTRA_TEXT, message); 

       // 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_menu) { 
        startActivity(Intent.createChooser(share, "Share using Messenger")); 
        return true; 
       } 

       return super.onOptionsItemSelected(item); 
      } 


      @SuppressWarnings("StatementWithEmptyBody") 
      @Override 
      public boolean onNavigationItemSelected (MenuItem item){ 
       // Handle navigation view item clicks here. 
       int id = item.getItemId(); 

       if (id == R.id.nav_camera) { 
        // Handle the camera action 
       } else if (id == R.id.nav_share) { 

       } else if (id == R.id.nav_manage) { 

       } else if (id == R.id.nav_signout) { 
        signOut(); 
       } else if (id == R.id.nav_deleteAccount) { 
        revokeAccess(); 
       } 

       DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
       drawer.closeDrawer(GravityCompat.START); 
       return true; 

      } 


      @Override 
      public void onConnected (@Nullable Bundle bundle){ 

      } 

      @Override 
      public void onConnectionSuspended (int i){ 
       mGoogleApiClient.connect(); 
      } 

      @Override 
      public void onConnectionFailed (@NonNull ConnectionResult connectionResult){ 
       Log.d(TAG, "Connection FAILED!"); 
      } 

     public void signOut() { 


      // Firebase sign out 
      FirebaseAuth.getInstance().signOut(); 

      // Google sign out 
      Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
        new ResultCallback<Status>() { 
         @Override 
         public void onResult(Status status) { 

          // Firebase sign out 
          mAuth.signOut(); 

          if (status.isSuccess()) 
           Log.d(TAG, "Log Out successful!"); 
          else 
           Log.d(TAG, "Log Out failed!"); 

          // finish this activity, and go back to the sign-in activity screen 
          finish(); 
         } 
        }); 
     } 

     public void revokeAccess() { 
      Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
        new ResultCallback<Status>() { 
         @Override 
         public void onResult(Status status) { 

          // Firebase sign out 
          mAuth.signOut(); 

          deleteAccount(clientUser); 

          if (status.isSuccess()) 
           Log.d(TAG, "Revoke successful!"); 
          else 
           Log.d(TAG, "Revoke failed!"); 

          // finish this activity, and go back to the sign-in activity screen 
          finish(); 
         } 
        }); 
     } 

     protected void onStart() { 
      super.onStart(); 

      mAuth.addAuthStateListener(mAuthListener); 

      //Snackbar snackbar = Snackbar.make(this.findViewById(R.id.mainSnackBarView), "Signed in as " + clientUser.getUserName(), Snackbar.LENGTH_SHORT); 
      //snackbar.show(); 

     } 

     protected void onStop() { 
      super.onStop(); 
      if (mGoogleApiClient.isConnected()) { 
       mGoogleApiClient.disconnect(); 
      } 

      if (mAuthListener != null) { 
       mAuth.removeAuthStateListener(mAuthListener); 
      } 
     } 

    } 

提前感謝!

回答

2

MainActivityonCreate()方法,你需要初始化mAuth

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    mAuth = FirebaseAuth.getInstance(); // <== ADD THIS 

    ... 
} 

更新:

MainActivitymCurrentUser爲null,因爲AuthStateListener尚未運行。在onStart()運行之前,收聽者不會註冊。將使用mCurrentUseronCreate()中的代碼移入偵聽器。

+0

嗨,鮑勃!接得好。我已經添加了,但是我仍然從'MainActivity.java:126'開始得到空例外: 在這些行上,我嘗試從Firebase用戶那裏獲取值:'mCurrentUser.getDisplayName' ....但它返回null。 你有什麼線索可以避免這種情況嗎?感謝您的幫助! – Jordan

+0

我更新了我的答案。 –

+0

非常感謝你鮑勃!這絕對有效,你節省了我的開發時間小時! 我想提一下,解決方案後出現了另一個錯誤。我必須在'AuthStateListener'之前移動'GoogleAPI'代碼,否則就會說GoogleAPIClient尚未連接。 無論現在都好! – Jordan