8

I have a very strange problem I developed my application using my HTC One V running 4.0.3 OS. Now the application works superb on mine and few other random 2.2 and 2.3 and 4+ devices but on some devices despite them having GooglePlayStore on them the application starts and it loads but does not show the map on other despite them having GPStore on them the application crashes saying GPStore/Service is not present.

I tried to test the application on AVD Devies but none of them have GooglePlayStore installed. I tried Google Play on Android 4.0 emulator approach to push GPStore on to them but no success.

My droid SDK is fully updated:
enter image description here

I compile my application with enter image description here

In my main activity I check if Google Play Service/Store is present to determine if GoogleMaps can be used:

public class Map extends FragmentActivity implements Observer
{
  private MapAgent agent;
  private Locator  locator;
  private Spinner  spinner;
  private Button   gps;

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

    // Get a new instance of Locator agent
    locator = new Locator();

    // Register as Observer to Locator agent
    locator.addObserver(this);

    // Check if Internet connection is available
    if(Services.connectivityServiceState(this))
    {
      // We have a working Internet connection
      // Check if we have a GooglePS in operating mode
      if(Services.playServiceState(this))
      {
        // Load the map
        setContentView(R.layout.activity_map);

        // Fetch dropdown list & gps button reference
        spinner = (Spinner) findViewById(R.id.bankslist);
        gps     = (Button)  findViewById(R.id.gpsbttn);

        // Register event listener with gps button
        gps.setOnClickListener(new GpsAction(this));

        // Register event listener with spinner
        spinner.setOnItemSelectedListener(new SpinnerAction());

        // Fetch our map
        agent = new MapAgent(this);

        // Move map camera to initial position
        agent.initialPosition();



      } else {
        // GooglePS is not in operating mode
        Messages.playNotificationMessage(this);
      }

    } else {
      // No Internet connection
      // Prompt user to turn on WiFi or Mobile
      Messages.internetConnectionRequestMessage(this);
    }
  }

The method that checks the state of GooglePlay Service is located in my Services.java bellow:

public class Services
{
  /**
   * OPERATING CODES
   */
  private static final int GPS_ERR_REQUEST = 9000;

  /**
   * Test device for GooglePlayServices, required for
   * GoogleMaps API V2.
   * 
   * @param  Activity
   * @result boolean
   */
  public static boolean playServiceState(Activity context)
  {
    // Fetch GooglePS operating code
    int code = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);

    // Check if GooglePS is operating
    if(code == ConnectionResult.SUCCESS)
    {
      // We have GooglePS in working condition
      return true;
    }

    // We have an error, check if it can be resolved by user
    /*if(GooglePlayServicesUtil.isUserRecoverableError(code))
    {
      // We can solve this error pull up GooglePS guide dialog
      Dialog guide = GooglePlayServicesUtil.getErrorDialog(code, context, GPS_ERR_REQUEST);

      // Show the guide dialog
      guide.show();

      // Dispose of our activity
      context.finish();
    }*/

    // We do not have GooglePS in operating mode
    // solve error and retry
    return false;
  }

  /**
   * Tests devices Wi-Fi and Mobile network for a
   * working Internet connection.
   * 
   * @param  Activity
   * @return boolean
   */
  public static boolean connectivityServiceState(Activity context)
  {
    // Fetch a CM instance
    ConnectivityManager con = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

    // Test both carriers for a working Internet connection
    NetworkInfo wifi = con.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    NetworkInfo mobi = con.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);

    // Check for Internet connection
    if(wifi.isConnected() || mobi.isConnected())
    {
      // We have a working internet connection
      return true;
    }

    // No internet connection
    return false;
  }

  /**
   * Test NETWORK service to determine if Google Location
   * services are enabled or not.
   */ 
  public static boolean networkServiceState(Activity context)
  {
    // Fetch a LM instance
    LocationManager provider = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

    // Return true for enabled GLS
    return provider.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
  }

  /**
   * Tests GPS service to determine if GPS
   * is enabled or not.
   * 
   * @param  Activity
   * @result boolean
   */
  public static boolean gpsServiceState(Activity context)
  {
    // Fetch a LM instance
    LocationManager provider = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

    // Return true for enabled GPS
    return provider.isProviderEnabled(LocationManager.GPS_PROVIDER);
  }

  /**
   * Checks if a GPS Radio is present
   * within the device.
   * 
   * @param  Activity
   * @return boolean
   */
  public static boolean hasGPS(Activity context)
  {
    // Refere to devices package manager for GPS service
    return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS);
  }
}

And my map is simply handled in my MapAgent class nothing impressive just handling markers.

  public MapAgent(FragmentActivity context)
  {
    // Fetch the map support fragment
    SupportMapFragment fragment = ((SupportMapFragment) context.getSupportFragmentManager().findFragmentById(R.id.map));

    // Fetch map and view
    map  = fragment.getMap();

    // Set initial zoom
    zoom = 7;

    // Check if this is the first run
    final SharedPreferences prefs = context.getSharedPreferences("slo.bankomati.core", Context.MODE_PRIVATE);

    if(prefs.getBoolean("firstrun", true))
    {
      // Check if database exists and delete it
      if(Database.exists(context))
      {
        Database.delete(context);
      } 
      prefs.edit().putBoolean("firstrun", false);
    }


    // Fetch all atms
    try {
      db = new Database(context);
      atms = db.getAtms();
      db.close();
    } catch (Exception e) {
      // TODO: Temporary solution
    }

    // Create an empty array for filtered results
    filtered = new ArrayList<Atm>();
    markers  = new HashMap<Marker, Atm>();

    // Reference the resources and context
    this.resources = context.getResources();
    this.context   = context;

    // Register camera & info window listener with the map
    map.setOnCameraChangeListener(this);
    //map.setOnInfoWindowClickListener(new ShowDetails(context, resources));
    map.setOnMarkerClickListener(new ShowDetails(context));
  }

I'm out of all ideas I can't get GooglePlay Service running on AVD 2.2+ I tried AVD 4.4 Google Play API it comes GPService but ti wont display the map. So to directly point out my sub questions:

1) If all AVD's from 2.2 up to 4.4 are all without working GooglePlay Services then how can we test application for multiple phones and OS versions without having multiple phones.

2) Is there a sure way or a more proper way to display GoogleMap on older devices I'm talking Android 2.2+ I used the most trivial way to display my map I have a SupportMap Fragment element in my Layout xml. The problem I'm experiencing is that some 2.2 and 2.3 phones that have GooglePlayStore on them will or wont open the application those that do open the application do not display the map but they do display the map zoom controls and Google logo at the bottom.

3) I added my layout file but I do not have my android phone anymore and AVD does not let me test application that require GooglePlayServices is it possible that my layout displayed bellow is causing the problem due to overlay layout.

I basically have a frame layout in the background I have GoogleMap and on top of that in top corner I have a spinner and a button. When I last tested this application it worked on my phone HTC One V Android 4.0.3.

<FrameLayout 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:id="@+id/root_view"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
    />

    <Button
        android:id="@+id/gpsbttn"
        android:layout_width="28dp"
        android:layout_height="28dp"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:background="@drawable/gps"
        android:minHeight="28dip"
        android:minWidth="28dip"
        android:text="" />

    <Spinner
        android:id="@+id/bankslist"
        android:layout_width="match_parent"
        android:layout_height="36dp"
        android:layout_marginLeft="48dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="10dp"
        android:entries="@array/banks_list"
        android:prompt="@string/banks_prompt" />

</FrameLayout>

EASIEST SOLUTION:
To all friends who come across this issue of not being able to fully test your applications via AVD make the switch to Genymotion Emulator it is a life saver. It is faster, it is less buggy and it supports every single feature a real phone does and makes testing for Android apps since 2.2 so much easier.

I went Genny and never looked back.

Community
  • 1
  • 1
Sterling Duchess
  • 1,970
  • 16
  • 51
  • 91
  • 1
    Be careful to not confuse the Google Play Store with Google Play Services. All the two really share is the name; I think you mostly mean Google Play Services in your question. – Scott Barta Nov 30 '13 at 18:13
  • Do you get any exceptions in LogCat? I am suspecting `GooglePlayServicesUtil.isGooglePlayServicesAvailable(context)` throws ClassNotFoundException because no class called `GooglePlayServicesUtil` is available in the device. In this case, you should catch the exception and return `false`. – ADTC Dec 03 '13 at 06:28

3 Answers3

7

According to an answer to this question: Google Maps - "App won't run unless you update Google Play services", which references this Google+ post: https://plus.google.com/+AndroidDevelopers/posts/Tyz491d96Ci, using Maps within your app isn't supported in the emulator; there are a number of bitter replies in that post.

One of the replies references this question: This app won't run unless you update Google Play Services (via Bazaar) which describes some emulator hacking that you can try if nothing else is working.

Community
  • 1
  • 1
Scott Barta
  • 79,344
  • 24
  • 180
  • 163
  • Thanks for the reply mate, I completely forgot about the question. Mainly due to my discovery of Genymotion emulator which allows to test GP Services dependant applications from Android 2.2 up to the latest version. – Sterling Duchess Dec 09 '13 at 23:34
5

In addition to the workaround Scott mentions, according to the Play Services documentation, all AVDs targeting 4.2.2 or greater will support Play Services.: http://developer.android.com/google/play-services/setup.html

There are also several people that have been able to install Play services onto older AVDs, but the legality of that might be questionable:

Community
  • 1
  • 1
anddev84
  • 1,473
  • 12
  • 30
3

Currently the Android Emulator does not allow Google Maps because it does not support the Google Play Services application(on devices < 4.2.2) which is required for the Maps API to work. I assume you are using Google maps. Looks like http://www.genymotion.com/ offers an Emulator that supports the Google Play Services functions. Try that if it does not work, try to get a real Device. It does not make much sense to me to be testing a map application on an Emulator. I would suggest investing a little money into a development device. It will pay for itself and reduce your headaches when dealing with these types of situations.

UPDATE

Try switching your Android Target to Google API's(same target number)

I have also pulled google play services.apk from a rooted device and installed that via command line on the emulator. This is not exactly recommended, and can be a bit troublesome.

In the documentation, that Scott provided a link to, it tells you the requirements areGoogle Play StoreandGoogle Play Services.

kandroidj
  • 13,784
  • 5
  • 64
  • 76
  • There are system images that have the Play Services APK and support it. None of them have the Google Play store itself. I believe the issue here is that the latest update to Maps doesn't allow third-party applications to display maps via the API when running in emulation. – Scott Barta Dec 05 '13 at 17:27