匿名登录到firebase身份验证,并在用户在身份验证过程中轮换他/她时添加onCompleteListener?

时间:2017-12-04 00:19:35

标签: android firebase firebase-authentication firebase-security

我正在制作随机聊天应用,其中每2个用户在1个房间。如果我不旋转设备,我的应用程序运行良好,但我只是在应用程序启动后尝试旋转几次以使应用程序健壮。然后,应用程序立即崩溃

如何在firebase身份验证正在进行时轮换他/她时,如何匿名登录firebase身份验证并添加onCompleteListener?

当我第一次启动该应用时,会显示dialog,用于通知用户应用正在初始化某些内容,dialog期间显示onCreateView fragment,应用尝试匿名登录firebase authentication并设置onCompleteListener,因为authentication完成后,

我必须使用uid插入firebase database '/user_state/{uid}/"home"'并解除dialog以使用户可以按下按钮,该按钮用于查找另一个用户也可以在需要uid的地方聊天。

因为两个工作都需要uid,所以我需要在authentication完成后立即完成这些工作。

我只是认为我可以通过'/user_state/{uid}/"home"'的云函数实现插入firebase,但我不知道如何知道我忽略初始化的时间dialog我之前展示过,因为我必须知道authentication何时完成,我需要回调函数。所以我添加了onCompleteListener这样的

FirebaseAuth.getInstance().signInAnonymously().addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "signInAnonymously:success");
                        mAuthInitDialog.dismiss();
                        mCurrentUser = mAuth.getCurrentUser();
                        UserState state = new UserState(STATE_HOME);
                        mFirebaseDatabase
                                .getReference("user_state/" + mCurrentUser.getUid())
                                .setValue(state);

                    } else {
                        Log.w(TAG, "signInAnonymously:failure", task.getException());
                        mAuthInitDialog.dismiss();
                        Toast.makeText(getActivity(), "Authentication Failed", Toast.LENGTH_SHORT).show();
                    }
                }
            });

但是当我旋转设备时,activitydestroyedlistener已经确定无效。所以,我只想到如下更改我的代码

Task mTask = FirebaseAuth.getInstance().signInAnonymously();
mTask.addOnCompleteListener( ...

我使用了onSaveInstanceState方法和Gson来保存我的Task Object,如下所示

bundle.putString(BUNDLE_TASK_AUTH, new Gson().toJson(mTaskAuth));

并恢复如下

if(savedInstanceState != null) {
    mTask =  new Gson().fromJson(savedInstanceState.getString(BUNDLE_TASK_AUTH), Task.class);
    mTask.setOnCompleteListener( ...
}

但是,我不确定侦听器是否可以捕获身份验证完成事件,即使每次重新创建片段后都会监听侦听器

因为我认为在销毁活动之后和重新创建活动之前可能会发生身份验证完成事件。

即使使用firebase authentication进行多次设备轮换,我也想制作健壮的应用。我该怎么办?

MainFragment.java的代码

public class MainFragment extends Fragment {
    private static final String TAG = "sgc109.MainFragment";
    private static final String DIALOG_PROGRESS = "DialogProgress";
    private static final String BUNDLE_IS_WAITING = "bundle_is_waiting";
    private static final String BUNDLE_TASK_AUTH = "bundle_task_auth";
    private static final String CMD_START_WAITING = "start_waiting";
    private static final String CMD_STOP_WAITING = "stop_waiting";
    private static final String CMD_EXIT = "exit";
    private static final String CMD_SEND = "send";
    private static final String STATE_HOME = "home";
    private static final String STATE_WAITING = "waiting";
    private static final String STATE_MATCHED = "matched";
    private static final String STATE_PENDING = "pending";



    private static final int REQUEST_CHAT_ROOM = 0;

    private boolean isWaiting;
    private boolean hasRequestedAuth;
    private Task mTaskAuth;
    private FirebaseAuth mAuth;
    private Button mEnterTheRoomButton;
    private ProgressDialog mProgressDialog;
    private ProgressDialog mAuthInitDialog;
    private FirebaseDatabase mFirebaseDatabase;
    private FirebaseUser mCurrentUser;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            Log.i(TAG, "retore savedInstanceState!");
            isWaiting = savedInstanceState.getBoolean(BUNDLE_IS_WAITING, false);
            mTaskAuth =  new Gson().fromJson(savedInstanceState.getString(BUNDLE_TASK_AUTH), Task.class);
        }

        if (isWaiting) {
            showProgressDialog();
        }

        View view = inflater.inflate(R.layout.fragment_main, container, false);

        mAuth = FirebaseAuth.getInstance();
        mCurrentUser = mAuth.getCurrentUser();
        mFirebaseDatabase = FirebaseDatabase.getInstance();
        if (mCurrentUser == null) {
            mAuthInitDialog = new ProgressDialog(getActivity());
            mAuthInitDialog.setTitle("첫 실행 초기화 중");
            mAuthInitDialog.setCanceledOnTouchOutside(false);
            mAuthInitDialog.setCancelable(false);
            mAuthInitDialog.show();

            if (mTaskAuth == null) {
                mTaskAuth = mAuth.signInAnonymously();
            }
            mTaskAuth.addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "signInAnonymously:success");
                        mAuthInitDialog.dismiss();
                        mCurrentUser = mAuth.getCurrentUser();
                        UserState state = new UserState(STATE_HOME);
                        mFirebaseDatabase
                                .getReference("user_state/" + mCurrentUser.getUid())
                                .setValue(state);

                    } else {
                        Log.w(TAG, "signInAnonymously:failure", task.getException());
                        mAuthInitDialog.dismiss();
                        Toast.makeText(getActivity(), "Authentication Failed", Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
        else {
            mFirebaseDatabase
                    .getReference()
                    .child("user_state")
                    .child(mCurrentUser.getUid())
                    .addListenerForSingleValueEvent(new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            UserState state = dataSnapshot.getValue(UserState.class);
                            if (state.state.equals(STATE_MATCHED)) {
                                enterChatRoom();
                            }
                        }

                        @Override
                        public void onCancelled(DatabaseError databaseError) {
                            Log.w(TAG, "onCancelled");
                        }
                    });
        }

        mEnterTheRoomButton = (Button) view.findViewById(R.id.activity_main_enter_the_room_button);
        mEnterTheRoomButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mCurrentUser == null) {
                    return;
                }
                if (!isWaiting) {
                    startWaitingForOtherUser();
                    isWaiting = true;
                }
                showProgressDialog();
            }
        });

        return view;
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mProgressDialog != null) mProgressDialog.dismiss();
        if (mAuthInitDialog != null) mAuthInitDialog.dismiss();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        Log.i(TAG, "onSavedInstaneState()");
        super.onSaveInstanceState(outState);
        outState.putBoolean(BUNDLE_IS_WAITING, isWaiting);
        outState.putString(BUNDLE_TASK_AUTH, new Gson().toJson(mTaskAuth));
    }

    public void showProgressDialog() {
        mProgressDialog = new ProgressDialog(getActivity());
        mProgressDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
            @Override
            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
                    isWaiting = false;
                    dialog.cancel();
                    stopWaitingForOtherUser();
                    return true;
                }
                return false;
            }
        });
        mProgressDialog.setCanceledOnTouchOutside(false);
        mProgressDialog.setTitle(R.string.find_other_user_progress_dialog_text);
        mProgressDialog.show();
    }

    public void stopWaitingForOtherUser() {
        CommandSender.sendCommand(CMD_STOP_WAITING);
    }

    public void startWaitingForOtherUser() {
        CommandSender.sendCommand(CMD_START_WAITING);
    }

    public void enterChatRoom() {
        isWaiting = false;
        Intent intent = ChatRoomActivity.newIntent(getActivity());
        startActivityForResult(intent, REQUEST_CHAT_ROOM);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != Activity.RESULT_OK) {
            return;
        }
        switch (requestCode) {
            case REQUEST_CHAT_ROOM:
                boolean reEnter = data.getBooleanExtra(ChatRoomActivity.EXTRA_RE_ENTER_ROOM, false);
                if (reEnter){
                    showProgressDialog();
                    startWaitingForOtherUser();
                }
            default:
                return;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我使用 ViewModel 解决了这个问题。我从here发现ViewModel保存了我们的数据,即使由于配置更改(例如设备轮换)而导致Activity被销毁。

我的更改后的代码如下。

<强> MainFragment.java

public class MainFragment extends Fragment {
    private static final String TAG = "sgc109.MainFragment";
    private static final String DIALOG_PROGRESS = "DialogProgress";
    private static final String BUNDLE_IS_WAITING = "bundle_is_waiting";
    private static final String BUNDLE_IS_AUTH_COMPLETE = "bundle_is_auth_complete";
    private static final String CMD_START_WAITING = "start_waiting";
    private static final String CMD_STOP_WAITING = "stop_waiting";
    private static final String CMD_EXIT = "exit";
    private static final String CMD_SEND = "send";
    private static final String STATE_HOME = "home";
    private static final String STATE_WAITING = "waiting";
    private static final String STATE_MATCHED = "matched";
    private static final String STATE_PENDING = "pending";


    private static final int REQUEST_CHAT_ROOM = 0;

    private boolean mIsWaiting;
    private boolean mIsAuthComplete;
    private Button mEnterTheRoomButton;
    private ProgressDialog mProgressDialog;
    private ProgressDialog mAuthInitDialog;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            Log.i(TAG, "retore savedInstanceState!");
            mIsWaiting = savedInstanceState.getBoolean(BUNDLE_IS_WAITING, false);
            mIsAuthComplete = savedInstanceState.getBoolean(BUNDLE_IS_AUTH_COMPLETE, false);
        }

        if (mIsWaiting) {
            showProgressDialog();
        }

        View view = inflater.inflate(R.layout.fragment_main, container, false);

        if (mIsAuthComplete) {
            showAuthInitDialog();
            MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
            model.getTask().addOnCompleteListener(new OnCompleteListener() {
                @Override
                public void onComplete(@NonNull Task task) {
                    mAuthInitDialog.dismiss();
                    if (task.isSuccessful()) {
                        Log.d(TAG, "signInAnonymously:success");
                        mIsAuthComplete = true;
                        UserState state = new UserState(STATE_HOME);
                        FirebaseDatabase
                                .getInstance()
                                .getReference("user_state/" + FirebaseAuth.getInstance().getCurrentUser().getUid())
                                .setValue(state);

                    } else {
                        Log.w(TAG, "signInAnonymously:failure", task.getException());
                        getActivity().finish();
                    }
                }
            });
        } else {
            FirebaseDatabase
                    .getInstance()
                    .getReference()
                    .child("user_state")
                    .child(FirebaseAuth.getInstance().getCurrentUser().getUid())
                    .addListenerForSingleValueEvent(new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            UserState state = dataSnapshot.getValue(UserState.class);
                            if (state.state.equals(STATE_MATCHED)) {
                                enterChatRoom();
                            }
                        }

                        @Override
                        public void onCancelled(DatabaseError databaseError) {
                            Log.w(TAG, "onCancelled");
                        }
                    });
        }

        mEnterTheRoomButton = (Button) view.findViewById(R.id.activity_main_enter_the_room_button);
        mEnterTheRoomButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (FirebaseAuth.getInstance().getCurrentUser() == null) {
                    Toast.makeText(getActivity(), "Shit Fuck!", Toast.LENGTH_SHORT).show();
                    return;
                }

                showProgressDialog();
                startWaitingForOtherUser();
                mIsWaiting = true;
            }
        });

        return view;
    }

    private void showAuthInitDialog() {
        mAuthInitDialog = new ProgressDialog(getActivity());
        mAuthInitDialog.setTitle("첫 실행 초기화 중");
        mAuthInitDialog.setCanceledOnTouchOutside(false);
        mAuthInitDialog.setCancelable(false);
        mAuthInitDialog.show();
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mProgressDialog != null) mProgressDialog.dismiss();
        if (mAuthInitDialog != null) mAuthInitDialog.dismiss();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        Log.i(TAG, "onSavedInstaneState()");
        super.onSaveInstanceState(outState);
        outState.putBoolean(BUNDLE_IS_WAITING, mIsWaiting);
        outState.putBoolean(BUNDLE_IS_AUTH_COMPLETE, mIsAuthComplete);
    }

    public void showProgressDialog() {
        mProgressDialog = new ProgressDialog(getActivity());
        mProgressDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
            @Override
            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
                    mIsWaiting = false;
                    dialog.cancel();
                    stopWaitingForOtherUser();
                    return true;
                }
                return false;
            }
        });
        mProgressDialog.setCanceledOnTouchOutside(false);
        mProgressDialog.setTitle(R.string.find_other_user_progress_dialog_text);
        mProgressDialog.show();
    }

    public void stopWaitingForOtherUser() {
        CommandSender.sendCommand(CMD_STOP_WAITING);
    }

    public void startWaitingForOtherUser() {
        CommandSender.sendCommand(CMD_START_WAITING);
    }

    public void enterChatRoom() {
        mIsWaiting = false;
        Intent intent = ChatRoomActivity.newIntent(getActivity());
        startActivityForResult(intent, REQUEST_CHAT_ROOM);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != Activity.RESULT_OK) {
            return;
        }
        switch (requestCode) {
            case REQUEST_CHAT_ROOM:
                boolean reEnter = data.getBooleanExtra(ChatRoomActivity.EXTRA_RE_ENTER_ROOM, false);
                if (reEnter) {
                    showProgressDialog();
                    startWaitingForOtherUser();
                }
            default:
                return;
        }
    }
}

<强> MyViewModel.java

public class MyViewModel extends ViewModel {
    private Task task;
    public Task getTask(){
        if (task == null){
            task = FirebaseAuth.getInstance().signInAnonymously();
        }
        return task;
    }
}