AndroidManifest.xml

<application
	android:allowBackup="true"
	android:icon="@mipmap/ic_launcher"
	android:label="@string/app_name"
	android:roundIcon="@mipmap/ic_launcher_round"
	android:supportsRtl="true"
	android:theme="@style/AppTheme">
	<meta-data android:name="com.facebook.accountkit.ApplicationName"
		android:value="@string/app_name" />
	<meta-data android:name="com.facebook.sdk.ApplicationId"
		android:value="@string/FACEBOOK_APP_ID" />
	<meta-data android:name="com.facebook.accountkit.ClientToken"
		android:value="@string/ACCOUNT_KIT_CLIENT_TOKEN" />

	<activity
		android:name="com.facebook.accountkit.ui.AccountKitActivity"
		android:theme="@style/AppLoginTheme"
		tools:replace="android:theme">
	</activity>
<resources>
	<style name="AppLoginTheme" parent="Theme.AccountKit"/>
</resources>
import com.facebook.accountkit.AccountKit;
import com.facebook.accountkit.AccessToken;

@Override
Protected void onCreate(Bundle savedInstanceState){
	AccessToken accessToken = AccountKit.getCurrentAccessToken();
	if (accessToken != null){
		launchAccountActivity();
	}
}

Launch Activity View

import UIKit

class ViewController: UIViewController {

	override func viewDidLoad(){
		super.viewDidLoad()
	}

	@IBAction func experiment(){
		let image = UIImage()
		let controller = UIActivityViewController(activityItems: [image],
			applicationActivities: nil)
		self.presentViewController(controller, animated: true, completion:nil)
	}
}
@IBAction func experiment(_ sender: Any){
	let nextController = UIImagePickerController()
	self.present(nextController, animated: true, completion: nil)
}

@IBAction func experiment(_ sender: Any){

	let image = UIImage()
	let controller = UIActivityViewController(activityItems: [image],
		self.present(controller, animated: true, completation: nil))
}
import UIKit

class DiceViewController: UIViewController {

	var firstValue: Int?
	var secondValue: Int?

	@IBOutlet var firstDie: UIImageView!
	@IBOutlet var secondDie: UIImageView!

	override func viewWillAppear(animated: Bool){

		if let firstValue = self.firstValue {
			self.firstDie.image = UIImage(named: "d\(firstValue)")
		} else {
			self.firstDie.image = nil;
		}

		if let secondValue = self.secondValue {
			self.secondDie.image = UIImage(named: "d\(secondValue)")
		} else {
			self.secondDie.image = nil
		}

		self.firstDie.alpha = 0
		self.secondDie.alpha = 0
	}
}

Implementation Steps

Name, Service, Conditions, Event Handler
Name:makeUppercase, Realtime Database, Trigger on specific path, makeUppercase handler

const functions = require('firebase-functions');

exports.emojify = functions.database.ref('/messages/{pushId}/text')
	.onWrite(event => {
		if(!event.data.val()|| event.data.previous.val()){
			console.log("not a new write event");
			return;
		}

		console.log("emojifying");

		const originalText = event.data.val();
		const emojifiedText = emojifyText(originalText);

		return event.data.ref.set(emojifiedText);
	});

	function emojifyText(text){
		var emojifiedText = text;
		emojifiedText = emojifiedText.replace(/\blob\b/id, "");
		emojifiedText = emojifiedText.replace(/\blob\b/id, "");
		return emojifiedText;
	}

FirebaseUI Authentication

Adding Sign In
-Email/Password
-Google
-Facebook
-Twitter
-GitHub

mPhotoPickerButton.setOnClickListener(new View.OnClickListener(){
	@Override
	public void onClick(View view){
		Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
		intent.setType("image/jpeg");
		intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
		startActivityForResult(Intent.createChooser(intent, "Complete action using"), RC_PHOTO_PICKER);
	}
});
service firebase.storage {
	match /b/friendlychat-12987.appspot.com/o {
		match /{allPaths=**} {
			allow read, write: if request.auth != null;
		}
	}
}

match /funGifs/cats/{catPics=**}

resource: existing storage data
request: incoming request data

allow read: if request.auth != null && imageId.matches(“.*.gif”)

String name = "Firebase":
name = 3;

var name = "Firebase";
name = 3;

final x = 42;
x = 1024;

const x = 42;
x = 1024

var x = 42;
var y = 1024;

System.out.println("Message");
Log.d(TAG, "Message");

public int multiply(int a, int b){
	return a * b;
}

String[] list = {"apple", "pear", "orange"};

for (int i = 0; i < list.length; i++){
	System.out.println(list[i])
}

Databse implementation

mSendButton.setOnClickListener(new View.OnClickListener(){
	@Override
	public void onClick(View view){
		mMessageEditText.setText("");
	}
});
{
	"rules": {
		".read": true,
		".write": ture
	}
}

Database Security
-Database security rules
-Security rule configuration examples
-Authentication with Firebase

{
	"chat": {
		"messages": {
			"-KS3PV-iwUZp5wkNq70s":{
				"name": "person1",
				"text": "hey!"
			},
			"-KS3PXhIhs8J_inrExy4":{
				"name": "person2",
				"text": "what's up?"
			}
		}
	},
	"special_chat": {
		"messages": {
			"-KR-DwqtKzlWGxSn9P0y":{
				"name": "person1",
				"text":"want to go to the movies?"
			},
			"-KR4tIpWmNn-EYxquSrw": {
				"name": "person3",
				"text": "Yeah! let's meet at 7."
			}
		}
	},
	"users": {
		"uid1":{
			"paid":true
		},
		"uid2": {
			"paid": false
		},
		"uid3": {
			"paid": true
		}
	}

}

Firebase Realtime Database

what is firebase databse?
what can it be used for?
realtime database in action
database structure best practices

“:
“golden”: 1.618
“fog”: true
“palindrome”: “tacocat”
“messages”: “message1”: “name”:”person”, “text”:”Hello?”
“message2”: “name”:”Individual”, “text”:”Hi!”

node should be “child” and “parent

{
	"questions": {
		"ABCDakarandomkey": {
			"question": "Who was the 13th president of the United States?"
			"choice_1": "Millard Fillmore",
			"choice_2": "Zachary Taylor",
			"choice_3": "Franklin Pierce",
			"choice_4": "James K. Polk",
			"answer" :"choice_1"
		},
		"EFGHakarandomkey":{
			"question": "In what year was the first gasoline combustion engine invented?",
			"choice_1":"1769",
			"choice_2":"1886",
			"choice_3":"1807",
			"choice_4":"1864",
			"answer": "choice_4"
		}
	},
	"players":{
		"user_key_1":{
			"name":"Person",
			"opponents":{
				"IJKLakarandomkey":"user_key_2",
				"MNOPakarandomkey":"user_key_6"
			},
			"questions":{
				"ABCDakarandomkey": "Correct",
				"EFGHakarandomkey": "Incorrect"
			}
		},
		"user_key_2": {
			"name": "Mai",
			"opponents": {
				"QRAAakarandomkey": "user_key_1",
				"SQUEakarandomkey": "user_key_6"
			},
			"questions": {
				"ABCDakarandomkey":"Incorrect",
				"EFGHakarandomkey":"Incorrect"
			}
		}
	},
	"opponents": {
		"couple_Key_1": "user_key_1_user_key_2",
		"user_1": "user_key_1",
		"user_2": "user_key_2",
		"winner": "user_key_1"
	}
}

Firebase

Be comfortable with
– making a simple mobile application
– basic command line
– calling a web or cloud API

FriendlyChat
APP, DB, FILE

package com.google.firebase.xxxx.friendlychat;
public class FriendlyMessage {
	private String text;
	private String name;
	private String photoUrl;

	public FriendlyMessage(){
	}

	public FriendlyMessage(String text, String name, String photoUrl){
		this.text = text;
		this.name = name;
		this.photoUrl = photoUrl;
	}

	public String getText(){
		return text;
	}

	public void setText(string text){
		this.text = text;
	}

	public String getName(){
		return name;
	}

	public void setName(String name){
		this.name = name;
	}
	public String getPhotoUrl{
		return photoUrl;
	}

	public void setPhotoUrl(String photoUrl){
		this.photoUrl = photoUrl;
	}
}
package com.google.firebase.xxxx.friendlychat;

import android.os.Bundle;
import android.support.v7.app.AppCompactActivity;
import android.text.Editable;
import android.text.TextWatcher;
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.ListView;
import android.widget.ProgressBar;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends(Bundle savedInstanceState){
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);

	mUsername = ANONYMOUS;

	mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
	mMessageListView = (ListView) findViewById(R.id.messageListView);
	mPhotoPickerButton = (ImageButton) findViewById(R.id.photoPickerButton);
	mMessageEditText = (EditText) findViewById(R.id.messageEditText);
	mSendButton = (Button) findViewById(R.id.sendButton);

	List<FriendlyMessage> friendlyMessages = new ArrayList<>();
	mMessageAdapter = new MessageAdapter(this, R.layout.item_message, friendlyMessages);
	mMessageListView.setAdapter(mMessageAdapter);

	mProgressBar.setVisibility(ProgressBar.INVISIBLE);

	mPhotoPickerButton.setOnClickListener(new View.OnClickListener(){
		@Override
		public void onClick(View view){

		}
	});

	mMessageEditText.addTextChangedListener(new TextWatcher(){
		@Override
		public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2){			
		}

		@Override
		public void onTestChanged(CharSequence charSequence, int i, int i1, int i2){
			if (charSequence.toString().trim().length() > 0){
				mSendButton.setEnable(true);
			} else {
				mSendButton.setEnabled(false);
			}
		}

		@Override
		public void afterTextChanged(Editable editable){
		}
	});
	mMessageEditText.setFilter(new InputFilter[]{new InputFilter.LengthFilter(DEFALT_MSG_LENGTH_LIMIT)});

	mSendButton.setOnClickListener(new View.OnClickListener(){
		@Override
		public void onClick(View view){
			mMessageEditText.setText("");
		}
	});

	@Override
	public boolean onCreateOptionsMenu(Menu menu){
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.main_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item){
		return super.onOptionsItemSelected(item);
	}
}

Create the Empty View

<red lines>
	<!-- Empty view for the list -->
	<RelativeLayout
		android:id="@+id/empty_view"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_centerInParent="true">

		<ImageView
			android:id="@+id/empty_shelter_image"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:layout_centerHorizontal="true"
			android:src="@drawable/ic_empty_shelter" />

		<TextView
			android:id="@+id/empty_title_text"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:layout_below="@+id/empty_shelter_image"
			android:layout_centerHorizontal="true"
			android:fontFamily="sans-serif-medium"
			android:paddingTop="16dp"
			android:text="@string/empty_view_title_text"
			android:textAppearance="?android:textAppearanceMedium" />

		<TextView
			android:id="@+id/empty_subtitle_text"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:layout_below="@+id/empty_title_text"
			android:layout_centerHorizontal="true"
			android:fontFamily="sans-serif"
			android:paddingTop="8dp"
			android:text="@string/empty_view_subtitle_text"
			android:textAppearance="?android:textAppearanceSmall"
			android:textColor="#A2AAB0">
	</RelativeLayout>

Using a CursorLoader
Activity -> LoaderCallbacks -> onCreate() ->getLoaderManager().initLoader()->onCreateLoader() -> onLoadFinished() swapCursor(cursor -> onLoaderReset() swapCursor(null)

CursorAdapter

ArrayAdapter
Data source: ArrayList of words
Data source: Cursor of pets

public class PetCursorAdapter extends CursorAdapter {

	public PetCursorAdapter(Context context, Cursor c){
		super(context, c, 0);
	}

	public view newView(Context context, Cursor c, ViewGroup parent){
		// create and return new blank list item
	}

	public void bindView(View view, Context context, Cursor c){
		// Populate list item view with pet data
	}
}

ContentProvider Update()

public class PetProvider extends ContentProvider {

	...

	@Override
	public int update(Uri uri, ContentValues contentValues, String selection,
		String[] selectionArgs){
		final int match = sUriMatcher.match(uri);
		switch (match){
			case PETS:
				return updatePet(uri, contentValues, selection, selectionArgs);
			case PET_ID:
				selection = PetEntry._ID + "=?";
				selectionArgs = new String[] { String.valueOf(ContentUris.parseId(uri))};
				return updatePet(uri, contentValues, selection, selectionArgs);
			default:
				throw new IllegalArgumentException("Update is not supported for " + uri);
		}
	}
}