How to load chat history on top of recycler view android - android

Hi I am developing a chat application like whatsapp. I have to load the chat history from the api when user scrolls down like in whatsapp. I get the data and set it to the adapter. But the history is loading at the bottom of recycler view. I need to add it on top for every scroll. This is my code. Please help me. Thanks in advance.
if (Status.equals("1")) {
historyList = resp.getHistory();
Log.i("history size",String.valueOf(resp.getHistory().size()));
String historysize = String.valueOf(resp.getHistory().size());
Message message = new Message();
for (int i = 0; i < resp.getHistory().size(); i++) {
String fromusertoken = String.valueOf(resp.getHistory().get(i).getFromUserToken());
String txtmsg = resp.getHistory().get(i).getMessage();
String username = String.valueOf(resp.getHistory().get(i).getFromUserName());
if (fromusertoken.equals(user_token)) {
Message messages = new Message();
messages.setUser_token(fromusertoken);
messages.setUsername(username);
messages.setIsMine(true);
messages.setMessage(txtmsg);
messageAdapter.add(messages);
}
else {
Message messages = new Message();
messages.setUser_token(fromusertoken);
messages.setUsername(username);
messages.setIsMine(false);
messages.setMessage(txtmsg);
messageAdapter.add(messages);
}
}
messageAdapter.notifyDataSetChanged();
onItemsLoadComplete();
Toast.makeText(Single_chat.this, msg, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(Single_chat.this, msg, Toast.LENGTH_SHORT).show();
}
}
} else {
Toast.makeText(Single_chat.this, "No Response", Toast.LENGTH_SHORT).show();
}
}

There is a way to set the item on top by editing the adapter class not the activity. We have to add the item list like messagelist.add(0,message). Now only i found. For your regular chat you have to add as normal like messagelist.add(message). This will add the item at bottom. Hope this will be useful for others.
public void add(Message message) {
messageList.add(message);
notifyItemInserted(messageList.size() - 1);
}
public void add(int i,Message message) {
messageList.add(0,message);
notifyItemInserted(messageList.size() - 1);
}

I changed the list in adapter as messagelist.add(0,message). It worked.
public void add(Message message) {
messageList.add(0,message);
notifyItemInserted(messageList.size() - 1);
}

you can insert the history message at the index 0
messageAdapter.add(0,messages);
every iteration it will replace the first message by the last inserted message.

chatHistoyList.add(adapter.getCurrentChatList());
adapter.setData(chatHistoryList);
adapter.notifyDataSetChanged();
//This method has to be in adapter
public List<Chat> getCurrentChatList() {
return currentChatList;
}

Related

How to clear/delete/remove my RecyclerView in Android?

When I search for a user in my database, it populates the RecyclerView, but when I make another search, and it can't find the user, I want it to also remove the RecyclerView content, but the old users content stays in the RecyclerView until I search for an existing user, then it changes to the new users content.
#OnClick(R.id.btn_search_user)
public void onSearchBtnClicked(View view) {
Log.e(LOG_TAG, "Search button clicked");
if (!TextUtils.isEmpty(etSearchUser.getText())) {
userNameSearch = etSearchUser.getText().toString();
if (!isNetworkAvailable()) {
Toast.makeText(this, "No internet, searching offline", Toast.LENGTH_SHORT).show();
mOwner = Owner.getByUsername(userNameSearch);
if(mOwner != null) {
searchUserByUserName(userNameSearch);
} else {
// I want the RecyclerView to be empty at this point.
tvGitHubUser.setText("was not found offline");
}
} else {
loadRepository(userNameSearch);
Log.e(LOG_TAG, "Owner is empty, searching online");
}
}
}
initRecycleView()
mGithubRecyclerView = (RecyclerView) findViewById(R.id.github_repository_recyclerview);
RecyclerView.LayoutManager mGithubLayoutManager = new LinearLayoutManager(getApplicationContext());
mGithubRecyclerView.setLayoutManager(mGithubLayoutManager);
mGithubRecyclerView.setHasFixedSize(true);
Simply, call recyclerView.setAdapter(null);
If you can show me your adapter code, I can provide better method.

How to perform Other app list item click using accessibility service like Voice Access app?

I am developing an application like VoiceAccess app. Using accessibility service I am able to perform all clicks which are on top activity(3rd party applications). But I am facing issue with ListItem clicks. I am trying this code for FaceBook app. below is my code. Can any one help me on this.
public class MyService extends AccessibilityService {
/**/
private SharedPreferences S_PREF;
private SharedPreferences.Editor editor;
private static final String TAG = MyService.class
.getSimpleName();
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
clickPerform(getRootInActiveWindow(), 0);
}
public void clickPerform(AccessibilityNodeInfo nodeInfo, final int depth) {
if (nodeInfo == null) return;
List<AccessibilityNodeInfo> list = nodeInfo
.findAccessibilityNodeInfosByViewId("com.facebook.katana:id/bookmarks_tab");
for (AccessibilityNodeInfo node : list) {
Log.i(TAG, "ViewID-: bookmarks_tab " + node.getChild(0));
if (S_PREF.getBoolean("fb_menu", false)) {
editor.putBoolean("fb_menu", false);
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
List<AccessibilityNodeInfo> list2 = nodeInfo
.findAccessibilityNodeInfosByViewId("com.facebook.katana:id/bookmarks_list");
for (AccessibilityNodeInfo node2 : list2) {
if (node2.getChild(0) != null)
if (S_PREF.getBoolean("fb_scroll_down", false)) {
editor.putBoolean("fb_scroll_down", false);
node2.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
}
}
editor.commit();
for (int i = 0; i < nodeInfo.getChildCount(); ++i) {
clickPerform(nodeInfo.getChild(i), depth+1);
}
}
#Override
public void onInterrupt() {
}
protected void onServiceConnected() {
S_PREF = getSharedPreferences("S_PREF", Context.MODE_PRIVATE);
editor = S_PREF.edit();
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.flags = AccessibilityServiceInfo.DEFAULT;
info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
setServiceInfo(info);
Toast.makeText(getApplicationContext(), "onServiceConnected", Toast.LENGTH_SHORT).show();
}
}
Below is the VoiceAccess screen.
When user says any number, then particular item click will be performed.
I am able to get 7,8,9,10 events but from 11 onwards I am not getting list items individually. My code returning listview id only.
Thanks in advance....
#steveenzoleko
I got solution for this problem by myself. Here
AccessibilityNodeInfo always doesn't return complete list or list size. It returns VIEWs. It may be TextView, Button etc... Every View has multiple methods like getText(), getContentDescription(), getClassName(), getChildCount(), getViewIdResourceName() etc... here Voice Access app detecting all views and giving them some numbers. For lists, using getChildCount() method in for loop we can getChildViews/listItems. Ex:
AccessibilityNodeInfo node = getRootInActiveWindow();
if(node != null) {
for(int i = 0; i < node.getChildCount(); i++){
AccessibilityNodeInfo childNode = node.getChild(i);
if(childNode != null){
Log.i("childNode", "-----getText->"+childNode.getText()+"---getContentDescription-->"+childNode.getContentDescription() );
}
}
}
use getText() and getContentDescription() methods to know text of textview, button, checkbox.
getClassName() method retuns the view type like TextView, Button, ImageView, CheckBox etc...
Maybe you can use dispatchGesture from AccessibilityService API 7.0.

Using popBackStack() in Android does not update android-listview with Firebase data

At the beginning of the chat app user see a list off groups (listview group) available and the user have the possibility to create a new group or click on some off the available groups and then start to write messages (listview messages). The functions CreateNewMessage and CreateNewGroup pushes information to firebase correctly
Above scenarios works finne problems arise when user navigates backwards (popBackStack()) from listview with messages to GroupFragment, here should user be presented a list off available groups but the listview is empty. The ReadGroupData() function is not reading the already created groups from firebase and inserts them in the group listview. How to make this happen?
GroupFragment:
public void ReadGroupData() {
Firebase firebaserootRef = new Firebase("https://000.firebaseio.com");
firebaserootRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot snapshot, String s) {
if (snapshot.getValue() != null) {
Group newGroup = new Group((String)snapshot.child("name").getValue(),
(String) snapshot.child("id").getValue());
if(!groupKeyValues.contains(newGroup.GetId())) {
groupKeyValues.add(newGroup.GetId());
AddToLstViewGroup(newGroup);
System.out.println("Read group data from firebase and
inserted in listView");
}
}
}
});
}
public void AddToLstViewGroup(Group newGroup) {
groupNameList.add(newGroup);
if(groupAdapter == null) {
groupAdapter = new GroupAdapter(getActivity(), groupNameList);
}
if (lstViewGroup == null) {
lstViewGroup = (ListView) getView().
findViewById(R.id.listView_group);
}
lstViewGroup.setOnItemClickListener(onItemClickListener);
lstViewGroup.setOnItemLongClickListener(onItemLongClickListener);
groupAdapter.notifyDataSetChanged();
lstViewGroup.setAdapter(groupAdapter);
}
ChatFragment:
public void ReadChatMessages(Firebase firebaseRootRef) {
firebaseRootRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot snapshot, String s) {
if (snapshot.child(GetGroupId()).child("messages").
getChildren() != null) {
for (DataSnapshot c :
snapshot.child(GetGroupId()).child("messages").getChildren()) {
String key = c.getKey();
Message newMessage = new Message();
newMessage.SetFrom((String) c.child("from").getValue());
newMessage.SetMsg((String)
c.child("message").getValue());
newMessage.SetTime((String) c.child("time").getValue());
newMessage.SetId((String) c.child("id").getValue());
if ((!msgKeyValues.contains(key)) ||
newMessage.GetFrom() != "") {
msgKeyValues.add(key);
AddToLstViewChat(newMessage);
//Automatic scrolls to last line in listView.
lstViewChat.setSelection(chatAdapter.getCount() -1);
}
}
}
}
public void AddToLstViewChat(Message newMessage) {
chatMsgList.add(newMessage);
if (chatAdapter == null) {
chatAdapter = new ChatAdapter(getActivity(), chatMsgList);
}
if(IsMsgFromMe(newMessage)) {
lstViewChat = (ListView)
getView().findViewById(R.id.listView_chat_message_me);
} else {
lstViewChat =
(ListView)getView().findViewById(R.id.listView_chat_message_others);
}
chatAdapter.notifyDataSetChanged();
lstViewChat.setAdapter(chatAdapter);
}
ChatActivity:
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
finish();
}
}
For all the code click on the link: "http://pastebin.com/97nR68Rm"
SOLUTION!
Kato thank you for you patience and help. I have now found a solution for the problem. I'm calling ReadGroupData() and ReadChatMessages() at the end (before return) in my onCreateView methods. As Kato pointed out onCreate() is not getting called on popBackStack()
In my AddToLStViewGroup the if statement for lstViewGroup is deleted so now it always sets the listView otherwise it will throw an exception for not finding the correct view, To clarifying:
Deleted this line:
if (lstViewGroup == null) {
lstViewGroup = (ListView)getView().findViewById(R.id.listView_group);
}
And replaced with:
ListView lstViewGroup=(ListView)getView().findViewById(R.id.listView_group);
Kato thank you for you patience and help. I have now found a solution for the problem. I'm calling ReadGroupData() and ReadChatMessages() at the end (before return) in my onCreateView methods. As Kato pointed out onCreate() is not getting called on popBackStack()
In my AddToLStViewGroup the if statement for listViewGroup is deleted so now it always sets the listView otherwise it will throw an exception for not finding the correct view.
To clarify:
I deleted this line:
if (lstViewGroup == null) {
lstViewGroup = (ListView)getView().findViewById(R.id.listView_group);
}
And replaced it with:
ListView lstViewGroup =(ListView)getView().findViewById(R.id.listView_group);
(The original asker posted the answer as part of the question. I'm copying it here as a matter of housekeeping.)

Trying to get an Android jabber app to check for a string in new messages and return a toast message

I have been able to create the if statement that checks for the string and it returns the toast message that i created but it keeps showing the toast message every time i open the chat. even if the most recent message doesn't contain the string I am looking for so i am assume it isn't checking to see if it is the last message received and it doesn't check to see if it is unread. the code is below. the reason i am trying to do this is because my parents share a facebook account and i want an easy way to display if the message is signed mom or dad. the code below only has the check for mom once it works i will be adding the check for dad signature. I am using the open source message client Xabber. Thank you for help.
public void setVisibleChat(String account, String user) {
final boolean remove = !AccountManager.getInstance()
.getArchiveMode(account).saveLocally();
AbstractChat chat = getChat(account, user);
if (chat == null)
chat = createChat(account, user);
else {
// Mark messages as read and them delete from db if necessary.
final ArrayList<MessageItem> messageItems = new ArrayList<MessageItem>();
for (MessageItem messageItem : chat.getMessages()) {
if (!messageItem.isRead()) {
messageItem.markAsRead();
messageItems.add(messageItem);
}
if (chat.getLastText().contains("Mom") && (!messageItem.isRead()));{
Toast.makeText(Application.getInstance(), "Message from Mom!", Toast.LENGTH_SHORT).show();
}
}
Application.getInstance().runInBackground(new Runnable() {
#Override
public void run() {
Collection<Long> ids = getMessageIds(messageItems, remove);
if (remove)
MessageTable.getInstance().removeMessages(ids);
else
MessageTable.getInstance().markAsRead(ids);
}
});
}
visibleChat = chat;
}
You've got an extra semi-colon here
if (chat.getLastText().contains("Mom") && (!messageItem.isRead())); <------
So your next block of code containing the Toast show statement will always be executed.
Remove the semi-colon

why show always last value of arraylist in listview?

I have start a timer which call getMessage webservice which return comming message for that user arraylist size always show right number of messages but when show in list view of that message show only last message send give by web service I have use this code.
public void handleMessage(Message msg)
{
super.handleMessage(msg);
if(msg.arg1!=RECIEVEFAILURE)
{
objrReceiveMessageSiteList =(ArrayList<ReceiveMessageSiteList>)msg.obj;
System.out.println("objrReceiveMessageSiteList.get(0)"+objrReceiveMessageSiteList.get(0).getMessageStatus());
System.out.println("objrReceiveMessageSiteList.get(0)"+objrReceiveMessageSiteList.size());
if(objrReceiveMessageSiteList.size()!=0 && !objrReceiveMessageSiteList.get(0).getMessageStatus().equalsIgnoreCase("No New Message"))
{
for(int i=0;i<objrReceiveMessageSiteList.size();i++)
{
objkeyvaluepair.setMessage(objrReceiveMessageSiteList.get(i).getMessage());
objkeyvaluepair.setMessageType(objrReceiveMessageSiteList.get(i).getMessageType());
objkeyvaluepair.setTimeStamp(objrReceiveMessageSiteList.get(i).getTimeStamp());
objkeyvaluepair.setSenderFirstName(objrReceiveMessageSiteList.get(i).getSenderFirstName());
objkeyvaluepair.setSenderId(objrReceiveMessageSiteList.get(i).getSenderId());
objkeyvaluepair.setRecieverFirstName(objrReceiveMessageSiteList.get(i).getReceiverFirstName());
messagerecord.add(objkeyvaluepair);
System.out.println("MESSAGE SIZE"+messagerecord.size());
System.out.println("MESSAGE---------- findeee"+messagerecord.get(i).getMessage());
}
System.out.println("objrReceiveMessageSiteList.get(0)--------------"+objrReceiveMessageSiteList.get(0).getMessageStatus());
message.setText(""+messagerecord.size());
}
}
}
};
inside this for loop arraylist is showing right message in syste.out.println.but when sending in adapter set adapter take right size but show only last message in all list view.please help me
You are adding the same object (objkeyvaluepair) to the ArrayList each iteration through the nested for loops.
In the inner-most for loop, you should be creating a new objkeyvaluepair object and then add this new object to the ArrayList.
change this method to the following:
public void handleMessage(Message msg)
{
super.handleMessage(msg);
if(msg.arg1!=RECIEVEFAILURE)
{
objrReceiveMessageSiteList =(ArrayList<ReceiveMessageSiteList>)msg.obj;
System.out.println("objrReceiveMessageSiteList.get(0)"+objrReceiveMessageSiteList.get(0).getMessageStatus());
System.out.println("objrReceiveMessageSiteList.get(0)"+objrReceiveMessageSiteList.size());
if(objrReceiveMessageSiteList.size()!=0 && !objrReceiveMessageSiteList.get(0).getMessageStatus().equalsIgnoreCase("No New Message"))
{
for(int i=0;i<objrReceiveMessageSiteList.size();i++)
{
//Create Local object of the Objkeyvaluepair here, for example
//ObjectKeyValuePair objkeyvaluePair=new OjectKeyvaluePair();
objkeyvaluepair.setMessage(objrReceiveMessageSiteList.get(i).getMessage());
objkeyvaluepair.setMessageType(objrReceiveMessageSiteList.get(i).getMessageType());
objkeyvaluepair.setTimeStamp(objrReceiveMessageSiteList.get(i).getTimeStamp());
objkeyvaluepair.setSenderFirstName(objrReceiveMessageSiteList.get(i).getSenderFirstName());
objkeyvaluepair.setSenderId(objrReceiveMessageSiteList.get(i).getSenderId());
objkeyvaluepair.setRecieverFirstName(objrReceiveMessageSiteList.get(i).getReceiverFirstName());
messagerecord.add(objkeyvaluepair);
System.out.println("MESSAGE SIZE"+messagerecord.size());
System.out.println("MESSAGE---------- findeee"+messagerecord.get(i).getMessage());
}
System.out.println("objrReceiveMessageSiteList.get(0)--------------"+objrReceiveMessageSiteList.get(0).getMessageStatus());
message.setText(""+messagerecord.size());
}
}
}
};

Categories

Resources