I'm developing real-time messenger application with Parse and want to display all of users in ListView. So I also want to reference if user is online or offline, I tried 'put' method to add column named "online" and put information about it. When it went wrong, I added that column myself, but it still did not work. Here it's what I tried in UserList class at all:
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import com.parse.FindCallback;
import com.parse.ParseException;
import com.parse.ParseUser;
import java.util.ArrayList;
import java.util.List;
public class UserList extends AppCompatActivity {
public static ArrayList<ParseUser> userList;
public static String TAG = "UserList";
public static ParseUser user = new ParseUser();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_list);
updateUserStatus(true);
}
#Override
protected void onDestroy() {
super.onDestroy();
updateUserStatus(false);
}
#Override
protected void onResume() {
super.onResume();
loadUserList();
}
private void updateUserStatus(boolean isOnline) {
user.put("online", isOnline);
user.saveEventually();
//System.out.println("getBoolean's result : " + user.getBoolean("online"));
}
private void loadUserList() {
ParseUser.getQuery().whereNotEqualTo("username", user.getUsername()).findInBackground(new FindCallback<ParseUser>() {
#Override
public void done(List<ParseUser> objects, ParseException e) {
if (objects != null) {
if (objects.size() == 0) System.out.println("No user found");
userList = new ArrayList<>(objects);
ListView list = (ListView) findViewById(R.id.userList);
list.setAdapter(new UserAdapter(UserList.this));
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
startActivity(new Intent(UserList.this, MainActivity.class));
finish();
}
});
}
else {
System.out.println("exception detected while loading user list");
e.printStackTrace();
}
}
});
}
}
UserAdapter class:
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import com.parse.ParseUser;
public class UserAdapter extends BaseAdapter {
public static String TAG = "UserAdapter";
public TextView labelname;
LayoutInflater layoutInflater;
public UserAdapter(Context context){
layoutInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return UserList.userList.size();
}
#Override
public ParseUser getItem(int index) {
return UserList.userList.get(index);
}
#Override
public long getItemId(int index) {
return index;
}
#Override
public View getView(int pos, View v, ViewGroup group) {
ParseUser c = getItem(pos);
if (v == null) {
v = layoutInflater.inflate(R.layout.chat_item, null);
}
labelname = (TextView) v;
labelname.setText(c.getUsername());
labelname.setCompoundDrawablesWithIntrinsicBounds(c.getBoolean("online") ? R.drawable.ic_online
: R.drawable.ic_offline, 0, R.drawable.arrow, 0);
return v;
}
}
I tried saveInBackground with SaveCallback, but it throws exception named:
Caused by: java.lang.IllegalArgumentException: Cannot save a ParseUser until it has been signed up. Call signUp first
But I'm puzzled more than I was 1 hour ago. I authorize my user in another class and it seems not to be problem.
This was open bug of Parse. might be possible that not solved yet. look at this and this too.
instead of saveEventually() use saveInBackground()
and
you can't do like that
ParseUser user = new ParseUser();
if you want logged user than get like this
ParseUser user = ParseUser.getCurrentUser();
and before getting logged user you must do sign up
Related
I have an Activity with a RecyclerView which display Livedata from a room database.
My aim is to start a new Activity with more data from the room database when the user is clicking on the corresponding item in the RecyclerView.
For that I overwrote the onClick() method in the adapter of the RecylcerView. Each object of the RecyclerView has a Id, I need that Id to get the corresponding data from the database. So I passed the Id from the Adapter to the Activity.
To search an element by Id in the database that I need the ViewModel object in the MainAcitivty. It is initialized in the onCreate() of the Activity. The method I called in the Adapter is outside the onCreate() and I get a null object reference exception when I try to use it.
How can I use the ViewModel outside of the onCreate() method of the Activity? Or is there another way to search for the element in the database?
Thank you!
The Adapter class:
In the onClick() method is the relevant part.
package com.example.fillmyplate.activities;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.fillmyplate.R;
import com.example.fillmyplate.entitys.Recipe;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
class RecipeAdapter extends RecyclerView.Adapter<RecipeAdapter.RecipeViewHolder> {
private static final String TAG = "RecipeAdapter";
private List<Recipe> mRecipes = new ArrayList<>();
private LayoutInflater mInflater;
private Context mContext;
private MainActivity mainActivity = new MainActivity();
private static int backGroundIndex = 0;
class RecipeViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView recipeTitleItemView;
ImageView imageView;
public RecipeViewHolder(View itemView) {
super(itemView);
recipeTitleItemView = itemView.findViewById(R.id.name);
imageView = itemView.findViewById(R.id.card_image_view);
Log.d(TAG, "RecipeViewHolder: index " + backGroundIndex);
if (backGroundIndex == 0) {
imageView.setImageResource(R.drawable.background_green);
backGroundIndex++;
} else if (backGroundIndex == 1 ) {
imageView.setImageResource(R.drawable.background_red);
backGroundIndex++;
} else if (backGroundIndex == 2 ) {
imageView.setImageResource(R.drawable.background_blue);
backGroundIndex = 0;
}
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int position = getAdapterPosition();
// This should be the mistake.
mainActivity.startKnownRecipeActivity(position);
}
}
public RecipeAdapter(Context context) {
mInflater = LayoutInflater.from(context);
this.mContext = context;
}
#NonNull
#Override
public RecipeAdapter.RecipeViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
// Inflate an item view
View mRecipeTitleView = mInflater.inflate(
R.layout.recipe_list_row, parent, false);
return new RecipeViewHolder(mRecipeTitleView);
}
// Get data into the corrsponding views
#Override
public void onBindViewHolder(RecipeAdapter.RecipeViewHolder holder, int position) {
Log.d(TAG, "onBindViewHolder: " + position);
Recipe currentRecipe = mRecipes.get(position);
Log.d(TAG, "onBindViewHolder: setText " + currentRecipe);
holder.recipeTitleItemView.setText(currentRecipe.getTitle());
}
#Override
public int getItemCount() {
return mRecipes.size();
}
public void setRecipes(List<Recipe> recipes) {
this.mRecipes = recipes;
Log.d(TAG, "setRecipes: notifydataChanged" );
notifyDataSetChanged();
}
}
MainActivity:
package com.example.fillmyplate.activities;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.media.Image;
import android.os.Build;
import android.os.Bundle;
import com.example.fillmyplate.R;
import com.example.fillmyplate.entitys.Recipe;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.cardview.widget.CardView;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainAcitivity";
private static final int NEW_RECIPE_ACTIVITY_REQUEST_CODE = 1;
private RecyclerView mRecyclerView;
private RecipeViewModel mRecipeViewmodel;
private RecyclerView.LayoutManager layoutManager;
//private final List<String> mTitleList = new LinkedList<>();
//NEU for adapter
private List<String> recipeDataList = new ArrayList<>();
RecipeRoomDatabase db;
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// RECYCLER VIEW STUFF
mRecyclerView = findViewById(R.id.recycler_view1);
mRecyclerView.setHasFixedSize(true);
// user linerar layout manager
layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);
// specify an adapter
final RecipeAdapter recipeAdapter = new RecipeAdapter(this);
//mAdapter = new RecipeAdapter(this, mTitleList);
mRecyclerView.setAdapter(recipeAdapter);
mRecipeViewmodel = ViewModelProviders.of(this).get(RecipeViewModel.class);
mRecipeViewmodel.getAllRecipes().observe(this, new Observer<List<Recipe>>() {
#Override
public void onChanged(List<Recipe> recipes) {
Log.d(TAG, "onChanged: " + recipes.toString());
for (Recipe rec : recipes) {
Log.d(TAG, "onChanged: " + rec.getTitle());
Log.d(TAG, "onChanged: recipe id " + rec.getUid());
}
recipeAdapter.setRecipes(recipes);
}
});
// DB
db = Room.databaseBuilder(getApplicationContext(), RecipeRoomDatabase.class, "appdb").build();
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, AddRecipeActivity.class);
startActivityForResult(intent, NEW_RECIPE_ACTIVITY_REQUEST_CODE);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult: ");
if (requestCode == NEW_RECIPE_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) {
Log.d(TAG, "onActivityResult: " + data.getStringExtra(AddRecipeActivity.EXTRA_REPLY));
// mTitleList.add(data.getStringExtra(AddRecipeActivity.EXTRA_REPLY));
Recipe rec = new Recipe(data.getStringExtra(AddRecipeActivity.EXTRA_REPLY));
mRecipeViewmodel.insert(rec);
} else {
Toast.makeText(
getApplicationContext(),
"saved",
Toast.LENGTH_LONG).show();
}
}
public void startKnownRecipeActivity(int position) {
Log.d(TAG, "startKnownRecipeActivity: Position " + position);
LiveData<List<Recipe>> recipe = mRecipeViewmodel.findById(position);
if (recipe.getValue().size() > 1) {
Log.d(TAG, "startKnownRecipeActivity: Error database found more than one recipe.");
} else {
Log.d(TAG, "startKnownRecipeActivity: Start activity with recipe " + recipe.getValue().get(0).getTitle());
}
}
}
The thing you need to do is to use a call back to send position back to activity.
To make sure that view position is correct you need to override 3 functions in RecyclerView Adapter:
#Override
public int getItemCount() {
return filteredUsers.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
For the Callback just create an Interface:
public interface AdapterListener {
void onClick(int id);
void onClick(ViewModel object);
}
Make a method in your Recycler Adapter:
private AdapterListener adapterListener;
public void setAdapterListener(AdapterListener mCallback) {
this.adapterListener = mCallback;
}
Implement this Interface on your Activity then you will get both methods of the interface.
public class MainActivity extends AppCompatActivity implements AdapterListener{
Register the listener by calling the setAdapterListener method in your activity after the initialization of the RecyclerView
adapterObject.setAdapterListener(MainActivity.this);
Then the last thing you need to do is call interface method in your item onClickListener, where u can either pass the complete model or just the id of the model
adapterListener.onClick(modelObject.getId());
OR
adapterListener.onClick(modelObject);
I have orders collection in firestore:
And I have Sellers collection and inside Sellers collection have another Fruits collection :
I want to get data in orders collection only orders collection fruit_ID equals Sellers/Fruits collection Document ID and add into recyclerview
Is it possible?
Activity class:
package com.example.freshbucket.Seller;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.widget.Toast;
import com.example.freshbucket.Adapter.OrdersSellerRecylerAdapter;
import com.example.freshbucket.Model.PlaceOrder;
import com.example.freshbucket.R;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.EventListener;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreException;
import com.google.firebase.firestore.Query;
import com.google.firebase.firestore.QuerySnapshot;
import javax.annotation.Nullable;
import static android.support.constraint.Constraints.TAG;
public class SellerGetOrdersActivity extends AppCompatActivity {
String fid, pro;
private FirebaseAuth mAuth = FirebaseAuth.getInstance();
String user_id = mAuth.getCurrentUser().getUid();
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference orders = db.collection("Orders");
private CollectionReference sellers = db.collection("Sellers/"+user_id+"/Fruits");
private OrdersSellerRecylerAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_seller_get_orders);
setupRecyclerView();
}
private void setupRecyclerView()
{
Query query =orders.orderBy("timestamp", Query.Direction.DESCENDING).whereEqualTo("fruit_ID",fid);
FirestoreRecyclerOptions<PlaceOrder> options = new FirestoreRecyclerOptions.Builder<PlaceOrder>().setQuery(query, PlaceOrder.class).build();
adapter = new OrdersSellerRecylerAdapter(options);
RecyclerView recyclerView = findViewById(R.id.ordersReView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
//swipe delete
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT| ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder viewHolder1) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int i) {
adapter.deleteItem(viewHolder.getAdapterPosition());
}
}).attachToRecyclerView(recyclerView);
}
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
sellers.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot queryDocumentSnapshots, #Nullable FirebaseFirestoreException e) {
if (e != null) {
Log.d(TAG, "Error:" + e.getMessage());
} else {
for (DocumentSnapshot doc :queryDocumentSnapshots){
fid = doc.getId();
// pro = doc.getString("province");
// fid = doc.getString("fruit_ID");
Toast.makeText(SellerGetOrdersActivity.this, "Register error:" +fid , Toast.LENGTH_SHORT).show();
}
}
}
});
}
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
}
Adapter:
package com.example.freshbucket.Adapter;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
import com.example.freshbucket.Model.PlaceOrder;
import com.example.freshbucket.R;
import com.firebase.ui.firestore.FirestoreRecyclerAdapter;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
public class OrdersSellerRecylerAdapter extends FirestoreRecyclerAdapter<PlaceOrder, OrdersSellerRecylerAdapter.OrdersSellerHolder> {
Context context;
public OrdersSellerRecylerAdapter(#NonNull FirestoreRecyclerOptions<PlaceOrder> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull final OrdersSellerHolder holder, int position, #NonNull final PlaceOrder model) {
holder.txtfruitname.setText(model.getName());
holder.txtqun.setText(model.getQun());
holder.txtcusname.setText(model.getCustomer_Name());
holder.txtaddress1.setText(model.getAddressLine1());
holder.txtaddress2.setText(model.getAddressLine2());
holder.txtcity.setText(model.getCity());
}
#NonNull
#Override
public OrdersSellerHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.order_list_item_seller,viewGroup, false);
context = viewGroup.getContext();
return new OrdersSellerHolder(v);
}
class OrdersSellerHolder extends RecyclerView.ViewHolder{
TextView txtfruitname, txtqun, txtcusname, txtaddress1, txtaddress2, txtcity;
EditText tctBprice;
public OrdersSellerHolder(#NonNull View itemView) {
super(itemView);
txtfruitname = itemView.findViewById(R.id.fruitnametext);
txtqun = itemView.findViewById(R.id.fruitquntext);
txtcusname = itemView.findViewById(R.id.cusnametext);
txtaddress1 = itemView.findViewById(R.id.addres1text);
txtaddress2 = itemView.findViewById(R.id.addres2text);
txtcity = itemView.findViewById(R.id.citytext);
}
}
public void deleteItem(int position) {
getSnapshots().getSnapshot(position).getReference().delete();
}
}
I want to get data in orders collection only orders collection
fruit_ID
OK, you want to get fruit_ID?
equals Sellers/Fruits collection Document ID and add into recyclerview
and you want to get fruit_ID, which equals with Sellers/Fruits ?
like if (fruit_ID.equals(sellerFruits_ID) {// get fruit_ID}
I will try to answer it.
PROBLEM
1. you as a seller and have your seller uid in your Sellers collection and want to get V4x1Dh..
2. You have buyer uid in your Orders collection and want to get 83Fmf..
3. You want to get Banana in Sellers/Fruits, which the Banana as id.
Lastly, you want to load datas of Sellers/Fruits into recyclerView because
you want to get data in orders collection only orders collection
fruit_ID
ANSWER
Answer number one: Please retrieve the Sellers ids and get V4x1Dh based ViewHolder position that I will explain later.
Answer number two: Please retrieve the Orders ids and get 83Fmf based ViewHolder position that I will explain later.
Answer number two: Please retrieve the Sellers Fruits ids let's say sellerFruit_ID and get Banana based ViewHolder position that I will explain later. NOTE: Since Banana in document it will be id.
DETAILS:
Retrieving the Sellers ids and get V4x1Dh:
firebaseFirestore
.collection("Sellers")
.addSnapshotListener(new EventListener<QuerySnapshot>(){
#Override
public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e){
for (DocumentChange doc : documentSnapshots.getDocumentChanges()){
if (doc.getType() == DocumentChange.Type.ADDED){
// RETRIEVING Orders id
String orders_ID = doc.getDocument().getId();
YourContentOrdersHere contentOrders = doc.getDocument().toObject(YourContentOrdersHere.class).withId(orders_ID);
// RETRIEVING Sellers id
String sellers_ID = doc.getDocument().getId();
YourContentSellersHere contentSellers = doc.getDocument().toObject(YourContentSellersHere.class).withId(sellers_ID);
contentListOrders.add(contentOrders); //example: List<YourContentOrdersHere> contentList
adapter.notifyDataSetChanged(); // before of course, you add this in onCreate adapterOrders = new YourAdapterOrders(contentListOrders);
contentListSellers.add(contents); //example: List<YourContentSellersHere> contentList
adapter.notifyDataSetChanged(); // before of course, you add this in onCreate adapterSellers = new YourAdapterSellers(contentListSellers);
}
}
}
});
make sure your content class extends the ids
public class YourContentOrdersHere extends OrdersId {
// make your constructor here of course
// make your getter to get id
}
and make OrdersId.class
public class OrdersId{
#Exclude
public String OrdersId;
public <T extends OrdersId> T withId(#NonNull final String id) {
this.OrdersId = id;
return (T) this;
}
}
and last one , from your adapter class retrieving OrdersId. As Example:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// GET YOUR `Sellers` id based position and getSellerId() from getter of your content class
String sellers_ID = contentListSeller.get(position).getSellerId(); // don't forget List<YourContentSellers> contentList = new ArrayList<>();
firebaseFirestore
.collection("Sellers")
.document(sellers_ID)
.collection("Fruits")
.document("Banana")
// STORE 'LIKE TAP' USING LIKE BUTTON
holder.likeHome.seOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
/* RETRIEVING VALUE UNDER currentUserId */
firebaseFirestore.collection("Posts/" + postId + "/Likes").document(currentUserId).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>(){
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task){
if (!task.getResult().exists()) {
/* STORE NEW VALUE */
Map<String, Object> likesMap = new HashMap<>();
likesMap.put("timestamp", FieldValue.serverTimestamp);
firebaseFirestore.collection("Posts/" + postId + "/Likes").document(currentUserId).set(likesMap);
} else {
// retrieve like timestamp
String whenToLike = task.getResult().getString("timestamp");
holder.setWhenToLike(whenToLike);
/* DELETE VALUE */
firebaseFirestore.collection("Posts/" + postId + "/Likes").document(currentUserId).delete();
}
}
});
}
});
}
I want to add a button for each item in the Firebase recycler view.
I've created the button, it's being showed, and i'm receiving the Toast when I press it.
But - How can I get the relevant item on it's list ?
For example - When I press the 'DELETE' I want to delete that certain mission 'aspodm'. (Sorry for the large picture, how do I make it smaller?)
This is how the database looks like (vfPvsk... is the user id, and 773f... is random uuid for mission id):
And that is the code of the relevant fragment. (The Toast when clicking the button is activated - I just don't know how to get to the relevant mission in order to delete it)
package com.airpal.yonatan.airpal;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
/**
* A simple {#link Fragment} subclass.
*/
public class PendingFragment_User extends Fragment {
private String TAG = "dDEBUG";
private RecyclerView mPendingList;
private DatabaseReference mMissionsDb;
private FirebaseAuth mAuth;
private String mCurrent_user_id;
private View mMainView;
Query queries;
public PendingFragment_User() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mMainView = inflater.inflate(R.layout.fragment_pending_user, container, false);
mPendingList = (RecyclerView)mMainView.findViewById(R.id.pending_recycler_user);
mAuth = FirebaseAuth.getInstance();
mCurrent_user_id = mAuth.getCurrentUser().getUid();
mMissionsDb = FirebaseDatabase.getInstance().getReference().child("Missions").child(mCurrent_user_id);
queries = mMissionsDb.orderByChild("status").equalTo("Available");
mMissionsDb.keepSynced(true);
mPendingList.setHasFixedSize(true);
mPendingList.setLayoutManager(new LinearLayoutManager(getContext()));
// Inflate the layout for this fragment
return mMainView;
}
#Override
public void onStart() {
super.onStart();
FirebaseRecyclerAdapter<Mission, PendingFragment_User.MissionsViewHolder> firebaseMissionsUserRecyclerAdapter = new FirebaseRecyclerAdapter<Mission, PendingFragment_User.MissionsViewHolder>(
Mission.class,
R.layout.missions_single_layout,
PendingFragment_User.MissionsViewHolder.class,
queries
) {
#Override
protected void populateViewHolder(PendingFragment_User.MissionsViewHolder missionViewHolder, final Mission missionModel, int missionPosition) {
// Log.d(TAG, "inside populateViewHolder" + missionModel.getType() + " , " + missionModel.getDescription());
missionViewHolder.setMissionName(missionModel.getType());
missionViewHolder.setMissionDescription(missionModel.getDescription());
missionViewHolder.setMissionStatus(missionModel.getStatus());
missionViewHolder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Toast.makeText(view.getContext(), "esto es un boton"+ view.getNextFocusUpId(), Toast.LENGTH_SHORT).show();
Log.d(TAG,"The button was pressed");
}
});
}
};
mPendingList.setAdapter(firebaseMissionsUserRecyclerAdapter);
}
public static class MissionsViewHolder extends RecyclerView.ViewHolder {
View mView;
Button button ;
public MissionsViewHolder(View itemView) {
super(itemView);
mView = itemView;
button = (Button)mView.findViewById(R.id.pending_single_button);
}
public void setMissionName(String name){
TextView mMissionNameView = mView.findViewById(R.id.mission_single_name);
mMissionNameView.setText(name);
}
public void setMissionStatus(String status){
TextView mMissionStatusView = mView.findViewById(R.id.mission_single_status);
mMissionStatusView.setText(status);
if (status.equals("Available")){
mMissionStatusView.setTextColor(Color.parseColor("#008000"));;
} else {
mMissionStatusView.setTextColor(Color.parseColor("#FF0000"));;
}
}
public void setMissionDescription(String description){
TextView mMissionDescriptionView = mView.findViewById(R.id.mission_single_description);
mMissionDescriptionView.setText(description);
}
}
}
Try using a subclass rather than anonymous one. Then, you'll be able to access the getItem(int position) method of the adapter. Something along the lines of:
private class MissionAdapter extends FirebaseRecyclerAdapter<Mission, PendingFragment_User.MissionsViewHolder> {
public MissionAdapter(Query queries){
super(Mission.class, R.layout.missions_single_layout, PendingFragment_User.MissionsViewHolder.class, queries);
}
#Override
protected void populateViewHolder(PendingFragment_User.MissionsViewHolder missionViewHolder, final Mission missionModel, final int missionPosition) {
Log.d(TAG, "inside populateViewHolder" + missionModel.getType() + " , " + missionModel.getDescription());
missionViewHolder.setMissionName(missionModel.getType());
missionViewHolder.setMissionDescription(missionModel.getDescription());
missionViewHolder.setMissionStatus(missionModel.getStatus());
missionViewHolder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Mission clickedMission = MissionAdapter.this.getItem(missionPosition);
if (clickedMission != null){ // for the sake of being extra-safe
Log.d(TAG,"The button was pressed for mission: " + clickedMission.getType());
}
}
});
}
}
I made it print a log, but you should be able to do anything you want with the retrieved Mission object in there.
I have three classes one user list holds the list of user when each user is clicked it directs you to chat class which holds the chats activity. I also have the conversation list which holds a single conversation. The problem is the list view does not show previous chats stored in parse data base how can I load the previous chats to my list view.
package com.example.user.mycareerchat;
import java.util.ArrayList;
import java.util.List;
import android.app.ActionBar;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.TextView;
import android.widget.Toast;
import com.example.user.mycareerchat.custom.CustomActivity;
import com.parse.FindCallback;
import com.parse.Parse;
import com.parse.ParseClassName;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.ParseUser;
public class UserList extends CustomActivity {
private static final String EXTRADATA = null;
// Declare Variables
// the chat list
private ArrayList<ParseUser> uList =new ArrayList<ParseUser>();
// the parseruser
public static ParseUser user=new ParseUser();
/////////////
public static ArrayList names = new ArrayList<String>();
private String currentUserId;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.user_list);
updateUserStatus(true);
}
#Override
protected void onDestroy() {
super.onDestroy();
updateUserStatus(false);
}
#Override
protected void onResume() {
super.onResume();
loadUserList();
}
private void loadUserList() {
currentUserId = ParseUser.getCurrentUser().getObjectId();
names = new ArrayList<String>();
ParseQuery<ParseUser> query = ParseUser.getQuery();
//don't include yourself
query.whereNotEqualTo("objectId", currentUserId);
query.findInBackground(new FindCallback<ParseUser>() {
public void done(List<ParseUser> userList, com.parse.ParseException e) {
if (e == null) {
for (int i=0; i<userList.size(); i++) {
names.add(userList.get(i).getUsername().toString());
uList = new ArrayList<ParseUser>(userList);
}
final ListView list = (ListView)findViewById(R.id.list);
ArrayAdapter namesArrayAdapter = new ArrayAdapter<String>(getApplicationContext(),
R.layout.chat_item, names);
list.setAdapter(namesArrayAdapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int i, long l) {
// openConversation(names, i);
String name= names.get(i).toString();
startActivity(new Intent(UserList.this, Chat.class).putExtra(EXTRADATA, name));
}
});
} else {
Toast.makeText(getApplicationContext(),
"Error loading user list",
Toast.LENGTH_LONG).show();
}
}
});
}
private void updateUserStatus(boolean online) {
user.put("online", online);
user.saveEventually();
}
private class UserAdapter extends BaseAdapter {
#Override
public int getCount() {
return uList.size();
}
#Override
public ParseUser getItem(int arg0) {
return uList.get(arg0);
}
#Override
public long getItemId(int arg0) {
return arg0;
}
#Override
public View getView(int pos, View v, ViewGroup arg2) {
if(v!=null)
v=getLayoutInflater().inflate(R.layout.chat_item,null);
ParseUser c= getItem(pos);
TextView lbl = (TextView) v;
lbl.setText(c.getUsername());
lbl.setCompoundDrawablesWithIntrinsicBounds(c.getBoolean("online")? R.drawable.ic_online:
R.drawable.ic_offline,0,
R.drawable.arrow,0);
return v;
}
}
}
//Conversation Class
package com.example.user.mycareerchat.model;
import com.example.user.mycareerchat.UserList;
import java.util.Date;
/**
* Created by user on 26/Aug/2015.
*/
public class Conversation {
public static final int STATUS_SENDING =0;
public static final int STATUS_SENT =1;
public static final int STATUS_FAILED =2;
private int status = STATUS_SENT;
private Date date;
private String sender;
private String msg;
//instatiates new conversation
public Conversation(String msg,Date date,String sender) {
this.msg =msg;
this.date = date;
this.sender = sender;
}
//instatiates new conversation
// public Conversation() {
//
// }
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public boolean isSent(){
return UserList.user.getUsername().equals(sender);
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
//Chat class
package com.example.user.mycareerchat;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Telephony;
import android.text.InputType;
import android.text.format.DateUtils;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import com.example.user.mycareerchat.custom.CustomActivity;
import com.example.user.mycareerchat.model.Conversation;
import com.parse.FindCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.ParseUser;
import com.parse.SaveCallback;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* This class represents single chat class message
*/
public class Chat extends CustomActivity {
private ArrayList<Conversation> convList;
private ChatAdapter adp;
private EditText txt;
private String buddy;
private Date lastMsgDate;
private boolean isRunning;
private static Handler handler;
private static final String EXTRA_DATA = null ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat);
convList = new ArrayList<Conversation>();
ListView list = (ListView) findViewById(R.id.listchat);
adp = new ChatAdapter();
list.setAdapter(adp);
list.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
list.setStackFromBottom(true);
txt = (EditText) findViewById(R.id.txt);
txt.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
setTouchNClick(R.id.btnSend);
buddy = getIntent().getStringExtra(EXTRA_DATA);
// getActionBar().setTitle(buddy);
loadConversationList();
handler = new Handler();
}
#Override
protected void onResume() {
super.onResume();
isRunning =true;
loadConversationList();
}
#Override
protected void onPause() {
super.onPause();
isRunning = false;
}
#Override
public void onClick(View v) {
super.onClick(v);
if(v.getId()== R.id.btnSend){
sendMessage();
}
}
private void sendMessage() {
if(txt.length()==0)
return;
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(txt.getWindowToken(),0);
String s =txt.getText().toString();
final Conversation c = new Conversation(s, new Date(),UserList.user.getUsername());
c.setStatus(Conversation.STATUS_SENDING);
convList.add(c);
adp.notifyDataSetChanged();
txt.setText(null);
ParseObject po = new ParseObject("Chat");
po.put("sender",UserList.user.getUsername());
po.put("receiver",buddy);
po.put("message",s);
po.saveEventually(new SaveCallback() {
#Override
public void done(ParseException e) {
if(e==null)
c.setStatus(Conversation.STATUS_SENT);
else
c.setStatus(Conversation.STATUS_FAILED);
adp.notifyDataSetChanged();
}
});
}
/*load the conversation list from parse server and save the data of the last message that will
* be used to load only new received messages*/
private void loadConversationList() {
//load all messsages
ParseQuery<ParseObject> q =ParseQuery.getQuery("Chat");
if(convList.size()==0){
ArrayList<String> al = new ArrayList<String>();
al.add(buddy);
al.add(ParseUser.getCurrentUser().getUsername());
q.whereContainedIn("sender", al);
q.whereContainedIn("receiver",al);
}
else{
//load only new received messages....
if(lastMsgDate!=null){
q.whereLessThan("createdAt",lastMsgDate);
q.whereEqualTo("sender", ParseUser.getCurrentUser().getUsername());
q.whereEqualTo("receiver",buddy);
adp.notifyDataSetChanged();
}
//load messages in the most recent order
q.orderByDescending("createdAt");
q.setLimit(30);
q.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> li, ParseException e) {
if(li != null && li.size() >0){
for (int i =li.size()-1;i>=0;i--){
ParseObject po = li.get(i);
Conversation c =new Conversation(po.getString("message"),po.getCreatedAt(),po.getString("sender"));
convList.add(c);
if(lastMsgDate == null || lastMsgDate.before(c.getDate()))
lastMsgDate = c.getDate();
adp.notifyDataSetChanged();
}
}
handler.postDelayed(new Runnable() {
#Override
public void run() {
if(isRunning)
loadConversationList();
}
},1000);
//
}
});
}
}
/*this class is the adapter class for chat listview. this adapter shows the sent and received messages
*in the list item*/
private class ChatAdapter extends BaseAdapter{
#Override
public int getCount() {
return convList.size();
}
#Override
public Conversation getItem(int arg0) {
return convList.get(arg0);
}
#Override
public long getItemId(int arg0) {
return arg0;
}
#Override
public View getView(int pos, View v, ViewGroup arg2) {
Conversation c = getItem(pos);
if(c.isSent())
v=getLayoutInflater().inflate(R.layout.chat_item_sent,null);
else
v=getLayoutInflater().inflate(R.layout.chat_item_rcv,null);
TextView lbl =(TextView) v.findViewById(R.id.lbl1);
lbl.setText(DateUtils.getRelativeDateTimeString(Chat.this,c.getDate().getTime (),DateUtils.SECOND_IN_MILLIS,DateUtils.DAY_IN_MILLIS,0));
lbl =(TextView) v.findViewById(R.id.lbl2);
lbl.setText(c.getMsg());
lbl =(TextView) v.findViewById(R.id.lbl3);
if (c.isSent()){
if (c.getStatus()==Conversation.STATUS_SENT)
lbl.setText("Delivered");
else if (c.getStatus()==Conversation.STATUS_SENDING)
lbl.setText("Sending...");
else
lbl.setText("Failed");
}
else
lbl.setText("");
return v;
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId()==android.R.id.home){
finish();
}
return super.onOptionsItemSelected(item);
}
}
I am working on an android app which is having functionality of tabs.
Everything is working fine but I am not able to call activtygroup from listadapter.
Here is my code for list adapter:
import java.util.ArrayList;
import android.app.Activity;
import android.app.ActivityGroup;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.tv.socialgoal.R;
import com.tv.socialgoal.imageloader.ImageLoader;
public class AllyListAdapter extends BaseAdapter{
Activity ctx;
ArrayList<Object> alist;
private ImageLoader imageLoader;
AllyBean allyBean;
private String photoPath;
public AllyListAdapter(Activity ctx, ArrayList<Object> alist) {
super();
this.ctx = ctx;
this.alist = alist;
imageLoader=new ImageLoader(ctx);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return alist.size();
}
#Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(int position, View arg1, ViewGroup arg2) {
LayoutInflater linf=(LayoutInflater) ctx.getSystemService(ctx.LAYOUT_INFLATER_SERVICE);
View v=linf.inflate(R.layout.ally_list_row, null);
TextView tv=(TextView)v.findViewById(R.id.allyName);
ImageView profileImage=(ImageView)v.findViewById(R.id.ally_image);
Button inviteBtn=(Button)v.findViewById(R.id.invite_btn);
//SHOW DATA FROM LIST
allyBean=(AllyBean)alist.get(position);
tv.setText(allyBean.getName());
photoPath=allyBean.getAvatar();
profileImage.setTag(photoPath);
imageLoader.displayImage(photoPath, ctx, profileImage, false);
inviteBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent intent=new Intent(ctx,AddRemoveFriendScreen.class);
//intent.putExtra("friendId", allyBean.getUserId());
ctx.startActivity(intent);
}
});
return v;
}
/*public void replaceContentView(String id, Intent newIntent) {
View view =getLocalActivityManager().startActivity(id,
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
.getDecorView();
this.setContentView(view);
}*/
}
Now I have to call AddRemoveFriends activtygroup.
Here is the code for activtygroup:
import java.util.ArrayList;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.ActivityGroup;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.tv.servercommunication.IServerResponse;
import com.tv.servercommunication.WebServiceCommunicator;
import com.tv.socialgoal.Constant;
import com.tv.socialgoal.R;
import com.tv.socialgoal.network.NetworkAvailablity;
import com.tv.task.TabViewActivity;
public class AddRemoveFriendScreen extends ActivityGroup implements OnClickListener, IServerResponse{
Button backBtn;
Button addRemoveFriendBtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.friends_profile_screen);
backBtn=(Button)findViewById(R.id.back_button);
addRemoveFriendBtn=(Button)findViewById(R.id.add_remove_frnd_btn);
backBtn.setOnClickListener(this);
addRemoveFriendBtn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.back_button:
break;
case R.id.add_remove_frnd_btn:
callAddFriend_WS();
break;
default:
break;
}
}
private Handler _handler = new Handler() {
public void dispatchMessage(Message msg) {
switch (msg.arg1) {
case Constant.PID_ADD_REMOVE_FRIEND:
if (parseResponse(msg.obj.toString()) == true) {
Intent intent = new Intent(getParent(),
TabViewActivity.class);
startActivity(intent);
} else {
runOnUiThread(new Runnable() {
public void run() {
Constant.showAlertDialog(
Constant.DIALOG_TITLE_ERROR,
"Invalid username or password.",
getParent(), false);
}
});
}
break;
default:
break;
}
}
};
// GET USER ACCESSTOCKEN AND USER ID
private boolean parseResponse(String response) {
String message = null;
JSONObject post;
boolean isUserInfoAvail = false;
try {
JSONObject postjsonObject = new JSONObject(response);
JSONObject posts = postjsonObject.getJSONObject("posts");
post = posts.getJSONObject("post");
message = post.getString("message");
if (message.equalsIgnoreCase("failure")) {
isUserInfoAvail = false;
} else {
isUserInfoAvail = true;
}
} catch (JSONException e1) {
e1.printStackTrace();
}
return isUserInfoAvail;
}
public void callAddFriend_WS() {
if (NetworkAvailablity.checkNetworkStatus(AddRemoveFriendScreen.this)) {
// PREPARE URL
Constant.methodURL = "http://admin.tvdevphp.com/goalmachine/add_friend.php";
// PREPARE REQUEST PARAMETER
ArrayList<NameValuePair> requestParaList = new ArrayList<NameValuePair>();
requestParaList.add(new BasicNameValuePair("self_user_id", "1"));
requestParaList.add(new BasicNameValuePair("user_friend_id", "2"));
// CALL WEBSERVICE
WebServiceCommunicator.getInstance().registerForServerResponse(
AddRemoveFriendScreen.this);
WebServiceCommunicator.getInstance().callGetAppWebService(
Constant.showDialog, getParent(),
Constant.methodURL, getParent(), Constant.PID_ADD_REMOVE_FRIEND,
false, requestParaList);
} else {
Constant.showAlertDialog(Constant.errorTitle,
Constant.MSG_CHECK_INTERNET_SETTING, getParent(),
false);
}
}
// SERVER RESPONSE METHOD
public void serverResponse(String response, int processid) {
Message msg = new Message();
msg.arg1 = processid;
msg.obj = response;
_handler.dispatchMessage(msg);
}
}
Please suggest me how to call activtygroup from listadapter.
Make it like this you can access everything by doing like this.
public class AddRemoveFriendScreen extends ActivityGroup implements OnClickListener, IServerResponse
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
.......
}
class AllyListAdapter extends BaseAdapter
{
//Now you can call everything from ActivityGroup
}
}
Hope this will help you.
According to the android developper reference, you may use Fragments.
ActivityGroup is deprecated. Use the new Fragment and FragmentManager APIs instead; these are also available on older platforms through the Android compatibility package.
You can try this trick.
inviteBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if(ctx instanceof ActivityGroup){
Intent intent = new Intent(ctx.getParent(),AddRemoveFriendScreen.class);
//intent.putExtra("friendId", allyBean.getUserId());
ctx.getParent().startActivity(intent);
}
else{
Intent intent = new Intent(ctx,AddRemoveFriendScreen.class);
//intent.putExtra("friendId", allyBean.getUserId());
ctx.startActivity(intent);
}
}
});
If it doesn't work just use internal class for your adapter in your AddRemoveFriendScreen class.