#はじめに
はじめまして、Life is Tech! Androidコース、メンターのなべです!
Life is Tech ! Advent Calendar 2018、Day 13ですね!
Day12はちゃーはんの記事でした!
Webは素人ですが、確かにCSS設計と音楽の作り方って似ているように感じました!
Web触ってみたい!(やることいっぱい笑)
Life is Tech !のAndroidアプリプログラミングコースではキャンプとスクールを通して、教科書を用いて基礎を学び、中高生がオリジナルのAndroidアプリケーションを作りリリースする過程に、モノづくりのプロセスやオリジナリティを養うことを目的としています。
今日からは後半戦ですよ!残り半分です。
今回の記事はAndroidで作るToDoアプリ!ですが、アカウントを利用して作るToDoアプリです。
#この記事の対象読者
1つでも引っかかったら読んでみることをお勧めします。
- Firebaseを触ってみたい人
- 普段他のコースでAndroidコース気になっている人
- FirebaseAuthでつまづいている人
- RealtimeDatabase使いたい人
- Firebaseが苦手な人(なんか多いらしい)
今回はAndroid以外のコースを学んでいるメンター、メンバーがいることも見込んで、1から全部書いています!
なので興味と時間があれば誰でも開発できますよ!
#Firebaseとは
みなさん、あのGoogleさんのサービス、Firebaseって知っていますか?
Firebaseは、mBaaS(mobile backend as a Service)と呼ばれる、スマートフォンアプリでよく利用される汎用的な機能をクラウドから提供するサービスの一つです。
あらかじめ決められたjavaコードを書くだけで簡単にサーバーとの情報のやり取りを行ってくれます!
Android/iOSアプリでAnalytics(広告)が出来たり、Notification(通知)の送信管理ができたり、Crashレポートやリアルタイムでデータ更新なんかも盛り込んだいろいろできる…とりあえずすごいサービスということだけわかってもらえれば十分です。
詳しくはこの記事とか、公式ドキュメントを見るといいです。日本でもAndroidエンジニアが増えてきた影響なのかわからないですけど、Firebaseのドキュメントは日本語翻訳された状態のもあります。ありがたいです。また、githubに機能ごとに分けられたサンプルソースも公開してくれているので導入も簡単です!
完成形
機能として、ログインをして、ToDo一覧が見れて、さらに項目の追加、削除機能をつけたアプリを目指します。
Chapter1 始める前の事前準備
1. 環境構築
Androidコースではない方は環境構築からしましょう!
普段Android使っているよ〜な人は新規プロジェクトを作って3.Firebaseの登録
から!
必要なものは以下の2点です。
詳しくはLife is Tech!のお持込みPC チェック&準備マニュアルを見てください。
Chapter 2. 新規プロジェクトの作成
2.プロジェクトを作成する
1. 最初の画面
"Start a new Android Studio"をクリックしてください。
2. Create Android Project画面
"Application name","Company domain"は必須項目です。自由に入力してください。
プロジェクトに関する値を入力して [Next] をクリックします。
3. Target Android Devices画面
APIを選ぶのですが、23ぐらいを選ぶのが無難でしょう(偏見)
終わったら、[Next] をクリックします。
4. Add an Activity to Mobile画面
"Empty Activity"を選択して[Next] をクリックします。
5. Configure Activity画面
そのまま[Finish]でプロジェクト作成です!
3. Firebaseの登録
次にFirebaseにプロジェクトを登録しましょう。
Firebaseコンソールはこちら。
Firebaseの設定を途中でAndroidStudioに導入します。やり方はこちら。
初めての製作する方は長くなるのでここでの説明は割愛させていただきます。
こちらの記事を参考にして進めてください。
プロジェクトを制作する時にFirebaseの方からこうしてくださいね、とやり方を教えてくれるので心配はありません。
4. ライブラリの追加
まず、AndroidStudio左上、「Android」という部分を押して、一番上の「Project」に変更します。
次に、下図のように アプリ名>app>src>build.gradleを開いて、 dependencies部分を変更しましょう。
// (割愛)
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.google.firebase:firebase-auth:16.0.5'
implementation 'com.google.firebase:firebase-core:16.0.6'
implementation 'com.google.firebase:firebase-database:16.0.5'
implementation 'com.google.android.gms:play-services-auth:16.0.1'
implementation "com.firebaseui:firebase-ui-auth:4.2.1"
//上記5行を追加
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
repositories {
mavenCentral()
}
apply plugin: 'com.google.gms.google-services'
//repositoriesからここまでも追記分です。忘れずに。
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'com.google.gms:google-services:4.2.0'
//上の行を追記
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
5. 権限の追加
最後に、 アプリ名/app/src/main/AndroidManifest.xml
に一部追記します。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="パッケージ名">
<uses-permission android:name="android.permission.INTERNET " />
<!--上の行を追加-->
<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">
<!--以下、省略-->
これで準備完了です!
一旦休憩しましょう
さてここからはコーディングですよ!Let'sコーディング!
Chapter3 レイアウトの作成
6.Activityレイアウトの作成
今度はAndroidの画面を作っていきますよ!
この記事の開発の流れとして、
1.ToDo機能
2.ログイン機能
3.新規作成機能
の流れで作っていきます。
今回、これらに必要なActivityは4つ作ります!
Activityの作り方はこちら
Activity名 | 内容 |
---|---|
MainActivity | メールアカウントを新規作成・ログインする |
LoginActivity | Googleアカウントでログインする |
ToDoActivity | (ログインした後)ToDoを表示させる |
AddActivity | (ログインした後)新たなToDoを作成する |
そのほか、ToDoアプリに必要なListViewを追加させるために2つ追加します。
クラス名 | 内容 |
---|---|
CustomAdapter | ArrayAdapterを継承して自作したクラス |
ToDoData | ToDoの情報をもつクラス |
各アクティビティにレイアウトを書いていきます。
レイアウトはActivityに必要な4つのレイアウトファイル(Activity作成時に自動に作成されます)、ToDoDataの情報の見た目の部分のレイアウトファイルを作成します。
こちらはアプリ名/app/src/main/res/layout
内に作ります。
レイアウト名 | 内容 |
---|---|
activity_login.xml | Googleアカウントでログインする |
activity_main.xml | メールアカウントを新規作成・ログインする |
activity_todo.xml | (ログインした後)ToDoを表示させる |
activity_add.xml | (ログインした後)新たなToDoを作成する |
card_view.xml | ListViewに表示させるレイアウト |
それでは、各レイアウトの解説です。
AndroidStudioは感覚的に置けるDesign、コードを書いて確実にレイアウトを書くTextモードがあります。最初はDesignで作成した方がわかりやすいですが、慣れてきたらTextモードで書くといいでしょう。
XCodeを使っている方はDesignの方を使うとそんなに違いを感じずスムーズに作れると思いますよ。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LoginActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="Googleでログインする" />
<com.google.android.gms.common.SignInButton
android:id="@+id/googleLoginButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<Button
android:id="@+id/mailLoginButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="メールアドレスでログイン・登録する" />
</LinearLayout>
</RelativeLayout>
その他あと3つ書いてしまうと記事が長くなってしまいますので、割愛させていただきます。
githubにアップロードしておりますのでご安心を。
7.Custom Layoutの作成
レイアウトの重要な部分として、カスタムレイアウトの部分をピックアップします。
ListViewに表示する一個だけの項目を書きます。
今回はタイトルと内容を作るアプリにするので、TextViewを2つ作ります。
TextView2つで1セットのレイアウトを作ったという意味です。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_margin="6dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/title_text_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:text="Sample Text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="30sp"
android:textStyle="bold" />
</LinearLayout>
<TextView
android:id="@+id/content_text_view"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_horizontal|top"
android:layout_marginLeft="3dp"
android:text="Sample Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
</LinearLayout>
Chapter4 Activityの作成
8.LoginActivity作成
LoginActivityの機能として、
- Googleアカウントでのログイン
- メールでのログインさせるための画面推移
の2点の作成をしました。
まず、FirebaseのAuthenticationのログイン方法のメール/パスワード
、Google
を有効にしましょう。
Googleのログイン部分は主にこのように書きます。
public void loginGoogle() {
mAuth = FirebaseAuth.getInstance();
// Google ログイン認証
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();
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
enableAutoManage
メソッドの第一引数はFragmentActivityを継承したActivityを渡します。
AppCompatActivity
はFragmentActivityのサブクラスですので、thisを渡しました。
第二引数には、OnConnectionFailedListener
を渡します。このリスナーはGoogleApiClientへの接続に失敗した時にコールバックされます。
続いて、GoogleのSignInButtonをレイアウトして、ログイン時の挙動を設定していきます。
SignInButton googleSignInButton = (SignInButton) findViewById(R.id.googleLoginButton);
googleSignInButton.setSize(SignInButton.SIZE_STANDARD);
googleSignInButton.setOnClickListener(this);
onClickListenerには先ほど記述したloginGoole()を呼ぶようにしています。
その後、OnActivityResult
メソッド内でsigninの結果を受け取り、オブジェクトから ID トークンを取得して Firebase 認証情報と交換し、Firebase認証情報を使用して、認証を行います。
@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 {
//ログインに失敗した場合
System.out.println(result.getStatus());
Toast.makeText(LoginActivity.this, "Error", Toast.LENGTH_SHORT).show();
}
}
}
private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
changeActivity();
Log.d("LoginActivity", "ログインに成功");
} else {
Toast.makeText(LoginActivity.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
LoginActivity全体はこちら
9.MainActivity作成
MainActivityにはメールでの新規作成・ログインの機能をつけています。
Googleのログイン機能と大した変わりはないです。
メールアカウントでの新規作成とログインの作成手順は似ているのでそんなに手間はかかりません。
まずはonCreate内にFirebaseAuth
オブジェクトの共有インスタンスを取得します。
public class MainActivity extends AppCompatActivity {
EditText emailFormEditText, passwordFormEditText;
public Intent data;
public FirebaseAuth mAuth;
private static final String TAG = "EmailPassword";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
emailFormEditText = (EditText) findViewById(R.id.email_log_in_edit_text);
passwordFormEditText = (EditText) findViewById(R.id.password_log_in_edit_text);
mAuth = FirebaseAuth.getInstance();
}
ユーザーがアプリに新規作成(ログイン)したら、そのユーザーのメールアドレスとパスワードをcreateUserWithEmailAndPassword
(signInWithEmailAndPassword
) に渡します。
public void addMailButton(View v) {
createAccount(emailFormEditText.getText().toString(), passwordFormEditText.getText().toString());
setResult(RESULT_OK, data);
}
private void createAccount(String email, String password) {
Log.d(TAG, "createAccount:" + email);
if (!checkEmpty()) {
return;
}
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// ログインに成功したら、ログインしたユーザーの情報でUIを更新します。
Log.d(TAG, "createUserWithEmail:success");
Toast.makeText(MainActivity.this, "新規作成に成功しました!", Toast.LENGTH_SHORT).show();
changeActivity();
} else {
// サインインに失敗した場合は、ユーザーにメッセージを表示します。
Log.w(TAG, "createUserWithEmail:failure", task.getException());
Toast.makeText(MainActivity.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
}
}
});
}
メールアドレスのフォーマットは、Firebaseの方で判定をしてくれるため、メールアドレスのフォーマットが普通でない(?)場合には、アカウントの作成が弾かれ、エラーを表示してくれます。
自動で判断してくれるので、コードを書かないと判別してくれないなんてことはないんです。便利ですね!
MainActivity全体はこちら
10.ToDoActivity作成
ついにログインしてからの項目に入ります!
ToDoActivityの要素としては
ListViewにfirebaseから受け取った情報を表示させることがメインです!
まず、FirebaseのDatabaseのルールをこのように変更してください。
さて、コードの部分です。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_to_do);
//ログイン情報を取得
user = FirebaseAuth.getInstance().getCurrentUser();
//user id = Uid を取得する
uid = user.getUid();
database = FirebaseDatabase.getInstance();
reference = database.getReference("users").child(uid);
mListView = (ListView) findViewById(R.id.list_view);
//CustomAdapterをセット
mCustomAdapter = new CustomAdapter(getApplicationContext(), R.layout.card_view, new ArrayList<ToDoData>());
mListView.setAdapter(mCustomAdapter);
//LongListenerを設定
mListView.setOnItemLongClickListener(this);
//firebaseと同期するリスナー
reference.addChildEventListener(new ChildEventListener() {
// データを読み込むときはイベントリスナーを登録して行う。
@Override
public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
// アイテムのリストを取得するか、アイテムのリストへの追加がないかリッスンします。
ToDoData toDoData = dataSnapshot.getValue(ToDoData.class);
mCustomAdapter.add(toDoData);
mCustomAdapter.notifyDataSetChanged();
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
// リスト内のアイテムに対する変更がないかリッスンします。
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
// リストから削除されるアイテムがないかリッスンします。
Log.d("ToDoActivity", "onChildRemoved:" + dataSnapshot.getKey());
ToDoData result = dataSnapshot.getValue(ToDoData.class);
if (result == null) return;
ToDoData item = mCustomAdapter.getUserDataKey(result.getFirebaseKey());
mCustomAdapter.remove(item);
mCustomAdapter.notifyDataSetChanged();
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
// 並べ替えリストの項目順に変更がないかリッスンします。
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
// ログを記録するなどError時の処理を記載する。
}
});
}
今回、重要な部分はFirebase RealtimeDatabaseを利用するにあたってのchildイベントについてです。
簡単に書くとイベントリスナーをセットすることで、全取得や更新取得などができるということです。
今回はlistViewに動的に加えるためのonChildAdded
と、DoneしたToDoを削除するためのonChildRemoved
に書いています。
詳しくはこちら
長押しすると削除される削除機能は、onItemLongClickListener
を使います。
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
final ToDoData toDoData = mCustomAdapter.getItem(position);
uid = user.getUid();
new AlertDialog.Builder(this)
.setTitle("Done?")
.setMessage("この項目を完了しましたか?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// OK button pressed
reference.child(toDoData.getFirebaseKey()).removeValue();
}
})
.setNegativeButton("No", null)
.show();
return false;
}
下の部分でFirebase上の項目を削除しています。
reference.child(toDoData.getFirebaseKey()).removeValue();
ListView自体削除しなくていいのか?という疑問があるかもしれませんが、それはonChildRemoved
に記述されているので問題ありません。
項目が削除されるイメージとして、
- 端末から削除コードが流れる
- firebase上のToDoの項目が削除される
onChildRemoved
が動き指定されたListViewの項目が削除される
という形になります。これにより、複数端末で同じアカウントでログインしている時、firebaseのDataを使っているため、リアルタイムで削除することが可能になります。
なんとなく、わかりましたか?
ToDoActivity全体はこちら
11.AddActivity作成
さて、お次はToDoの項目を追加するためのActivityです!
AddActivityはそんなに重くないです。保存する部分が一番重要です。
public void save(View v) {
String title = titleEditText.getText().toString();
String context = contentEditText.getText().toString();
String key = reference.push().getKey();
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String uid = user.getUid();
// 引数のToDoDataの内容をデータベースに送る。
ToDoData toDoData = new ToDoData(key, title, context);
reference.child("users").child(uid).child(key).setValue(toDoData).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void v) {
finish();
}
});
}
この部分でコードを送信しています。
reference.child("users").child(uid).child(key).setValue(toDoData)
childがディレクトリ構造のような意味をしています。
URL的に見ると、
https://アプリ名.firebaseio.com/users/ユーザーid/送信時の乱数/ToDoの項目(タイトル等)
というような形になります。
AddActivity全体はこちら
12.ToDoData作成
もう少しです!頑張って!
次にデータの作成です。簡単にすると"型","テンプレート"といったところでしょうか。
public class ToDoData {
public String title;
public String context;
public String firebaseKey;
public ToDoData(String key, String title, String context) {
this.firebaseKey = key;
this.title = title;
this.context = context;
}
public ToDoData() {
}
public String getFirebaseKey() {
return firebaseKey;
}
public void setFirebaseKey(String firebaseKey) {
this.firebaseKey = firebaseKey;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContext() {
return context;
}
public void setContext(String context) {
this.context = context;
}
}
今回の項目はFirebaseKey、Title、Contentの3つなので、それに対応するgetter,setterを作ってあげるだけで問題なしです。
ToDoData全体はこちら
13.CustomAdapter作成
最後です!
CustomAdapterはArrayAdapterを継承して自作したクラスです。
public class CustomAdapter extends ArrayAdapter<ToDoData> {
//ArrayAdapter継承クラスはコンストラクタを設置することが義務付けられている。
private List<ToDoData> mCards;
public CustomAdapter(Context context, int layoutResourceId, List<ToDoData> toDoData) {
super(context, layoutResourceId, toDoData);
this.mCards = toDoData;
}
@Override
public int getCount() {
return mCards.size();
}
@Nullable
@Override
public ToDoData getItem(int position) {
return mCards.get(position);
}
@NonNull
@Override
public View getView(final int position, @Nullable View convertView, @NonNull final ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView != null) {
viewHolder = (ViewHolder) convertView.getTag();
} else {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.card_view, null);
viewHolder = new ViewHolder();
viewHolder.titleTextView = (TextView) convertView.findViewById(R.id.title_text_view);
viewHolder.contentTextView = (TextView) convertView.findViewById(R.id.content_text_view);
convertView.setTag(viewHolder);
}
ToDoData toDoData = mCards.get(position);
viewHolder.titleTextView.setText(toDoData.getTitle());
viewHolder.contentTextView.setText(toDoData.getContent());
return convertView;
}
public ToDoData getToDoDataKey(String key) {
for (ToDoData toDoData : mCards) {
if (toDoData.getFirebaseKey().equals(key)) {
return toDoData;
}
}
return null;
}
static class ViewHolder {
TextView titleTextView;
TextView contentTextView;
}
}
CustomAdapterのitemとなるcard_view.xmlのそれぞれのViewのインスタンスをまとめて管理するためのViewHolderクラスを新しく作ることが大切です。
今回はtitleとcontextを表示させるためのTextView2つをまとめて管理しています。ViewHolderのインスタンスを生成すれば2つのViewのインスタンスをlayoutファイルから生成することができます。
実際に起動してみよう
これで遂にアプリが完成です!
お疲れ様です
AndroidStudioにあるエミュレーターでも、お手持ちのAndroidスマートフォンでも起動することが可能です。
あとはUIですね。このままリリースまで持っていきます!
後々リリースしたデザインとかもおまけに追記します!
FirebaseAuthの他に使うことができる機能として、メールリンク、インスタ、Lineでのログインなどがあるので別な記事に書こうと思います!
完成リポジトリ
githubに公開しています。
https://github.com/yukiyuki961/ToDoApp
おわりに
なんとか記事を完成に持っていけました…。
なかなかQiitaなどに記事を上げる機会が無く、今回はチャレンジの意味を込めての参加でした(笑)
今までもFirebaseを利用してのアプリ開発はありましたが、今までは最初にPushするときのfirebaseのkeyを端末に保存して、そのディレクトリ下に項目を作っていました。
要するに1つの端末でしか閲覧ができなかったというわけです。
ある意味言い返すと同じキーで端末を動かしていたので、他のユーザーが投稿したのが見れるのでSNSの様な感じに捉えることも可能ですが…セキュリティに問題ありですね
今回、Firebase Authを利用したアプリケーションの開発をしました!
これによって端末間のリアルタイム同期ができるようになりました。
書く前より1歩技術力が成長した気分です
12月ですね。普通に寒くて毎日凍えてます笑
ToDoアプリは作って色々追加してみてもなかなか埋まらないものですね。
これを機に筋トレの時間増やすか!目指せ-5kg!
Life is Tech!の社員のまるちゃんに「なべ、太った?」と言われもしているので、本格的にやろうと思います笑
ここまで読んでいただきありがとうございました!
明日はDay14!
超イケメンメンターとしさんです!
Swiftの記事のようですね。
最近SwimeeでSwift触って勉強したいと思いました!楽しみです!
以上! Life is Tech! Androidメンターのなべでした!