3

I'm just learning how to set up Firebase data in Android. I am able to write to the db, but I am unable to read it and display it back on my app. My app is very simple (It just has one main screen for now) and I don't care how the data is displayed on the page as I am just learning - I'm trying to display it in a text view for now.

Here is my Main Activity java:

package com.example.ispotrachel.myapplication;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;

import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.ValueEventListener;

import java.util.HashMap;
import java.util.Map;


public class MainActivity extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Firebase.setAndroidContext(this);

    Firebase ref = new Firebase("https://blistering-torch-9015.firebaseio.com");

    class User {
        private int birthYear;
        private String fullName;

        public User() {
        }

        public User(String fullName, int birthYear) {
            this.fullName = fullName;
            this.birthYear = birthYear;
        }

        public long getBirthYear() {
            return birthYear;
        }

        public String getFullName() {
            return fullName;
        }
    }

     User user1 = new User("Name 1", 1982);
     User user2 = new User("Name 2", 1972);

     Firebase usersRef = ref.child("users");

     Map<String, User> users = new HashMap<String, User>();
     users.put("user1", user1);
     users.put("user 2", user2);

    usersRef.setValue(users);

    Firebase postRef = ref.child("posts");

    Map<String, String> post1 = new HashMap<String, String>();
    post1.put("author", "user1");
    post1.put("title", "Announcing COBOL, a New Programming Language");
    postRef.push().setValue(post1);

    Map<String, String> post2 = new HashMap<String, String>();
    post2.put("author", "user2");
    post2.put("title", "The Turing Machine");
    postRef.push().setValue(post2);
    ref.addValueEventListener(new ValueEventListener() {


    @Override
    public void onDataChange(DataSnapshot arg0) {
            //System.out.println(arg0.getValue());
            TextView textViewSample = (TextView) findViewById(R.id.sampleTextView);
            textViewSample.setText(arg0.getValue(String.class));
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {
            System.out.println("the read failed");
        }

    });
}}

Here is my activity_main.xml:

<LinearLayout 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"           android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">


<TextView
    android:id="@+id/sampleTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world"/>


</LinearLayout>

When I run the app, it crashes. Here is the logcat error message:

12-27 12:15:02.678    1895-1895/com.example.ispotrachel.myapplication I/art﹕ Not late     enabling -Xcheck:jni (already on)
12-27 12:15:02.946    1895-1907/com.example.ispotrachel.myapplication I/art﹕ Background     sticky concurrent mark sweep GC freed 3867(286KB) AllocSpace objects, 0(0B) LOS objects, 11% free, 1009KB/1135KB, paused 2.595ms total 117.910ms
12-27 12:15:03.317    1895-1926/com.example.ispotrachel.myapplication D/OpenGLRenderer﹕ Render dirty regions requested: true
12-27 12:15:03.320    1895-1895/com.example.ispotrachel.myapplication D/﹕ HostConnection::get() New Host Connection established 0xa6667e80, tid 1895
12-27 12:15:03.327    1895-1895/com.example.ispotrachel.myapplication D/Atlas﹕ Validating map...
12-27 12:15:03.391    1895-1926/com.example.ispotrachel.myapplication D/﹕ HostConnection::get() New Host Connection established 0xa66ef3b0, tid 1926
12-27 12:15:03.405    1895-1926/com.example.ispotrachel.myapplication I/OpenGLRenderer﹕ Initialized EGL, version 1.4
12-27 12:15:03.422    1895-1926/com.example.ispotrachel.myapplication D/OpenGLRenderer﹕ Enabling debug mode 0
12-27 12:15:03.439    1895-1926/com.example.ispotrachel.myapplication W/EGL_emulation﹕ eglSurfaceAttrib not implemented
12-27 12:15:03.439    1895-1926/com.example.ispotrachel.myapplication W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xa66b7880, error=EGL_SUCCESS
12-27 12:15:07.474    1895-1926/com.example.ispotrachel.myapplication W/EGL_emulation﹕ eglSurfaceAttrib not implemented
12-27 12:15:07.474    1895-1926/com.example.ispotrachel.myapplication W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xa66b7880, error=EGL_SUCCESS
12-27 12:15:13.993    1895-1895/com.example.ispotrachel.myapplication D/AndroidRuntime﹕    Shutting down VM 

--------- beginning of crash
12-27 12:15:13.993    1895-1895/com.example.ispotrachel.myapplication E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.ispotrachel.myapplication, PID: 1895 com.firebase.client.FirebaseException: Failed to bounce to type 
        at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:196)
        at com.example.ispotrachel.myapplication.MainActivity$1.onDataChange(MainActivity.java:79) 
        at com.firebase.client.core.ValueEventRegistration$1.run(ValueEventRegistration.java:48)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

 Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
        at [Source: java.io.StringReader@c8f7297; line: 1, column: 1]
        at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:575)
        at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:46)
        at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:11)
        at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
        at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:192)
        at com.example.ispotrachel.myapplication.MainActivity$1.onDataChange(MainActivity.java:79)
        at com.firebase.client.core.ValueEventRegistration$1.run(ValueEventRegistration.java:48)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)device not found
5
  • What happens instead of working? (E.g., error messages.) Commented Dec 27, 2014 at 0:32
  • @ispotrachel: please add that stack trace to your question, by clicking the edit link under it. That will also allow you to format them into something more readable. Commented Dec 27, 2014 at 14:18
  • All, @FrankvanPuffelen, I updated my question with the error message. Thank you!! Commented Dec 27, 2014 at 18:30
  • 1
    If you put a breakpoint on the line that crashes, I suspect that you will find that arg0.getValue() returns a Map<String, String>. If that is the case, you can get the title of the post with something like ((Map<String,String)arg0.getValue()).get("title"). Have a look at the example here: firebase.com/docs/android/guide/… Commented Dec 27, 2014 at 21:02
  • Hi @FrankvanPuffelen. When I follow the tutorial, I'm able to do a system.out.print. The issue comes to when I try to print the data in a list or text box in the app. Commented Dec 27, 2014 at 22:07

2 Answers 2

2

tl;dr

It looks like you're trying to load a JSON object into a String.

The error message Failed to bounce to type indicates that the Firebase client got back some data, but is unable to convert it into the type you specified.

Details about the problem

You're adding a ValueEventListener to the root of your Firebase here:

ref.addValueEventListener(new ValueEventListener() { ...

In that value event listener you're telling Firebase to load the whole Firebase as a String:

textViewSample.setText(arg0.getValue(String.class));

And this would work fine if you had a very simple Firebase that only contained a single string. However, based on the rest of your code, it looks like your Firebase has a lot more than one String in it :)

How to fix it You have a couple of options:

  1. Attach your event listener further down the tree. You could get user's full name as a string:

    ref.child("users/user1/fullName").addValueEventListener(new ValueEventListener() {
    
        @Override
        public void onDataChange(DataSnapshot arg0) {
            TextView textViewSample = (TextView) findViewById(R.id.sampleTextView);
            textViewSample.setText(arg0.getValue(String.class));
        }
        ...
    }
    
  2. Or, you can get a whole user, but parse it as a User instead of a String:

    ref.child("users/user1/fullName").addValueEventListener(new ValueEventListener() {
    
        @Override
        public void onDataChange(DataSnapshot arg0) {
            User tempUser = arg0.getValue(User.class);
            TextView textViewSample = (TextView) findViewById(R.id.sampleTextView);
            textViewSample.setText(tempUser.getFullName());
        }
        ...
    }
    
Sign up to request clarification or add additional context in comments.

Comments

0

I have the similar problem.

This is the code how I retrieve data from firebase:

    DatabaseReference chatRef = database.getReference("chats");
    chatRef.keepSynced(true);
    Query queryRef = chatRef.orderByChild("id");

    queryRef.addChildEventListener(new ChildEventListener() {
        // Retrieve new posts as they are added to the database
        @Override
        public void onChildAdded(DataSnapshot snapshot, String previousChildKey) {
            ChatPost newPost = snapshot.getValue(ChatPost.class);
            ChatPost topic = new ChatPost(newPost.id, newPost.topic);
            addChatTopic(topic);
            System.out.println("NEW Child Topic: " + newPost.topic);

            chatAdapter.addItem(newPost);
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {
            ChatPost newPost = dataSnapshot.getValue(ChatPost.class);
            ChatPost topic = new ChatPost(newPost.id, newPost.topic);
            addChatTopic(topic);
            System.out.println("CHANGED Child Topic: " + newPost.topic);

            chatAdapter.updateItem(newPost);
        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {
            ChatPost newPost = dataSnapshot.getValue(ChatPost.class);
            ChatPost topic = new ChatPost(newPost.id, newPost.topic);
            chatTopicsList.add(topic);
            System.out.println("REMOVED Child Topic: " + newPost.topic);

            chatAdapter.removeItem(newPost);
        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

It worked until I didn't use push() for add a new item. My data in firebase console looks like here.

The text of exception:

07-05 16:45:07.097 29997-29997/com.skl.bingofire E/AndroidRuntime: FATAL EXCEPTION: main Process: com.skl.bingofire, PID: 29997 com.google.firebase.database.DatabaseException: Expected a List while deserializing, but got a class java.util.HashMap at com.google.android.gms.internal.zzaix.zza(Unknown Source) at com.google.android.gms.internal.zzaix.zza(Unknown Source) at com.google.android.gms.internal.zzaix.zzb(Unknown Source) at com.google.android.gms.internal.zzaix$zza.zze(Unknown Source) at com.google.android.gms.internal.zzaix$zza.zzaC(Unknown Source) at com.google.android.gms.internal.zzaix.zzd(Unknown Source) at com.google.android.gms.internal.zzaix.zzb(Unknown Source) at com.google.android.gms.internal.zzaix.zza(Unknown Source) at com.google.firebase.database.DataSnapshot.getValue(Unknown Source) at com.skl.bingofire.activities.MainActivity$7.onChildAdded(MainActivity.java:228) at com.google.android.gms.internal.zzaer.zza(Unknown Source) at com.google.android.gms.internal.zzagp.zzSu(Unknown Source) at com.google.android.gms.internal.zzags$1.run(Unknown Source) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 07-05 16:45:16.924 29997-30029/com.skl.bingofire E/DynamiteModule: Failed to load module descriptor class: Didn't find class "com.google.android.gms.dynamite.descriptors.com.google.firebase.auth.ModuleDescriptor" on path: DexPathList[[zip file "/data/app/com.skl.bingofire-1/base.apk"],nativeLibraryDirectories=[/data/app/com.skl.bingofire-1/lib/arm, /vendor/lib, /system/lib]]

I used this model:

class ChatPost {
    public String id;
    public String topic;
    public String color;
    public ArrayList<Message> messages;
}

I figured out and I found that if list of data contains key for example "-KLdskjdkjkjdjksjdksjdjsdjsjk" firebase recognise the hole list as "HashMap" else as "ArrayList". I changed my model to this structure:

class ChatPost {
    public String id;
    public String topic;
    public String color;
    public HashMap<String, Message> messages;
}

And added to the rest of chats message with key like "-KLdskjdkjkjdjksjdksjdjsdjsjk". And my code now is working. But I think it is not obvious.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.