1. Are you ready for the Galaxy S20? Here is everything we know so far!

Creating a Store Locator - Location bugs and errors, database start. Please help clean code!

Discussion in 'Android Development' started by Zukky, Apr 13, 2012.

  1. Zukky

    Zukky Lurker
    Thread Starter

    I am building a store locator app that shows you the opening times of stores.

    I am in the process of building my app and would love some assistance. I will display the bugs that I am getting:


    The app carries on running, even when it is killed from the task manager. Basically, I go into "AroundMe" app and when I see the google map within there. My location and layout from the MyLocationOverlay is still running and can be seen within that app. That leads me to believe that my app is not being destroyed? I am finding it difficult to destroy.


    This is my first ever app, so my structure of my code seems un-clean and spaghetti like. I have tried following a structure by having variables within "onCreate" method (as seen in the coding pasted below). However, it seems like the locationManager should not be in the main class? But i'm not sure. Can someone clarify?


    I want to create a database. Create a database and have opening times and an address that is displayed onto my map api. A tutorial link would be helpful if someone can supply? I have searched google but I can't really find it. Would I need a SQL database? Or can I just create a mapOverlay and have each pointer on the address with a note about opening times?

    Answering anyone of these would be highly beneficial to my app success. I would love if someone can restructure the code written at this very moment and tell me how I should place it.

    Thank you very much,

    Zukky.

    CODE:

    package application.project.minutemap;

    import com.google.android.maps.MapActivity;
    import com.google.android.maps.MapController;
    import com.google.android.maps.MapView;
    import com.google.android.maps.MyLocationOverlay;
    import android.app.AlertDialog;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.location.Criteria;
    import android.location.Location;
    import android.location.LocationListener;
    import android.location.LocationManager;
    import android.os.Bundle;
    import android.provider.Settings;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.widget.Button;
    import android.widget.CheckBox;
    import android.widget.CompoundButton;
    import android.widget.CompoundButton.OnCheckedChangeListener;
    import android.widget.Toast;

    public class MinuteMapActivity extends MapActivity implements LocationListener {
    /** Called when the activity is first created. */
    private LocationManager locationManager;
    private String provider;
    private MyLocationOverlay myLocationOverlay;

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // ---load the BasicViewsExample activity---

    // the methods on the map are initialised here - onCreate
    satelliteDisplay();
    zoomControls();
    storeFinderButton();
    location();
    GPSAlert();
    mapMarker();
    myLocationButton();

    }

    private void location() {
    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    locationManager.requestLocationUpdates(
    LocationManager.NETWORK_PROVIDER, 0, 0, this);
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
    0, this);

    Criteria criteria = new Criteria();
    provider = locationManager.getBestProvider(criteria, false);
    locationManager.getLastKnownLocation(provider);

    }

    private void GPSAlert() {
    LocationManager pGps = (LocationManager) this
    .getSystemService(Context.LOCATION_SERVICE);
    if (!pGps.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
    promptGPS();
    }
    }

    private void promptGPS() {
    AlertDialog.Builder prompt = new AlertDialog.Builder(this);
    prompt.setCancelable(false);
    prompt.setTitle("Warning");
    prompt.setMessage("Your GPS is disabled! Would you like to turn it on?");
    prompt.setPositiveButton("Enable GPS",
    new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
    GPSSettings();
    }
    });

    prompt.setNegativeButton("Do nothing",
    new DialogInterface.OnClickListener() {

    @Override
    public void onClick(DialogInterface dialog, int which) {
    dialog.cancel();

    }
    });
    AlertDialog alert = prompt.create();
    alert.show();

    };

    private void GPSSettings() {
    Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
    startActivity(myIntent);
    }

    private void mapMarker() {
    MapView mp = (MapView) findViewById(R.id.mapView);
    final MapController mapController = mp.getController();
    myLocationOverlay = new MyLocationOverlay(this, mp);
    mp.getOverlays().add(myLocationOverlay);
    myLocationOverlay.enableCompass();
    myLocationOverlay.enableMyLocation();
    myLocationOverlay.runOnFirstFix(new Runnable() {
    public void run() {
    mapController.animateTo(myLocationOverlay.getMyLocation());
    }
    });
    }

    private void myLocationButton() {
    MapView mp = (MapView) findViewById(R.id.mapView);
    final MapController mapController = mp.getController();
    final Button myLocationButton = (Button) findViewById(R.id.myLocationButton);
    myLocationButton.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
    if (myLocationButton.isClickable()) {
    mapController.animateTo(myLocationOverlay.getMyLocation());
    mapController.setZoom(20);
    }

    }
    });

    }

    private void storeFinderButton() {
    final Button storeFinderButton = (Button) findViewById(R.id.storeFinderButton);
    storeFinderButton.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View arg0) {
    if (storeFinderButton.isClickable()) {
    Intent myIntent = new Intent(getBaseContext(),
    StoreFinderActivity.class);
    myIntent.setFlags(myIntent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    startActivity(myIntent);
    }
    }
    });
    }

    // method for Zoomcontrols
    private void zoomControls() {
    MapView mp = (MapView) findViewById(R.id.mapView);
    mp.setBuiltInZoomControls(true);
    }

    // method for SatelliteDisplay CheckBox
    private void satelliteDisplay() {
    final MapView mp = (MapView) findViewById(R.id.mapView);
    final CheckBox mapchgBtn = (CheckBox) findViewById(R.id.satBtn);
    mapchgBtn.setOnCheckedChangeListener(new OnCheckedChangeListener() {

    @Override
    public void onCheckedChanged(CompoundButton buttonView,
    boolean isChecked) {
    if (mapchgBtn.isChecked()) {
    mp.setSatellite(true);
    } else
    mp.setSatellite(false);
    }
    });

    }


    @Override
    // MinuteMapActivity deceleration of class would not work without this
    // method - forcing the isRouteDisplayed to return false.
    protected boolean isRouteDisplayed() {
    return false;
    }

    @Override
    public void onLocationChanged(Location location) {

    }

    @Override
    public void onProviderDisabled(String provider) {
    Toast.makeText(this, "GPS Off", Toast.LENGTH_SHORT).show();

    }

    @Override
    public void onProviderEnabled(String provider) {
    Toast.makeText(this, "GPS On", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    // TODO Auto-generated method stub

    }



    protected void onResume() {
    super.onResume();
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
    0, this);
    // locationManager.requestLocationUpdates(
    // LocationManager.NETWORK_PROVIDER, 0, 0, this);
    myLocationOverlay.enableMyLocation();
    myLocationOverlay.enableCompass();
    }

    protected void onStop() {
    super.onStop();
    locationManager.removeUpdates(this);
    myLocationOverlay.disableMyLocation();
    myLocationOverlay.disableCompass();
    }

    // protected void onStop(){
    // super.onStop();
    // this.stop();
    //
    //
    // }

    }
     



    1. Download the Forums for Android™ app!


      Download

       
  2. alostpacket

    alostpacket Over Macho Grande?

    Have you considered something more simple to start with? Have you gone through and read the code for the demos and tutorials?

    I'm just saying this because MapView is notoriously buggy and complex. So you took a big bite for your first app :)
     
  3. Zukky

    Zukky Lurker
    Thread Starter

    Yes, done it all. Just stuck. Would love the assistance. I'm strained for time.
     
  4. alostpacket

    alostpacket Over Macho Grande?

    OK I will try my best here:

    I had a long writeup but something went screwy, so this might be a bit shorter. Let me know if something is unclear. :)

    1)
    The app carries on running, even when it is killed from the task manager.


    You are likely "leaking" your activity because the location manager service is keeping a reference to it. This is partly because you are defining your Activity as the listener.

    Personally I think this habit java and Android devs have of making their activities listeners is quite a bad anti-pattern. But that's just my opinion (so take it with a grain of salt).

    The problem is that the Activity is being kept in memory because something is holding a reference to it. If you separate out your listeners and other tasks to either objects, inner classes, or separate classes, you would then be able to set the object to null in you onDestroy(); method. Once the object is null, no service or other object or class will hold a reference to it and the garbage collector can come along and remove it from memory.


    2) This is my first ever app, so my structure of my code seems un-clean and spaghetti like.

    You should consider separating out the responsibilities to other classes. onCreate() is used for initialization, and should only contain code to setup your activity and any objects it needs.

    What you read about the LocationManager was probably that when you first obtain a reference to it, you must do so from the main UIThread:

    LocationManager myLM = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

    Then you can pass the myLM object reference to a background thread to do work if you wish (but you dont have to). The important part is that system services need to be first accessed from the context on the main UI thread.

    3) I want to create a database.

    The database would be Sqlite. There are a lot of tutorials on getting started with Sqlite on Android. Check the sticky post at the top of this thread.
     
  5. alostpacket

    alostpacket Over Macho Grande?

    Also another style tip that helped me a lot. I make all my methods verbs or "actions" and all my properties, class variables, etc, are nouns or "things"

    so methods are like

    Code (Text):
    1. private void doSomething()
    2. {
    3.      //some code
    4. }
    5.  
    6. private int calculateNumber()
    7. {
    8.      //some code
    9.      return 9000;
    10. }
    and variables would be like
    Code (Text):
    1.  
    2. String itemName = "whatever";
    3.  
    4. int numberOfItems = 10;
    This little trick helps make code a lot easier to read at a glance.
     
  6. wubbzy

    wubbzy Well-Known Member

    How are you "destroying" your app? I'm not sure what you mean my app is not destroyed. Read android activity lifecycle Activity | Android Developers or do you mean GPS and other network providers keep running.

    App is only destroyed when you press the device back button. The destroyed apps VM and process may still hang around i.e. you may see them in something like "advanced task killer". This is because android does not completely destroy the VM and app process. It marks it for reclamation only when it needs more memory. This has advantage in that next time you startup your app, it will spring back to life immediately.

    Above code in my opinion is in wrong place. It should be in onPause not in onStop, which is called when your app is no longer on screen.
     
Loading...
Similar Threads - Creating Store Locator
  1. soulartist
    Replies:
    14
    Views:
    575
  2. Relaxing Leg
    Replies:
    0
    Views:
    454
  3. Sajivjess
    Replies:
    1
    Views:
    529
  4. RicardoM
    Replies:
    1
    Views:
    555
  5. My project
    Replies:
    9
    Views:
    749
  6. grizmixstir
    Replies:
    3
    Views:
    1,053
  7. kdmoore
    Replies:
    3
    Views:
    1,186
  8. cwg01
    Replies:
    3
    Views:
    2,913
  9. kumaranil13k
    Replies:
    4
    Views:
    1,135
  10. 5g Moto Android 11
    Replies:
    2
    Views:
    2,351

Share This Page

Loading...