从导航抽屉活动返回会导致应用崩溃

时间:2018-11-01 09:49:24

标签: android android-activity kotlin

我正在从here教程中学习如何制作具有Google登录功能的应用,并在尝试退出navigation-drawer活动时遇到了一些问题。它的工作方式是首先启动GoogleSigninAcitivity供用户登录。批准登录后,我将启动导航抽屉活动Main2Activity。单击抽屉中的特定项目后,我将结束Main2Activity并返回到GoogleSigninAcitivity并继续注销。但是,在这种情况下,一旦我单击名为nav_share的抽屉项目,应用程序就会崩溃。

这是GoogleSigninActivity的代码:

package nus.is3261.kotlinapp

import android.app.Activity
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_google_signin.*
import com.google.android.gms.auth.api.Auth
import com.google.android.gms.common.api.GoogleApiClient
import com.google.firebase.auth.FirebaseAuth
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.ConnectionResult
import com.google.firebase.auth.FirebaseUser
import android.content.Intent
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.firebase.auth.GoogleAuthProvider

class GoogleSigninActivity : AppCompatActivity(), View.OnClickListener, GoogleApiClient.OnConnectionFailedListener {

    private val TAG = "JSAGoogleSignIn"
    private val REQUEST_CODE_SIGN_IN = 1234
    private val REQUEST_CODE_SIGN_OUT = 123
    private val WEB_CLIENT_ID = "xxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com"

    private var mAuth: FirebaseAuth? = null

    private var mGoogleApiClient: GoogleApiClient? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_google_signin)

        btn_sign_in.setOnClickListener(this)
        btn_sign_out.setOnClickListener(this)
        btn_disconnect.setOnClickListener(this)

        val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(WEB_CLIENT_ID)
                .requestEmail()
                .build()

        mGoogleApiClient = GoogleApiClient.Builder(this)
                .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .build()

        mAuth = FirebaseAuth.getInstance()
    }

    override fun onStart() {
        super.onStart()

        // Check if user is signed in (non-null) and update UI accordingly.
        val currentUser = mAuth!!.currentUser
        updateUI(currentUser)
    }

    override fun onClick(v: View?) {
        val i = v!!.id

        when (i) {
            R.id.btn_sign_in -> signIn()
            R.id.btn_sign_out -> signOut()
            R.id.btn_disconnect -> revokeAccess()
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent();
        if (requestCode == REQUEST_CODE_SIGN_IN) {
            val result = Auth.GoogleSignInApi.getSignInResultFromIntent(data)
            if (result.isSuccess) {
                // successful -> authenticate with Firebase
                val account = result.signInAccount
                firebaseAuthWithGoogle(account!!)
            } else {
                // failed -> update UI
                updateUI(null)
                Toast.makeText(applicationContext, "SignIn: failed!",
                        Toast.LENGTH_SHORT).show()
            }
        } else if ((requestCode == REQUEST_CODE_SIGN_OUT)&&(resultCode == Activity.RESULT_OK)){
            mGoogleApiClient?.connect()
            signOut()
        }
    }

    private fun firebaseAuthWithGoogle(acct: GoogleSignInAccount) {
        Log.e(TAG, "firebaseAuthWithGoogle():" + acct.id!!)

        val credential = GoogleAuthProvider.getCredential(acct.idToken, null)
        mAuth!!.signInWithCredential(credential)
                .addOnCompleteListener(this) { task ->
                    if (task.isSuccessful) {
                        // Sign in success
                        Log.e(TAG, "signInWithCredential: Success!")
                        val user = mAuth!!.currentUser
                        updateUI(user)
                    } else {
                        // Sign in fails
                        Log.w(TAG, "signInWithCredential: Failed!", task.exception)
                        Toast.makeText(applicationContext, "Authentication failed!",
                                Toast.LENGTH_SHORT).show()
                        updateUI(null)
                    }
                }
    }

    override fun onConnectionFailed(connectionResult: ConnectionResult) {
        Log.e(TAG, "onConnectionFailed():" + connectionResult);
        Toast.makeText(applicationContext, "Google Play Services error.", Toast.LENGTH_SHORT).show();
    }

    private fun signIn() {
        val intent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient)
        startActivityForResult(intent, REQUEST_CODE_SIGN_IN)
    }

    private fun signOut() {
        // sign out Firebase
        mAuth!!.signOut()

        // sign out Google
        Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback { updateUI(null) }
    }

    private fun revokeAccess() {
        // sign out Firebase
        mAuth!!.signOut()

        // revoke access Google
        Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback { updateUI(null) }
    }

    private fun updateUI(user: FirebaseUser?) {
        if (user != null) {
            val myIntent = Intent(this, Main2Activity::class.java)
            startActivityForResult(myIntent, REQUEST_CODE_SIGN_OUT)
//            tvStatus.text = "Google User email: " + user.email!!
//            tvDetail.text = "Firebase User ID: " + user.uid

//            btn_sign_in.visibility = View.GONE
//            layout_sign_out_and_disconnect.visibility = View.VISIBLE
        } else {
            tvStatus.text = "Signed Out"
            tvDetail.text = null

            btn_sign_in.visibility = View.VISIBLE
            layout_sign_out_and_disconnect.visibility = View.GONE
        }
    }

}

这是我从Main2Activity返回的地方:

override fun onNavigationItemSelected(item: MenuItem): Boolean {
    // Handle navigation view item clicks here.
    when (item.itemId) {
        R.id.nav_basics -> {
            basicFragment()
        }
        R.id.nav_loops -> {
            loopFragment()
        }
        R.id.nav_functions -> {
            functionFragment()
        }
        R.id.nav_chart -> {

        }
        R.id.nav_share -> {
            signOut()
            return true
        }
    }

    drawer_layout.closeDrawer(GravityCompat.START)
    return true
}

fun signOut(){
    drawer_layout.closeDrawer(GravityCompat.START)
    val myIntent = Intent()
    myIntent.putExtra("SignOut", "SignOut")
    setResult(Activity.RESULT_OK, myIntent)
    finish()
}

我觉得我做错了什么,但是我似乎找不到错误所在。 这是我单击nav_share时立即显示的logcat错误:被截断的单词在说GoogleApiCliet is not connected yet

enter image description here

2 个答案:

答案 0 :(得分:2)

签到注销方法mGoogleApiClient已正确初始化和连接。否则,您可以先致电mGoogleApiClient.connect(),然后再致电signout

private fun signOut() {
        // sign out Firebase
        mAuth!!.signOut()

        // sign out Google
        Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback { updateUI(null) }
    }

答案 1 :(得分:1)

您要转到其他活动,然后在下面的代码中调用

drawer_layout.closeDrawer(GravityCompat.START)

但是您需要首先执行此代码,然后继续进行任何重定向。 其背后的原因是,当您已经重定向到另一个活动时,您将获得canvas_layout为null。 希望对您有帮助