I've got a problem with reading data from google firebase. It seems like the method onDataChange is not called no matter if I change data in the database or not and I don't know why. What makes me curious is that I am able to write data into the database. I would be very thankful if someone could help me. Here is my code:
public class MainActivity extends AppCompatActivity implements LocationListener, View.OnClickListener {
MapView mapView;
MyLocationNewOverlay myLocationOverlay;
private static final String TAG = "MainActivity";
String content = "a";
String author = "b";
Double latitude = 53.2;
Double longitude = 11.5;
private ItemizedIconOverlay<OverlayItem> messagesOverlay;
private List<OverlayItem> items = new ArrayList<>();
private long totalNumberChilds;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//set up the mapView and show the MyLocationOverlay
mapView = findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
mapView.setMultiTouchControls(true);
mapView.getController().setZoom(5);
messagesOverlay = new ItemizedIconOverlay<OverlayItem>(items, getResources().getDrawable(R.drawable.briefumschlag), null, this);
myLocationOverlay = new MyLocationNewOverlay(new GpsMyLocationProvider(getApplicationContext()), mapView);
myLocationOverlay.enableMyLocation();
mapView.getOverlays().add(messagesOverlay);
mapView.getOverlays().add(myLocationOverlay);
GeoPoint point = this.myLocationOverlay.getMyLocation();
if(point==null){
return;
} else {
mapView.getController().animateTo(point);
}
//initialize the Overlay for the Messages
//messagesOverlay.addItem(new OverlayItem(author, "", new GeoPoint(latitude, longitude)));
//declare the database variables in onCreate
//NOTE: Unless you are signed in, this will not be useable.
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");
// Read from the database
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
messagesOverlay.removeAllItems();
Toast.makeText(MainActivity.this, "yesss", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDataChange: Successsfully called!");
for (DataSnapshot ds : dataSnapshot.getChildren()) {
//Message message = new Message();
//String author1 = ds.child("messageAuthor").getValue(String.class);
//String content1 = ds.child("messageContent").getValue(String.class);
//Double latitude1 = ds.child("messageLatitude").getValue(Double.class);
//Double longitude1 = ds.child("messageLongitude").getValue(Double.class);
//messagesOverlay.addItem(new OverlayItem("by" + author1, "", new GeoPoint(latitude1, longitude1)));
}
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
}
});
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.testButton) {
addMessage();
}
}
public void addMessage() {
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");
String id = myRef.push().getKey();
Message message = new Message(author, content, latitude, longitude);
myRef.child(id).setValue(message);
Toast.makeText(this, "Message added", Toast.LENGTH_LONG).show();
}
#Override
public void onLocationChanged(Location location) {
GeoPoint point = new GeoPoint(location);
if(point==null){
return;
} else {
mapView.getController().animateTo(point);
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
I just found the error, I removed the lines
if(point==null){
return;
} else {
mapView.getController().animateTo(point);
}
and now the onDataChange method is called. Thank you so much for your help!
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
This activity displays geofences to the map. They're added as objects to an arraylist and then used by initArea() and are shown on the map. My issue is initArea() runs before onDataChange() so nothing is added to the arraylist and a null pointer exception is thrown. I want onDatachange() to run first so that the arraylist is populated. Thanks in advance :)
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GeoQueryEventListener {
private static final String TAG = "Maps";
private GoogleMap mMap;
private LocationRequest locationRequest;
private LocationCallback locationCallback;
private FusedLocationProviderClient fusedLocationProviderClient;
private Marker currentLocation;
private DatabaseReference locationRef;
private GeoFire geofire;
private List<LatLng> geoFence;
ArrayList<geofenceObj> geoTemp = new ArrayList<>();
private String userID;
private FirebaseDatabase mFirebaseDatabase;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private DatabaseReference myRef;
private int check;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
mAuth = FirebaseAuth.getInstance();
mFirebaseDatabase = FirebaseDatabase.getInstance();
myRef = mFirebaseDatabase.getReference();
FirebaseUser user = mAuth.getCurrentUser();
userID = user.getUid();
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
}
};
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
showData(dataSnapshot);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Dexter.withActivity(this)
.withPermission(Manifest.permission.ACCESS_FINE_LOCATION)
.withListener(new PermissionListener() {
#Override
public void onPermissionGranted(PermissionGrantedResponse response) {
buildLocationRequest();
buildlocationcallback();
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(MapsActivity.this);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(MapsActivity.this);
initArea();
settingGeofire();
}
#Override
public void onPermissionDenied(PermissionDeniedResponse response) {
Toast.makeText(MapsActivity.this, "Permissions not enabled ", Toast.LENGTH_SHORT).show();
}
#Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
}
}).check();
}
private void showData(DataSnapshot dataSnapshot) {
geoTemp.clear();
for(DataSnapshot i : dataSnapshot.getChildren()) {
for(int j=1; j<=dataSnapshot.child("users").child(userID).getChildrenCount(); j++) {
String ID = String.valueOf(j);
if (i.child(userID).child(ID).getValue() != null) {
geofenceObj geofence = new geofenceObj();
geofence.setName(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getName());
geofence.setRadius(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getRadius());
geofence.setLat(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLat());
geofence.setLng(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLng());
geoTemp.add(geofence);
Log.d(TAG, "Added " + geofence.getName());
}
}
}
}
private void initArea() {
geoFence = new ArrayList<>();
geoFence.add(new LatLng(0, 0));
for(int i = 0; i <= geoTemp.size(); i++){
geoFence.add(new LatLng(geoTemp.get(i).getLat(), geoTemp.get(i).getLat()));
}
Log.d(TAG, "Initialised Area");
}
You can't change the order in which asynchronous data is loaded. But what you can change is when you initialize the map that depends on the data. So move the call to initArea() into the onDataChange (or the showData) method, so that is runs after the data has been loaded.
private void showData(DataSnapshot dataSnapshot) {
geoTemp.clear();
for(DataSnapshot i : dataSnapshot.getChildren()) {
for(int j=1; j<=dataSnapshot.child("users").child(userID).getChildrenCount(); j++) {
String ID = String.valueOf(j);
if (i.child(userID).child(ID).getValue() != null) {
geofenceObj geofence = new geofenceObj();
geofence.setName(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getName());
geofence.setRadius(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getRadius());
geofence.setLat(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLat());
geofence.setLng(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLng());
geoTemp.add(geofence);
Log.d(TAG, "Added " + geofence.getName());
}
}
}
// Now that the data is loaded and processed, we can initialize the map
initArea();
}
hi guys I would like as a title to read a single node created previously in my realtime firebase database, the database is thus created:
Users
---- UID1
---- Email:
---- Fullname:
---- Phone:
---- Coins:
---- UID2
---- Email:
---- Fullname:
---- Phone:
---- Coins:
so my database has a structure like the one shown and I need to read in onDataChange and then write the data in a TextView.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_page_coins_);
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("Utenti");
myRef.child("Rapp Coins %").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String coinsRapp = dataSnapshot.getValue(String.class);
mCoins.setText(coinsRapp);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
this method I used doesn't work as I can't get it to take the data I need.
I need to take the Coins value: within each different logged user, so each logged in user reads his data.
I the UID value that identifies each user, I created it based on his mobile number, so each user has his own mobile number that identifies him as UID.
this is all my code, as you can see the data that saves the UID is contained in mPhone, which was saved and then brought into this activity through the SharedPreferences.
public class PageCoins_Activity extends AppCompatActivity implements RewardedVideoAdListener {
private static final String TAG = MainActivity.class.getName();
private FirebaseAuth mAuth;
private AdView mBannerTop;
private AdView mBannerBot;
private RewardedVideoAd mRewardedVideoAd;
public double Coins;
double coinsOp = 0.00;
double coinsCl = 0.00;
double coinssum = 0.00;
Button mButton;
Button mPhonebtn;
TextView mCoinscounter;
TextView mCoins;
FirebaseDatabase mDatabase;
EditText mPhoneEdt;
TextView mPhone;
#Override
protected void onStart(){
super.onStart();
updateUI();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_page_coins_);
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("Utenti");
myRef.child("Rapp Coins %").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String coinsRapp = dataSnapshot.getValue(String.class);
mCoins.setText(coinsRapp);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
mAuth = FirebaseAuth.getInstance();
initFirebase();
//counter CRD
mCoinscounter = (TextView)findViewById(R.id.Textcoins);
mButton = (Button)findViewById(R.id.btn2);
mPhoneEdt = (EditText)findViewById(R.id.NumberPhEdt);
mPhone = (TextView) findViewById(R.id.NumberPhTxt);
mCoins = (TextView)findViewById(R.id.txtGen);
mPhonebtn = (Button)findViewById(R.id.buttonPhone);
//mPhoneEdt.setVisibility(View.GONE);
//mPhone.setVisibility(View.VISIBLE);
findViewById(R.id.btn2).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mRewardedVideoAd.isLoaded()) {
mRewardedVideoAd.show();
}
// Write a message to the database
DatabaseReference myRef = mDatabase.getReference();
myRef.child("Utenti").child(mPhone.getText().toString()).child("Rapp Coins Day %").setValue(mCoinscounter.getText().toString());
}
});
mRewardedVideoAd = MobileAds.getRewardedVideoAdInstance(this);
mRewardedVideoAd.setRewardedVideoAdListener(this);
//Set Orientation Portrait
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// Banner Top View Coins
mBannerTop = (AdView) findViewById(R.id.adViewTopcoins);
AdRequest adRequest = new AdRequest.Builder().setRequestAgent("android_studio:ad_template").build();
mBannerTop.loadAd(adRequest);
// Banner Bot View Coins
mBannerBot = (AdView) findViewById(R.id.adViewBotcoins);
AdRequest adRequest1 = new AdRequest.Builder().setRequestAgent("android_studio:ad_template").build();
mBannerBot.loadAd(adRequest1);
getnumberprefs();
//ADMob Video
loadRewardedVideoAd();
}
private void getnumberprefs() {
SharedPreferences numb = getSharedPreferences(Register_Activity.NUMB, MODE_PRIVATE);
String numberphn = numb.getString(Register_Activity.KEY_NUMB,null);
mPhone.setText(numberphn);
}
//boolean changepgcoins = true;
public void changeNumber(View view) {
/*if (changepgcoins == true){
mPhoneEdt.setVisibility(View.GONE);
mPhone.setVisibility(View.VISIBLE);
changepgcoins = false;
}else{
mPhoneEdt.setVisibility(View.VISIBLE);
mPhone.setVisibility(View.GONE);
changepgcoins = true;
}*/
}
private void initFirebase() {
mDatabase = FirebaseDatabase.getInstance();
}
public void HomeClick(View view){
Intent intenthome = new Intent(this, MainActivity.class);
finish();
startActivity(intenthome);
}
public void displayCrd (double amount){
mCoinscounter.setText(String.format("%.2f", amount));
}
private void loadRewardedVideoAd() {
mRewardedVideoAd.loadAd("ca-app-pub-3940256099942544/5224354917",
new AdRequest.Builder().build());
}
public void logout(View view) {
mAuth.signOut();
updateUI();
}
private void updateUI() {
FirebaseUser currentuser = mAuth.getCurrentUser();
if(currentuser == null){
Intent intTologin = new Intent(this, Login_Activity.class);
finish();
startActivity(intTologin);
}
}
#Override
public void onRewardedVideoAdLoaded() {
Log.d(TAG, "Video Caricato");
}
#Override
public void onRewardedVideoAdOpened() {
}
#Override
public void onRewardedVideoStarted() {
}
#Override
public void onRewardedVideoAdClosed() {
loadRewardedVideoAd();
}
#Override
public void onRewarded(RewardItem rewardItem) {
Toast.makeText(this, " RAPp " + " COINS " + " : " + rewardItem.getAmount(), Toast.LENGTH_LONG).show();
Coins += rewardItem.getAmount();
displayCrd(Coins/40200*100);
}
#Override
public void onRewardedVideoAdLeftApplication() {
}
#Override
public void onRewardedVideoAdFailedToLoad(int i) {
Log.d(TAG, "Caricamento Fallito");
}
#Override
public void onRewardedVideoCompleted() {
loadRewardedVideoAd();
}
#Override
protected void onDestroy() {
if (!isEmpty(mCoins)){
String coinsopen = mCoins.getText().toString();
String coinscounter = mCoinscounter.getText().toString();
coinsOp = Double.parseDouble(String.format(coinsopen.replace(',', '.'), "%.2f"));
coinsCl = Double.parseDouble(String.format(coinscounter.replace(',', '.'), "%.2f"));
coinssum = (coinsOp + coinsCl);
mCoinscounter.setText(String.valueOf(coinssum));
// Write a message to the database
DatabaseReference myRef = mDatabase.getReference();
myRef.child("Utenti").child(mPhone.getText().toString()).child("Rapp Coins %").setValue(mCoinscounter.getText().toString());
}else{
// Write a message to the database
DatabaseReference myRef = mDatabase.getReference();
myRef.child("Utenti").child(mPhone.getText().toString()).child("Rapp Coins %").setValue(mCoinscounter.getText().toString());
}
super.onDestroy();
}
private boolean isEmpty(TextView mCoins) {
String input = mCoins.getText().toString();
return input.length() == 0.00;
}
}
I really ask for help on the solution of this thing because it's the last thing I need to finish and I can't thank you.
{
"Utenti" : {
"3********4" : {
"E-Mail" : "",
"Full Name" : "",
"Phone" : "",
"Rapp Coins %" : "",
"Rapp Coins Day %" : ""
},
"3********1" : {
"E-Mail" : "",
"Full Name" : "",
"Phone" : "",
"Rapp Coins %" : "",
"Rapp Coins Day %" : ""
},
}
}
this is my database so composed.
I have a Firebase Realtime database, where I store Google Maps Marker data. It looks like this: Firebase Database
My application has the option to add your own marker to the database, my problem is that my application only reads the info from Studio 1 and T1, not from the random key added by .push(). when i add a marker via the app. Any ideas on how to get it to read the marker info that is under the random key? My code looks as follows:
public class MapsActivity extends FragmentActivity implements
OnMapReadyCallback, GoogleMap.OnMarkerClickListener {
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference mProfileRef = firebaseDatabase.getReference("Studios");
ChildEventListener mChildEventListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
Button addAStudio = (Button) findViewById(R.id.addAStudio);
addAStudio.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(MapsActivity.this, Rent.class);
startActivity(intent);
}
});
}
#Override
public void onMapReady(GoogleMap googleMap){
googleMap.setOnMarkerClickListener(this);
LatLng Copenhagen = new LatLng(55.67, 12.56);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(Copenhagen, 18));
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
//get marker info from Firebase Database and add to map
addMarkersToMap(googleMap);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
googleMap.setMyLocationEnabled(true);
}
#Override
public void onStop(){
if(mChildEventListener != null)
mProfileRef.removeEventListener(mChildEventListener);
super.onStop();
}
private void addMarkersToMap(final GoogleMap map){
mChildEventListener = mProfileRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
FirebaseMarker marker = dataSnapshot.getValue(FirebaseMarker.class);
String StudioName = marker.getStudioName();
String StudioAdress = marker.getStudioAddress();
String StudioDescription = marker.getStudioDescription();
double latitude = marker.getLatitude();
double longitude = marker.getLongitude();
LatLng location = new LatLng(latitude, longitude);
map.addMarker(new MarkerOptions()
.position(location)
.title(StudioName)
.snippet(StudioAdress)
.snippet(StudioDescription))
.showInfoWindow();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public boolean onMarkerClick(Marker marker) {
return false;
}
And
public class FirebaseMarker {
public String studioName;
public String studioDescription;
public String studioAddress;
public double latitude;
public double longitude;
//required empty constructor
public FirebaseMarker() {
}
public FirebaseMarker(String studioName, String studioDescription, String studioAdress, double latitude, double longitude) {
this.studioName = studioName;
this.studioDescription = studioDescription;
this.studioAddress = studioAdress;
this.latitude = latitude;
this.longitude = longitude;
}
public String getStudioName() {
return studioName;
}
public void setStudioName(String studioName) {
this.studioName = studioName;
}
public String getStudioDescription() {
return studioDescription;
}
public void setStudioDescription(String studioDescription) {
this.studioDescription = studioDescription;
}
public String getStudioAddress() {
return studioAddress;
}
public void setStudioAddress(String studioAddress) {
this.studioAddress = studioAddress;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
}
and finally where add a new marker to the database:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rent);
saveStudio = findViewById(R.id.saveStudio);
studioNameTextField = findViewById(R.id.studioNameTextField);
studioInfoTextField = findViewById(R.id.studioInfoTextField);
studioAdressTextField = findViewById(R.id.studioAdressTextField);
mDatabase = FirebaseDatabase.getInstance();
mDataBaseRef = mDatabase.getReference("Studios");
saveStudio = findViewById(R.id.saveStudio);
saveStudio.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Map<String, FirebaseMarker> newStudioAdd = new HashMap<>();
newStudioAdd.put(studioNameTextField.getText().toString(),
new FirebaseMarker(
studioNameTextField.getText().toString(),
studioInfoTextField.getText().toString(),
studioAdressTextField.getText().toString(),
53.669115, 12.560311
)
);
mDataBaseRef.push().setValue(newStudioAdd);
Intent intent = new Intent(Rent.this, MapsActivity.class);
startActivity(intent);
}
});
}
as of now the latitude and longitude are hardcoded, as i want it to read the markers before i continue.
This is happening because Studio 1 and T1 have different paths than the T2. As I see in your database schema, your T2 as an extra child (-LH-3 ... GbsF) which is generated by the push() method. In order to display all those objects correctly, you need to have the same paths for all objects. So you can achieve this, either by adding Studio 1 and T1 in the same way, using the push() method or by adding the T2 without using the push() method.
FirebaseMarker firebaseMarker = new FirebaseMarker(
studioNameTextField.getText().toString(),
studioInfoTextField.getText().toString(),
studioAdressTextField.getText().toString(),
53.669115, 12.560311);
mDataBaseRef.push().setValue(firebaseMarker);
Assuming that the Studios node is a direct child of your Firebase database, here is how you can add the markers on the map:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference studiosRef = rootRef.child("Studios");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
FirebaseMarker marker = dataSnapshot.getValue(FirebaseMarker.class);
String StudioName = marker.getStudioName();
String StudioAdress = marker.getStudioAddress();
String StudioDescription = marker.getStudioDescription();
double latitude = marker.getLatitude();
double longitude = marker.getLongitude();
LatLng location = new LatLng(latitude, longitude);
map.addMarker(new MarkerOptions()
.position(location)
.title(StudioName)
.snippet(StudioAdress)
.snippet(StudioDescription))
.showInfoWindow();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
studiosRef.addListenerForSingleValueEvent(valueEventListener);
I have an Activity called ChatActivity where the users are going to be messaging each other. The activity is retrieving the messages as they are sent but when messages are displayed here are's duplicates of every message.
I do have AutoRefresh but it's not refreshing the way I want it to refresh. In my Activity there is swipe refresh as well and when I swipe it refreshes properly. This is the snap when swipe refresh is used:
How can I make my Auto Refresh display my messages like how it does when I swipe to refresh it? here is my code:
public class ChatActivity extends AppCompatActivity {
private Toolbar mChatToolbar; //used
private String mChatUser; //used
private String mthumb_image;
private String userName;
private String mCurrentUserId;
private TextView mUserStatus;
private EditText mChatMessageView;
private CircleImageView mProfileImage;
private FirebaseAuth mAuth;
private ImageButton mChatAddBtn;
private DatabaseReference mRootRef;
// Storage Firebase
private StorageReference mImageStorage;
private static final int GALLERY_PICK = 1;
private RecyclerView mMessagesList;
private SwipeRefreshLayout mRefreshLayout;
private ArrayList<Messages> arrayList_Messages = new ArrayList<>();
private MessageAdapter mAdapter;
private static final int TOTAL_ITEMS_TO_LOAD = 10;
private int mCurrentPage = 1;
private final Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
mChatMessageView = (EditText) findViewById(R.id.chat_message_view);
mChatAddBtn = (ImageButton) findViewById(R.id.chat_add_btn);
mChatToolbar = (Toolbar) findViewById(R.id.chat_app_bar);
setSupportActionBar(mChatToolbar);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowCustomEnabled(true);
//for Custom Action bar
actionBar.setDisplayShowCustomEnabled(true);
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View customBar = inflater.inflate(R.layout.chat_custom_bar,null);
actionBar.setCustomView(customBar);
//getting intent Data
gettingIntentData();
// initializing user view
intCustomBarViewAndSetData();
doTheAutoRefresh();
mRootRef = FirebaseDatabase.getInstance().getReference();
mAuth = FirebaseAuth.getInstance();
mCurrentUserId = mAuth.getCurrentUser().getUid();
//------- IMAGE STORAGE ---------
mImageStorage = FirebaseStorage.getInstance().getReference();
mRootRef.child("Chat").child(mCurrentUserId).child(mChatUser).child("seen").setValue(true);
LoadMessages();
//getting information about user online or offline and thumb image
mRootRef.child("Users").child(mChatUser).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String thumb_image = dataSnapshot.child("thumb_image").getValue().toString();
Picasso.with(ChatActivity.this).load(thumb_image).placeholder(R.drawable.my_profile).into(mProfileImage);
String lastSeen = dataSnapshot.child("online").getValue().toString();
if(lastSeen.equals("true")){
mUserStatus.setText("Online");
}
else{
//converting string into long
Long lastTime = Long.parseLong(lastSeen);
// creating an instance of GetTimeAgo class
GetTimeAgo getTimeAgo = new GetTimeAgo();
String lastSeenTime = GetTimeAgo.getTimeAgo(lastTime,getApplicationContext());
mUserStatus.setText(lastSeenTime);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
//for creating chat object
mRootRef.child("Chat").child(mCurrentUserId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(!dataSnapshot.hasChild(mChatUser)){
Map chatAddMap = new HashMap();
chatAddMap.put("seen",false);
chatAddMap.put("timestamp", ServerValue.TIMESTAMP);
Map chatUserMap = new HashMap();
chatUserMap.put("Chat/"+mCurrentUserId+"/"+mChatUser, chatAddMap);
chatUserMap.put("Chat/"+mChatUser+"/"+mCurrentUserId, chatAddMap);
mRootRef.updateChildren(chatUserMap, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if(databaseError!= null){
Toast.makeText(ChatActivity.this, "Error: "+databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
// Retrieving the chat messages into recyclerview
LoadMessages();
mRefreshLayout.setRefreshing(true);
mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
mCurrentPage++;
//onRefresh remove the current messages from arraylist and load new messages
arrayList_Messages.clear();
// Load message
LoadMessages();
}
});
}
private void doTheAutoRefresh()
{
handler.postDelayed(new Runnable() {
#Override
public void run()
{
LoadMessages();
// Write code for your refresh logic
doTheAutoRefresh();
}
}, 5000);
}
// Load all messages from database into recyclerView
private void LoadMessages() {
DatabaseReference messageRef = mRootRef.child("messages").child(mCurrentUserId).child(mChatUser);
//Query to load message per page i.e. 10
/*
per page load 10 message and onRefresh mCurrentpage is increment by 1
page 1 => load 10 messages (mCurrentPage = 1 then 1*10 =10)
page 2 => load 20 messages (mCurrentPage = 2 then 2*10 =20) and so on
*/
Query messageQuery = messageRef.limitToLast(mCurrentPage * TOTAL_ITEMS_TO_LOAD);
messageQuery.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Messages messages = dataSnapshot.getValue(Messages.class);
arrayList_Messages.add(messages);
mRefreshLayout.setRefreshing(true);
mAdapter.notifyDataSetChanged();
mMessagesList.scrollToPosition(arrayList_Messages.size()-1);
//when data load completely set refreshing
mRefreshLayout.setRefreshing(false);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
// send button
public void chatSendButton(View view){
sendMessage();
}
//sending a message
private void sendMessage() {
String message = mChatMessageView.getText().toString().trim();
if(!TextUtils.isEmpty(message)){
mChatMessageView.setText("");
String current_user_ref="messages/"+mCurrentUserId+"/"+mChatUser;
String chat_user_ref= "messages/"+mChatUser+"/"+mCurrentUserId;
DatabaseReference chat_push_key = mRootRef.child("messages").child(mCurrentUserId).
child(mChatUser).push();
String push_key = chat_push_key.getKey();
Map messageMap = new HashMap();
messageMap.put("message",message);
messageMap.put("type","text");
messageMap.put("from",mCurrentUserId);
messageMap.put("seen",false);
messageMap.put("time", ServerValue.TIMESTAMP);
Map messageUserMap = new HashMap();
messageUserMap.put(current_user_ref+ "/"+push_key,messageMap);
messageUserMap.put(chat_user_ref+ "/"+push_key,messageMap);
mRootRef.updateChildren(messageUserMap, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if(databaseError!=null){
Log.d("TAG",databaseError.getMessage().toString());
}
}
});
}
}
//add button
public void chatAddButton(View view){
mChatAddBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent galleryIntent = new Intent();
galleryIntent.setType("image/*");
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(galleryIntent, "SELECT IMAGE"), GALLERY_PICK);
}
});
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == GALLERY_PICK && resultCode == RESULT_OK){
Uri imageUri = data.getData();
final String current_user_ref = "messages/" + mCurrentUserId + "/" + mChatUser;
final String chat_user_ref = "messages/" + mChatUser + "/" + mCurrentUserId;
DatabaseReference user_message_push = mRootRef.child("messages")
.child(mCurrentUserId).child(mChatUser).push();
final String push_id = user_message_push.getKey();
StorageReference filepath = mImageStorage.child("message_images").child( push_id + ".jpg");
filepath.putFile(imageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
if(task.isSuccessful()){
String download_url = task.getResult().getDownloadUrl().toString();
Map messageMap = new HashMap();
messageMap.put("message", download_url);
messageMap.put("seen", false);
messageMap.put("type", "image");
messageMap.put("time", ServerValue.TIMESTAMP);
messageMap.put("from", mCurrentUserId);
Map messageUserMap = new HashMap();
messageUserMap.put(current_user_ref + "/" + push_id, messageMap);
messageUserMap.put(chat_user_ref + "/" + push_id, messageMap);
mChatMessageView.setText("");
mRootRef.updateChildren(messageUserMap, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if(databaseError != null){
Log.d("CHAT_LOG", databaseError.getMessage().toString());
}
}
});
}
}
});
}
}
private void intCustomBarViewAndSetData() {
TextView mTitleView = (TextView) findViewById(R.id.custom_bar_title);
mUserStatus = (TextView) findViewById(R.id.custom_bar_seen);
mProfileImage = (CircleImageView) findViewById(R.id.custom_bar_image);
mMessagesList = (RecyclerView) findViewById(R.id.messages_list);
mMessagesList.setLayoutManager(new LinearLayoutManager(this));
mRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.message_swipe_layout);
mMessagesList.setHasFixedSize(true);
mAdapter = new MessageAdapter(this, arrayList_Messages);
mMessagesList.setAdapter(mAdapter);
//showing name on toolbar
mTitleView.setText(userName);
mTitleView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent profileIntent = new Intent(ChatActivity.this, ProfileActivity.class);
profileIntent.putExtra("user_id", mChatUser);
startActivity(profileIntent);
}
});
}
private void gettingIntentData() {
Intent intent =getIntent();
userName = intent.getStringExtra("Username");
mChatUser = intent.getStringExtra("user_id");
}
}
Clear the list before load in doTheAutoRefresh().
arrayList_Messages.clear();
LoadMessages();
I'm new to android and I cannot figure out why my onCreate() in my activity is being called over and over.
In my MainActivity I have this function search, that is called when a button is pressed.
private void search(View v){
//Get input fields if null then dont restrict search
...
...
Intent i = new Intent(getApplicationContext(), PersonActivity.class);
i.putExtra("miles",numMiles);
i.putExtra("min",numMin);
startActivity(i);
}
Then in my PersonActivity Class I have this onCreate Method.
public class PersonActivity extends ActionBarActivity {
private static final String TAG = MainActivity.class.getSimpleName();
public ArrayList<PersonInfo> people;
private LayoutInflater inflater;
private Context _context;
public PersonInfoListAdapter _adapter;
public static ListView _list;
public int _position;
private static final String APP_ID = "4cae6e4d7d89bc4b02196b352ae91650";
// Find this in your developer console
private static final String API_KEY = "4A3243EECEA842F7B1FC6E7A4B00DA7A";
public PersonActivity() {}
#Override
protected void onCreate(Bundle savedInstanceState) {;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_person);
View listV = findViewById(R.id.friendList);
_list = (ListView) listV;
CMApiCredentials.initialize(APP_ID, API_KEY, getApplicationContext());
try {
people = new ArrayList<PersonInfo>();
Context context = _list.getContext();
_adapter = new PersonInfoListAdapter(context, people);
_list.setAdapter(_adapter);
} catch (Exception e) {
e.printStackTrace();
}
_list.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
View parentRow = (View) view.getParent();
return true;
}
});
Integer numMin = -1;
Integer numMiles = -1;
Bundle extras = getIntent().getExtras();
if (extras != null) {
numMin = extras.getInt("min");
numMiles = extras.getInt("miles");
Log.d("Person Activity", "Miles" + numMiles.toString());
}
queryForPeople(numMiles, numMin);
}
private void queryForPeople(Integer numMiles, Integer numMin){
//Get users location
LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
Location lastKnownLoc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
double lat = lastKnownLoc.getLatitude();
double lon = lastKnownLoc.getLongitude();
Intent myIntent = new Intent(this, PersonActivity.class);
startActivity(myIntent);
//search for friends
PersonInfo.searchObjects(this, SearchQuery.filter("location").near(lon, lat).within(numMiles, DistanceUnits.mi).searchQuery(),
new Response.Listener<CMObjectResponse>() {
#Override
public void onResponse(CMObjectResponse response) {
List<CMObject> objectList = response.getObjects();
for (CMObject o : objectList) {
PersonInfo p = (PersonInfo) o;
people.add(p);
Log.d(TAG, "Person was found: " + p.getName());
}
}
});
_adapter.notifyDataSetChanged();
}
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
Toast.makeText(
getBaseContext(),
"Location changed: Lat: " + loc.getLatitude() + " Lng: "
+ loc.getLongitude(), Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderDisabled(String provider) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
The problem is this onCreate() in my personActivity is being called over an over. And I cannot figure out why. queryForPeople makes a call to and API that returns information that I use to populate the people ArrayList that is used in the adapter.
Any Ideas?
Your queryForPeople method calls startActivity on the activity you're already running from. So this will end up being infinitely recursive. I don't see why you would want to start yourself from anywhere in your activity, it just doesn't make sense. Unless you intended something else with those two lines, simply remove them.