1

I'm working on a project which is to create a full working Google Maps example.

I was trying to program an imagebutton that tracks and display your own location, but it doesn't seem to be working.

MapsActivity.java:

package com.example.ali.googleandroid;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageButton;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;


public class MapsActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

    private static final int REQUEST_FINE_LOCATION = 0;

    private GoogleMap mMap;

    GoogleApiClient mGoogleApiClient;
    LocationRequest mLocationRequest;

    LatLng latLng;
    SupportMapFragment mFragment;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        loadPermissions(Manifest.permission.ACCESS_FINE_LOCATION, REQUEST_FINE_LOCATION);


        if (!isGooglePlayServicesAvailable()) {
            finish();
        }
        setContentView(R.layout.activity_maps);
//      setUpMapifNeeded();

        mFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mMap = mFragment.getMap();

        mMap.setMyLocationEnabled(true);

        buildGoogleApiClient();

        mGoogleApiClient.connect();

        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Location myLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

        Criteria criteria = new Criteria();

        String provider = locationManager.getBestProvider(criteria, true);

        if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    public void requestPermissions(@NonNull String[] permissions, int requestCode)
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for Activity#requestPermissions for more details.
            return;
        }



        if ( myLocation != null) {

            double latitude = myLocation.getLatitude();
            double longitude = myLocation.getLongitude();


            LatLng latLng = new LatLng(latitude, longitude);


            mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));

            mMap.animateCamera(CameraUpdateFactory.zoomTo(20));
            mMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title(" You are here!"));

        }



    }


    protected void onResume() {
        super.onResume();
        setUpMapifNeeded();
    }


    private void setUpMapifNeeded() {

        if (mMap == null) {

            mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
        }
        if (mMap != null) {
            setUpMap();
        }
    }


    private void setUpMap() {
        mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
    }


    public void TrackOwnLocation(View v) {

        mMap.setMyLocationEnabled(true);

        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

        Criteria criteria = new Criteria();

        String provider = locationManager.getBestProvider(criteria, true);

        if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    public void requestPermissions(@NonNull String[] permissions, int requestCode)
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for Activity#requestPermissions for more details.
            return;
        }

        Location mylocation = locationManager.getLastKnownLocation(provider);

        double latitude = mylocation.getLatitude();

        double longitude = mylocation.getLongitude();

        LatLng latLng = new LatLng(latitude, longitude);

        mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));

        mMap.animateCamera(CameraUpdateFactory.zoomTo(20));
        mMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title(" You are here!"));

    }


    private boolean isGooglePlayServicesAvailable() {
        int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (ConnectionResult.SUCCESS == status) {
            return true;
        } else {
            GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
            return false;
        }
    }


    protected synchronized void buildGoogleApiClient() {
        //    Toast.makeText(this,"buildGoogleApiClient",Toast.LENGTH_SHORT).show();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }

    @Override
    public void onConnected(Bundle bundle) {
        Toast.makeText(this, "onConnected", Toast.LENGTH_SHORT).show();
        Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                mGoogleApiClient);
        if (mLastLocation != null) {
            //place marker at current position
            mMap.clear();
            latLng = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
            MarkerOptions markerOptions = new MarkerOptions();
            markerOptions.position(latLng);
            markerOptions.title("Current Position");
            markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
            Marker m = mMap.addMarker(markerOptions);
        }

        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(5000); //5 seconds
        mLocationRequest.setFastestInterval(3000); //3 seconds
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        //mLocationRequest.setSmallestDisplacement(0.1F); //1/10 meter

        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);


    }

    @Override
    public void onConnectionSuspended(int i) {
        Toast.makeText(this, "onConnectionSuspended", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Toast.makeText(this, "onConnectionFailed", Toast.LENGTH_SHORT).show();
    }


    public void onLocationChanged(Location location) {

        //place marker at current position
        mMap.clear();
        latLng = new LatLng(location.getLatitude(), location.getLongitude());
        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(latLng);
        markerOptions.title("Current Position");
        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
        Marker m = mMap.addMarker(markerOptions);

        Toast.makeText(this, "Location Changed", Toast.LENGTH_SHORT).show();

        //If you only need one location, unregister the listener
        //LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);

    }


    private void loadPermissions(String perm, int requestCode) {
        if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
            if (!ActivityCompat.shouldShowRequestPermissionRationale(this, perm)) {
                ActivityCompat.requestPermissions(this, new String[]{perm}, requestCode);
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case REQUEST_FINE_LOCATION: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // granted
                } else {
                    // no granted
                }
                return;
            }

        }


    }

}

XML Layout file:

<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"

    xmlns:android="http://schemas.android.com/apk/res/android">



<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:map="http://schemas.android.com/apk/res-auto" android:layout_width="386dp"
    android:layout_height="380dp" android:id="@+id/map" tools:context=".MapsActivity"
    android:name="com.google.android.gms.maps.SupportMapFragment" />

    <ImageButton
        android:layout_width="103dp"
        android:layout_height="103dp"
        android:id="@+id/DiaryEntry"
        android:adjustViewBounds="true"
        android:padding="20dp"
        android:scaleType="fitXY"

        android:layout_alignTop="@+id/trackownlocation"
        android:layout_alignParentEnd="true"
        android:layout_alignBottom="@+id/trackownlocation"
        android:src="@drawable/create_entry"
        android:background="@drawable/button_state"

        android:layout_alignParentStart="false" />

    <ImageButton
        android:onClick="TrackOwnLocation"
        android:layout_width="103dp"
        android:layout_height="103dp"
        android:id="@+id/trackownlocation"
        android:src="@drawable/own_location"
        android:adjustViewBounds="true"
        android:padding="20dp"
        android:scaleType="fitXY"
        android:layout_below="@+id/map"
        android:layout_alignParentStart="false"
        android:background="@drawable/button_state2"

        />

    <ImageButton
        android:layout_width="103dp"
        android:layout_height="103dp"
        android:id="@+id/help"
        android:adjustViewBounds="true"
        android:padding="20dp"
        android:scaleType="fitXY"

        android:src="@drawable/help"
        android:background="@drawable/button_state3"
        android:layout_alignTop="@+id/trackownlocation"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="41dp" />



</RelativeLayout>

Android Manifest file:

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

    <!--
         The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
         Google Maps Android API v2, but you must specify either coarse or fine
         location permissions for the 'MyLocation' functionality. 
    -->


    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="22" />

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />


    <permission
        android:name="com.example.ali.googleandroid.permission.MAPS_RECEIVE"
        android:protectionLevel="signature" />

    <uses-permission android:name="com.example.ali.googleandroid.permission.MAPS_RECEIVE" />




    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />



    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.location.GPS_ENABLED_CHANGE" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />



    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >

        <!--
             The API key for Google Maps-based APIs is defined as a string resource.
             (See the file "res/values/google_maps_api.xml").
             Note that the API key is linked to the encryption key used to sign the APK.
             You need a different API key for each encryption key, including the release key that is used to
             sign the APK for publishing.
             You can define the keys for the debug and release targets in src/debug/ and src/release/. 
        -->
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />

        <activity
            android:name=".MapsActivity"
            android:label="@string/title_activity_maps" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
Rob Neal
  • 201
  • 2
  • 13
  • doesnt seem to be working means? any errors? – Lal Nov 17 '15 at 18:25
  • when i run the emulator, the google map fragment were working fine but when i press the imagebutton, it was not working. – Rob Neal Nov 17 '15 at 18:26
  • again what do you mean by not working? is the application crashing? or are there any errors? – Lal Nov 17 '15 at 18:30
  • when it is pressed, it doesnt track and display my location – Rob Neal Nov 17 '15 at 18:35
  • what are you trying to do with ImageButtons, also i dnt see any click events in your code – Heshan Sandeepa Nov 17 '15 at 18:37
  • look at TrackOwnLocation method@HeshanSandeepa – Rob Neal Nov 17 '15 at 18:52
  • 1
    Take a look at this answer: http://stackoverflow.com/a/30255219/4409409 – Daniel Nugent Nov 17 '15 at 18:53
  • @DanielNugent I copied your code and i ran the program. This line : `LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, (LocationListener) this);` is giving me ClassCastException – Rob Neal Nov 17 '15 at 19:04
  • 1
    Take a look at the Activity class definition, are you implementing `LocationListener `? Also, take a look at the modified solution here, it's updated to use getMapAsync(): http://stackoverflow.com/a/33741294/4409409 – Daniel Nugent Nov 17 '15 at 19:19
  • @DanielNugent sorry i missed this bit out, it works but i have another exception: `java.lang.SecurityException: Client must have ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to perform any location operations.` I have removed access fine location in manifest file and it still doesn't work and vice versa for access coarse location. – Rob Neal Nov 17 '15 at 19:24
  • 1
    You need at least one of those permissions, I would recommend going with ACCESS_FINE_LOCATION. – Daniel Nugent Nov 17 '15 at 19:27
  • @DanielNugent that what i did. I still got the same exception. I think I'm close xD – Rob Neal Nov 17 '15 at 19:29
  • 1
    Are you testing on a device or an emulator? – Daniel Nugent Nov 17 '15 at 19:30
  • @DanielNugent emulator – Rob Neal Nov 17 '15 at 19:31
  • 1
    Well that might be the problem. It looks like your target api level is 22 (provided you're using Eclipse), so you shouldn't need to request permissions at runtime. If you're using Android Studio and have the target api set to 23, then you would need to request the permission at runtime, see here: http://stackoverflow.com/a/33488107/4409409 and here: http://stackoverflow.com/questions/32224534/access-fine-location-permission-error-emulator-only – Daniel Nugent Nov 17 '15 at 19:35
  • @DanielNugent The first link is helpful. I added the code and I have received no exceptions. However, i still dont see my own location. – Rob Neal Nov 17 '15 at 19:44
  • 1
    For testing on an emulator, you will need to emulate the location data: http://stackoverflow.com/questions/2279647/how-to-emulate-gps-location-in-the-android-emulator – Daniel Nugent Nov 17 '15 at 19:48
  • @DanielNugent I moved the code from TrackOwnLocation() method inside onCreate() method. ( after the line, `mGoogleApiClient.connect()` I have `Location Manager`, `Criteria`, `String provider` and so on. I ran the code and I got a RunTime Exception: `Unable to start activity ComponentInfo{com.example.ali.googleandroid/com.example.ali.googleandroid.MapsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'double android.location.Location.getLatitude()' on a null object reference` – Rob Neal Nov 17 '15 at 19:54
  • @DanielNugent please see updated MapsActivity.java – Rob Neal Nov 17 '15 at 19:57
  • 1
    The returned result from `getLastLocation()` can be null, you need a null check: `if (mLastLocation != null) {` – Daniel Nugent Nov 17 '15 at 20:13
  • @DanielNugent that what I did. No exceptions, perfect but still dont see my own location. I have made new changes to MapsActivity.java and the manifest file. Please see. – Rob Neal Nov 17 '15 at 20:18
  • @DanielNugent i have this code : `LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Location myLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);` maybe this is the problem? – Rob Neal Nov 17 '15 at 20:21
  • 1
    Emulators don't have any built in way to get location, you need to fake it. Are you following the answer here? http://stackoverflow.com/questions/2279647/how-to-emulate-gps-location-in-the-android-emulator – Daniel Nugent Nov 17 '15 at 20:23
  • @DanielNugent on it now – Rob Neal Nov 17 '15 at 20:27
  • 1
    @DanielNugent Thank you so much! It works. Now im going to develop it further. I have another question, it is the last one. How can I program the button to show my current location. – Rob Neal Nov 17 '15 at 20:42
  • @DanielNugent do you mean when the button is pressed, it requests location updates? – Rob Neal Nov 17 '15 at 21:09

0 Answers0