I am new to android development.I have a recyclerview with Viewholder for displaying photo.I have implement like feature in my app but only problem that I am facing is when I add a like on the photo the like does not show on photo I liked instead it is showing like on another photo that is down below,when I see in firebase database it looks fine but it does not display in the right position in recycler view.
I think it is not updating position how can I solve this?
this is my adapter class
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, final int position) {
// mHolder = holder;
photo = moviesList.get(position);
// final VideoHolder viewHolder2 = (VideoHolder)holder;
int viewType = getItemViewType(holder.getAdapterPosition());
switch ( viewType ) {
case IMAGE_TYPE:
PhotoHolder photoview = (PhotoHolder) holder;
mPhotoHolder = photoview;
getCurrentUsername();
getLikesPhotoString();
final ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(getItem(position).getImage_path(),photoview.image);
photoview.mHeart.setOnLikeListener(new OnLikeListener() {
#Override
public void liked(LikeButton likeButton) {
addNewPhotolike(mPhotoHolder);
}
#Override
public void unLiked(LikeButton likeButton) {
removePhotolike(mPhotoHolder);
}
});
photoview.Star.setOnLikeListener(new OnLikeListener() {
#Override
public void liked(LikeButton likeButton) {
}
#Override
public void unLiked(LikeButton likeButton) {
}
});
break;
case VIDEO_TYPE:
final VideoHolder viewHolder2 = (VideoHolder)holder;
mVideoHolder = viewHolder2;
break;
}
}
#Override
public int getItemCount() {
return moviesList.size();
}
public Photo getItem(int position) {
return moviesList.get(position);
}
#Override
public int getItemViewType ( int position ) {
int viewType;
if (moviesList.get(position).getType_post().contains("Photo")) {
viewType = IMAGE_TYPE;
} else{
viewType = VIDEO_TYPE;
}
return viewType;
}
this is were photo like is added to firebase
private void addNewPhotolike(TestAdapter.PhotoHolder holder, final int position){
Log.d(TAG, "addNewlike: adding new like ");
String newLikeID = mReference.push().getKey();
Likes likes = new Likes();
likes.setUser_id(FirebaseAuth.getInstance().getCurrentUser().getUid());
mReference.child(mContext.getString(R.string.dbname_photos))
.child(getItem(position).getPhoto_id())
.child(mContext.getString(R.string.field_likes))
.child(newLikeID)
.setValue(likes);
mReference.child(mContext.getString(R.string.dbname_user_photos))
.child(getItem(position).getUser_id())
.child(getItem(position).getPhoto_id())
.child(mContext.getString(R.string.field_likes))
.child(newLikeID)
.setValue(likes);
holder.mHeartPhoto.setLiked(true);
HashMap<String ,String> notificationData = new HashMap<>();
notificationData.put("from",FirebaseAuth.getInstance().getCurrentUser().getUid());
notificationData.put("type","likes");
notificationData.put("photo_desc",getItem(position).getDescription());
holder.mNotification.child(getItem(position).getUser_id()).push().setValue(notificationData).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
// getLikesString(mHolder);
getLikesPhotoString(mPhotoHolder,position);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// getLikesString(mHolder);
getLikesPhotoString(mPhotoHolder,position);
}
});
}
This is my code where like is retrieved from firebase and shown in text.
private void getLikesPhotoString(final TestAdapter.PhotoHolder holder, final int postion){
Log.d(TAG, "getLikesString: getting likes string");
try{
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
reference.keepSynced(true);
Query query = reference
.child(mContext.getString(R.string.dbname_photos))
.child(getItem(postion).getPhoto_id())
.child(mContext.getString(R.string.field_likes));
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
holder.usersPhoto = new StringBuilder();
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference
.child(mContext.getString(R.string.dbname_users))
.orderByChild(mContext.getString(R.string.field_user_id))
.equalTo(singleSnapshot.getValue(Likes.class).getUser_id());
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
Log.d(TAG, "onDataChange: found like: " +
singleSnapshot.getValue(User.class).getUsername());
holder.usersPhoto.append(singleSnapshot.getValue(User.class).getUsername());
holder.usersPhoto.append(",");
}
String[] splitUsers = holder.usersPhoto.toString().split(",");
if( holder.usersPhoto.toString().contains(currentUsername + ",")){
holder.likephotobycurrentUser = true;
}else{
holder.likephotobycurrentUser = false;
}
Log.d(TAG, "onDataChange: likes string: " + holder.mLIkePhotoString);
// setupwidjets();
int length = splitUsers.length;
if(length == 1){
holder.mLIkePhotoString = "Liked by " + splitUsers[0];
}
else if(length == 2){
holder.mLIkePhotoString = "Liked by " + splitUsers[0]
+ " and " + splitUsers[1];
}
else if(length == 3){
holder.mLIkePhotoString = "Liked by " + splitUsers[0]
+ ", " + splitUsers[1]
+ " and " + splitUsers[2];
}
else if(length == 4){
holder.mLIkePhotoString = "Liked by " + splitUsers[0]
+ ", " + splitUsers[1]
+ ", " + splitUsers[2]
+ " and " + splitUsers[3];
}
else if(length > 4){
holder.mLIkePhotoString = "Liked by " + splitUsers[0]
+ ", " + splitUsers[1]
+ ", " + splitUsers[2]
+ " and " + (splitUsers.length - 3) + " others";
}
Log.d(TAG, "onDataChange: likes string: " + holder.mLIkePhotoString);
//setup likes string
// setupLikePhotostring(holder, holder.mLIkePhotoString);
holder.mHeartPhoto.setLiked(true);
if (holder.likephotobycurrentUser){
holder.mHeartPhoto.setLiked(true);
}else {
holder.mHeartPhoto.setLiked(false);
}
holder.likes.setText(holder.mLIkePhotoString);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
if(!dataSnapshot.exists()){
holder.mLIkePhotoString = "";
holder.likephotobycurrentUser = false;
//setupwidjets();
// setupLikePhotostring(holder,holder.mLIkePhotoString);
if (holder.likephotobycurrentUser){
holder.mHeartPhoto.setLiked(true);
}else {
holder.mHeartPhoto.setLiked(false);
}
holder.likes.setText(holder.mLIkePhotoString);
holder.mHeartPhoto.setLiked(false);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}catch (NullPointerException e){
Log.e(TAG, "removeStar: NullPointer"+e.getMessage());
holder.mLIkePhotoString = "";
holder.likephotobycurrentUser = false;
// setupLikePhotostring(mPhotoHolder,holder.mLIkePhotoString);
if (holder.likephotobycurrentUser){
holder.mHeartPhoto.setLiked(true);
}else {
holder.mHeartPhoto.setLiked(false);
}
holder.likes.setText(holder.mLIkePhotoString);
}
}
Change this line
photo = moviesList.get(holder.getAdapterPosition());
to
photo = moviesList.get(position);
where position variable is same as we got in below function
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, final int position);
And also change holder.getAdapterPosition() to position in onBindViewHolder(...) function.
Related
I'm currently creating an android project (A Vehicle Rental System) with Firebase as a server. Realtime Database is alright, meanwhile, every time I try to access the images stored in the Firebase Storage, it always gives out an error:
W/NetworkRequest: no auth token for request
W/NetworkRequest: No App Check token for request.
W/NetworkRequest: error sending network request GET /*insert imageURI here*/ failed
W/ExponenentialBackoff: network unavailable, sleeping.
Here is my CustomAdapter:
private ArrayList<ModelItem> modelItemsArrayList;
private OnItemClickListener onItemClickListener;
private static final String TAG = "ModelAdapter: ";
private FirebaseStorage storage;
private StorageReference storageReference;
private Context context;
public interface OnItemClickListener{
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
onItemClickListener = listener;
}
public static class ModelAdapterViewHolder extends RecyclerView.ViewHolder{
public ImageView modelImageView;
public TextView modelTextView;
public TextView brandTextView;
public CardView modelCardView;
public ModelAdapterViewHolder(#NonNull View itemView, OnItemClickListener listener) {
super(itemView);
modelImageView = itemView.findViewById(R.id.cvFrontProfileImageView);
modelTextView = itemView.findViewById(R.id.cvModelTextView);
brandTextView = itemView.findViewById(R.id.cvBrandTextView);
itemView.setOnClickListener(view -> {
if(listener != null) {
int position = getBindingAdapterPosition();
if(position != RecyclerView.NO_POSITION) {
listener.onItemClick(position);
}
}
});
}
}
public ModelAdapter(ArrayList<ModelItem> modelItemsArrayList) {
Log.d(TAG, "ModelAdapter: called");
this.modelItemsArrayList = modelItemsArrayList;
Log.d(TAG, "ModelAdapter: modelItemsArrayList.size() = " + modelItemsArrayList.size());
}
#NonNull
#Override
public ModelAdapterViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.model_item_cardview, parent, false);
return new ModelAdapterViewHolder(view, onItemClickListener);
}
#Override
public void onBindViewHolder(#NonNull ModelAdapter.ModelAdapterViewHolder holder, int position) {
//enter data from Firebase here
ModelItem currentItem = modelItemsArrayList.get(position);
Log.d(TAG, "modelItemsArraylist.size() = " + modelItemsArrayList.size());
storage = FirebaseStorage.getInstance();
storageReference = storage.getReferenceFromUrl("gs://roadtrip-7a905.appspot.com/")
.child(currentItem.getmImageResource());
try {
Log.d(TAG, "onBindViewHolder: inside try catch nest");
final File file = File.createTempFile("image", "jpg");
storageReference.getFile(file).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
holder.modelImageView.setImageBitmap(bitmap);
Log.d(TAG, "onBindViewHolder: " + file.getPath() + " successfully loaded");
}
}).addOnFailureListener(e -> {
//Toast.makeText(context, "Failed to Load image: " + currentItem.getmImageResource(),
//Toast.LENGTH_SHORT).show();
Log.d(TAG, "onBindViewHolder: addOnFailureListener: " + e.toString());
});
} catch (Exception e) {
Log.d(TAG, "onBindViewHolder: " + e.toString());
}
//holder.modelImageView.setImageResource(currentItem.getmImageResource()); ==> setFile from storage here
holder.modelTextView.setText(currentItem.getmModelText());
holder.brandTextView.setText(currentItem.getmBrandText());
Log.d(TAG, currentItem.getmImageResource() + "\n"
+ currentItem.getmModelText() + "\n"
+ currentItem.getmBrandText());
}
#Override
public int getItemCount() {
return modelItemsArrayList.size();
}
And here is my CustomClass
package com.example.roadtrip;
public class ModelItem {
private String mImageResource;
private String mModelText;
private String mBrandText;
public ModelItem() {
}
public ModelItem(String mImageResource, String mModelText, String mBrandText) {
this.mImageResource = mImageResource;
this.mModelText = mModelText;
this.mBrandText = mBrandText;
}
public String getmImageResource() {
return mImageResource;
}
public void setmImageResource(String mImageResource) {
this.mImageResource = mImageResource;
}
public String getmModelText() {
return mModelText;
}
public void setmModelText(String mModelText) {
this.mModelText = mModelText;
}
public String getmBrandText() {
return mBrandText;
}
public void setmBrandText(String mBrandText) {
this.mBrandText = mBrandText;
}
}
I've been stuck for more than a week already. Can someone help me?
P.S. It's my first time posting here. I apologize for the Logs in the code, I was just trying to debug.
Trying to retrieve data and place it into RecyclerView. But i always end up getting a null adapter error. My List Adapter is not being recognized.
I have initialized adapter and recyclerview in OnCreate(), OnViewCreated() nothing changed except app-crash.
Can you guys shed any light please?
My List Adapter:
public class PostListAdapter extends RecyclerView.Adapter<PostListAdapter.ViewHolder>{
private static final String TAG = "PostListAdapter";
private static final int NUM_GRID_COLUMNS = 3;
private ArrayList<Post> mPosts;
private Context mContext;
public class ViewHolder extends RecyclerView.ViewHolder{
SquareImageView mPostImage;
public ViewHolder(View itemView) {
super(itemView);
mPostImage = (SquareImageView) itemView.findViewById(R.id.post_image);
int gridWidth = mContext.getResources().getDisplayMetrics().widthPixels;
int imageWidth = gridWidth/NUM_GRID_COLUMNS;
mPostImage.setMaxHeight(imageWidth);
mPostImage.setMaxWidth(imageWidth);
}
}
ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(mContext);
public PostListAdapter(Context context, ArrayList<Post> posts) {
mPosts = posts;
mContext = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.layout_view_post, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
ImageLoader.getInstance().init(ImageLoaderConfiguration.createDefault(mContext));
UniversalImageLoader.setImage(mPosts.get(position).getImage(), holder.mPostImage);
//GlideApp.with(mContext).load(mPosts.get(position)).into(holder.mPostImage);
//imageLoader.displayImage(mPosts.get(position).getImage(), holder.mPostImage);
final int pos = position;
holder.mPostImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "onClick: selected a post");
//TODO
//view the post in more detail
}
});
}
#Override
public int getItemCount() {
return mPosts.size();
}
}
My Fragment (where i initiliaze adapter and recyclerview):
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search, container, false);
mFilters = view.findViewById(R.id.ic_search);
mSearchText = view.findViewById(R.id.input_search);
mRecyclerView = view.findViewById(R.id.recyclerView);
mFrameLayout = view.findViewById(R.id.container);
getElasticSearchPassword();
init();
return view;
}
private void setupPostsList(){
RecyclerViewMargin itemDecorator = new RecyclerViewMargin(GRID_ITEM_MARGIN, NUM_GRID_COLUMNS);
mRecyclerView.addItemDecoration(itemDecorator);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), NUM_GRID_COLUMNS);
mRecyclerView.setLayoutManager(gridLayoutManager);
mAdapter = new PostListAdapter(getActivity(), mPosts);
mRecyclerView.setAdapter(mAdapter);
}
private void init(){
mFilters.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "onClick: navigating to filters activity.");
Intent intent = new Intent(getActivity(), FiltersActivity.class);
startActivity(intent);
}
});
mSearchText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if(actionId == EditorInfo.IME_ACTION_SEARCH
||actionId == EditorInfo.IME_ACTION_DONE
|| event.getAction() == KeyEvent.ACTION_DOWN
|| event.getKeyCode() == KeyEvent.KEYCODE_ENTER){
mPosts = new ArrayList<Post>();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
ElasticSearchAPI searchAPI = retrofit.create(ElasticSearchAPI.class);
HashMap<String, String> headerMap = new HashMap<String, String>();
headerMap.put("Authorization", Credentials.basic("", mElasticSearchPassword));
String searchString = "";
if(!mSearchText.equals("")){
searchString = searchString + mSearchText.getText().toString() + "*";
}
if(!mPrefCity.equals("")){
searchString = searchString + " city:" + mPrefCity;
}
if(!mPrefStateProv.equals("")){
searchString = searchString + " state_province:" + mPrefStateProv;
}
if(!mPrefCountry.equals("")){
searchString = searchString + " country:" + mPrefCountry;
}
Call<HitsObject> call = searchAPI.search(headerMap, "AND", searchString);
call.enqueue(new Callback<HitsObject>() {
#Override
public void onResponse(Call<HitsObject> call, Response<HitsObject> response) {
HitsList hitsList = new HitsList();
String jsonResponse = "";
try{
Log.d(TAG, "onResponse: server response: " + response.toString());
if(response.isSuccessful()){
hitsList = response.body().getHits();
}else{
jsonResponse = response.errorBody().string();
}
Log.d(TAG, "onResponse: hits: " + hitsList);
for(int i = 0; i < hitsList.getPostIndex().size(); i++){
Log.d(TAG, "onResponse: data: " + hitsList.getPostIndex().get(i).getPost().toString());
mPosts.add(hitsList.getPostIndex().get(i).getPost());
}
Log.d(TAG, "onResponse: size: " + mPosts.size());
//setup the list of posts
setupPostsList();
}catch (NullPointerException e){
Log.e(TAG, "onResponse: NullPointerException: " + e.getMessage() );
}
catch (IndexOutOfBoundsException e){
Log.e(TAG, "onResponse: IndexOutOfBoundsException: " + e.getMessage() );
}
catch (IOException e){
Log.e(TAG, "onResponse: IOException: " + e.getMessage() );
}
}
#Override
public void onFailure(Call<HitsObject> call, Throwable t) {
Log.e(TAG, "onFailure: " + t.getMessage() );
Toast.makeText(getActivity(), "search failed", Toast.LENGTH_SHORT).show();
}
});
}
return false;
}
});
}
public void viewPost(String postId){
ViewPostFragment fragment = new ViewPostFragment();
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
Bundle args = new Bundle();
args.putString(getString(R.string.arg_post_id), postId);
fragment.setArguments(args);
transaction.replace(R.id.container, fragment, getString(R.string.fragment_view_post));
transaction.addToBackStack(getString(R.string.fragment_view_post));
transaction.commit();
mFrameLayout.setVisibility(View.VISIBLE);
ImageLoader.getInstance().init(ImageLoaderConfiguration.createDefault(getActivity()));
}
#Override
public void onResume() {
super.onResume();
getFilters();
}
private void getElasticSearchPassword(){
Log.d(TAG, "getElasticSearchPassword: retrieving elasticsearch password.");
Query query = FirebaseDatabase.getInstance().getReference()
.child(getString(R.string.node_elasticsearch))
.orderByValue();
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
DataSnapshot singleSnapshot = dataSnapshot.getChildren().iterator().next();
mElasticSearchPassword = singleSnapshot.getValue().toString();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void getFilters(){
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
mPrefCity = preferences.getString(getString(R.string.preferences_city), "");
mPrefStateProv = preferences.getString(getString(R.string.preferences_state_province), "");
mPrefCountry = preferences.getString(getString(R.string.preferences_country), "");
Log.d(TAG, "getFilters: got filters: \ncity: " + mPrefCity + "\nState/Prov: " + mPrefStateProv
+ "\nCountry: " + mPrefCountry);
}
}
It seems like you never call the method setupPostsList(). You should move your code in Fragment from onCreateView() to onViewCreated() - that's the mehod where all views in fragment are created and you can use findViewById(). First find all view by ids and then call method setupPostsList() to set up the recycle view.
The issue is the recycler view is not displaying the data after the onchanged method is called. Or if it does, it takes a long time to display the information. heres the code:
public void onFilter(Filters filters) {
Query query = mFireStore.collection("Products");
// Category (equality filter)
if (filters.hasCategory()) {
query = query.whereEqualTo(Product.FIELD_CATEGORY, filters.getCategory());
}
// City (equality filter)
if (filters.hasCity()) {
query = query.whereEqualTo(Product.FIELD_CITY, filters.getCity());
}
// Price (equality filter)
if (filters.hasPrice()) {
query = query.whereEqualTo(Product.FIELD_PRICE, filters.getPrice());
}
// Sort by (orderBy with direction)
if (filters.hasSortBy()) {
query = query.orderBy(filters.getSortBy(), filters.getSortDirection());
}
// Limit items
query = query.limit(LIMIT);
Log.d("Query Info", query.toString());
FirestoreRecyclerOptions<Product> response = new FirestoreRecyclerOptions.Builder<Product>()
.setQuery(query,Product.class)
.build();
adapter = new FirestoreRecyclerAdapter<Product,ExploreViewholder>(response) {
#Override
public ExploreViewholder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_view_explore_item, parent, false);
return new ExploreViewholder(view);
}
#Override
protected void onBindViewHolder(#NonNull ExploreViewholder holder, int position, #NonNull Product model) {
holder.productName.setText(model.getProductName());
holder.creatorName.setText(mUser.getDisplayName());
holder.productDesc.setText(model.getProductDescription());
// Glide.with(getContext())
// .load(model.getProductImageUrl())
// .into(holder.productImage);
}
#Override
public void onError(FirebaseFirestoreException e) {
Log.e("error", e.getMessage());
}
};
adapter.notifyDataSetChanged();
mRecycler.setAdapter(adapter);
}
This is where the method gets called, i get data from the viewmodel, no problem with that but the recycler view dosent display the data.
mViewModel.getMutableLiveData().observe(this, new Observer<Filters>() {
#Override
public void onChanged(#Nullable Filters filters) {
if (filters != null){
Log.d("ExploreFragObserver", filters.getCategory() + " ");
Log.d("ExploreFragObserver", filters.getCity() + "");
Log.d("ExploreFragObserver", filters.getSortBy() + " ");
Log.d("ExploreFragObserver", filters.getPrice() + " ");
onFilter(filters);
Log.d("Done Loading Adapt", filters.getSortBy() + " ");
Log.d("ExploreFragObserver", filters.getCategory() + " ");
Log.d("ExploreFragObserver", filters.getCity() + "");
Log.d("ExploreFragObserver", filters.getSortBy() + " ");
Log.d("ExploreFragObserver", filters.getPrice() + " ");
// onFilter(Filters.getDefault());
}
}
});
A dialog fragment sets the data for the filters object in the viewmodel that both this fragment and the calling fragment both share.
I think you forgot to add adapter.startListening().
We are creating a chat application using openfire, smack. In that there is a chatscreen where users can send and receive messages and media files. For storing messages we are using Realm as local db. I want to show the progress of files during upload of files.
My Upload file code is :
public void firebasestorageMeth(final String msg, final String path, final String filetype, final String mykey, final String otheruserkey, final String username) {
StorageReference riversRef = STORAGE_REFERENCE.child(mykey).child("files").child(GetTimeStamp.timeStampDate());
final String timestampdate = GetTimeStamp.timeStampDate();
final String timestamptime = GetTimeStamp.timeStampTime();
final long id = GetTimeStamp.Id();
ChatMessageRealm cmr = new ChatMessageRealm(mykey + otheruserkey, otheruserkey, msg, mykey, timestamptime, timestampdate, filetype, String.valueOf(id), "0", "",path);
ChatHelper.addChatMesgRealmMedia1(cmr, this, mykey, otheruserkey);
sendBroadcast(new Intent().putExtra("reloadchatmediastatus", MEDIA_STARTING).putExtra("reloadchatmediaid", String.valueOf(id)).putExtra("reloadchatmedialocalurl", path).setAction("reloadchataction"));
Log.d(TAG, cmr.getChatref()+cmr.getMsgid()+cmr.getMsgstring()+"file path extension upload file" + path);
riversRef.putFile(Uri.fromFile(new File(path)))
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
umpref.setUri(String.valueOf(id), path);
Uri downloadUrl = taskSnapshot.getDownloadUrl();
Log.d(TAG, "file uploaded" + downloadUrl);
ChatMessageRealm cmr = new ChatMessageRealm(mykey + otheruserkey, otheruserkey, msg, mykey, timestamptime, timestampdate, filetype, String.valueOf(id), "1", String.valueOf(downloadUrl),path);
ChatHelper.addChatMesgRealmMedia1(cmr, getApplicationContext(), mykey, otheruserkey);
sendBroadcast(new Intent().putExtra("reloadchatmediastatus", MEDIA_SUCCESS).putExtra("reloadchatmediaid", String.valueOf(id)).putExtra("reloadchatmediaurl", String.valueOf(downloadUrl)).putExtra("reloadchatmedialocalurl", path).setAction("reloadchataction"));
Toast.makeText(getApplicationContext(), "File Uploaded ", Toast.LENGTH_LONG).show();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
sendBroadcast(new Intent().putExtra("reloadchatmediastatus", MEDIA_FAILED).putExtra("reloadchatmediaid", String.valueOf(id)).putExtra("reloadchatmedialocalurl", path).setAction("reloadchataction"));
exception.printStackTrace();
}
})
.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
#Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
int progress = (int) ((100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount());
sendBroadcast(new Intent().putExtra("reloadchatmediastatus", progress + " ").putExtra("reloadchatmediaid", String.valueOf(id)).putExtra("reloadchatmedialocalurl", path).setAction("reloadchataction"));
}
});
}
The chatadapter code is :
public class ChatAdapter1 extends RecyclerView.Adapter<ChatAdapter1.MyViewHolder> {
ArrayList<ChatMessageRealm> mList = new ArrayList<>();
private Context context;
private UserSession session;
public static final int SENDER = 0;
public static final int RECIPIENT = 1;
String TAG = "ChatAdapter1";
public ChatAdapter1(ArrayList<ChatMessageRealm> list, Context context) {
this.mList = list;
this.context = context;
session = new UserSession(context);
}
#Override
public int getItemViewType(int position) {
if (mList.get(position).getSenderjid().matches(session.getUserKey())) {
return SENDER;
} else {
return RECIPIENT;
}
}
#Override
public int getItemCount() {
return mList.size();
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
switch (viewType) {
case SENDER:
View viewSender = inflater.inflate(R.layout.row_chats_sender, viewGroup, false);
viewHolder = new MyViewHolder(viewSender);
break;
case RECIPIENT:
View viewRecipient = inflater.inflate(R.layout.row_chats_receiver, viewGroup, false);
viewHolder = new MyViewHolder(viewRecipient);
break;
}
return (MyViewHolder) viewHolder;
}
#Override
public void onBindViewHolder(final ChatAdapter1.MyViewHolder holder, int position) {
final ChatMessageRealm comment = mList.get(position);
holder.setIsRecyclable(false);
// holder.otherSender_sender.setText(comment.getSenderjid());
holder.otherSender_Timestamp.setText(comment.getSendertime() + "," + comment.getSenderdate());
// holder.status.setVisibility(View.GONE);
switch (comment.getMsgtype()) {
case "text":
// holder.btndown.setVisibility(View.GONE);
String decryptedmsg = comment.getMsgstring();
holder.commentString.setText(decryptedmsg);
// holder.photo.setVisibility(View.GONE);
break;
case "photo":
Glide.clear(holder.imgchat);
holder.imgchat.setVisibility(View.VISIBLE);
holder.progress.setVisibility(View.VISIBLE);
if (getItemViewType(position) == SENDER) {
// holder.btndown.setVisibility(View.GONE);
// holder.btnopen.setVisibility(View.VISIBLE);
try {
Glide.with(context).load(comment.getMsglocalurl()).into(holder.imgchat);
}catch (Exception e){
e.printStackTrace();
}
}
break;
}
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView otherSender_Timestamp, commentString,progress;
public ImageView imgchat;
public Button btndown, btnopen;
public MyViewHolder(View itemView) {
super(itemView);
otherSender_Timestamp = (TextView) itemView.findViewById(R.id.meSender_TimeStamp);
commentString = (TextView) itemView.findViewById(R.id.commentString);
progress = (TextView) itemView.findViewById(R.id.mediaprogress);
imgchat = (ImageView) itemView.findViewById(R.id.imgchat);
btndown = (Button) itemView.findViewById(R.id.btndown);
btnopen = (Button) itemView.findViewById(R.id.btnopen);
}
}
}
ChatActivity code is:
public class ChatActivity extends ToadoBaseActivity {
private EditText typeComment;
private ImageButton sendButton, attachment, takephoto;
Intent intent;
private RecyclerView recyclerView;
DatabaseReference dbChat;
private String otheruserkey;
LinearLayoutManager linearLayoutManager;
private MarshmallowPermissions marshmallowPermissions;
private ArrayList<String> mResults = new ArrayList<>();
private ActionMode actionMode;
UploadFileService uploadFileService;
boolean mServiceBound = false;
SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy hh:mm aa");
private ChatAdapter1 mAdapter;
LinkedHashSet<ChatMessageRealm> uniqueStrings = new LinkedHashSet<ChatMessageRealm>();
private ArrayList<ChatMessageRealm> chatList = new ArrayList<>();
private ArrayList<String> chatListIds = new ArrayList<>();
String username, mykey;
private UserSession session;
String receiverToken = "nil";
boolean clicked;
LinearLayout layoutToAdd;
LinearLayout commentView;
private ChildEventListener dbChatlistener;
ImageButton photoattach, videoattach;
Uri videoUri;
public String dbTableKey;
EncryptUtils encryptUtils = new EncryptUtils();
private ImageButton imgdocattach;
private ImageButton locattach;
private LinearLayout spamView;
TextView tvTitle;
ImageView imgprof;
private ArrayList<String> imagesPathList;
private final int PICK_IMAGE_MULTIPLE = 199;
private ProgressBar progressBar;
UserMediaPrefs umprefs;
private Boolean mBounded;
private String TAG = "ChatActivity";
// AbstractXMPPConnection connection;
Realm mRealm;
Boolean chatexists;
private String otherusername;
private String profpic;
private MyXMPP2 myxinstance;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat1);
session = new UserSession(this);
mykey = session.getUserKey();
// connection = MyXMPP2.getInstance(this,).getConn();
mRealm = Realm.getDefaultInstance();
checkChatRef(otheruserkey);
clicked = false;
layoutToAdd = (LinearLayout) findViewById(R.id.attachmentpopup);
marshmallowPermissions = new MarshmallowPermissions(this);
spamView = (LinearLayout) findViewById(R.id.spamView);
umprefs = new UserMediaPrefs(this);
//get these 2 things from notifications also
intent = getIntent();
otheruserkey = intent.getStringExtra("otheruserkey");
otherusername = intent.getStringExtra("otherusername");
profpic = intent.getStringExtra("profpic");
System.out.println("recevier token chat act oncreate" + otheruserkey);
imgprof = (ImageView) findViewById(R.id.icon_profile);
tvTitle = (TextView) findViewById(R.id.tvTitle);
tvTitle.setText(otherusername);
commentView = (LinearLayout) findViewById(R.id.commentView);
progressBar = (ProgressBar) findViewById(R.id.progress);
typeComment = (EditText) findViewById(R.id.typeComment);
sendButton = (ImageButton) findViewById(R.id.sendButton);
attachment = (ImageButton) findViewById(R.id.attachment);
takephoto = (ImageButton) findViewById(R.id.takephoto);
photoattach = (ImageButton) findViewById(R.id.photoattach);
imgdocattach = (ImageButton) findViewById(R.id.docattach);
videoattach = (ImageButton) findViewById(R.id.videoattach);
locattach = (ImageButton) findViewById(R.id.locationattach);
myxinstance = MyXMPP2.getInstance(ChatActivity.this, getString(R.string.server), mykey);
mAdapter = new ChatAdapter1(chatList, this);
recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(mAdapter);
sendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println(mykey + " chat created " + otheruserkey);
ChatMessageRealm cm = null;
if (!typeComment.getText().toString().matches("")) {
cm = new ChatMessageRealm(mykey + otheruserkey, otheruserkey, typeComment.getText().toString(), mykey, GetTimeStamp.timeStampTime(), GetTimeStamp.timeStampDate(), "text", String.valueOf(GetTimeStamp.Id()), "1");
}
if (cm != null)
myxinstance.sendMessage(cm);
loadData();
typeComment.setText("");
}
});
attachment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (layoutToAdd.getVisibility() == View.VISIBLE)
layoutToAdd.setVisibility(View.GONE);
else
layoutToAdd.setVisibility(View.VISIBLE);
}
});
takephoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
dispatchTakePictureIntent();
} catch (ActivityNotFoundException anfe) {
anfe.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
#Override
protected void onResume() {
super.onResume();
mykey = session.getUserKey();
username = session.getUsername();
loadData();
}
private void loadData() {
Sort sort[] = {Sort.ASCENDING};
String[] fieldNames = {"msgid"};
RealmResults<ChatMessageRealm> shows = mRealm.where(ChatMessageRealm.class).equalTo("chatref", mykey + otheruserkey).findAllSorted(fieldNames, sort);
if (shows.size() > 0) {
Log.d(TAG, shows.size() + "LOAD DATA CALLED " + shows.get(shows.size() - 1).getMsgstring());
for (ChatMessageRealm cm : shows) {
if (!chatList.contains(cm)) {
chatList.add(cm);
}
if (!chatListIds.contains(cm.getMsgid())) {
chatListIds.add(cm.getMsgid());
}
mAdapter.notifyDataSetChanged();
}
mAdapter.notifyDataSetChanged();
recyclerView.scrollToPosition(chatList.size() - 1);
}
}
private void checkChatRef(String otheruserkey) {
RealmQuery<ActiveChats> query = mRealm.where(ActiveChats.class);
query.equalTo("otherkey", otheruserkey);
RealmResults<ActiveChats> result1 = query.findAll();
if (result1.size() == 0) {
chatexists = false;
} else {
chatexists = true;
}
System.out.println(result1.size() + "chat exists chatactivity" + chatexists);
}
#Override
protected void onStart() {
super.onStart();
registerReceiver(this.reloadData, new IntentFilter("reloadchataction"));
}
#Override
protected void onStop() {
super.onStop();
if (reloadData != null)
unregisterReceiver(reloadData);
}
private void dispatchTakePictureIntent() throws IOException {
CropImage.activity()
.setGuidelines(CropImageView.Guidelines.ON)
.setMultiTouchEnabled(true)
.start(this);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "request code chatactivity" + requestCode);
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (data != null) {
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
Log.d(TAG, "crop activity");
CropImage.ActivityResult result = CropImage.getActivityResult(data);
if (resultCode == RESULT_OK) {
final String imguri = result.getUri().toString();
try {
final File file = createImageFile();
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
final int chunkSize = 1024; // We'll read in one kB at a time
byte[] imageData = new byte[chunkSize];
InputStream in = null;
OutputStream out = null;
try {
in = getContentResolver().openInputStream(Uri.parse(imguri));
out = new FileOutputStream(file);
int bytesRead;
while ((bytesRead = in.read(imageData)) > 0) {
out.write(Arrays.copyOfRange(imageData, 0, Math.max(0, bytesRead)));
}
String s = file.getAbsolutePath();
Log.d(TAG, "image cropped uri chatact22" + file.getAbsolutePath());
Intent intent = new Intent(ChatActivity.this, ImageComment.class);
intent.putExtra("URI", s);
intent.putExtra("comment_type", "photo");
startImageComment(intent);
} catch (Exception ex) {
Log.e("Something went wrong.", ex.toString());
} finally {
try {
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}.execute();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String imageFileName = "pic-" + GetTimeStamp.timeStamp() + ".jpg";
File image = OpenFile.createFile(this, imageFileName);
// Save a file: path for use with ACTION_VIEW intents
Log.d(TAG, "file createimagefile: " + image.getAbsolutePath());
return image;
}
private void startImageComment(Intent intent) {
Log.d(TAG, "image comment sending" + intent.getStringExtra("URI"));
intent.putExtra("username", username);
intent.putExtra("otheruserkey", otheruserkey);
intent.putExtra("receiverToken", receiverToken);
intent.putExtra("mykey", mykey);
startActivity(intent);
}
BroadcastReceiver reloadData = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getStringExtra("reloadchat") != null) {
Log.d(TAG, " reloading data broadcast receiver" + intent.getStringExtra("reloadchat"));
loadData();
mAdapter.notifyDataSetChanged();
} else if (intent.getStringExtra("reloadchatmediastatus") != null) {
if (intent.getStringExtra("reloadchatmediastatus").matches(MEDIA_STARTING))
loadData();
Log.d(TAG, " reloading data status " + intent.getStringExtra("reloadchatmediastatus"));
Log.d(TAG, " reloading data media id " + intent.getStringExtra("reloadchatmediaid"));
if (!intent.getStringExtra("reloadchatmediastatus").matches(MEDIA_FAILED)) {
final String msgid = intent.getStringExtra("reloadchatmediaid");
String fileprogress = intent.getStringExtra("reloadchatmediastatus");
int ind1 = chatListIds.indexOf(msgid);
Log.d(TAG, ind1 + "chat list broadcast progress " + fileprogress);
Log.d(TAG, "chat list broadcast" + chatListIds.size());
try {
// View ve = linearLayoutManager.findViewByPosition(ind1);
// View v = recyclerView.findViewHolderForAdapterPosition(ind1).itemView;
View v = recyclerView.findViewHolderForLayoutPosition(ind1).itemView;
ChatAdapter1.MyViewHolder holder = (ChatAdapter1.MyViewHolder) recyclerView.getChildViewHolder(v);
holder.commentString.setVisibility(View.VISIBLE);
holder.commentString.setText("file prog " + fileprogress);
mAdapter.notifyDataSetChanged();
Log.d(TAG, holder.getItemViewType() + "," + holder.getLayoutPosition() + "," + holder.commentString.getText().toString() + " VIEW HOLDER? " + v);
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (intent.getStringExtra("reloadchatmediaurl") != null)
Log.d(TAG, " reloading data media url " + intent.getStringExtra("reloadchatmediaurl"));
}
};
}
I am trying to update my recyclerview dynamically in the broadcast receiver- reloadData in ChatActivity.
My logs tell me that i am receiving correct data from the sendbroadcast in the UploadFileService, the problem is in following code inside the broadcast receiver on ChatActivity, it is getting correct data but the data is not showing on the recycler view:
try {
View v = recyclerView.findViewHolderForLayoutPosition(ind1).itemView;
ChatAdapter1.MyViewHolder holder = (ChatAdapter1.MyViewHolder) recyclerView.getChildViewHolder(v);
holder.commentString.setVisibility(View.VISIBLE);
holder.commentString.setText("file prog " + fileprogress);
mAdapter.notifyDataSetChanged();
Log.d(TAG, holder.getItemViewType() + "," + holder.getLayoutPosition() + "," + holder.commentString.getText().toString() + " VIEW HOLDER? " + v);
} catch (Exception e) {
e.printStackTrace();
}
I get correct values , such as:
08-03 19:31:25.240 705-705/com.app.toado D/ChatActivity: 0,30,file prog 34 VIEW HOLDER? android.widget.LinearLayout{ff24ae0 V.E...... ......I. 0,621-660,1380 #7f1100f2 app:id/message_container}
08-03 19:31:26.346 705-705/com.app.toado D/ChatActivity: 0,30,file prog 100 VIEW HOLDER? android.widget.LinearLayout{e8a33ce V.E...... ......I. 0,621-660,1380 #7f1100f2 app:id/message_container}
08-03 19:31:26.347 705-705/com.app.toado D/ChatActivity: 0,30,file prog upload success VIEW HOLDER? android.widget.LinearLayout{e8a33ce V.E...... ......I. 0,621-660,1380 #7f1100f2 app:id/message_container}
I have tried using View ve = linearLayoutManager.findViewByPosition(ind1); and View v = recyclerView.findViewHolderForAdapterPosition(ind1).itemView; but they are also not working. Also tried adding notifydatasetchanged to it.
The try catch is also not throwing any error in the logs.
Can someone please help in figuring out why are the changes not showing on the recycler view but are showing in logs?
Are you sure you're updating the RecyclerView's Adapter from the UI Thread? Whenever you try to update the ViewHolder, you have to be certain you're doing so on the UI or it will not behave as expected.
When the modification to the ViewHolder is changed, check that Looper.myLooper().equals(Looper.getMainLooper());. If it returns false, it means you aren't updating on the UI Thread, the necessary place for all graphical updates to be made.
If this is the case, you just need to make sure that you can synchronize your changes on the UI, using Activity.runOnUiThread(Runnable r);.
I'm getting android run time exception for this java class:
I am not getting where the problem is occurring, I have tried almost all similar questions' answers but no help! Also, I have tried to run the code by commenting almost all the unrelated functions, but that didn't rule out the error too.
public class MainActivity extends AppCompatActivity
implements GoogleApiClient.OnConnectionFailedListener {
private String intentsChild;
private String curFirebaseLocation;
public static final String ANONYMOUS = "anonymous";
private static final String TAG = "MainActivity";
private FirebaseAuth mFirebaseAuth;
private FirebaseUser mFirebaseUser;
private String mUsername;
private String mPhotoUrl;
private GoogleApiClient mGoogleApiClient;
private Button mSendButton;
private RecyclerView mMessageRecyclerView;
private LinearLayoutManager mLinearLayoutManager;
private ProgressBar mProgressBar;
private EditText mMessageEditText;
private DatabaseReference mFirebaseDatabaseReference;
private FirebaseRecyclerAdapter<FriendlyMessage, MessageViewHolder>
mFirebaseAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setStatusBarTranslucent(true);
// Set default username is anonymous.
mUsername = ANONYMOUS;
// Initialize Firebase Auth
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseUser = mFirebaseAuth.getCurrentUser();
//initialize facebook app activation
FacebookSdk.sdkInitialize(getApplicationContext());
AppEventsLogger.activateApp(getApplication());
if (mFirebaseUser == null) {
// Not signed in, launch the Sign In activity
startActivity(new Intent(this, SignInActivity.class));
finish();
return;
} else {
mUsername = mFirebaseUser.getDisplayName();
if (mFirebaseUser.getPhotoUrl() != null) {
mPhotoUrl = mFirebaseUser.getPhotoUrl().toString();
}
}
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API)
.build();
// Initialize ProgressBar and RecyclerView.
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mMessageRecyclerView = (RecyclerView) findViewById(R.id.messageRecyclerView);
mLinearLayoutManager = new LinearLayoutManager(this);
mLinearLayoutManager.setStackFromEnd(true);
mMessageRecyclerView.setLayoutManager(mLinearLayoutManager);
mFirebaseDatabaseReference = FirebaseDatabase.getInstance().getReference();
curFirebaseLocation = "users/" + mFirebaseAuth.getCurrentUser().getUid().trim() + "/messages";
intentsChild = "users/" + mFirebaseAuth.getCurrentUser().getUid().trim() + "/intents";
Toast.makeText(this, "users/" + mFirebaseAuth.getCurrentUser().getUid().trim(), Toast.LENGTH_SHORT).show();
// if(mFirebaseDatabaseReference.child(curFirebaseLocation).getParent() == null){
// Toast.makeText(this, curFirebaseLocation + " already exists.", Toast.LENGTH_SHORT).show();
IntentMessage tempintent = new IntentMessage("", "");
FriendlyMessage tempmessage = new FriendlyMessage("Hello, I'm Ed, your personal assistant cum friend",
"Ed", "https://cdn1.iconfinder.com/data/icons/user-pictures/100/male3-512.png", "1476880306");
mFirebaseDatabaseReference.child(curFirebaseLocation).setValue(tempmessage);
mFirebaseDatabaseReference.child(intentsChild).setValue(tempintent);
// }
Toast.makeText(this, curFirebaseLocation, Toast.LENGTH_SHORT).show();
// New child entries
mFirebaseAdapter = new FirebaseRecyclerAdapter<FriendlyMessage,
MessageViewHolder>(
FriendlyMessage.class,
R.layout.item_message,
MessageViewHolder.class,
mFirebaseDatabaseReference.child(curFirebaseLocation)) {
#Override
protected void populateViewHolder(MessageViewHolder viewHolder,
FriendlyMessage friendlyMessage, int position) {
mProgressBar.setVisibility(ProgressBar.INVISIBLE);
viewHolder.messageTextView.setText(friendlyMessage.getText());
viewHolder.messengerTextView.setText(friendlyMessage.getName());
if (friendlyMessage.getPhotoUrl() == null) {
viewHolder.messengerImageView
.setImageDrawable(ContextCompat
.getDrawable(MainActivity.this,
tod));
} else {
Glide.with(MainActivity.this)
.load(friendlyMessage.getPhotoUrl())
.into(viewHolder.messengerImageView);
}
if (friendlyMessage.getName().equals("Ed")){
//TODO : Do this as it is necessary
// viewHolder.diffForRecSend.setBackgroundColor(ContextCompat.getColor(MainActivity.this, R.color.white));
// viewHolder.diffForRecSend.setBackgroundResource(R.drawable.abcd123);
}
else {
//TODO : Do this as it is necessary
// viewHolder.diffForRecSend.setBackgroundColor(ContextCompat.getColor(MainActivity.this, R.color.colorAccent));
// viewHolder.diffForRecSend.setBackgroundResource(R.drawable.abcd1234);
}
}
};
mFirebaseDatabaseReference.child(intentsChild).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
IntentMessage newIntentMessage = dataSnapshot.getValue(IntentMessage.class);
String name = newIntentMessage.getIntentName();
String fields = newIntentMessage.getIntentFields();
if (name.equals("") || fields.equals(""))
return;
IntentMessage temp = new IntentMessage("", "");
mFirebaseDatabaseReference.child(intentsChild).child("-KUWmGwxVe0HCYtYWfdI").setValue(temp);
// IntentFiringActivity newIntentFiringActivity;
Log.d(TAG, "onChildUpdated: " + name + fields);
System.out.println("onChildUpdated: " + name + fields);
if (name.equals("gmail"))
fireGmailIntent(fields.split("\\$"));
else if (name.equals("alarm1"))
fireAlarmIntent(fields.split("\\$"));
else if (name.equals("alarm2"))
fireAlarmIntent2(fields.split("\\$"));
// newIntentFiringActivity = new IntentFiringActivity(name, fields);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
IntentMessage newIntentMessage = dataSnapshot.getValue(IntentMessage.class);
Log.d(TAG, "onChildRemoved: " + newIntentMessage.getIntentName() + newIntentMessage.getIntentFields());
System.out.println("onChildRemoved: " + newIntentMessage.getIntentName() + newIntentMessage.getIntentFields());
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mFirebaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
#Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
int friendlyMessageCount = mFirebaseAdapter.getItemCount();
int lastVisiblePosition =
mLinearLayoutManager.findLastCompletelyVisibleItemPosition();
// If the recycler view is initially being loaded or the
// user is at the bottom of the list, scroll to the bottom
// of the list to show the newly added message.
if (lastVisiblePosition == -1 ||
(positionStart >= (friendlyMessageCount - 1) &&
lastVisiblePosition == (positionStart - 1))) {
mMessageRecyclerView.scrollToPosition(positionStart);
}
}
});
mMessageRecyclerView.setLayoutManager(mLinearLayoutManager);
mMessageRecyclerView.setAdapter(mFirebaseAdapter);
mMessageEditText = (EditText) findViewById(R.id.messageEditText);
mMessageEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (charSequence.toString().trim().length() > 0) {
mSendButton.setEnabled(true);
} else {
mSendButton.setEnabled(false);
}
}
#Override
public void afterTextChanged(Editable editable) {
}
});
mSendButton = (Button) findViewById(R.id.sendButton);
mSendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Long tsLong = (System.currentTimeMillis() / 1000);
String ts = tsLong.toString();
FriendlyMessage friendlyMessage = new
FriendlyMessage(mMessageEditText.getText().toString(),
mUsername,
mPhotoUrl,
ts);
mFirebaseDatabaseReference.child(curFirebaseLocation)
.push().setValue(friendlyMessage);
mMessageEditText.setText("");
}
});
}
private void fireAlarmIntent(String[] intentFields) {
int hours = Integer.parseInt(intentFields[0].trim());
int minutes;
if(intentFields[1].trim().equals("")){
minutes = 0;
}
else {
minutes = Integer.parseInt(intentFields[1].trim());
}
Intent i = new Intent(AlarmClock.ACTION_SET_ALARM);
i.putExtra(AlarmClock.EXTRA_SKIP_UI, true);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra(AlarmClock.EXTRA_HOUR, hours);
i.putExtra(AlarmClock.EXTRA_MINUTES, minutes);
int temp1 = 1;
startActivityForResult(i, temp1);
String temp = "Alarm set for " + hours + " : " + minutes;
Log.d(TAG, temp);
// Toast.makeText(this, temp, Toast.LENGTH_SHORT).show();
}
private void fireAlarmIntent2(String[] intentFields) {
int hours = Integer.parseInt(intentFields[0].trim());
int curhours = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
int finalhours = (hours + curhours) % 24;
int curmin = Calendar.getInstance().get(Calendar.MINUTE);
Intent i = new Intent(AlarmClock.ACTION_SET_ALARM);
i.putExtra(AlarmClock.EXTRA_SKIP_UI, true);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra(AlarmClock.EXTRA_HOUR, finalhours);
i.putExtra(AlarmClock.EXTRA_MINUTES, curmin);
int temp1 = 1;
startActivityForResult(i, temp1);
String temp = "Alarm set for " + finalhours + " : " + curmin;
Log.d(TAG, temp);
Log.d(TAG, "currentHours: " + curhours + " and received from server : " + hours + " hence total is : " + finalhours);
// Toast.makeText(this, temp, Toast.LENGTH_SHORT).show();
}
private void fireGmailIntent(String[] intentFields) {
String[] email = new String[1];
email[0] = intentFields[0];
Log.d(TAG, "My unique log " + email[0]);
String subject = intentFields[1];
String body = intentFields[2];
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setType("message/rfc822");
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_EMAIL, email);
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
intent.putExtra(Intent.EXTRA_TEXT, body);
Log.d(TAG, "My unique log " + email[0] + "__" + subject + "__" + body);
if (intent.resolveActivity(getPackageManager()) != null) {
int temp = 4;
startActivityForResult(intent, temp);
Log.d(TAG, "My unique log " + email[0] + "__" + subject + "__" + body + "again");
}
}
protected void setStatusBarTranslucent(boolean makeTranslucent) {
if (makeTranslucent) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
// Firebase instance variables
#Override
public void onStart() {
super.onStart();
// Check if user is signed in.
// TODO: Add code to check if user is signed in.
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
startActivity(new Intent(this, SignInActivity.class));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.sign_out_menu:
mFirebaseAuth.signOut();
LoginManager.getInstance().logOut();
FirebaseAuth.getInstance().signOut();
Auth.GoogleSignInApi.signOut(mGoogleApiClient);
mUsername = ANONYMOUS;
startActivity(new Intent(this, SignInActivity.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
// An unresolvable error has occurred and Google APIs (including Sign-In) will not
// be available.
Log.d(TAG, "onConnectionFailed:" + connectionResult);
Toast.makeText(this, "Google Play Services error.", Toast.LENGTH_SHORT).show();
}
public static class MessageViewHolder extends RecyclerView.ViewHolder {
public TextView messageTextView;
public TextView messengerTextView;
public CircleImageView messengerImageView;
public LinearLayout diffForRecSend;
public MessageViewHolder(View v) {
super(v);
messageTextView = (TextView) itemView.findViewById(R.id.messageTextView);
messengerTextView = (TextView) itemView.findViewById(R.id.messengerTextView);
messengerImageView = (CircleImageView) itemView.findViewById(R.id.messengerImageView);
diffForRecSend = (LinearLayout) itemView.findViewById(R.id.message_main_id);
}
}
}
This is the logcat error:
Process: com.google.firebase.codelab.friendlychat, PID: 20107
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.google.firebase.codelab.friendlychat.FriendlyMessage
at com.google.android.gms.internal.zzaln.zzd(Unknown Source)
at com.google.android.gms.internal.zzaln.zzb(Unknown Source)
at com.google.android.gms.internal.zzaln.zza(Unknown Source)
at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
at com.firebase.ui.database.FirebaseRecyclerAdapter.parseSnapshot(FirebaseRecyclerAdapter.java:147)
at com.firebase.ui.database.FirebaseRecyclerAdapter.getItem(FirebaseRecyclerAdapter.java:136)
at com.firebase.ui.database.FirebaseRecyclerAdapter.onBindViewHolder(FirebaseRecyclerAdapter.java:176)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5453)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5486)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4723)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4599)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1988)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1384)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1347)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:549)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3003)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2881)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3265)
at android.view.View.layout(View.java:16969)
at android.view.ViewGroup.layout(ViewGroup.java:5583)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1189)
at android.view.View.layout(View.java:16969)
at android.view.ViewGroup.layout(ViewGroup.java:5583)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:396)
at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
at android.view.View.layout(View.java:16969)
at android.view.ViewGroup.layout(ViewGroup.java:5583)
at android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:437)
at android.view.View.layout(View.java:16969)
at android.view.ViewGroup.layout(ViewGroup.java:5583)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:396)
at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
at android.view.View.layout(View.java:16969)
at android.view.ViewGroup.layout(ViewGroup.java:5583)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:2001)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1844)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1753)
at android.view.View.layout(View.java:16969)
at android.view.ViewGroup.layout(ViewGroup.java:5583)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:396)
at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
at com.android.internal.policy.PhoneWindow$DecorView.onLayout(PhoneWindow.java:2728)
at android.view.View.layout(View.java:16969)
at android.view.ViewGroup.layout(ViewGroup.java:5583)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2552)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2255)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1321)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6708)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:894)
at android.view.Choreographer.doCallbacks(Choreographer.java:696)
at android.view.Choreographer.doFrame(Choreographer.java:631)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:880)
at android.os.Handler.handleCallback(Handler.java:822)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Loop
The following is just a snapshot of my json structure for reference:
{
"users" : {
"ERyWg81WxrXUb0sjsu9hv9T7K0E3" : {
"intents" : {
"intentName" : "",
"intentValue" : ""
},
"messages" : {
"-KViVgc7ZG051eMXP0-5" : {
"name" : "Ed",
"text" : "Hello, I'm Ed, your personal assistant cum friend",
"timestamp" : "1476880306"
}
}
},
"Y9UNlizDSobddO8cdq7K4ChipYa2" : {
"intents" : {
"intentName" : "",
"intentValue" : ""
},
"messages" : {
"-KViVgc7ZG051eMXP0-5" : {
"name" : "Ed",
"text" : "Hello, I'm Ed, your personal assistant cum friend",
"timestamp" : "1476880306"
}
}
}
}
}
EDIT
OK, after debugging, I have discovered that the problem lies in these lines :
So, the problem is now narrowed down. Please help me find the rest of the error:
mFirebaseAdapter = new FirebaseRecyclerAdapter<FriendlyMessage,
MessageViewHolder>(
FriendlyMessage.class,
R.layout.item_message,
MessageViewHolder.class,
mFirebaseDatabaseReference.child(curFirebaseLocation)) {
#Override
protected void populateViewHolder(MessageViewHolder viewHolder,
FriendlyMessage friendlyMessage, int position) {
//...//
}
EDIT 2:
I noted an important aspect: While running the app without a data connection, the app still was showing the error "unfortunately Ed has stopped", this is not natural as earlier when my app was working(when my app was at one stage less than what it is today), it first used to load some data from the firebase database, then showed error. But this time, it shows the error even before it loads the data from the database, this leads to a conclusion that the error doesn't lie in the snapshot part of the problem, as if it would have had the case, the app wouldn't have shown the error in the offline state as until the data loads up, it should have been showing the progress dialog continuously.
EDIT 3 I found why am I getting the error:
This line :
mFirebaseAdapter = new FirebaseRecyclerAdapter(
FriendlyMessage.class,
R.layout.item_message,
MessageViewHolder.class,
mFirebaseDatabaseReference.child(curFirebaseLocation)) {...
In this line, when I pass some other string instead of curFirebaseLocation, there is no error and my app loads up fine but when I pass the curFirebaseLocation variable, I get the error as seen in the LogCat above. Now, I only need to know why am I getting the error unable to convert java.lang.String to ...FriendlyMessage, even when the value of both curFirebaseLocation and the string that I pass(upon which I get no error) is exactly the same. I think it has soething to do with the FirebaseRecyclerAdapter. Please help!!
NOTE: I logged the output of the curFirebaseLocation and intentsMessage Strings and found out that they were perfectly fine. When I copied them and pasted them in the browser, they led me to the exactly expected location.
Please mention if any more clarification is needed.
Thanks in advance!
Firebase needs an empty constructor in class. Make sure you explicitly defined an empty constructor in your FriendlyMessage class.
There was a problem with the authentication and database synchronisation of Firebase, the user which was accessing the database was not registered in the auth section, also there were a few minor glitches, the code is working fine now and I'm getting the child nodes correctly.