Search code examples
androidfirebasefirebase-realtime-databasefirebaseui

Getting "Failed to bounce to type"


I am getting error while i build android chat app using firebase. When i send message then it's ok but after send the message i get error. Error look like as below.

04-17 15:21:54.242 12961-12961/learning.firebase.app.learningfirebase E/AndroidRuntime: FATAL EXCEPTION: main
    com.firebase.client.FirebaseException: Failed to bounce to type
        at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:183)
        at learning.firebase.app.learningfirebase.FirebaseListAdapter$1.onChildAdded(FirebaseListAdapter.java:63)
        at com.firebase.client.core.ChildEventRegistration.fireEvent(ChildEventRegistration.java:48)
        at com.firebase.client.core.view.DataEvent.fire(DataEvent.java:45)
        at com.firebase.client.core.view.EventRaiser$1.run(EventRaiser.java:38)
        at android.os.Handler.handleCallback(Handler.java:725)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:176)
        at android.app.ActivityThread.main(ActivityThread.java:5365)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
        at dalvik.system.NativeStart.main(Native Method)
     Caused by: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class learning.firebase.app.learningfirebase.Chat]: can not instantiate from JSON object (need to add/enable type information?)
     at [Source: java.io.StringReader@42285cd8; line: 1, column: 2]
        at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:984)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:276)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
        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:181)
            ... 13 more

My MainActivity.java

public class MainActivity extends ListActivity {
    private static final String FIREBASE_URL = "https://bohrachat.firebaseio.com/";

    private String mUsername;
    private Firebase mFirebaseRef;
    private ValueEventListener mConnectedListener;
    private ChatListAdapter mChatListAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setupUsername();

        setTitle("Chatting as " + mUsername);

        // Setup our Firebase mFirebaseRef
        mFirebaseRef = new Firebase(FIREBASE_URL).child("chat");

        // Setup our input methods. Enter key on the keyboard or pushing the send button
        EditText inputText = (EditText) findViewById(R.id.messageInput);
        inputText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
                if (actionId == EditorInfo.IME_NULL && keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
                    sendMessage();
                }
                return true;
            }
        });

        findViewById(R.id.sendButton).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendMessage();
            }
        });

    }
    @Override
    public void onStart() {
        super.onStart();
        // Setup our view and list adapter. Ensure it scrolls to the bottom as data changes
        final ListView listView = getListView();
        // Tell our list adapter that we only want 50 messages at a time
        mChatListAdapter = new ChatListAdapter(mFirebaseRef.limit(50), this, R.layout.chat_message, mUsername);
        listView.setAdapter(mChatListAdapter);
        mChatListAdapter.registerDataSetObserver(new DataSetObserver() {
            @Override
            public void onChanged() {
                super.onChanged();
                listView.setSelection(mChatListAdapter.getCount() - 1);
            }
        });

        // Finally, a little indication of connection status
        mConnectedListener = mFirebaseRef.getRoot().child(".info/connected").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                boolean connected = (Boolean) dataSnapshot.getValue();
                if (connected) {
                    Toast.makeText(MainActivity.this, "Connected to Firebase", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(MainActivity.this, "Disconnected from Firebase", Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onCancelled(FirebaseError firebaseError) {
                // No-op
            }
        });
    }

    @Override
    public void onStop() {
        super.onStop();
        mFirebaseRef.getRoot().child(".info/connected").removeEventListener(mConnectedListener);
        mChatListAdapter.cleanup();
    }

    private void setupUsername() {
        SharedPreferences prefs = getApplication().getSharedPreferences("ChatPrefs", 0);
        mUsername = prefs.getString("username", null);
        if (mUsername == null) {
            Random r = new Random();
            // Assign a random user name if we don't have one saved.
            mUsername = "JavaUser" + r.nextInt(100000);
            prefs.edit().putString("username", mUsername).commit();
        }
    }

    private void sendMessage() {
        EditText inputText = (EditText) findViewById(R.id.messageInput);
        String input = inputText.getText().toString();
        if (!input.equals("")) {
            // Create our 'model', a Chat object
            Chat chat = new Chat(input, mUsername,"Today : ");
            // Create a new, auto-generated child of that chat location, and save our chat data there
            mFirebaseRef.push().setValue(chat);
            inputText.setText("");

            Bundle b=new Bundle();
            b.putString("mUsername",mUsername);
            b.putString("mMessage",input);

            Intent intent = new Intent();
            intent.putExtras(b);
            intent.setAction("learning.firebase.app.learningfirebase.CUSTUM_INTENT");
            sendBroadcast(intent);

        }
    }

}


Chat.java


public class Chat {

    private String message;
    private String author;
    private String datetime;

    // Required default constructor for Firebase object mapping
    @SuppressWarnings("unused")

    Chat(String message, String author,String datetime) {
       this.message = message;
        this.author = author;
        this.datetime=datetime;
    }

    public String getMessage() {
        return message;
    }

    public String getAuthor() {
        return author;
    }

    public String getDatetime() {
        return datetime;
    }
}

ChatListAdapter.java

public class ChatListAdapter extends FirebaseListAdapter<Chat> {

    // The mUsername for this client. We use this to indicate which messages originated from this user
    private String mUsername;

    public ChatListAdapter(Query ref, Activity activity, int layout, String mUsername) {
        super(ref, Chat.class, layout, activity);
        this.mUsername = mUsername;
    }

    /**
     * Bind an instance of the <code>Chat</code> class to our view. This method is called by <code>FirebaseListAdapter</code>
     * when there is a data change, and we are given an instance of a View that corresponds to the layout that we passed
     * to the constructor, as well as a single <code>Chat</code> instance that represents the current data to bind.
     *
     * @param view A view instance corresponding to the layout we passed to the constructor.
     * @param chat An instance representing the current state of a chat message
     */
    @Override
    protected void populateView(View view, Chat chat) {
        // Map a Chat object to an entry in our listview
        String author = chat.getAuthor();
        TextView authorText = (TextView) view.findViewById(R.id.author);
        authorText.setText(author + ": ");
        // If the message was sent by this user, color it differently
        if (author != null && author.equals(mUsername)) {
            authorText.setTextColor(Color.RED);
        } else {
            authorText.setTextColor(Color.BLUE);
        }
        ((TextView) view.findViewById(R.id.message)).setText(chat.getMessage());
        ((TextView) view.findViewById(R.id.datetime)).setText(chat.getDatetime());
    }
}

My Firebase screenshot enter image description here

Please help me about this. I follow firebase github chat project. After I just add one value, means date time, I get this error.


Solution

  • tl;dr: make the Chat class static and add a parameterless/default constructor to it.

    Minimal code that works in a single file (Main.java):

    public class Main {
        public static class Chat {
            private String message;
            private String author;
            private String datetime;
    
            // Required default constructor for Firebase object mapping
            public Chat() {}
    
            public Chat(String message, String author, String datetime) {
                this.message = message;
                this.author = author;
                this.datetime = datetime;
            }
    
            public String getMessage() { return message; }    
            public String getAuthor() { return author; }    
            public String getDatetime() { return datetime; }    
        }    
    
        public static void main(String[] args) throws Exception {
            Firebase ref = new Firebase("https://stackoverflow.firebaseio.com/36675151/-KFaDuobfEA1FLslYZMM");
            ref.addListenerForSingleValueEvent(new ValueEventListener() {
                public void onDataChange(DataSnapshot dataSnapshot) {
                    System.out.println(dataSnapshot.getValue(Chat.class));
                }
    
                public void onCancelled(FirebaseError error) {
                }
            });
    
            Thread.sleep(10000);
        }
    }
    

    The JSON data:

    "-KFaDuobfEA1FLslYZMM": {
      "author": "user73181",
      "datetime": "today heyy",
      "message": "xjcjcj"
    }
    

    The things that are different from your code:

    • I removed everything that has nothing to do with the error message. For example this is a Java program, not an Android program. That simple change removes thousands of potential problems. But since your problem remained, it means that the problem is not related to Android. This sort of isolating the problem makes it a lot easier to find the cause. It's typically known as a minimal, complete/compilable verifiable example.
    • I included everything into a single file. Not only does this makes it easier to copy/paste, it also means interaction between files cannot be the cause. In this case, it did mean I had to make the Chat class static, which is likely one cause of your problem.
    • I had to add a parameterless/default constructor, which is what Kato pointed you to on [your previous question]. (Failed to bounce to type, Chat example error when adding another value,) and what I told you to add. This is likely the second cause of your problem.
    • I included the JSON as text, instead of as an image. This means that you can now copy/paste my JSON to see if your problem stems from that (it doesn't btw). You can easily get your JSON by clicking the Export button in your Firebase dashboard. Doing so saves me from having to type it.