package deal com.androidbash.androidbashfirebasejokeposter;
import android.content material.Intent;
import android.os.Bundle;
import android.help.v4.content.ContextCompat;
import android.help.v7.app.AppCompatActivity;
import android.help.v7.widget.LinearLayoutManager;
import android.help.v7.widget.RecyclerView;
import android.textual content.Editable;
import android.textual content.TextWatcher;
import android.util.Log;
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.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.widespread.ConnectionResult;
import com.google.android.gms.widespread.api.GoogleApiClient;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.MutableData;
import com.google.firebase.database.Transaction;
import java.util.HashMap;
import java.util.Map;
import de.hdodenhof.circleimageview.CircleImageView;
/*
* Created By AndroidBash on 30/07/2016
*/
public class MainActivity extends AppCompatActivity implements
GoogleApiClient.OnConnectionFailedListener
personal static last String TAG = “AndroidBash”;
public static remaining String JOKES = “jokes”;
personal String mUsername;
personal String mPhotoUrl;
personal EditText mJokeEditText;
personal Button mPostButton;
personal RecyclerView mRecyclerView;
personal LinearLayoutManager mLinearLayoutManager;
personal FirebaseRecyclerAdapter
personal ProgressBar mProgressBar;
personal DatabaseReference mFirebaseDatabaseReference;
personal FirebaseAuth mFirebaseAuth;
personal FirebaseUser mFirebaseUser;
personal GoogleApiClient mGoogleApiClient;
@Override
protected void onCreate(Bundle savedInstanceState)
tremendous.onCreate(savedInstanceState);
setContentView(R.format.activity_main);
// Initialize Firebase Auth
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseUser = mFirebaseAuth.getCurrentUser();
if (mFirebaseUser == null)
// Consumer has not signed in, launch the Sign In exercise
startActivity(new Intent(this, SignInActivity.class));
finish();
return;
else
mUsername = mFirebaseUser.getDisplayName();
if (mFirebaseUser.getPhotoUrl() != null)
mPhotoUrl = mFirebaseUser.getPhotoUrl().toString();
//The primary entry level for Google Play providers integration. Builder to configure a GoogleApiClient is required.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API)
.construct();
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mRecyclerView = (RecyclerView) findViewById(R.id.mRecyclerView);
mLinearLayoutManager = new LinearLayoutManager(this);
mLinearLayoutManager.setStackFromEnd(true);
//Gets a Reference to your Firebase Database.
// You must have included a google-services.json (downloaded from Firebase console) beneath “app” folder of your challenge.
mFirebaseDatabaseReference = FirebaseDatabase.getInstance().getReference();
//Adapter for Firebase RecyclerView : FirebaseRecyclerAdapter
/**
* @param modelClass Firebase will marshall the info at a location into an occasion of a class that you simply present
* @param modelLayout That is the format used to characterize a single item within the listing. You’ll be chargeable for populating an
* instance of the corresponding view with the info from an instance of modelClass.
* @param viewHolderClass The category that maintain references to all sub-views in an instance modelLayout.
* @param ref The Firebase location to observe for knowledge modifications. May also be a slice of a location, utilizing some
* mixture of limit()
, startAt()
, and endAt()
*/
mFirebaseAdapter = new FirebaseRecyclerAdapter
Joke.class,
R.format.item_joke_layout,
MyJokeViewHolder.class,
mFirebaseDatabaseReference.youngster(JOKES))
@Override
protected void populateViewHolder(MyJokeViewHolder viewHolder, remaining Joke joke, int place)
/**
* Each time the info on the given Firebase location modifications, this technique will probably be referred to as for every item that wants
* to be displayed. The primary two arguments correspond to the mLayout and mModelClass given to the constructor of
* this class. The third argument is the merchandise's position within the listing.
*
* Your implementation ought to populate the view utilizing the info contained in the mannequin.
*
* @param viewHolder The view to populate
* @param mannequin The thing containing the info used to populate the view
* @param place The place in the record of the view being populated
*/
mProgressBar.setVisibility(ProgressBar.INVISIBLE);
viewHolder.jokeTextView.setText(joke.textual content);
viewHolder.jokeAuthorTextView.setText(joke.identify);
viewHolder.likeCount.setText(joke.likeCount + "");
//Earlier than loading jokes from firebase database to the RecyclerView, we verify whether or not the current consumer has
//appreciated the joke or not. Relying on true/false we set the likes button.
//likesGivenBy is a Map
if (joke.likesGivenBy.get(mFirebaseUser.getUid()) == null)
viewHolder.likeButton.setBackgroundResource(R.drawable.ic_favorite_border_black_24dp);
else
viewHolder.likeButton.setBackgroundResource(R.drawable.ic_favorite_black_24dp);
//If the Consumer has no google profile picture we set a default image.
if (joke.photoUrl == null)
viewHolder.circleImageView.setImageDrawable(ContextCompat.getDrawable(MainActivity.this,
R.drawable.ic_face_black_24dp));
else
//Masses the picture in to circleImageView from the given URL
Glide.with(MainActivity.this)
.load(joke.photoUrl)
.into(viewHolder.circleImageView);
//OnClickListener for like button.
//runTransaction technique : Runs a transaction on the info at this location.
//Parameters:
//handler - An object to deal with operating the transaction
viewHolder.likeButton.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
mFirebaseDatabaseReference.baby(JOKES).baby(joke.jokeKey).runTransaction(new Transaction.Handler()
@Override
public Transaction.End result doTransaction(MutableData currentData)
/*Transaction.End result doTransaction(MutableData currentData)
This technique might be referred to as, probably a number of occasions, with the current knowledge at this location.
It's chargeable for inspecting that knowledge and returning a (Transaction.End result) specifying either the specified new knowledge at the location or that the transaction ought to be aborted.
Since this technique could also be referred to as repeatedly for the same transaction, be extraordinarily careful of any unwanted effects
that could be triggered by this technique. As well as, this technique known as from inside the Firebase library's run loop,
so care can also be required when accessing knowledge that could be in use by different threads in your software.
Parameters:
currentData - The current knowledge on the location. Update this to the specified knowledge at the location
Returns:
Either the brand new knowledge, or an indication to abort the transaction*/
Joke joke = currentData.getValue(Joke.class);
if (joke == null)
return Transaction.success(currentData);
if (joke.likesGivenBy.containsKey(mFirebaseUser.getUid()))
Log.i("AndroidBash", "User has already Liked. So it can be considered as Unliked.");
joke.likeCount = joke.likeCount - 1;
joke.likesGivenBy.remove(mFirebaseUser.getUid());
else
Log.i("AndroidBash", "User Liked");
joke.likeCount = joke.likeCount + 1;
joke.likesGivenBy.put(mFirebaseUser.getUid(), true);
// Set worth and report transaction success
currentData.setValue(joke);
return Transaction.success(currentData);
@Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot)
// Transaction accomplished
Log.d(TAG, "postTransaction:onComplete:" + databaseError);
);
);
;
mFirebaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver()
@Override
public void onItemRangeInserted(int positionStart, int itemCount)
tremendous.onItemRangeInserted(positionStart, itemCount);
int jokeCount = mFirebaseAdapter.getItemCount();
int lastVisiblePosition = mLinearLayoutManager.findLastCompletelyVisibleItemPosition();
// If the recycler view is initially being loaded or the consumer is on the bottom of the listing, scroll
// to the underside of the record to point out the newly added message.
if (lastVisiblePosition == -1 ||
(positionStart >= (jokeCount - 1) && lastVisiblePosition == (positionStart - 1)))
mRecyclerView.scrollToPosition(positionStart);
);
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mRecyclerView.setAdapter(mFirebaseAdapter);
mJokeEditText = (EditText) findViewById(R.id.post_joke_et);
mJokeEditText.addTextChangedListener(new TextWatcher()
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int j, int okay)
@Override
public void onTextChanged(CharSequence charSequence, int i, int j, int okay)
if (charSequence.toString().trim().size() > 0)
mPostButton.setEnabled(true);
else
mPostButton.setEnabled(false);
@Override
public void afterTextChanged(Editable editable)
);
mPostButton = (Button) findViewById(R.id.button);
mPostButton.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
Map
//Key underneath which a joke will probably be saved. Firebase assigns a singular id for every new joke pushed.
String key = mFirebaseDatabaseReference.baby(JOKES).push().getKey();
//Creates a new Joke object
Joke joke = new Joke(mFirebaseUser.getUid(), mJokeEditText.getText().toString(), mUsername,
mPhotoUrl, key, likesGivenBy);
//New Map can be created from a Joke object.
Map
//Creates a new Map and puts the Map (joke object) which is to be saved in Firebase Database.
Map
childUpdates.put("/jokes/" + key, values);
//updateChildren technique inserts the Joke underneath "/jokes/key" node.
mFirebaseDatabaseReference.updateChildren(childUpdates);
//EditText filed shall be set back "" as soon as the joke is posted.
mJokeEditText.setText("");
);
@Override
public void onPause()
super.onPause();
@Override
public void onResume()
tremendous.onResume();
@Override
public void onDestroy()
tremendous.onDestroy();
@Override
public boolean onCreateOptionsMenu(Menu menu)
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return true;
@Override
public boolean onOptionsItemSelected(MenuItem item)
change (item.getItemId())
case R.id.sign_out_menu:
mFirebaseAuth.signOut();
Auth.GoogleSignInApi.signOut(mGoogleApiClient);
mFirebaseUser = null;
mUsername = null;
mPhotoUrl = null;
startActivity(new Intent(this, SignInActivity.class));
finish();
return true;
default:
return super.onOptionsItemSelected(item);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent knowledge)
tremendous.onActivityResult(requestCode, resultCode, knowledge);
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
Log.d(TAG, "onConnectionFailed:" + connectionResult);
public static class MyJokeViewHolder extends RecyclerView.ViewHolder
public TextView jokeTextView;
public TextView jokeAuthorTextView;
public CircleImageView circleImageView;
public ImageButton likeButton;
public TextView likeCount;
public MyJokeViewHolder(View v)
super(v);
jokeTextView = (TextView) itemView.findViewById(R.id.jokeTextView);
jokeAuthorTextView = (TextView) itemView.findViewById(R.id.jokeAuthorTextView);
circleImageView = (CircleImageView) itemView.findViewById(R.id.circleImageView);
likeButton = (ImageButton) itemView.findViewById(R.id.like_button);
likeCount = (TextView) itemView.findViewById(R.id.like_count);