The marker is not display using Geofire - android-studio

I am using Geofire to display all buses near by the users all getting well but the marker is not showing in map when the key is enter here is my code
List<Marker> markerslist = new ArrayList<>();
private void getbusesatlocation() {
databaseReference = FirebaseDatabase.getInstance().getReference().child(("tracker"));
final GeoFire geoFire = new GeoFire(databaseReference);
GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(20.899580, 77.750101), 1000);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
#Override
public void onKeyEntered(String key, GeoLocation location) {
Log.i("key", key);
for (Marker marker : markerslist) {
if (marker.getTag().equals(key))
return;
}
LatLng buslocation = new LatLng(location.latitude, location.longitude);
Marker mMarker = mMap.addMarker(new MarkerOptions().position(buslocation).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)));
mMarker.setTag(key);
markerslist.add(mMarker);
}
#Override
public void onKeyExited(String key) {
Log.i("exited", key);
for (Marker marker : markerslist) {
if (marker.getTag().equals(key)) {
marker.remove();
markerslist.remove(marker);
return;
}
}
}
#Override
public void onKeyMoved(String key, GeoLocation location) {
Log.i("moving", key);
for (Marker marker : markerslist) {
if (marker.getTag().equals(key)) {
marker.setPosition(new LatLng(location.latitude, location.longitude));
}
}
}
#Override
public void onGeoQueryReady() {
}
#Override
public void onGeoQueryError(DatabaseError error) {
}
});
}
I have checked onkey is giving me latitude and longitude but when i am adding the marker in map the marker is not showing please help me

I have solved my problem just using old dependency of Geofire.I do not know what is happening with new version of geofire but this version is working fine for me implementation 'com.firebase:geofire-java:2.3.1' ;)

Related

Android studio how to delete messages in chat properly

I'm facing an issue with deleting messages in my chat app. I have two types of messages, image and text. and I delete them like this:
DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference("Chats");
Query query = dbRef.orderByChild("time").equalTo(msgTimeStamp);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for(DataSnapshot ds: snapshot.getChildren()) {
if (ds.child("sender").getValue().equals(myUID) && !ds.child("message").getValue().toString().equalsIgnoreCase("This message was deleted")) {
holder.messageLayout.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
View view = LayoutInflater.from(mContext).inflate(R.layout.custon_view_for_dialog, null);
builder.setView(view);
Button delete = view.findViewById(R.id.delete);
Button cancel = view.findViewById(R.id.cancel);
final AlertDialog dialog = builder.create();
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deleteMessage(position);
dialog.dismiss();
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
return true;
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
And here is the delete function:
private void deleteMessage(int position) {
String msgTimeStamp = mChats.get(position).getTime();
DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference("Chats");
Query query = dbRef.orderByChild("time").equalTo(msgTimeStamp);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (final DataSnapshot ds: snapshot.getChildren())
{
if(ds.child("type").getValue().equals("text"))
{
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("message", "This message was deleted");
ds.getRef().updateChildren(hashMap);
}
else
{
FirebaseStorage firebaseStorage = FirebaseStorage.getInstance();
StorageReference storageReference = firebaseStorage.getReferenceFromUrl(ds.child("message").getValue().toString());
storageReference.delete().addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("message", "This message was deleted");
hashMap.put("type","text");
ds.getRef().updateChildren(hashMap);
}
});
}
}
so my idea here is if the message is text, then I set the text as "This message was deleted" and if the message is an image, I change its type to text and set it also to "This message was deleted" and delete the image from Firebase Storage. The deleting works for me and here is how it looks like after deleting:
The issue I'm facing is that I can still delete the message even if it is already deleted!!
I don't want the AlertDialog for deleting to appear when I click on a deleted message !!.
as you can see I added this to my condition :
!ds.child("message").getValue().toString().equalsIgnoreCase("This message was deleted")
but the issue is still there, deleted messages can be deleted more than once! how can I prevent this from happening? please help

Toggle TextToSpeech on and off using a togglebutton?

So i have an app connected to firebase. The app retrieves data(a string) from firebase into a text view and then the TextToSpeech feature reads the text out(not from the textView but it itself retrieves the same data from firebase real-time database). I have used onDataChange() meathod so the texttospeech feature reads the text out as soon as any change in the data occurs on firebase, and not on the click of any button. Now i want to place a toggle button in my app and use it to either turn the tts feature on or off but i cant get it to work. When the toggle button is off, i want the texttospeech feature to stop and when the button state is on, i want the texttospeech feature to turn back on.This is what ive tried:
mtts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR){
mtts.setLanguage(Locale.US); }else{
Toast.makeText(MainActivity.this, "Couldnt initialize speech function!", Toast.LENGTH_SHORT).show();
}
}
}); mIvToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
reff = FirebaseDatabase.getInstance().getReference().child("Match").child("Screen1");
reff.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String tts= dataSnapshot.getValue().toString();
mtts.speak(tts, TextToSpeech.QUEUE_FLUSH, null);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}else{
mtts.stop();
mtts.shutdown();
}
}
});
TIA !
When you attach a valueEventListener the listener will trigger as long as there is change in the data, even though you checked the toggle to off. So the thing that you should do is to remove the listener when you are done:
Directly under this:
mtts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR){
mtts.setLanguage(Locale.US);
}else{
Toast.makeText(MainActivity.this, "Couldnt initialize speech function!", Toast.LENGTH_SHORT).show();
}
}
});
Add these:
//the reference
reff=FirebaseDatabase.getInstance().getReference().child("Match").child("Screen1");
//make a listener
ValueEventListener listener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String tts= dataSnapshot.getValue().toString();
mtts.speak(tts, TextToSpeech.QUEUE_FLUSH, null);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
}
};
//toggle
mIvToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
//add listener
reff.addValueEventListener(listener);
}else{
//remove listener
reff.removeEventListener(listener);
mtts.stop();
mtts.shutdown();
}
}
});

Trouble with logic flow for filtering search method on CS50 Pokedex

The app compiles fine but initially it shows nothing in the list. When I use the search bar, it doesn't display my filtered information and when I get rid of search, the entire list is finally display. Any help would be really appreciated, this is my first time ever coding in Java.
Here is my adapter code.
public class PokedexAdapter extends RecyclerView.Adapter<PokedexAdapter.PokedexViewHolder> implements Filterable {
public static class PokedexViewHolder extends RecyclerView.ViewHolder {
public LinearLayout containerView;
public TextView textView;
PokedexViewHolder(View view) {
super(view);
containerView = view.findViewById(R.id.pokedex_row);
textView = view.findViewById(R.id.pokedex_row_text_view);
containerView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Pokemon current = (Pokemon) containerView.getTag();
Intent intent = new Intent(v.getContext(), PokemonActivity.class);
intent.putExtra("name", current.getName());
intent.putExtra("url", current.getUrl());
v.getContext().startActivity(intent);
}
});
}
}
private List<Pokemon> pokemon = new ArrayList<>();
private RequestQueue requestQueue;
private List<Pokemon> filteredPokemon = new ArrayList<>();
PokedexAdapter(Context context) {
requestQueue = Volley.newRequestQueue(context);
loadPokemon();
}
public void loadPokemon() {
String url = "https://pokeapi.co/api/v2/pokemon?limit=365";
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray results = response.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
JSONObject result = results.getJSONObject(i);
String name = result.getString("name");
pokemon.add(new Pokemon(
name.substring(0, 1).toUpperCase() + name.substring(1),
result.getString("url")
));
}
notifyDataSetChanged();
} catch (JSONException e) {
Log.e("cs50", "Json error", e);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("cs50", "Pokemon list error");
}
});
requestQueue.add(request);
}
#NonNull
#Override
public PokedexViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.pokedex_row, parent, false);
return new PokedexViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull PokedexViewHolder viewholder, int position){
Pokemon results = pokemon.get(position);
viewholder.textView.setText(results.getName());
viewholder.containerView.setTag(results);
}
#Override
public int getItemCount() {
return filteredPokemon.size();
}
#Override
public Filter getFilter() {
return new PokemonFilter();
}
private class PokemonFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
// implement your search here
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0) {
//No filter implemented return whole list
results.values = pokemon;
results.count = pokemon.size();
}
else {
List<Pokemon> filtered = new ArrayList<>();
for (Pokemon pokemon : filtered) {
if (pokemon.getName().toUpperCase().startsWith(constraint.toString())) {
filtered.add(pokemon);
}
}
results.values = filtered;
results.count = filtered.size();
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredPokemon = (List<Pokemon>) results.values;
notifyDataSetChanged();
}
}
}
I really am not sure what is going on and given my knowledge of the subject, you could really help with understanding the logic better. Please let me know if there is any other information you would like from me about the code.
You might have already solved it and finished the Android tracks but this was the only thing I changed and it seemed to work after that.
for (Pokemon pokemon : pokemon) {
if (pokemon.getName().toUpperCase().startsWith(constraint.toString().toUpperCase()) {
filtered.add(pokemon);
}
}

Android Don't execute anything until location variable exists

Goodmorning,
I've tried to implement the method that request permission first and than execute something but without success ...
Here is my MainActivity code:
public class MainActivity extends AppCompatActivity {
public static String latitudineCorrente = ""; //current Latitude
public static String longitudineCorrente = ""; //current Longitude
private SharedPreferences sharedPreferences; //shared preferences
private SharedPreferences.Editor mEditor; // shared preferences editor
/* Variable for getting location */
private FusedLocationProviderClient fusedLocationProviderClient;
private LocationRequest locationRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String appLanguage = "ita";
LanguageUtil.setAppLanguage(getApplicationContext(), appLanguage);
/* .... other code.... */
sharedPreferences = this.getSharedPreferences("appname", MODE_PRIVATE);
mEditor = sharedPreferences.edit(); // set edit sharedpreferences
richiamaPermessi(); //permission request
requestLocationUpdates(); // function requestlocationupdates();
CaricamentoInizialeApplicazione(); // function for presetting configurations
}
private void CaricamentoInizialeApplicazione() {
boolean configIniziale = sharedPreferences.getBoolean("configurazioneinizialeok", false);
if(!configIniziale)
{
/* can't execute this because Double.parseDouble(this.latitudineCorrente), Double.parseDouble(this.longitudineCorrente) */
ApiMarkers.getMarkers(MainActivity.this, 0, 400,
Double.parseDouble(this.latitudineCorrente), Double.parseDouble(this.longitudineCorrente),
0, 0,0,1, 0,0,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
/* response elaborations */
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
dialog.dismiss();
Toast.makeText(MainActivity.this, "" + error.getMessage(), Toast.LENGTH_LONG).show();
error.printStackTrace();
}
});
mEditor.putBoolean("configurazioneinizialeok", true);
mEditor.commit();
}
}
/* Function for requist location updates */
public void requestLocationUpdates() {
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) ==
PermissionChecker.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) ==
PermissionChecker.PERMISSION_GRANTED) {
fusedLocationProviderClient = new FusedLocationProviderClient(this);
locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setFastestInterval(1500);
locationRequest.setInterval(3000);
fusedLocationProviderClient.requestLocationUpdates(locationRequest, new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
mEditor = sharedPreferences.edit();
mEditor.putString("latitudine", String.valueOf(locationResult.getLastLocation().getLatitude()));
mEditor.putString("longitudine", String.valueOf(locationResult.getLastLocation().getLongitude()));
MainActivity.latitudineCorrente = String.valueOf(locationResult.getLastLocation().getLatitude());
MainActivity.longitudineCorrente = String.valueOf(locationResult.getLastLocation().getLongitude());
Log.d("coordinate", "MAIN ACTIVITY: Latitudine: " + MainActivity.latitudineCorrente + "/"
+ "Longitudine: " + MainActivity.longitudineCorrente);
}
}, getMainLooper());
} else richiamaPermessi();
}
/* Function for requesting access */
public void richiamaPermessi()
{
Permissions.check(this, new String[] { Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION},
"Permessi di locazione obbligatori per determinare la propria posizione!",
new Permissions.Options().setSettingsDialogTitle("Avviso").setRationaleDialogTitle("Permessi locazione"),
new PermissionHandler() {
#Override
public void onGranted() {
requestLocationUpdates();
}
#Override
public void onDenied(Context context, ArrayList<String> deniedPermissions) {
super.onDenied(context, deniedPermissions);
richiamaPermessi();
}
});
}
}
The problem is executing function ApiMarkers.getMarkers(.... with latitude and longitude filled ...) but can't execute because latitude and longitude are not loaded... I spent two nights without solution :(
Thanks for any help!
Cristian

AltBeacon api return empty collection while ranging beacons

I am trying to range beacons and I am doing exactly what it is written here:
http://altbeacon.github.io/android-beacon-library/samples.html
didRangeBeaconsInRegion method is firing but always with empty collection.
I have installed "locate" by altbeacon and it located 3 beacons.
this is my code: am I missing something?
public class BeaconSingletone implements BeaconConsumer {
private static BeaconSingletone instance;
private final org.altbeacon.beacon.BeaconManager beaconManager2;
private ArrayList<BeaconThin> listNearBeacons = new ArrayList<>();
BeaconRegion region = new BeaconRegion("ranged region",
UUID.fromString("B9407F30-F5F8-466E-AFF9-25556B57FE6D"), null, null);
private List<EventInterface> listeners = new ArrayList<EventInterface>();
private BeaconSingletone()
{
beaconManager2 = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(ar_activity.get());
// To detect proprietary beacons, you must add a line like below corresponding to your beacon
// type. Do a web search for "setBeaconLayout" to get the proper expression.
beaconManager2.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
beaconManager2.bind(this);
public static BeaconSingletone getInstance() {
if(instance == null) {
instance = new BeaconSingletone();
}
return instance;
}
private void showNotification(Region region, final List<Beacon> list) {
listNearBeacons.clear();
listNearBeacons.add(new BeaconThin(3514,7580,-1));
for (Iterator<EventInterface> i = listeners.iterator(); i.hasNext(); ) {
EventInterface item = i.next();
//item.NewBeaconFound(list.get(0).getMajor(),list.get(0).getMinor(),Utils.computeAccuracy(list.get(0)));
item.NewBeaconsFound(listNearBeacons);
}
return;
}
#Override
public void onBeaconServiceConnect() {
beaconManager2.addRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<org.altbeacon.beacon.Beacon> beacons, org.altbeacon.beacon.Region region) {
if (beacons.size() > 0) {
Log.i("BeaconManager", "The first beacon I see is about "+beacons.iterator().next().getDistance()+" meters away.");
}
}
});
try {
beaconManager2.startRangingBeaconsInRegion(new org.altbeacon.beacon.Region("mybeacons", null, null, null));
} catch (RemoteException e) { }{
}
}
#Override
public Context getApplicationContext() {
return ar_activity.get();
}
#Override
public void unbindService(ServiceConnection serviceConnection) {
ar_activity.get().unbindService(serviceConnection);
}
#Override
public boolean bindService(Intent intent, ServiceConnection serviceConnection, int i) {
return ar_activity.get().bindService(intent, serviceConnection, i);
}
}
You need to add a beacon layout for the beacon type you are using (iBeacon?). Replace this line:
beaconManager2.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
With the proper layout from here:
https://beaconlayout.wordpress.com

Resources