Google Maps API V2: GPS icon doesn't appear
Asked Answered
L

2

0

In my app I have recently upgraded Google Maps from V1 to V2. Now, with an HTC One S (Android 4.1.1) when I switch on GPS and enter in the map activity, the app recognizes that GPS is on but its icon doesn't appear and the app can't find my location.
On devices like Samsung Galaxy Y (Android 2.3) the map works without problems.
On others like Samsung Galaxy S2 (Android 4.1.2), HTC Wildfire (Android 2.3) the GPS icon doesn't appear but the apps finds my location.
Where I'm wrong?

Class:

public class CercaPuntoVendita extends FragmentActivity implements OnMarkerClickListener, LocationSource, LocationListener {

    // Identificatore del messaggio della Map
    private final static int MAP_MESSAGE_ID = 1;

    // Identificatore della ProgressBar
    private final static int PROGRESS_DIALOG_ID = 1;

    // Riferimento alla Map
    private GoogleMap map;

    // Riferimento alle UiSettings
    private UiSettings uis;

    // Riferimento al GeoCoder
    private Geocoder geocoder;

    // Riferimento alla EditText
    private EditText inputName;

    // Livello di Zoom
    private int nMetriDiametroCitta = 10000;
    private int nMetriDiametroVia = 1500;

    //Riferimento al MapController
    public static MapController mapController;  

    //Otteniamo il riferimento al LocationManager
    private LocationManager myLocationManager = null;
    private OnLocationChangedListener myLocationListener = null;
    private Criteria myCriteria;

    private PuntiVendita overlays = null;

    private Context ctx = this;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Mettiamo la View a tutto schermo
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        // Visualizziamo la Map
        setContentView(R.layout.cerca_punto_vendita);

        // Gestione font
        Button btnSearch = (Button) findViewById(R.id.searchButton);
        Typeface tf = Typeface.createFromAsset(ctx.getAssets(), "fonts/CRAI_regular.ttf");
        Utils.setFontMultiple(tf, btnSearch);

        // Set up della map
        setUpMapIfNeeded();

        // Riferimento al campo di testo
        inputName = (EditText)findViewById(R.id.addressName);

        // Otteniamo il riferimento al geocoder
        geocoder = new Geocoder(this,Locale.ITALY);

        // Otteniamo il riferimento al location manager
        myLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        // Verifichiamo se il GPS è abilitato altrimenti avvisiamo l'utente
        if(!myLocationManager.isProviderEnabled("gps")) {
            Utils.showWarningDialog(this, "GPS è attualmente disabilitato. E' possibile abilitarlo dal menu impostazioni.");
        }

        // muovo la mappa su Roma
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(41.893, 12.482), calculateZoomLevel(nMetriDiametroCitta)));
    }

    @Override
    public void onPause() {
        super.onPause();

        map.setLocationSource(null);
        myLocationManager.removeUpdates(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        setUpMapIfNeeded();

        map.setMyLocationEnabled(true);
        uis = map.getUiSettings();
        uis.setMyLocationButtonEnabled(false);
        myCriteria = new Criteria();
        myCriteria.setAccuracy(Criteria.ACCURACY_COARSE);
        myLocationManager = (LocationManager)getSystemService(LOCATION_SERVICE);

        // Verifichiamo se il GPS è abilitato altrimenti avvisiamo l'utente
        if(myLocationManager.isProviderEnabled("gps")) {
            try {
                Location loc = myLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(loc.getLatitude(), loc.getLongitude()), calculateZoomLevel(nMetriDiametroVia))); 
            } catch (NullPointerException e) {
            }

            //Register for location updates using a Criteria, and a callback on the specified looper thread.
            myLocationManager.requestLocationUpdates(
              0L,    //minTime
              0.0f,    //minDistance
              myCriteria,  //criteria
              this,    //listener
              null);   //looper

            //Replaces the location source of the my-location layer.
            map.setLocationSource(this);
        }
        //myLocationManager.getProviders(true); 
    }   

    public static double getRound(double x, int digits){
        double powerOfTen = Math.pow(10, digits);
        return (Math.round(x * powerOfTen) / powerOfTen);
    }

    /**
     * Permette di iniziare la ricerca
     * 
     * @param button
     *            Riferimento al button
     */
    public void searchPlace(View button) {
        hideSoftInput();

        Thread searchThread = new Thread("SearchThread") {

            @Override
            public void run() {
                // Otteniamo il messaggio
                Message message = mapHandler.obtainMessage();
                // Utilizziamo il Geocoder per fare la ricerca
                try {
                    List<Address> risultati = geocoder.getFromLocationName(inputName.getText().toString().trim(), 1);
                    // Se c'e' qualcosa lo notifichiamo
                    if (risultati != null && risultati.size() > 0) {
                        message.obj = risultati.get(0);
                        mapHandler.sendMessage(message);
                    } else {
                        runOnUiThread(new Runnable() {                
                            public void run() {
                                Utils.msg(CercaPuntoVendita.this, "Nessun risultato trovato");
                            }
                        });
                    }
                } catch (IOException e) {
                    // Non facciamo nulla ma arriva il messaggio vuoto
                    mapHandler.sendEmptyMessage(MAP_MESSAGE_ID);
                } finally {
                    dismissDialog(PROGRESS_DIALOG_ID);
                }
            }

        };
        // Visualizziamo la progressDialog
        showDialog(PROGRESS_DIALOG_ID);
        // Facciamo partire il Thread
        searchThread.start();
    }

    private final Handler mapHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // Si ottengono le informazioni se presenti sulla posizione
            if (msg != null && msg.obj != null) {
                // Estraiamo le informazioni di posizione
                try { 
                    Address address = (Address)msg.obj;
                    Log.d("CercaPuntoVendita.this", "" + address.getLocality());
                    GeoPoint pointToGo = new GeoPoint((int)(address.getLatitude()*1000000),(int)(address.getLongitude()*1000000));
                    float dZoom = 0;
                    if (address.getLocality().equalsIgnoreCase(inputName.getText().toString().trim())) {
                        // se la locality è uguale alla stringa di ricerca, si tratta di una citta'
                        dZoom = calculateZoomLevel(nMetriDiametroCitta);
                    } else {
                        dZoom = calculateZoomLevel(nMetriDiametroVia);
                    }
                    map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(address.getLatitude(), address.getLongitude()), dZoom));
                } catch (NullPointerException ex) {
                    Utils.msg(CercaPuntoVendita.this, "Nessun risultato trovato");
                    Log.w("Punti Vendita - Cerca", (ex.getMessage() == null)?"address = null":ex.getMessage()); 
                }
            } else {
                Utils.msg(CercaPuntoVendita.this, "Nessun risultato trovato");
            }
            Log.i("GEOCODER", "" + msg);
            if (msg != null) {
                Log.i("GEOCODER", "" + msg.obj);
            }
        }
    };

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
        case PROGRESS_DIALOG_ID:
            ProgressDialog progressDialog = new ProgressDialog(this, ProgressDialog.STYLE_SPINNER);
            progressDialog.setIndeterminate(true);
            progressDialog.setTitle("Cerca Punti Vendita");
            progressDialog.setMessage("Cercando...");
            return progressDialog;
        default:
            return null;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Menù di gestione modalità di visualizzazione che, per renderle checkable le inseriamo in un sottomenu
        SubMenu mapSubMenu = menu.addSubMenu("Modalità Mappa");
        mapSubMenu.setIcon(android.R.drawable.ic_menu_mapmode);
        int firstItem = Menu.FIRST;
        MenuItem trafficItem = mapSubMenu.add(1, firstItem, firstItem, "Traffic");
        trafficItem.setCheckable(true);
        trafficItem.setChecked(false);
        MenuItem satelliteItem = mapSubMenu.add(1, firstItem + 1, firstItem + 1, "Satellite");
        satelliteItem.setCheckable(true);
        trafficItem.setChecked(false);
        // Visualizziamo il menu
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Modifichiamo lo stato di quella selezionata
        item.setChecked(!item.isChecked());
        // Abilitiamo o meno l'opzione relativa
        switch (item.getItemId()) {
            case Menu.FIRST:
                map.setTrafficEnabled(item.isChecked());
                break;
            case Menu.FIRST + 1:
                if (item.isChecked())
                    map.setMapType(MAP_TYPE_SATELLITE);
                else
                    map.setMapType(MAP_TYPE_NORMAL);
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    protected boolean isRouteDisplayed() {
        return false;
    }

    private void hideSoftInput() {
        InputMethodManager inputManager = (InputMethodManager) CercaPuntoVendita.this.getSystemService(Context.INPUT_METHOD_SERVICE); 
        inputManager.hideSoftInputFromWindow(CercaPuntoVendita.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }

    public boolean onMarkerClick(Marker mrk) {
        final ProgressDialog progressDialog = ProgressDialog.show(ctx, "", "Caricamento in corso.\nAttendere prego...");
        final String sSnippet = mrk.getSnippet();
        new Thread() {
            @Override
            public void run() {
                try {
                    sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                Intent intent = new Intent(ctx, PuntoVenditaDett.class);
                intent.putExtra("myPdvId", sSnippet);
                ctx.startActivity(intent);

                progressDialog.dismiss();
            }
        }.start();

        return true;
    }

    private void setUpMap() { 
        // Gestiamo gli Overlay
        Drawable starImg = getResources().getDrawable(R.drawable.logominicrai);
        if (overlays == null)
            overlays = new PuntiVendita(starImg, this);
        map.setOnMarkerClickListener(this);
        for (int i=0; i < overlays.size(); i++) {
            LatLng llPunto = new LatLng(overlays.getItem(i).getPoint().getLatitudeE6()/1E6, overlays.getItem(i).getPoint().getLongitudeE6()/1E6);

            map.addMarker(new MarkerOptions()
                .position(llPunto)
                //.title(name)
                .snippet(overlays.getItem(i).getSnippet())
                .icon(BitmapDescriptorFactory
                    .fromResource(R.drawable.logominicrai)));
        }
    }

    private void setUpMapIfNeeded() {
        // Do a null check to confirm that we have not already instantiated the map.
        if (map == null) {
            // Try to obtain the map from the SupportMapFragment.
            map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
            // Check if we were successful in obtaining the map.
            if (map != null) {
                setUpMap();
            }
        }
    }

    public void onLocationChanged(Location location) {
        if (myLocationListener != null) {
            myLocationListener.onLocationChanged(location);

            LatLng latlng = new LatLng(location.getLatitude(), location.getLongitude());
            map.animateCamera(CameraUpdateFactory.newLatLng(latlng));
        }
    }

    public void onProviderDisabled(String provider) {
        // TODO Auto-generated method stub

    }

    public void onProviderEnabled(String provider) {
        // TODO Auto-generated method stub

    }

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

    }

    public void activate(OnLocationChangedListener listener) {
        myLocationListener = listener;
    }

    public void deactivate() {
        myLocationListener = null;
    }
}

Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.gmaps"
    android:versionCode="2"
    android:versionName="2" >

    <uses-sdk android:minSdkVersion="9" />

    <!-- Google Maps API V2 -->
    <permission
        android:name="com.example.gmaps.permission.MAPS_RECEIVE"
        android:protectionLevel="signature" />
    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />
    <uses-permission android:name="com.example.gmaps.permission.MAPS_RECEIVE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />     

    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/icon"
        android:label="@string/app_name" >

        <activity
            android:name="com.fedrasoft.craiinforma.App"
            android:configChanges="orientation|keyboardHidden|keyboard"
            android:screenOrientation="portrait"
            android:launchMode="singleTask" >
            <!-- android:alwaysRetainTaskState="true" --> 
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name="com.fedrasoft.craiinforma.CercaPuntoVendita"
            android:label="@string/title_activity_cerca_punto_vendita"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="CercaPuntoVendita" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

        <uses-library android:name="com.google.android.maps" />

        <!-- Google Maps API V2 -->
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="my key" /> 
    </application>

</manifest>
Lahr answered 22/4, 2013 at 19:17 Comment(6)
You do not provice enough details. Did you setMyLocationEnabled(true) on GoogleMap?Hebrides
@DoctororDrive Yes, I set it.Lahr
Are you sure that teh GPS is actually ON on that phone?Aviv
@Aviv Yes because I check it in the code with myLocationManager.isProviderEnabled("gps")Lahr
Maybe the GPS is just unreachable (you don't det the updates) and the icon does not appear because of HTC's firmware? Did you try Google Maps and check whether you see the icon? Try "Fake GPS Location" app (from GooglePlay) for instant mock location.Hebrides
@DoctororDrive I tried Google Maps and the GPS works fine, the icon appearsLahr
L
2

Following the advice of @Nevermore I solved the problem implementing OnMyLocationChangeListener instead of LocationSource and LocationListener.
I changed the code in this way:

public class CercaPuntoVendita extends FragmentActivity implements OnMarkerClickListener, OnMyLocationChangeListener {
    //...
    public void onMyLocationChange(Location location) {
        mMap.animateCamera(
            CameraUpdateFactory.newLatLng(
                new LatLng(location.getLatitude(), location.getLongitude())));
    }
}
Lahr answered 26/4, 2013 at 15:50 Comment(0)
L
1

I found that this problem depends on the instruction:

map.setLocationSource(this);

If I don't use it, the GPS works fine but it can't "follow" my location. I must put this instruction in a way that it can always set the location source, even when I turn on GPS on the fly...

Lahr answered 24/4, 2013 at 6:50 Comment(1)
The latest release introduced OnMyLocationChangeListener, so you don't need to implement (and set) a custom LocationSource (nor the manual location update requests!) anymore in order to "follow" the My Location dot. You only need to enable the my-location layer via map.setMyLocationEnabled(true), map.setOnMyLocationChangeListener(this) and animate the camera in the corresponding callback provided by that interface.Standpoint

© 2022 - 2024 — McMap. All rights reserved.