Last active
January 28, 2024 19:16
-
-
Save sunmeat/47e57b9788361c10d7a6bea216d851bb to your computer and use it in GitHub Desktop.
firebase chat with authentication android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
AndroidManifest.xml: | |
проверить наличие | |
<activity android:name=".AuthActivity" /> | |
========================================================================================================================== | |
AuthActivity.java: | |
package com.alex.firebase; | |
import android.content.Intent; | |
import android.os.Bundle; | |
import android.support.annotation.NonNull; | |
import android.view.View; | |
import android.widget.Toast; | |
import com.google.android.gms.auth.api.Auth; | |
import com.google.android.gms.auth.api.signin.GoogleSignInAccount; | |
import com.google.android.gms.auth.api.signin.GoogleSignInOptions; | |
import com.google.android.gms.auth.api.signin.GoogleSignInResult; | |
import com.google.android.gms.common.ConnectionResult; | |
import com.google.android.gms.common.SignInButton; | |
import com.google.android.gms.common.api.GoogleApiClient; | |
import com.google.android.gms.tasks.OnCompleteListener; | |
import com.google.android.gms.tasks.Task; | |
import com.google.firebase.auth.AuthCredential; | |
import com.google.firebase.auth.AuthResult; | |
import com.google.firebase.auth.FirebaseAuth; | |
import com.google.firebase.auth.GoogleAuthProvider; | |
public class AuthActivity extends AppCompatActivity implements | |
GoogleApiClient.OnConnectionFailedListener, View.OnClickListener { | |
private static final int RC_SIGN_IN = 9001; | |
private SignInButton mAuthButton; | |
private FirebaseAuth mFirebaseAuth; | |
private GoogleApiClient mGoogleApiClient; | |
// Firebase instance variables | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_auth); | |
mAuthButton = findViewById(R.id.auth_button); | |
mAuthButton.setOnClickListener(this); | |
mFirebaseAuth = FirebaseAuth.getInstance(); | |
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) | |
.requestIdToken(getString(R.string.default_web_client_id)) | |
.requestEmail() | |
.build(); | |
mGoogleApiClient = new GoogleApiClient.Builder(this) | |
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */) | |
.addApi(Auth.GOOGLE_SIGN_IN_API, gso) | |
.build(); | |
} | |
@Override | |
public void onClick(View v) { | |
switch (v.getId()) { | |
case R.id.auth_button: | |
authorize(); | |
break; | |
} | |
} | |
private void authorize() { | |
Intent authorizeIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient); | |
startActivityForResult(authorizeIntent, RC_SIGN_IN); | |
} | |
@Override | |
public void onActivityResult(int requestCode, int resultCode, Intent data) { | |
super.onActivityResult(requestCode, resultCode, data); | |
if (requestCode == RC_SIGN_IN) { | |
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data); | |
if (result.isSuccess()) { | |
GoogleSignInAccount account = result.getSignInAccount(); | |
firebaseAuthWithGoogle(account); | |
} else { | |
// Google Sign In failed | |
} | |
} | |
} | |
private void firebaseAuthWithGoogle(GoogleSignInAccount acct) { | |
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null); | |
mFirebaseAuth.signInWithCredential(credential) | |
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { | |
@Override | |
public void onComplete(@NonNull Task<AuthResult> task) { | |
// 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()) { | |
Toast.makeText(AuthActivity.this, "authentication failed!", | |
Toast.LENGTH_SHORT).show(); | |
} else { | |
startActivity(new Intent(AuthActivity.this, MainActivity.class)); | |
finish(); | |
} | |
} | |
}); | |
} | |
@Override | |
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { | |
Toast.makeText(this, "connection failed!", Toast.LENGTH_SHORT).show(); | |
} | |
} | |
========================================================================================================================== | |
activity_auth.xml: | |
<?xml version="1.0" encoding="utf-8"?> | |
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:id="@+id/sign_in_layout" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:gravity="center" | |
android:orientation="vertical"> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_gravity="center_horizontal" | |
android:layout_marginTop="40dp" | |
android:gravity="center" | |
android:text="Авторизуйтесь, пожалуйста" | |
android:textSize="30sp" | |
android:textStyle="bold" /> | |
<com.google.android.gms.common.SignInButton | |
android:id="@+id/auth_button" | |
android:layout_width="150dp" | |
android:layout_height="wrap_content" | |
android:layout_centerInParent="true" | |
android:layout_gravity="center" | |
android:visibility="visible" /> | |
</FrameLayout> | |
========================================================================================================================== | |
menu / main_menu.xml: | |
<?xml version="1.0" encoding="utf-8"?> | |
<menu xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:app="http://schemas.android.com/apk/res-auto"> | |
<item | |
android:id="@+id/sign_out_menu" | |
android:title="Sign Out" | |
app:showAsAction="never" /> | |
</menu> | |
========================================================================================================================== | |
MainActivity.java: (можно менять код целиком) | |
/* | |
что было добавлено: | |
1) активити теперь реализует интерфейс GoogleApiClient.OnConnectionFailedListener, требующий метод | |
public void onConnectionFailed(@NonNull ConnectionResult connectionResult); | |
2) сущности для работы с авторизацией | |
private GoogleApiClient mGoogleApiClient; | |
private FirebaseAuth mFirebaseAuth; | |
private FirebaseUser mFirechatUser; | |
3) их инициализация в onCreate | |
4) работа с меню для разлогинивания в методе | |
public boolean onOptionsItemSelected(MenuItem item); | |
*/ | |
package com.alex.firebase; | |
import android.content.Intent; | |
import android.support.annotation.NonNull; | |
import android.os.Bundle; | |
import android.view.Menu; | |
import android.view.MenuInflater; | |
import android.view.MenuItem; | |
import android.view.View; | |
import android.widget.Button; | |
import android.widget.EditText; | |
import android.widget.ProgressBar; | |
import android.widget.TextView; | |
import android.widget.Toast; | |
import com.google.android.gms.auth.api.Auth; | |
import com.google.android.gms.common.ConnectionResult; | |
import com.google.android.gms.common.api.GoogleApiClient; | |
import com.google.firebase.auth.FirebaseAuth; | |
import com.google.firebase.auth.FirebaseUser; | |
import com.google.firebase.database.DatabaseReference; | |
import com.firebase.ui.database.FirebaseRecyclerAdapter; | |
import com.google.firebase.database.FirebaseDatabase; | |
import de.hdodenhof.circleimageview.CircleImageView; | |
import com.bumptech.glide.Glide; | |
public class MainActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener { | |
private GoogleApiClient mGoogleApiClient; | |
private FirebaseAuth mFirebaseAuth; | |
private FirebaseUser mFirechatUser; | |
private DatabaseReference db; | |
private FirebaseRecyclerAdapter<ChatMessage, MyViewHolder> fireAdapter; | |
private RecyclerView rv; | |
private LinearLayoutManager lm; | |
private ProgressBar progress; | |
String mPhotoUrl; | |
private EditText edit; | |
public static final String DEFAULT_NAME = "Alex"; | |
private String userName; | |
public static class MyViewHolder extends RecyclerView.ViewHolder { | |
TextView msgTextView; | |
TextView userTextView; | |
CircleImageView userImageView; | |
public MyViewHolder(View v) { | |
super(v); | |
msgTextView = itemView.findViewById(R.id.msgTextView); | |
userTextView = itemView.findViewById(R.id.userTextView); | |
userImageView = itemView.findViewById(R.id.userImageView); | |
} | |
} | |
@Override | |
public boolean onCreateOptionsMenu(Menu menu) { | |
MenuInflater inflater = getMenuInflater(); | |
inflater.inflate(R.menu.main_menu, menu); | |
return true; | |
} | |
@Override | |
public boolean onOptionsItemSelected(MenuItem item) { | |
switch (item.getItemId()) { | |
case R.id.sign_out_menu: | |
mFirebaseAuth.signOut(); | |
Auth.GoogleSignInApi.signOut(mGoogleApiClient); | |
userName = DEFAULT_NAME; | |
startActivity(new Intent(this, AuthActivity.class)); | |
return true; | |
default: | |
return super.onOptionsItemSelected(item); | |
} | |
} | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
progress = findViewById(R.id.progressBar); | |
rv = findViewById(R.id.messageRecyclerView); | |
lm = new LinearLayoutManager(this); | |
lm.setStackFromEnd(true); | |
rv.setLayoutManager(lm); | |
userName = DEFAULT_NAME; | |
edit = findViewById(R.id.msgEditText); | |
// https://stackoverflow.com/questions/42355796/firebase-google-sign-in-will-not-work-android !!! | |
mGoogleApiClient = new GoogleApiClient.Builder(this) | |
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */) | |
.addApi(Auth.GOOGLE_SIGN_IN_API) | |
.build(); | |
mFirebaseAuth = FirebaseAuth.getInstance(); | |
mFirechatUser = mFirebaseAuth.getCurrentUser(); | |
if (mFirechatUser == null) { | |
startActivity(new Intent(this, AuthActivity.class)); | |
finish(); | |
return; | |
} else { | |
userName = mFirechatUser.getDisplayName(); | |
if (mFirechatUser.getPhotoUrl() != null) { | |
mPhotoUrl = mFirechatUser.getPhotoUrl().toString(); | |
} | |
} | |
db = FirebaseDatabase.getInstance().getReference(); | |
fireAdapter = new FirebaseRecyclerAdapter<ChatMessage, MyViewHolder>( | |
ChatMessage.class, | |
R.layout.chat_message, | |
MyViewHolder.class, | |
db.child("messages")) { | |
@Override | |
protected void populateViewHolder(MyViewHolder viewHolder, | |
ChatMessage friendlyMessage, int position) { | |
progress.setVisibility(ProgressBar.INVISIBLE); | |
viewHolder.msgTextView.setText(friendlyMessage.getText()); | |
viewHolder.userTextView.setText(friendlyMessage.getName()); | |
if (friendlyMessage.getPhotoUrl() == null) { | |
viewHolder.userImageView | |
.setImageDrawable(ContextCompat | |
.getDrawable(MainActivity.this, | |
R.drawable.ic_account_circle_black_36dp)); | |
} else { | |
Glide.with(MainActivity.this) | |
.load(friendlyMessage.getPhotoUrl()) | |
.into(viewHolder.userImageView); | |
} | |
} | |
}; | |
fireAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { | |
@Override | |
public void onItemRangeInserted(int positionStart, int itemCount) { | |
super.onItemRangeInserted(positionStart, itemCount); | |
int friendlyMessageCount = fireAdapter.getItemCount(); | |
int lastVisiblePosition = | |
lm.findLastCompletelyVisibleItemPosition(); | |
if (lastVisiblePosition == -1 || | |
(positionStart >= (friendlyMessageCount - 1) && | |
lastVisiblePosition == (positionStart - 1))) { | |
rv.scrollToPosition(positionStart); | |
} | |
} | |
}); | |
rv.setLayoutManager(lm); | |
rv.setAdapter(fireAdapter); | |
Button mSendButton = findViewById(R.id.sendButton); | |
mSendButton.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View view) { | |
ChatMessage friendlyMessage = new | |
ChatMessage(edit.getText().toString(), userName, mPhotoUrl); | |
db.child("messages").push().setValue(friendlyMessage); | |
edit.setText(""); | |
} | |
}); | |
} | |
@Override | |
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { | |
Toast.makeText(this, "connection failed (MainActivity)", Toast.LENGTH_SHORT).show(); | |
} | |
} | |
========================================================================================================================== | |
build.gradle (Module:app): | |
... | |
implementation 'com.google.firebase:firebase-auth:16.0.2' | |
implementation 'com.google.android.gms:play-services-auth:15.0.1' | |
... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment