Android Question B4A and firebase database.

fredo

Well-Known Member
Licensed User
Longtime User
... where can I find the strFirebaseSignedInUserToken?

Hi Daniel,

the value for strFirebaseSignedInUserToken will be automatically assigned by the Sub auth_TokenAvailable after the user has successfully signed in.

08-08-_2016_07-33-20.jpg
 
Upvote 0

Daniel-White

Active Member
Licensed User
Longtime User
I´ll capture the thread here to give a impression of the lib i wrapped so far... Basically it is working. Did not made much tests with it for sure...

As of now i dont know how - in b4a - i could work with the result given from the log.

Ok, here we go.

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim realtime As FirebaseDatabase
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    realtime.Initialize("Realtime")
    realtime.PersistenceEnabled = True
    realtime.goOnline

    Dim ref As DatabaseReference
    ref.Initialize("Reference",realtime.getReferencefromUrl("https://tactical-patrol-603.firebaseio.com/"))
    ref.addChildEventListener
    ref.addListenerForSingleValueEvent
    ref.addValueEventListener
etc  etc etc etc     ;)
End Sub

Please note that i created the database in the console with importing a json file to the database....

Attached you can find a json export from the firebase console...


Hi folks question for everybody, Thanks you DonManfred for this lib, I did a test, and surprise, when I changed a field in the DB in FB console and WoW the code in the Android detect the changed too. :eek: soooooooooooo nice really. Thanksssss for wrapped this lib.


I am rookie guy in database , only worked with sqlite, etc, but I noticed in the DonManfred lib we have this "ref.setValue" and I was playing with it, and create a new field in the Firebase DB with a new value an example ref.setValue("Rookie","yes"). and the originals fields disappears. only leave the new one field "Rookie, Yes"

I am not sure, but with this lib, can I update fields in the DB ? I am working with FirebaseStorage, and we don't have in the API of FirebaseStorage the dir *.* we cannot list the files in fireStorage (security measures of FireBase Storage :mad: LoL ), so I would like to upload each path an example "/Public/somehwere/hereIam.txt", in the DB of fireBase hence the others APPs or clients can access the DB and download the path and later the APP client will know where to download the files in firebase Storage.:cool:

The question is " with this lib, can I update fields in the DB o_O ? ":D
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
You are orking with a reference to the root-object.
If you write the value new you write the hole root object new. including all childs

I guess you need
- to look at the documentation and example-codes provided by Firebase.
- The way seems to be: get a ref to root, get a child reference (or child of child of child), set the new value fo the child.

i fact i´m not sure how this may work (as i wrote in post #1).

WE need to find out how it should work....

My hope is to get help from the community!

Have a look as the method Updatechilds. It wants a MAP with new values for the childs...

something like this i guess

B4X:
dim m as map
m.initialize
m.put("fieldname", value)
[,,]
ref.UpdateChilds(m)
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
look at the quick-start-android app source...

Here you find, for ex,

B4X:
package com.google.firebase.quickstart.database;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.quickstart.database.models.User;

public class SignInActivity extends BaseActivity implements View.OnClickListener {

    private static final String TAG = "SignInActivity";

    private DatabaseReference mDatabase;
    private FirebaseAuth mAuth;

    private EditText mEmailField;
    private EditText mPasswordField;
    private Button mSignInButton;
    private Button mSignUpButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sign_in);

        mDatabase = FirebaseDatabase.getInstance().getReference();
        mAuth = FirebaseAuth.getInstance();

        // Views
        mEmailField = (EditText) findViewById(R.id.field_email);
        mPasswordField = (EditText) findViewById(R.id.field_password);
        mSignInButton = (Button) findViewById(R.id.button_sign_in);
        mSignUpButton = (Button) findViewById(R.id.button_sign_up);

        // Click listeners
        mSignInButton.setOnClickListener(this);
        mSignUpButton.setOnClickListener(this);
    }

    @Override
    public void onStart() {
        super.onStart();

        // Check auth on Activity start
        if (mAuth.getCurrentUser() != null) {
            onAuthSuccess(mAuth.getCurrentUser());
        }
    }

    private void signIn() {
        Log.d(TAG, "signIn");
        if (!validateForm()) {
            return;
        }

        showProgressDialog();
        String email = mEmailField.getText().toString();
        String password = mPasswordField.getText().toString();

        mAuth.signInWithEmailAndPassword(email, password)
                .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        Log.d(TAG, "signIn:onComplete:" + task.isSuccessful());
                        hideProgressDialog();

                        if (task.isSuccessful()) {
                            onAuthSuccess(task.getResult().getUser());
                        } else {
                            Toast.makeText(SignInActivity.this, "Sign In Failed",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                });
    }

    private void signUp() {
        Log.d(TAG, "signUp");
        if (!validateForm()) {
            return;
        }

        showProgressDialog();
        String email = mEmailField.getText().toString();
        String password = mPasswordField.getText().toString();

        mAuth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        Log.d(TAG, "createUser:onComplete:" + task.isSuccessful());
                        hideProgressDialog();

                        if (task.isSuccessful()) {
                            onAuthSuccess(task.getResult().getUser());
                        } else {
                            Toast.makeText(SignInActivity.this, "Sign Up Failed",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                });
    }

    private void onAuthSuccess(FirebaseUser user) {
        String username = usernameFromEmail(user.getEmail());

        // Write new user
        writeNewUser(user.getUid(), username, user.getEmail());

        // Go to MainActivity
        startActivity(new Intent(SignInActivity.this, MainActivity.class));
        finish();
    }

    private String usernameFromEmail(String email) {
        if (email.contains("@")) {
            return email.split("@")[0];
        } else {
            return email;
        }
    }

    private boolean validateForm() {
        boolean result = true;
        if (TextUtils.isEmpty(mEmailField.getText().toString())) {
            mEmailField.setError("Required");
            result = false;
        } else {
            mEmailField.setError(null);
        }

        if (TextUtils.isEmpty(mPasswordField.getText().toString())) {
            mPasswordField.setError("Required");
            result = false;
        } else {
            mPasswordField.setError(null);
        }

        return result;
    }

    // [START basic_write]
    private void writeNewUser(String userId, String name, String email) {
        User user = new User(name, email);

        mDatabase.child("users").child(userId).setValue(user);
    }
    // [END basic_write]

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button_sign_in:
                signIn();
                break;
            case R.id.button_sign_up:
                signUp();
                break;
        }
    }
}

B4X:
  // [START basic_write]
    private void writeNewUser(String userId, String name, String email) {
        User user = new User(name, email);

        mDatabase.child("users").child(userId).setValue(user);
    }
    // [END basic_write]

this we need to do similar i guess...
 
Upvote 0

fredo

Well-Known Member
Licensed User
Longtime User
Some sources that helped me getting started with Firebase realtime database
  • For me an eyeopener was the Firebase blog: here
  • Firebase blog on denormalization: here
  • Structuring Data: here
  • Oldschool SQL translated to Firebase: here
  • Insights to NoSQL: here
  • A real good NoSQL read: here
To get a grip on the functionality as the creators intended I compiled the Quickstart Database App with Android Studio as described here.
It is a simple social app where users can post and comment posts.

Tags: #FIBAS #Firebase #Firebasedatabase #NoSQL
 
Last edited:
Upvote 0

fredo

Well-Known Member
Licensed User
Longtime User
A JAVA example from the Database Quickstart looked up in Android Studio:

08-08-_2016_19-33-19.jpg


B4X:
    private void writeNewPost(String userId, String username, String title, String body) {
        // Create new post at /user-posts/$userid/$postid and at
        // /posts/$postid simultaneously
        String key = mDatabase.child("posts").push().getKey();
        Post post = new Post(userId, username, title, body);
        Map<String, Object> postValues = post.toMap();

        Map<String, Object> childUpdates = new HashMap<>();
        childUpdates.put("/posts/" + key, postValues);
        childUpdates.put("/user-posts/" + userId + "/" + key, postValues);

        mDatabase.updateChildren(childUpdates);
    }

or

B4X:
private void postComment() {
        final String uid = getUid();
        FirebaseDatabase.getInstance().getReference().child("users").child(uid)
                .addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        // Get user information
                        User user = dataSnapshot.getValue(User.class);
                        String authorName = user.username;

                        // Create new comment object
                        String commentText = mCommentField.getText().toString();
                        Comment comment = new Comment(uid, authorName, commentText);

                        // Push the comment, it will appear in the list
                        mCommentsReference.push().setValue(comment);

                        // Clear the field
                        mCommentField.setText(null);
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });

I use these excerpts to build my testapp in B4A.

Since there is no converter JAVA-->B4A I translate it manually in Babysteps and tests.
 
Upvote 0

freedom2000

Well-Known Member
Licensed User
Longtime User
Firebase auth is needed to use the examples, since the authentication runs with access tokens.

If you already have a project with a Firebase setup than you easily import the following modules:
testfiba.bas
fibadbhelp.bas

and don't forget to set the needed variables in starter (e.g. "strFirebaseSignedInUserToken")​

As said above "If you recognize serious security problems or performance issues please let me know."

Hi, first of all, thank you for this code !

I am trying to test it...
I have successfully configured my test project, it compiles (with version 8) and run.
But I fail to initialize google auth

I have added this line of code in activity.create

B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("testfiba")
    Starter.auth.Initialize("Auth")
End Sub

But obviously it never initialize...
and I can't excecute these lines to sign in...

B4X:
Sub Button4_Click ' SIGN IN
Log("#-Button4_Click")  
    If Starter.auth.CurrentUser.IsInitialized Then
        Auth_SignedIn(Starter.auth.CurrentUser )
    End If
'  
End Sub

Please help me to find where I fail !
Thank you
 
Last edited:
Upvote 0

Daniel-White

Active Member
Licensed User
Longtime User
DonManfred and Fredo, guys you open my mind a lottttttttttt thanks you indeed, I have been thinking, I figure out my requirement in the post #42 now, I integrated FireBase Storage and FireBase Database.

Remember my problem, in post #42, I can upload the files to FireBase Storage, but how the APP client can download it? the APP client need to know the path to download. here is the code very simple.

B4X:
For x=0 To lista.Size-1
             Log("uploading to firebase="&lista.Get(x))
             Storage.UploadFile(File.DirRootExternal,"/DCIM/Camera/"&lista.Get(x),$"/Public/${Pais& DateTime.Date(DateTime.Now)&"/" &lista.Get(x)}"$)
             ref.Initialize("Reference",realtime.getReferencefromUrl("https://sorryITisAlittleSECRET.firebaseio.com/"& Pais&  DateTime.Date(DateTime.now)  &"/" & x   ))  
             ref.setValue(lista.Get(x),"I don't know")
        Next

about the ref.setValue(lista.Get(x),"I don't know") and the word "I don't know" really, I don't know, but it is working, that command, will put the number in front of the name of the archive. check the images.

I have this in my FireBase Storage

upload_2016-8-8_21-1-4.png


And in the fireBase Database this
upload_2016-8-8_21-2-24.png



So in theory, I can make an APP client with a calendar picker to show which days the firebase storage has photos, and when the user pick up a day go to read in the database the names of files and the route.
B4X:
    ref.Initialize("Reference",realtime.getReferencefromUrl("https://sorryITisAlittleSECRET.firebaseio.com"))
      

    ref.addChildEventListener
    ref.addListenerForSingleValueEvent
    ref.addValueEventListener
    Log("ref imagesizes = "&ref.Child("ve08"))

and return the Json
Value={ve08={08={2016 20:24:23=[20160806_230713.jpg, 20160806_230713.jpg, 20160806_230719.jpg], 2016 20:28:42=[20160806_230713.jpg, 20160806_230713.jpg, 20160806_230719.jpg], 2016 20:30:59=[20160806_230713.jpg, 20160806_230713.jpg, 20160806_230719.jpg]}}}


I will make the APP client, I think I have the route to put this to work.
 
Upvote 0

Daniel-White

Active Member
Licensed User
Longtime User
About how to put a value in a specific field of database, using the donManfred example,
you are rights guys, I only needed

ref.Initialize("Reference",realtime.getReferencefromUrl("https://TheBucket.firebaseio.com/imagesizes/0/ext")) '<---- noticed the /0/ext my target field to modify the value
ref.setValue(" This is the New value for field ext","")

Now the value in /0/ext will have "This is the New value for field ext"

I am in the same boat, trying to learn this, I don't know if my approach is correct :confused:, but it is working. if look to modify one field and replicate in other mobile APP clients.
 
Upvote 0

freedom2000

Well-Known Member
Licensed User
Longtime User
Is there an errormessage if you look in the filtered log?

No I have just checked the logs and there is no error message

this line is properly executed : Starter.auth.Initialize("Auth")

But this one gives "false" : If Starter.auth.CurrentUser.IsInitialized Then

I must do something wrong but where ?
I am running in debug mode

Thanks for your help anyway !
 
Upvote 0

freedom2000

Well-Known Member
Licensed User
Longtime User
Did you had a working test with Erels example here?

Do you have your "Auth" setup complete in the Firebase console?

Yes I have found where it fails !

this sub must be modified like this :

B4X:
Sub Button4_Click ' SIGN IN
Log("#-Button4_Click")   
    If Starter.auth.CurrentUser.IsInitialized Then
        Auth_SignedIn(Starter.auth.CurrentUser )
    Else
        Starter.auth.SignInWithGoogle
    End If
'   
End Sub

I will now check the interesting part : yours !
 
Upvote 0

Daniel-White

Active Member
Licensed User
Longtime User
No I have just checked the logs and there is no error message

this line is properly executed : Starter.auth.Initialize("Auth")

But this one gives "false" : If Starter.auth.CurrentUser.IsInitialized Then

I must do something wrong but where ?
I am running in debug mode

Thanks for your help anyway !
Hi Daniel,

the value for strFirebaseSignedInUserToken will be automatically assigned by the Sub auth_TokenAvailable after the user has successfully signed in.

View attachment 46754


Thanks Fredo, I only re-check in your code the auth, and I added the auth with google. and now the token is working :D, and your code work great. perhaps only I need to deploy in the activity testfiba the "auth.SignInWithGoogle" in the button of sign in.
Thanks for share your code. Now, I can upload data with your code and with the library of DonManfred do the same too, interesting. :D

B4X:
In Service starter  <-------

Sub Service_Create
    'This is the program entry point.
    'This is a good place to load resources that are not specific to a single activity.
        auth.Initialize("auth")
    If auth.CurrentUser.IsInitialized Then Auth_SignedIn(auth.CurrentUser)

End Sub

Sub Auth_SignedIn (User As FirebaseUser)
    Log("SignedIn: " & User.DisplayName)
'    lblName.Text = "Hello: " & User.DisplayName
End Sub

and in activity testfiba <----
Sub Button4_Click ' SIGN IN
Log("#-Button4_Click")   
    auth.SignInWithGoogle   'I only added  it:D
End Sub
 
Upvote 0

Daniel-White

Active Member
Licensed User
Longtime User
Yes I have found where it fails !

this sub must be modified like this :

B4X:
Sub Button4_Click ' SIGN IN
Log("#-Button4_Click")  
    If Starter.auth.CurrentUser.IsInitialized Then
        Auth_SignedIn(Starter.auth.CurrentUser )
    Else
        Starter.auth.SignInWithGoogle
    End If
'  
End Sub

I will now check the interesting part : yours !
LoL, we are in the same page in the concurrent time . I noticed too. mmm the firebase database synchronized our minds too lol
cheers
 
Upvote 0

fredo

Well-Known Member
Licensed User
Longtime User
...synchronized...
@Daniel-White and @freedom2000 be aware, the example from #28 uses the "REST api" and not the "Realtime lib".

The REST api ist helpful for the demonstrated PUT, GET and DELETE methods.
E.g. if you change data via PUT from one device the data is changed in the cloud, but the other devices are not aware of the change until you perform a GET and compare the local data.

To have the really flabbergasting feelings you have to use the Realtime lib from @DonManfred !!!
If you use the Realtime lib and write some data to a node from one device, all other online devices of that connection are updated locally in milliseconds. If some devices are offline they will be updated automatically if the device is online later.


Tags: #FIBAS #Firebase #Firebasedatabase #REST #Realtimedatabase
 
Last edited:
Upvote 0
Top