getting nearby users android with firebase - java

i am using firebase realtime database to store two types of users for two apps, users A will use App A to update their info and such, and users B will use app B to search nearby users A that they need their services from. I have been successful in uploading user A info from app A, even with location using geofire, now what i need is to show a list of usera A inside app B that are nearby. please help with answers regarding best ways/practices and if this here isnt the best method then suggestions are welcome..... thanks
public class MainActivity extends AppCompatActivity implements LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,Home.OnFragmentInteractionListener
{
public static String userId;
public static final int MY_REQUEST_PERMISSION_LOCATION = 1;
private long UPDATE_INTERVAL = 10 * 1000; /* 10 secs */
private long FASTEST_INTERVAL = 2000; /* 2 sec */
private static final String TAG_HOME = "home";
private static final String TAG_MY_PREF = "my__preferences";
private static final String TAG_NOTIFICATIONS = "notifications";
private static final String TAG_SETTINGS = "settings";
public static String CURRENT_TAG = TAG_HOME;
private String [] activityTitles;
SharedPreferences sharedPreferences;
String name;
String imageURI;
private boolean shouldLoadHomeFragOnBackPress = true;
private Handler mHandler;
Toolbar toolbar;
DrawerLayout drawer;
NavigationView navigationView;
private View navHeader;
private static int navItemIndex = 0;
private ImageView imgProfile;
private TextView txtName, txtEmail;
private DatabaseReference mDatabase;
GoogleApiClient mGoogleApiClient;
private boolean isPermissionGranted = false;
private LocationRequest mLocationRequest;
public double lat, lng;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById (R.id.toolbar);
setSupportActionBar(toolbar);
mHandler = new Handler ();
mGoogleApiClient = new GoogleApiClient . Builder (this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
activityTitles = getResources().getStringArray(R.array.nav_item_activity_titles);
drawer = (DrawerLayout) findViewById (R.id.drawer_layout);
navigationView = (NavigationView) findViewById (R.id.nav_view);
navHeader = navigationView.getHeaderView(0);
txtName = (TextView) navHeader . findViewById (R.id.username);
imgProfile = (ImageView) navHeader . findViewById (R.id.smallProfile);
setUpNavigationView();
if (savedInstanceState == null) {
navItemIndex = 0;
CURRENT_TAG = TAG_HOME;
loadHomeFragment();
}
sharedPreferences = getSharedPreferences(UserData, Context.MODE_PRIVATE);
name = sharedPreferences.getString(full_name, null);
imageURI = sharedPreferences.getString(imagesrc, null);
upload();
Glide.with(MainActivity.this).load(Uri.parse(imageURI)).into(imgProfile);
loadNavHeader();
}
public void loadNavHeader() {
txtName.setText(name);
}
private void loadHomeFragment() {
selectNavMenu();
// set toolbar title
setToolbarTitle();
// if user select the current navigation menu again, don't do anything
// just close the navigation drawer
if (getSupportFragmentManager().findFragmentByTag(CURRENT_TAG) != null) {
drawer.closeDrawers();
// show or hide the fab button
return;
}
Runnable mPendingRunnable = new Runnable() {
#Override
public void run() {
// update the main content by replacing fragments
Fragment fragment = getHomeFragment ();
FragmentTransaction fragmentTransaction = getSupportFragmentManager ().beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.fade_in,
android.R.anim.fade_out);
fragmentTransaction.replace(R.id.frame, fragment, CURRENT_TAG);
fragmentTransaction.commitAllowingStateLoss();
}
};
if (mPendingRunnable != null) {
mHandler.post(mPendingRunnable);
}
//Closing drawer on item click
drawer.closeDrawers();
// refresh toolbar menu
invalidateOptionsMenu();
}
private void upload() {
userId = sharedPreferences.getString("UID", null);
String username = sharedPreferences . getString (full_name, null);
String photoUri = sharedPreferences . getString (imagesrc, null);
mDatabase = FirebaseDatabase.getInstance().getReference("users/B");
mDatabase.child(userId).child("name").setValue(username);
mDatabase.child(userId).child("imageuri").setValue(photoUri);
}
#Override
public void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
public void onStop() {
super.onStop();
if (isPermissionGranted) {
mGoogleApiClient.disconnect();
}
}
public void onPause() {
if (isPermissionGranted)
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
super.onPause();
}
public void onResume() {
if (isPermissionGranted) {
if (mGoogleApiClient.isConnected())
startLocationUpdates();
}
super.onResume();
}
private Fragment getHomeFragment() {
switch(navItemIndex) {
case 0:
// home
Home home = new Home();
return home;
case 1:
//subjects
MYPref myPref = new MYPref();
return myPref;
case 2:
//
NotificationFragment notificationsFragment = new NotificationFragment();
return notificationsFragment;
case 3:
Settings settings = new Settings();
return settings;
default:
return new Home ();
}
}
private void setToolbarTitle() {
getSupportActionBar().setTitle(activityTitles[navItemIndex]);
}
private void selectNavMenu() {
navigationView.getMenu().getItem(navItemIndex).setChecked(true);
}
private void setUpNavigationView() {
//Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
navigationView.setNavigationItemSelectedListener(new NavigationView . OnNavigationItemSelectedListener () {
// This method will trigger on item Click of navigation menu
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Check to see which item was being clicked and perform appropriate action
switch(menuItem.getItemId()) {
//Replacing the main content with ContentFragment Which is our Inbox View;
case R . id . nav_home :
navItemIndex = 0;
CURRENT_TAG = TAG_HOME;
break;
case R . id . nav_my_subjects :
navItemIndex = 1;
CURRENT_TAG = TAG_MY_PREF;
break;
case R . id . nav_notification :
navItemIndex = 2;
CURRENT_TAG = TAG_NOTIFICATIONS;
break;
case R . id . nav_settings :
navItemIndex = 3;
CURRENT_TAG = TAG_SETTINGS;
break;
case R . id . nav_logout :
LoginManager.getInstance().logOut();
FirebaseAuth.getInstance().signOut();
Intent i = new Intent(MainActivity.this, LoginActivity.class);
startActivity(i);
finish();
default:
navItemIndex = 0;
}
//Checking if the item is in checked state or not, if not make it in checked state
if (menuItem.isChecked()) {
menuItem.setChecked(false);
} else {
menuItem.setChecked(true);
}
menuItem.setChecked(true);
loadHomeFragment();
return true;
}
});
ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) {
#Override
public void onDrawerClosed(View drawerView) {
// Code here will be triggered once the drawer closes as we dont want anything to happen so we leave this blank
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
// Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank
super.onDrawerOpened(drawerView);
}
};
//Setting the actionbarToggle to drawer layout
drawer.setDrawerListener(actionBarDrawerToggle);
//calling sync state is necessary or else your hamburger icon wont show up
actionBarDrawerToggle.syncState();
}
#Override
public void onBackPressed() {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawers();
return;
}
// This code loads home fragment when back key is pressed
// when user is in other fragment than home
if (shouldLoadHomeFragOnBackPress) {
// checking if user is on other navigation menu
// rather than home
if (navItemIndex != 0) {
navItemIndex = 0;
CURRENT_TAG = TAG_HOME;
loadHomeFragment();
return;
}
}
super.onBackPressed();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String []{ Manifest.permission.ACCESS_COARSE_LOCATION }, MY_REQUEST_PERMISSION_LOCATION);
}
return;
}
Location mCurrentLocation = LocationServices . FusedLocationApi . getLastLocation (mGoogleApiClient);
// Note that this can be NULL if last location isn't already known.
if (mCurrentLocation != null) {
// Print current location if not null
Log.d("DEBUG", "current location: " + mCurrentLocation.toString());
mDatabase = FirebaseDatabase.getInstance().getReference("users/B");
GeoFire gf = new GeoFire(mDatabase.child(userId));
gf.setLocation("location", new GeoLocation (mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude()));
lat = mCurrentLocation.getLatitude();
lng = mCurrentLocation.getLongitude();
}
// Begin polling for new location updates.
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
if (i == CAUSE_SERVICE_DISCONNECTED) {
Toast.makeText(this, "Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
} else if (i == CAUSE_NETWORK_LOST) {
Toast.makeText(this, "Network lost. Please re-connect.", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
String msg = "Updated Location: "+
Double.toString(location.getLatitude()) + "," +
Double.toString(location.getLongitude());
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
protected void startLocationUpdates() {
// Create the location request
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL)
.setFastestInterval(FASTEST_INTERVAL);
// Request location updates
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String []{ Manifest.permission.ACCESS_COARSE_LOCATION }, MY_REQUEST_PERMISSION_LOCATION);
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
return;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch(requestCode) {
case MY_REQUEST_PERMISSION_LOCATION :
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
isPermissionGranted = true;
} else {
isPermissionGranted = false;
}
}
}
#Override
public void onFragmentInteraction() {
}
}
my firebase database

For anyone who will find this useful i managed to do it by placing the addValueEventListenermethod of firebase within the addQueryEventListener and pass the String key that is returned by the onKeyEnteredmethod as part of the path in my database reference,
something like this
temp2=FirebaseDatabase.getInstance().getReference("users/A");
GeoFire geofire=new GeoFire(temp2.child("A_location"));
GeoQuery geoQuery=geofire.queryAtLocation(new GeoLocation(lat,lng),10);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
#Override
public void onKeyEntered(String key, GeoLocation location) {
temp2.child(key).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Person person1 = dataSnapshot.getValue(Person.class);
String name = person1.getName();
String imageUri = person1.getImageUri();
System.out.print(name + " " + imageUri);
Toast.makeText(getActivity(),name,Toast.LENGTH_LONG).show();
personList.add(new Person(name, imageUri));
RVAdapter adapter=new RVAdapter(getActivity(),personList);
rv.setAdapter(adapter);
}
My only question is now is this method efficient if there are alot of users?

Related

How to display a message in MainActivity if there is no Internet?

If there is no Internet, display a certain xml in full screen when the application starts, that there is no Internet, and if there is, perform MainActivity.
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, MaterialSearchBar.OnSearchActionListener, PopupMenu.OnMenuItemClickListener {
private static final String TAG = "MainActivity";
#SuppressLint("StaticFieldLeak")
public static MaterialSearchBar searchBar;
private DrawerLayout drawer;
private NavigationView navigationView;
private AdView mAdView;
private static List<String> listPermissionsNeeded;
public boolean isInternetAvailable() {
try {
InetAddress address = InetAddress.getByName("www.google.com");
return !address.equals("");
} catch (UnknownHostException e) {
// Log error
}
return false;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate: setting things up");
StaticUtils.requestQueue = (RequestQueue) Volley.newRequestQueue(getApplicationContext());
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Admob banner
MobileAds.initialize(this, new OnInitializationCompleteListener() {
#Override
public void onInitializationComplete(InitializationStatus initializationStatus) {
}
});
mAdView = findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
mAdView.loadAd(adRequest);
mAdView.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
super.onAdLoaded();
mAdView.setVisibility(View.VISIBLE);
}
#Override
public void onAdFailedToLoad(int i) {
super.onAdFailedToLoad(i);
mAdView.setVisibility(View.GONE);
}
});
//restoring recent searches list
StaticUtils.recentSearchesList = getArrayList(StaticUtils.KEY_LIST_PREFERENCCES);
if (StaticUtils.recentSearchesList==null){
StaticUtils.recentSearchesList = new ArrayList<>();
}
StaticUtils.savedImagesList = new ArrayList<>();
searchBar = findViewById(R.id.searchToolBar);
searchBar.setHint("Search Wallpapers");
searchBar.setOnSearchActionListener(this);
searchBar.hideSuggestionsList();
drawer = findViewById(R.id.drawer_layout);
navigationView = findViewById(R.id.nav_view);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
navigationView.setNavigationItemSelectedListener(this);
//sets home fragment open by default
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new HomeFragment()).commit();
playLogoAudio(); //to play the logo audio
searchEvents(); //advanced search events
}
#Override
public void onBackPressed() {
Log.d(TAG, "onBackPressed: back button invoked.");
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
public void grantPermissionBottomSheet(){
View dialogView = getLayoutInflater().inflate(R.layout.layout_bottomsheet, null);
final BottomSheetDialog dialog = new BottomSheetDialog(this);
Button ok = dialogView.findViewById(R.id.bt_bottomsheet);
ok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "onClick: bottomSheet button clicked.");
requestPermissions(MainActivity.this);
dialog.dismiss();
}
});
dialog.setContentView(dialogView);
dialog.show();
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Log.d(TAG, "onNavigationItemSelected: navigation item pressed.");
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_home) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new HomeFragment()).commit();
} else if (id == R.id.nav_saved) {
NetworkUtils network = new NetworkUtils(this);
if(network.checkConnection(drawer)){ //if network connected
Intent i = new Intent(MainActivity.this, SecondActivity.class);
i.putExtra(StaticUtils.KEY_FRAG_ID,2);
i.putExtra(StaticUtils.KEY_SEARCH_DATA,"Saved");
startActivity(i);
}
}else if (id == R.id.nav_downloads) {
//downloaded images
if (permissionsGranted(this)) {
Intent i = new Intent(MainActivity.this, SecondActivity.class);
i.putExtra(StaticUtils.KEY_FRAG_ID, 4); //4 for downloads section
i.putExtra(StaticUtils.KEY_SEARCH_DATA, "Downloads");
startActivity(i);
}else{
grantPermissionBottomSheet();
}
} else if (id == R.id.nav_share) {
//share the app intent
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "Hey! look what I found from play store.\nDownload cool & amazing wallpapers for your device from this app, "+getResources().getString(R.string.app_name)+", among various categories.\n\nCheck this out:\n"+StaticUtils.playStoreUrlDefault+getPackageName()+"\nDownload now:)");
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, "Share app through..."));
} else if (id == R.id.nav_rate) {
//rate the app intent
Uri uri = Uri.parse("market://details?id=" + getApplicationContext().getPackageName());
Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);
// To count with Play market backstack, After pressing back button,
// to taken back to our application, we need to add following flags to intent.
goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY |
Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
try {
startActivity(goToMarket);
} catch (Exception e) {
startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("http://play.google.com/store/apps/details?id=" + getApplicationContext().getPackageName())));
}
} else if (id == R.id.nav_about) {
//about page
Intent i = new Intent(MainActivity.this, SecondActivity.class);
i.putExtra(StaticUtils.KEY_FRAG_ID,3); //3 for about fragment
i.putExtra(StaticUtils.KEY_SEARCH_DATA,"About");
startActivity(i);
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
public void playLogoAudio(){
Log.d(TAG, "playLogoAudio: playing logo audio");
View headerView = navigationView.getHeaderView(0);
ImageView drawerLogo = headerView.findViewById(R.id.imageLogo);
drawerLogo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaPlayer mediaPlayer = MediaPlayer.create(MainActivity.this,R.raw.hello);
mediaPlayer.start();
}
});
}
#Override
public boolean onMenuItemClick(MenuItem item) {
return false;
}
#Override
public void onSearchStateChanged(boolean enabled) {
if (enabled){
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new SearchFragment()).commit();
}else{
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new HomeFragment()).commit();
}
}
#Override
public void onSearchConfirmed(CharSequence text) {
Log.d(TAG, "onSearchConfirmed: confirmed search: "+text);
Intent i = new Intent(this,SecondActivity.class);
i.putExtra(StaticUtils.KEY_FRAG_ID,1);
i.putExtra(StaticUtils.KEY_SEARCH_DATA,String.valueOf(text));
if(new NetworkUtils(getApplicationContext()).checkConnection(drawer)) { //start intent if network connected
StaticUtils.recentSearchesList.add(String.valueOf(text)); //adds the query to the recents list
if (StaticUtils.recentSearchesList.size()>20){
StaticUtils.recentSearchesList.remove(0);
}
SearchFragment.updateAdapter(this,StaticUtils.recentSearchesList);
searchBar.setText(""); //removes the search query
startActivity(i);
}
}
#Override
public void onButtonClicked(int buttonCode) {
Log.d(TAG, "onButtonClicked: search interface button clicked: "+buttonCode);
switch (buttonCode){
case MaterialSearchBar.BUTTON_NAVIGATION:
drawer.openDrawer(GravityCompat.START);
break;
case MaterialSearchBar.BUTTON_BACK:
searchBar.disableSearch();
}
}
#Override
public void onPointerCaptureChanged(boolean hasCapture) {}
public void saveArrayList(ArrayList<String> list, String key){
Log.d(TAG, "saveArrayList: saving recent searchList data");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = prefs.edit();
Gson gson = new Gson();
String json = gson.toJson(list);
editor.putString(key, json);
editor.apply();
}
public ArrayList<String> getArrayList(String key){
Log.d(TAG, "getArrayList: getting saved recent searchList data");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
Gson gson = new Gson();
String json = prefs.getString(key, null);
Type type = new TypeToken<ArrayList<String>>() {}.getType();
return gson.fromJson(json, type);
}
#Override
protected void onPause() {
super.onPause();
//Saving arraylist when activity gets paused
saveArrayList(StaticUtils.recentSearchesList,StaticUtils.KEY_LIST_PREFERENCCES);
}
public void searchEvents(){
Log.d(TAG, "searchEvents: managing the search events");
searchBar.addTextChangeListener(new TextWatcher() {
ArrayList<String> tempList = new ArrayList<>();
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
Log.d(TAG, "beforeTextChanged: clearing the list");
if (!tempList.isEmpty()){
tempList.clear();
}
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.d(TAG, "onTextChanged: changing search query");
for (String string : StaticUtils.recentSearchesList) {
if (s.length() > 0) {
if (string.matches("(?i)(" + s + ").*")) {
tempList.add(string);
SearchFragment.updateAdapter(getApplicationContext(), tempList);
}
}else{
SearchFragment.updateAdapter(getApplicationContext(), StaticUtils.recentSearchesList);
}
}
}
#Override
public void afterTextChanged(Editable s) {}
});
}
#Override
protected void onResume() {
super.onResume();
navigationView.setCheckedItem(R.id.nav_home);
if (!permissionsGranted(this)){ //checking and requesting permissions
grantPermissionBottomSheet();
}
}
public static boolean permissionsGranted(Context context) {
Log.d(TAG, "checkPermissions: checking if permissions granted.");
int result;
listPermissionsNeeded = new ArrayList<>();
for (String p:permissions) {
result = ContextCompat.checkSelfPermission(context,p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
//if all/some permissions not granted
return listPermissionsNeeded.isEmpty();
}
public static void requestPermissions(Activity activity){
Log.d(TAG, "requestPermissions: requesting permissions.");
ActivityCompat.requestPermissions(activity, listPermissionsNeeded.toArray(new
String[listPermissionsNeeded.size()]), StaticUtils.MULTIPLE_PERMISSIONS);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
Log.d(TAG, "onRequestPermissionsResult: action when permission granted or denied");
if (requestCode == StaticUtils.MULTIPLE_PERMISSIONS) {
if (grantResults.length <= 0) {
// no permissions granted.
showPermissionDialog();
}
}
}
public void showPermissionDialog(){
Log.d(TAG, "showPermissionDialog: requesting permissions");
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Are you sure?");
builder.setMessage("You'll not be able to use this app properly without these permissions.");
builder.setPositiveButton("Try Again", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//re-requesting permissions
requestPermissions(MainActivity.this);
}
});
builder.setNegativeButton("Cancel", null);
builder.show();
}
}
I would suggest some kind of different flow.
Most apps have something called a "Splash screen" (usually with a logo, sometimes kind of a progress bar).
what you can do is create a splash activity, - if there is internet call your MainActiviy, otherwise call another activity NetworkErrorActivity with the XML you want.

Implement Back Pressed In Android Fragments

I've been stuck in a situation and i need some help over here. There are many articles on this topic here but none of them answered my question. I want to implement onBackPressed() in fragments and show dialog box which shows to exit the application or not. Any help would be appreciated.
LoginFragment.java
public class LoginFragment extends Fragment {
public static final String TAG = LoginFragment.class.getSimpleName();
private EditText mEtEmail;
private EditText mEtPassword;
private Button mBtLogin;
private TextView mTvRegister;
private TextView mTvForgotPassword;
private TextInputLayout mTiEmail;
private TextInputLayout mTiPassword;
private ProgressBar mProgressBar;
private CompositeSubscription mSubscriptions;
private SharedPreferences mSharedPreferences;
#NonNull
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_login,container,false);
mSubscriptions = new CompositeSubscription();
initViews(view);
initSharedPreferences();
return view;
}
private void initViews(View v) {
mEtEmail = v.findViewById(R.id.et_email);
mEtPassword = v.findViewById(R.id.et_password);
mBtLogin = v.findViewById(R.id.btn_login);
mTiEmail = v.findViewById(R.id.ti_email);
mTiPassword = v.findViewById(R.id.ti_password);
mProgressBar = v.findViewById(R.id.progress);
mTvRegister = v.findViewById(R.id.tv_register);
mTvForgotPassword = v.findViewById(R.id.tv_forgot_password);
mBtLogin.setOnClickListener(view -> login());
mTvRegister.setOnClickListener(view -> goToRegister());
mTvForgotPassword.setOnClickListener(view -> showDialog());
}
private void initSharedPreferences() {
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
}
private void login() {
setError();
String email = mEtEmail.getText().toString();
String password = mEtPassword.getText().toString();
int err = 0;
if (!validateEmail(email)) {
err++;
mTiEmail.setError("Email should be valid !");
}
if (!validateFields(password)) {
err++;
mTiPassword.setError("Password should not be empty !");
}
if (err == 0) {
loginProcess(email,password);
mProgressBar.setVisibility(View.VISIBLE);
} else {
showSnackBarMessage("Enter Valid Details !");
}
}
private void setError() {
mTiEmail.setError(null);
mTiPassword.setError(null);
}
private void loginProcess(String email, String password) {
mSubscriptions.add(NetworkUtil.getRetrofit(email, password).login()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(this::handleResponse,this::handleError));
}
private void handleResponse(Response response) {
mProgressBar.setVisibility(View.GONE);
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putString(Constants.TOKEN,response.getToken());
editor.putString(Constants.EMAIL,response.getMessage());
editor.apply();
mEtEmail.setText(null);
mEtPassword.setText(null);
Intent intent = new Intent(getActivity(), HomeActivity.class);
startActivity(intent);
}
private void handleError(Throwable error) {
mProgressBar.setVisibility(View.GONE);
if (error instanceof HttpException) {
Gson gson = new GsonBuilder().create();
try {
String errorBody = ((HttpException) error).response().errorBody().string();
Response response = gson.fromJson(errorBody,Response.class);
showSnackBarMessage(response.getMessage());
} catch (IOException e) {
e.printStackTrace();
}
} else {
showSnackBarMessage("No Internet Connection!");
}
}
private void showSnackBarMessage(String message) {
if (getView() != null) {
Snackbar.make(getView(),message,Snackbar.LENGTH_SHORT).show();
}
}
private void goToRegister(){
FragmentTransaction ft = getFragmentManager().beginTransaction();
RegisterFragment fragment = new RegisterFragment();
ft.replace(R.id.fragmentFrame,fragment,RegisterFragment.TAG);
ft.addToBackStack(null).commit();
}
private void showDialog(){
ResetPasswordDialog fragment = new ResetPasswordDialog();
fragment.show(getFragmentManager(), ResetPasswordDialog.TAG);
}
#Override
public void onDestroy() {
super.onDestroy();
mSubscriptions.unsubscribe();
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity implements ResetPasswordDialog.Listener {
public static final String TAG = MainActivity.class.getSimpleName();
private LoginFragment mLoginFragment;
private ResetPasswordDialog mResetPasswordDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
loadFragment();
}
}
private void loadFragment() {
if (mLoginFragment == null) {
mLoginFragment = new LoginFragment();
}
getFragmentManager().beginTransaction().replace(R.id.fragmentFrame, mLoginFragment, LoginFragment.TAG).commit();
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
String data = intent.getData().getLastPathSegment();
Log.d(TAG, "onNewIntent: " + data);
mResetPasswordDialog = (ResetPasswordDialog) getFragmentManager().findFragmentByTag(ResetPasswordDialog.TAG);
if (mResetPasswordDialog != null)
mResetPasswordDialog.setToken(data);
}
#Override
public void onPasswordReset(String message) {
showSnackBarMessage(message);
}
private void showSnackBarMessage(String message) {
Snackbar.make(findViewById(R.id.activity_main), message, Snackbar.LENGTH_SHORT).show();
}
}
In My Login Fragment, I want to show a dialog box "Do you want to exit the application or not". On Yes it dismiss the current fragment and end the activity otherwise it'll remain active. Help please!
You can even try this way
MainActivity.java
#Override
public void onBackPressed() {
if (getFragmentManager() != null && getFragmentManager().getBackStackEntryCount() >= 1) {
String fragmentTag = getFragmentManager().findFragmentById(R.id.frame_container).getTag();
if(fragmentTag.equals(LoginFragment.getTag())){
// show Dialog code
}else{
super.onBackPressed();
}
} else {
super.onBackPressed();
}
}
Add this code in your main activity so that when login fragment is added and you click backpress, then on first if the fragment is added to fragment transaction, then first it finds the fragment and check if its tag is equals to the login fragment tag. Then if both tag matches, then you can show your exit alert dialog.
Android team has prepared a new way of handling the back button pressed on Fragments for us, so you should check this out. It's called OnBackPressedDispatcher.
You need to register OnBackPressedCallback to the fragment where do you want to intercept back button pressed. You can do it like this inside of the Fragment:
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
OnBackPressedCallback callback = new OnBackPressedCallback(true) {
#Override
public void handleOnBackPressed() {
//show exit dialog
}
};
requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
}

SharedPreferences gives default values on some devices

I am using this code to save key-value pair in shared preferences and its working fine on my device but on emulators and other real devices, it always returns the default values.
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
public static final String USER_PREFS = "com.aamir.friendlocator.friendlocator.USER_PREFERENCE_FILE_KEY";
SharedPreferences sharedPreferences;
private static String userKey="";
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
static final int PERMISSION_ACCESS_FINE_LOCATION = 1;
boolean FINE_LOCATION_PERMISSION_GRANTED = false;
TextView textViewLocationData;
TextView textViewKeyDisplay;
Button buttonRefresh;
Button btnCopyKey;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
goToActivityFriends();
}
});
fab.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_people_white_48dp));
textViewLocationData = (TextView) findViewById(R.id.textViewLocationData);
textViewKeyDisplay =(TextView) findViewById(R.id.tvKeyDisplay);
buttonRefresh = (Button) findViewById(R.id.buttonRefresh);
btnCopyKey = (Button) findViewById(R.id.btnCopyKey);
sharedPreferences = getApplicationContext().getSharedPreferences(USER_PREFS, Context.MODE_PRIVATE);
String key = sharedPreferences.getString("key", "");
if(!key.equals("")) {
textViewKeyDisplay.setText(key);
}
// Create an instance of GoogleAPIClient.
buildGoogleApiClient();
//user_sp = getSharedPreferences(USER_PREFS, 0);
buttonRefresh.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
displayLocation();
}
});
btnCopyKey.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("userKey", textViewKeyDisplay.getText().toString());
clipboard.setPrimaryClip(clip);
Toast.makeText(getBaseContext(), "Key copied !", Toast.LENGTH_SHORT).show();
}
});
}
#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
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) mGoogleApiClient.connect();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
private void displayLocation() {
int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
if ( permissionCheck != PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},PERMISSION_ACCESS_FINE_LOCATION);
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
textViewLocationData.setText(latitude + ", " + longitude);
sharedPreferences = getApplicationContext().getSharedPreferences(USER_PREFS, Context.MODE_PRIVATE);
String key = sharedPreferences.getString("key", "");
Log.d("User Key",key);
updateServers(latitude, longitude,key);
} else {
textViewLocationData
.setText("Couldn't get the location. Make sure location is enabled on the device");
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_ACCESS_FINE_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
FINE_LOCATION_PERMISSION_GRANTED = true;
//displayLocation();
} else {
FINE_LOCATION_PERMISSION_GRANTED = false;
}
return;
}
}
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i("", "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onConnected(Bundle arg0) {
// Once connected with google api, get the location
//displayLocation();
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
public void goToActivityFriends () {
Intent intent = new Intent(this, com.aamir.friendlocator.friendlocator.Friends.class);
startActivity(intent);
}
public void updateServers(Double lat,Double lon,String Key) {
if (Key.equals("")) {
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("")
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
SendLocation cleint = retrofit.create(SendLocation.class);
Call<com.aamir.friendlocator.friendlocator.Models.SendLocation> call = cleint.registerUser(String.valueOf(lat), String.valueOf(lon), Key);
call.enqueue(new Callback<com.aamir.friendlocator.friendlocator.Models.SendLocation>() {
#Override
public void onResponse(Call<com.aamir.friendlocator.friendlocator.Models.SendLocation> call, Response<com.aamir.friendlocator.friendlocator.Models.SendLocation> response) {
Log.d("Response", response.body().getUserKey());
if (!response.body().getUserKey().isEmpty()) {
String key_user = response.body().getUserKey();
textViewKeyDisplay.setText(key_user);
// Writing data to SharedPreferences
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("key", userKey);
if(editor.commit()){
Log.d("saved","saved");
}
}
}
#Override
public void onFailure(Call<com.aamir.friendlocator.friendlocator.Models.SendLocation> call, Throwable t) {
Log.e("Response", t.toString());
}
});
}
else {
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://demoanalysis.com/pro03/FriendLocator/")
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
SendLocation cleint = retrofit.create(SendLocation.class);
Call<com.aamir.friendlocator.friendlocator.Models.SendLocation> call = cleint.updateLocation(String.valueOf(lat), String.valueOf(lon), Key);
call.enqueue(new Callback<com.aamir.friendlocator.friendlocator.Models.SendLocation>() {
#Override
public void onResponse(Call<com.aamir.friendlocator.friendlocator.Models.SendLocation> call, Response<com.aamir.friendlocator.friendlocator.Models.SendLocation> response) {
Log.d("Response", response.body().getLocationStatus());
if (!response.body().getLocationStatus().isEmpty()) {
Toast.makeText(MainActivity.this,response.body().getLocationStatus(),Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<com.aamir.friendlocator.friendlocator.Models.SendLocation> call, Throwable t) {
Log.e("Response", t.toString());
}
});
}
}
}
On some devices, it's working perfectly. I did change context from this to getApplicationContext but no progress. I have updated the code.
Edit:
tl;dr : you write the wrong variable into the preferences.
Your variable userKey is never written and always an empty string.
In your retrofit onResponse you put userKey as value of "key" into the
preferences. This writes an empty string into the preferences. This will work and give you no error.
Please assign userKey with the value of key_user.
Your response is only stored to key_user.
Or directly remove the local variable key_user as follows:
public void onResponse(Call<com.aamir.friendlocator.friendlocator.Models.SendLocation> call, Response<com.aamir.friendlocator.friendlocator.Models.SendLocation> response) {
Log.d("Response", response.body().getUserKey());
if (!response.body().getUserKey().isEmpty()) {
String userKey = response.body().getUserKey();
textViewKeyDisplay.setText(userKey);
// Writing data to SharedPreferences
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("key", userKey);
if(editor.commit()){
Log.d("saved","saved");
}
}
}
Before:
In your code to save, you directly try to gather the previously saved value using editor.apply();
As documentation states out, apply will save your changes in background on a different thread.
Therefore your changes might not be saved at the time you try to get the value,
some lines below.
Try to use editor.commit(); instead and check if the problem is still there.
I'm share here my own Preference Class it's too easy so you can put in any project.
Put this class into your util folder or anywhere.
AppPreference.java
package util;
import android.content.Context;
import android.content.SharedPreferences;
/**
* Created by Pranav on 25/06/16.
*/
public class AppPreference {
public static final String PREF_IS_LOGIN = "prefIsLogin";
public static final class PREF_KEY {
public static final String LOGIN_STATUS = "loginstatus";
}
public static final void setStringPref(Context context, String prefKey, String key, String value) {
SharedPreferences sp = context.getSharedPreferences(prefKey, 0);
SharedPreferences.Editor edit = sp.edit();
edit.putString(key, value);
edit.commit();
}
public static final String getStringPref(Context context, String prefName, String key) {
SharedPreferences sp = context.getSharedPreferences(prefName, 0);
return sp.getString(key, "");
}
}
Set Preference Value in Login.java when user Login set value like this :
AppPreference.setStringPref(context, AppPreference.PREF_IS_LOGIN, AppPreference.PREF_KEY.LOGIN_STATUS, "0");
Then you will get Login Status Value in any Class by Calling like this :
String LoginStatus = AppPreference.getStringPref(context, AppPreference.PREF_IS_LOGIN, AppPreference.PREF_KEY.LOGIN_STATUS);

Preventing two markers for current location in Google Maps

My MainActivity looks like this:-
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, OnMapReadyCallback, LocationListener {
public static GoogleMap mMap;
public boolean flag = false;
public static boolean markerAlready = false;
public static PlaceAutocompleteFragment placeAutoComplete;
private LocationManager mLocationManager = null;
private String provider = null;
Circle c;
private Marker mCurrentPosition = null;
Marker marker;
public static Location location;
CircleOptions mOptions;
public static Location l;
FancyButton button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.btnGuide);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "Opens guides's details!", Toast.LENGTH_SHORT).show();
}
});
int perm = ContextCompat.checkSelfPermission(
MainActivity.this,
Manifest.permission.ACCESS_COARSE_LOCATION);
if (perm == PackageManager.PERMISSION_GRANTED) {
start();
final LocationManager manager = (LocationManager) getSystemService( Context.LOCATION_SERVICE );
if ( !manager.isProviderEnabled( LocationManager.GPS_PROVIDER ) ) {
buildAlertMessageNoGps();
}
} else {
ActivityCompat.requestPermissions(
MainActivity.this,
new String[] {Manifest.permission.ACCESS_COARSE_LOCATION},
44
);
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == 44) { //write request
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
start();
}
}
else if (Build.VERSION.SDK_INT >= 23 && !shouldShowRequestPermissionRationale(permissions[0])) {
Toast.makeText(MainActivity.this, "Go to Settings and Grant the permission to use this feature.", Toast.LENGTH_SHORT).show();
}
}
public void start()
{
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingSearchView searchView = findViewById(R.id.floating_search_view);
searchView.setSearchHint("");
placeAutoComplete = (PlaceAutocompleteFragment) getFragmentManager().findFragmentById(R.id.place_autocomplete);
Fragment a = getFragmentManager().findFragmentById(R.id.place_autocomplete);
a.setUserVisibleHint(false);
placeAutoComplete.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(Place place) {
if (marker != null)
marker.remove();
flag = true;
Log.d("Maps", "Place selected: " + place.getLatLng());
marker = mMap.addMarker(new MarkerOptions().position(place.getLatLng()).title(place.getName().toString()).zIndex(800));
mMap.moveCamera(CameraUpdateFactory.newLatLng(place.getLatLng()));
mMap.animateCamera(CameraUpdateFactory.zoomIn());
mMap.animateCamera(CameraUpdateFactory.zoomTo(13), 2000, null);
}
#Override
public void onError(Status status) {
Log.d("Maps", "An error occurred: " + status);
}
});
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
flag = false;
mMap.clear();
locateCurrentPosition();
placeAutoComplete.setText(null);
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
//region NavDrawer Activity
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
if(id == R.id.emergency){
List<String> HelpLineNumbers = new ArrayList<>();
HelpLineNumbers.add("Women's Helpline");
HelpLineNumbers.add("Police");
HelpLineNumbers.add("Hospital");
HelpLineNumbers.add("Fire Department");
HelpLineNumbers.add("Ambulance");
HelpLineNumbers.add("Men's Helpline");
final CharSequence[] helpLine = HelpLineNumbers.toArray(new String[HelpLineNumbers.size()]);
AlertDialog.Builder mBuilder = new AlertDialog.Builder(MainActivity.this);
mBuilder.setTitle("Helpline Numbers");
mBuilder.setItems(helpLine, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
String selectedText = helpLine[i].toString();
}
});
AlertDialog alertDialogObject = mBuilder.create();
alertDialogObject.show();
}
List<String> HelpLineNumbers = new ArrayList<>();
HelpLineNumbers.add("Women's Helpline");
HelpLineNumbers.add("Police");
HelpLineNumbers.add("Hospital");
HelpLineNumbers.add("Fire Department");
HelpLineNumbers.add("Ambulance");
HelpLineNumbers.add("Men's Helpline");
final CharSequence[] helpLine = HelpLineNumbers.toArray(new String[HelpLineNumbers.size()]);
AlertDialog.Builder mBuilder = new AlertDialog.Builder(MainActivity.this);
mBuilder.setTitle("Helpline Numbers");
mBuilder.setItems(helpLine, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
String selectedText = helpLine[i].toString();
}
});
AlertDialog alertDialogObject = mBuilder.create();
//Show the dialog
alertDialogObject.show();
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.myProfile) {
// Handle the camera action
} else if (id == R.id.myTrips) {
} else if (id == R.id.fir) {
} else if (id == R.id.logout) {
} else if (id == R.id.contactus) {
} else if (id == R.id.feedback) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
private void setupBottomNavigationView()
{
Log.d("BottomNv", "setupBottomNavigationView: setting up botNavView");
BottomNavigationViewEx bottomNavigationViewEx = findViewById(R.id.bnve);
BottomNavigationViewHelper.setupBottomNavigationView(bottomNavigationViewEx);
BottomNavigationViewHelper.enableNavigation(this,bottomNavigationViewEx);
}
//endregion
//region Maps Methods
public void onMapReady(GoogleMap googleMap) {
LocationManager lm = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
boolean gps_enabled = false;
boolean network_enabled = false;
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch(Exception ex) {
Log.e("Error", "onMapReady: ");
}
try {
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch(Exception ex) {
Log.e("Error", "onMapReady: " );
}
if(!gps_enabled && !network_enabled)
{
buildAlertMessageNoGps();
}
mMap = googleMap;
mMap = googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
if (isProviderAvailable() && (provider != null))
{
locateCurrentPosition();
}
setupBottomNavigationView();
}
public void locateCurrentPosition()
{
int status = getPackageManager().checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION,
getPackageName());
if (status == PackageManager.PERMISSION_GRANTED) {
location = mLocationManager.getLastKnownLocation(provider);
updateWithNewLocation(location);
// mLocationManager.addGpsStatusListener(this);
long minTime = 5000;// ms
float minDist = 5.0f;// meter
mLocationManager.requestLocationUpdates(provider, minTime, minDist, this);
l=location;
if(l != null)
placeAutoComplete.setBoundsBias(new LatLngBounds(new LatLng(l.getLatitude(),l.getLongitude()),new LatLng(l.getLatitude()+2,l.getLongitude()+2)));
}
}
private void updateWithNewLocation(Location location) {
if (location != null && provider != null) {
double lng = location.getLongitude();
double lat = location.getLatitude();
if(!flag)
addBoundaryToCurrentPosition(lat, lng);
CameraPosition camPosition = new CameraPosition.Builder()
.target(new LatLng(lat, lng)).zoom(12f).build();
if (mMap != null && !flag)
mMap.animateCamera(CameraUpdateFactory
.newCameraPosition(camPosition));
} else {
Log.d("Location error", "Something went wrong");
}
}
//*****************************************************************//
private void addBoundaryToCurrentPosition(double lat, double lang) {
Geocoder myLocation = new Geocoder(getApplicationContext(), Locale.getDefault());
String addressStr = "";
try {
List<Address> myList = myLocation.getFromLocation(lat,lang, 1);
Address address;
address = (Address) myList.get(0);
Log.d("LOCC", address.getAddressLine(0));
addressStr += address.getAddressLine(0) ;
} catch (IOException e) {
e.printStackTrace();
}
MarkerOptions mMarkerOptions = new MarkerOptions();
mMarkerOptions.position(new LatLng(lat, lang));
mMarkerOptions.icon(BitmapDescriptorFactory
.fromResource(R.drawable.ic_location));
mMarkerOptions.anchor(0.5f, 0.5f);
if( mOptions == null)
{
mOptions = new CircleOptions()
.center(new LatLng(lat, lang)).radius(5000)
.strokeColor(0x110000FF).strokeWidth(1).fillColor(0x110000FF);
c = mMap.addCircle(mOptions);
}
else {
c.remove();
mOptions = new CircleOptions()
.center(new LatLng(lat, lang)).radius(5000)
.strokeColor(0x110000FF).strokeWidth(1).fillColor(0x110000FF);
c = mMap.addCircle(mOptions);
}
if (mCurrentPosition != null)
mCurrentPosition.remove();
mCurrentPosition = mMap.addMarker(mMarkerOptions);
mCurrentPosition.setTitle(addressStr);
}
private boolean isProviderAvailable() {
mLocationManager = (LocationManager) getSystemService(
Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);
provider = mLocationManager.getBestProvider(criteria, true);
if (mLocationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
provider = LocationManager.NETWORK_PROVIDER;
return true;
}
if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
provider = LocationManager.GPS_PROVIDER;
return true;
}
if (provider != null) {
return true;
}
return false;
}
#Override
public void onLocationChanged(Location location) {
updateWithNewLocation(location);
}
#Override
public void onProviderDisabled(String provider) {
updateWithNewLocation(null);
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
switch (status) {
case LocationProvider.OUT_OF_SERVICE:
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
break;
case LocationProvider.AVAILABLE:
break;
}
}
public void buildAlertMessageNoGps()
{
new MaterialDialog.Builder(this)
.title("Location")
.content("Enable Location")
.positiveText("Enable GPS!")
.negativeText("No, Thanks!")
.cancelable(false)
.positiveColor(Color.rgb(232,42,42))
.negativeColor(Color.rgb(232,42,42))
.onPositive(new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
Intent myIntent = new Intent( Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(myIntent);
}
})
.onNegative(new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
Toast.makeText(MainActivity.this, "Location Access Required!!", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
})
.show();
}
//endregion
}
As you can see in the method addBoundaryToCurrentPosition(), below that "//******//" (it's a part of MainActivity), I've set a marker at current location towards the end of the method which is supposed to refresh after every 5000ms.
Moreover I have a bottomNavigationView which is supposed to show nearby places. It's code is as below:-
public class BottomNavigationViewHelper {
private static final String TAG = "BottomNavigationViewHel";
static Menu menu;
static MenuItem menuItem;
public static Location l;
public static void setupBottomNavigationView(BottomNavigationViewEx bottomNavigationViewEx)
{
Log.d(TAG, "setupBottomNavigationView: setting up BottomNavView");
bottomNavigationViewEx.enableAnimation(true);
bottomNavigationViewEx.enableItemShiftingMode(false);
bottomNavigationViewEx.enableShiftingMode(false);
bottomNavigationViewEx.setTextVisibility(true);
menu = bottomNavigationViewEx.getMenu();
}
public static void enableNavigation(final Context context, BottomNavigationViewEx view)
{
view.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.ic_hospital:
menuItem = menu.getItem(0);
menuItem.setChecked(true);
String Hospital = "hospital";
Log.d("onClick", "Button is Clicked");
MainActivity.mMap.clear();
locate(MainActivity.location);
MainActivity.markerAlready = false;
MainActivity.placeAutoComplete.setText("Hospitals near me");
String urlhospital = getUrl(MainActivity.l.getLatitude(), MainActivity.l.getLongitude(), Hospital);
Object[] DataTransferhospital = new Object[2];
DataTransferhospital[0] = MainActivity.mMap;
DataTransferhospital[1] = urlhospital;
Log.d("onClick", urlhospital);
GetNearbyPlacesData getNearbyPlacesDatahospital = new GetNearbyPlacesData();
getNearbyPlacesDatahospital.execute(DataTransferhospital);
break;
case R.id.ic_police:
menuItem = menu.getItem(1);
menuItem.setChecked(true);
String Police = "police";
Log.d("onClick", "Button is Clicked");
MainActivity.mMap.clear();
locate(MainActivity.location);
MainActivity.markerAlready = false;
MainActivity.placeAutoComplete.setText("Police Stations near me");
String urlpolice = getUrl(MainActivity.l.getLatitude(), MainActivity.l.getLongitude(), Police);
Object[] DataTransferpolice = new Object[2];
DataTransferpolice[0] = MainActivity.mMap;
DataTransferpolice[1] = urlpolice;
Log.d("onClick", urlpolice);
GetNearbyPlacesData getNearbyPlacesDatapolice = new GetNearbyPlacesData();
getNearbyPlacesDatapolice.execute(DataTransferpolice);
break;
case R.id.ic_food:
menuItem = menu.getItem(2);
menuItem.setChecked(true);
String Restaurant = "restaurant";
Log.d("onClick", "Button is Clicked");
MainActivity.mMap.clear();
MainActivity.markerAlready = false;
MainActivity.placeAutoComplete.setText("Restaurants near me");
locate(MainActivity.location);
String urlrestaurant = getUrl(MainActivity.l.getLatitude(), MainActivity.l.getLongitude(), Restaurant);
Object[] DataTransferrestaurant = new Object[2];
DataTransferrestaurant[0] = MainActivity.mMap;
DataTransferrestaurant[1] = urlrestaurant;
Log.d("onClick", urlrestaurant);
GetNearbyPlacesData getNearbyPlacesDatarestaurant = new GetNearbyPlacesData();
getNearbyPlacesDatarestaurant.execute(DataTransferrestaurant);
break;
}
return false;
}
});
}
private static String getUrl(double latitude, double longitude, String nearbyPlace) {
StringBuilder googlePlacesUrl = new StringBuilder("https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
googlePlacesUrl.append("location=" + latitude + "," + longitude);
googlePlacesUrl.append("&radius=" + 10000);
googlePlacesUrl.append("&type=" + nearbyPlace);
googlePlacesUrl.append("&sensor=true");
googlePlacesUrl.append("&key=" + "AIzaSyATuUiZUkEc_UgHuqsBJa1oqaODI-3mLs0");
Log.d("getUrl", googlePlacesUrl.toString());
return (googlePlacesUrl.toString());
}
public static void locate(Location location) {
if (location != null) {
double lng = location.getLongitude();
double lat = location.getLatitude();
CameraPosition camPosition = new CameraPosition.Builder()
.target(new LatLng(lat, lng)).zoom(12f).build();
if (MainActivity.mMap != null) {
MainActivity.mMap.animateCamera(CameraUpdateFactory
.newCameraPosition(camPosition));
} else {
Log.d("Location error", "Something went wrong");
}
final MarkerOptions mMarkerOptions = new MarkerOptions();
mMarkerOptions.position(new LatLng(lat, lng));
mMarkerOptions.icon(BitmapDescriptorFactory
.fromResource(R.drawable.ic_location));
final Marker m = MainActivity.mMap.addMarker(mMarkerOptions);
CircleOptions mOptions;
final Circle c;
mOptions = new CircleOptions()
.center(new LatLng(lat, lng)).radius(5000)
.strokeColor(0x110000FF).strokeWidth(1).fillColor(0x110000FF);
c = MainActivity.mMap.addCircle(mOptions);
}
}
}
In this I've created a method locate() , towards the end, which is called in switch cases. It fetches current location from MainActivity and sets marker after clearing the map.
The problem that I face is that when I click one of the buttons in BottomNavView, at first only one marker for current location is visible (that by BottomNav) but after some random time, marker by MainActivity also starts showing up. Hence two markers for current location show up.
I've tried creating a handler to remove marker by bottomNav after 5000ms but marker of MainActivity starts showing after random amount of time.
How do I prevent two markers from showing up simultaneously while at the same time ensuring that at least on of the markers is visible at all times??
First, you need to change your Marker variable name to more a readable name because it makes you confuse:
private Marker mCurrentPosition = null;
Marker marker;
What current position means? is it location or marker? What is marker? I think the better name for the above code is following:
private Marker mMarkerCurrentPosition = null;
private Marker mMarkerSelectedPlace;
Second, you adding a marker with BottomNavigationViewHelper.locate without removing the previous marker:
public static void locate(Location location) {
...
final Marker m = MainActivity.mMap.addMarker(mMarkerOptions);
...
}
Furthermore, you should change your code so you can't access the MainActivity variable outside the class by modifying the method parameters to something like this:
public static void locate(GoogleMap map, Location location) {
}
Last, don't use GoogleMap.clear() to clear your markers. Instead, try to always removing all the markers added to the GoogleMap one by one. You can achieve it by always adding the item to a list. Then, you can remove each item by iterating the lists. For example:
List<Marker> markers;
// add 3 marker
markers.add(mMap.addMarker(mMarkerOptions));
markers.add(mMap.addMarker(mMarkerOptions));
markers.add(mMap.addMarker(mMarkerOptions));
// remove markers
for (Iterator<Marker> it = markers.listIterator(); it.hasNext(); ) {
Marker marker = iter.next();
// remove the marker from map
marker.remove();
// remove marker from list
iter.remove();
}

How to keep websockets listening as a background service?

I have a service to handle my websocket events however it stops listening when the UI is closed - however, I can still emit messages (eg. location data). How do I keep websockets running in the background so it will listen for events on boot or when the main UI thread is closed?
public class HomeActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
public static final String TAG = HomeActivity.class.getSimpleName();
public static final String PREFS_NAME = "MyPrefsFile";
String userName = "init";
String token = "init";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo wInfo = wifiManager.getConnectionInfo();
String macAddress = wInfo.getMacAddress();
TextView textView = (TextView) findViewById(R.id.txtMac);
textView.setText(macAddress);
startService(new Intent(getBaseContext(), wsService.class));
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
userName = settings.getString("username","does not exist");
token = settings.getString("token","does not exist");
textView = (TextView) findViewById(R.id.txtEmail);
textView.setText(userName);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("Beacon");
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.home, 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);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camera) {
// Handle the camera action
} else if (id == R.id.nav_gallery) {
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
} else if (id == R.id.nav_logout) {
Log.i(TAG, "<<<<---- LOGOUT ---->>> ");
Intent i = new Intent(getApplicationContext(), HomeActivity.class);
startActivity(i);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
This is the service being started from the activity above:
public class wsService extends Service implements OnPreparedListener {
public static final String PREFS_NAME = "MyPrefsFile";
double longitude = 0;
double latitude = 0;
long time = 0;
float speed = 0;
float accuracy = 0;
float bearing = 0;
boolean sound_stopped = true;
String userName = "init";
String token = "init";
public static final String TAG = wsService.class.getSimpleName();
private LocationRequest mLocationRequest;
MediaPlayer mp;
/** indicates how to behave if the service is killed */
int mStartMode;
/** interface for clients that bind */
IBinder mBinder;
/** indicates whether onRebind should be used */
boolean mAllowRebind;
private Socket mSocket;
{
try {
mSocket = IO.socket("http://192.168.0.2:5000");
} catch (URISyntaxException e) {}
}
/** Called when the service is being created. */
#Override
public void onCreate() {
Log.d(TAG, "-- Starting wsService --");
new LongOperation().execute("test");
mp = MediaPlayer.create(this, R.raw.led);
String locationProvider = LocationManager.NETWORK_PROVIDER;
mLocationRequest = LocationRequest.create() // Create the LocationRequest object
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000) // 10 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds
// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener);
}
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
Log.d(TAG, "-- Starting BACKGROUND wsService --");
mSocket.connect();
mSocket.on("to_mobile", onCommand);
return "Executed";
}
#Override
protected void onPostExecute(String result) {
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
//Listening new message event to receive message
private Emitter.Listener onCommand = new Emitter.Listener() {
#Override
public void call(final Object... args) {
JSONObject data = (JSONObject)args[0];
String command = null;
try {
command = data.getString("command");
} catch (JSONException e) {
e.printStackTrace();
}
Log.i(TAG, "<<<<---- RECEIVING COMMAND ----->>> " + command);
if (command.equals("ping_audio_start")) {
start_sound();
}
if (command.equals("ping_audio_stop")) {
stop_sound();
}
if (command.equals("ping_gps")) {
Log.i(TAG, "<<<<---- RESPONDING GPS REQUEST ----->>> ");
mSocket.emit("from_mobile", gps_string);
}
}
};
String gps_string = "HELLO FROM DROID";
private void handleNewLocation(Location location) {
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo wInfo = wifiManager.getConnectionInfo();
String macAddress = wInfo.getMacAddress();
longitude = location.getLongitude();
latitude = location.getLatitude();
time = location.getTime();
speed = location.getSpeed();
accuracy = location.getAccuracy();
bearing = location.getBearing();
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
userName = settings.getString("username","does not exist");
token = settings.getString("token","does not exist");
gps_string = "{ \"mac\":\"" + macAddress
+ "\", \"userName\":\"" + userName
+ "\", \"token\":\"" + token
+ "\", \"time\":\"" + time
+ "\", \"longitude\":\"" + longitude
+ "\", \"latitude\":\"" + latitude
+ "\", \"speed\":\"" + speed
+ "\", \"accuracy\":\"" + accuracy
+ "\", \"bearing\":\"" + bearing
+ "\"}";
mSocket.emit("from_mobile", gps_string);
Log.i(TAG, "<<<<---- SENDING GPS DATA ---->>> ");
}
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
handleNewLocation(location);
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
public void start_sound() {
Log.i(TAG, "<<<<---- START PING ----->>>");
mp.release();
mp = MediaPlayer.create(this, R.raw.led);
mp.setLooping(true);
mp.start();
mp.setVolume(1, 1);
sound_stopped = false;
}
public void stop_sound() {
Log.i(TAG, "<<<<---- STOP PING ----->>> ");
mp.stop();
sound_stopped = true;
}
public void onPrepared(MediaPlayer player) {
player.start();
}
/** The service is starting, due to a call to startService() */
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return mStartMode;
}
/** A client is binding to the service with bindService() */
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** Called when all clients have unbound with unbindService() */
#Override
public boolean onUnbind(Intent intent) {
return mAllowRebind;
}
/** Called when a client is binding to the service with bindService()*/
#Override
public void onRebind(Intent intent) {
}
/** Called when The service is no longer used and is being destroyed */
#Override
public void onDestroy() {
}
}
IntentService is running only for as long as the it needs to handle the Intent. i.e if there are no intents left to process, the service closes automatically.
Try a normal service instead.

Categories