Pages

Showing posts with label api. Show all posts
Showing posts with label api. Show all posts

Thursday, March 24, 2016

Doctor on Demand Improves Patient Care using Google Maps APIs



Editors note: Since the launch of Google Maps ten years ago, maps have come a long way. To celebrate a decade of map innovation, we’re highlighting unique maps built by our developer community. Read how guest bloggers, Ed Bindl and Jacinda Shelly, Software Engineers for Doctor on Demand, use the Google Maps APIs to bring unique mapping experiences to users.

Maps can do much more for an online business than help people get from point A to point B. You might not think that a website for making video appointments with medical professionals would benefit from mapping — but at Doctor on Demand, maps connect our patients to physicians faster and allow physicians to prescribe medications at the right pharmacies. Google Maps make our user experience much more satisfying, which means patients will use our service again.
We use the Google Maps APIs, including the Geolocation and Javascript APIs, to show patients a map of nearby pharmacies before they start a video call with a medical professional. For our users, maps make it easy and convenient to connect with physicians and pick up prescriptions at the pharmacy. But maps can be helpful for other businesses in other ways. And now that we see the great value of incorporating reliable map functionality into our app, wed love to share how you can do the same:

  • Choose a familiar interface. Use a map that’s easy for people to navigate – if it’s hard to understand and requires extensive instructions, they won’t use it. We picked Google Maps because our patients know them well.

  • Configure maps for many platforms. If your users find maps helpful on your desktop website, they’ll want to use maps from any browser or device. We’ve made sure our maps work just as well on iOS and Android devices as they do on a desktop computer.

  • Maintain accuracy. In our case, we have to update the geolocation information for about 65,000 pharmacies across the country every evening. We use the Google Maps Geocoding API, which minimizes the time it takes to keep our map accurate. We keep a database of all pharmacies from Surescripts, a healthcare network, and each night we get an update to that database that adds, removes, and updates pharmacies and their locations. We use the Google Maps Javascript API to place the pharmacies on our map when a patient is asked to select a pharmacy.

  • Meet compliance standards. In order to comply with medical regulations, Doctor On Demand must connect patients with physicians licensed in their state. We use the Google Maps Reverse Geocoding API to accurately determine the state a patient is located in before connecting them with a physician.

  • Help users save time and make better choices. Before we built our pharmacy map, patients had to tell doctors which pharmacy they wanted to use. Then doctors emailed us the details. However, our support team had to follow up with doctors and patients to make sure we had the right pharmacy, since patients might say something like, “the drugstore down the street from my house.” Today, there’s no doubt about which pharmacy is the right one, since patients can clearly see their local outlets on the map.

Our pharmacy map inspires us to think about new ways to use maps in the future – like plotting the movement of cold and flu outbreaks and sharing this data with patients and doctors. We see a direct connection between maps and improving patient care. In the greater scheme, Google Maps improve the health of our patients, and, the health of our business.


Read More..

Friday, February 26, 2016

Custom InfoWindow for Google Maps Android API v2


To create Custom InfoWindow for Google Maps Android API v2:

- Make your Activity implements GoogleMap.InfoWindowAdapter.

- Override getInfoWindow(Marker marker) and getInfoContents(Marker marker).

The API will first call getInfoWindow(Marker) and if null is returned, it will then call getInfoContents(Marker). If this also returns null, then the default info window will be used.

The first of these (getInfoWindow()) allows you to provide a view that will be used for the entire info window. The second of these (getInfoContents()) allows you to just customize the contents of the window but still keep the default info window frame and background.

- setInfoWindowAdapter(this).


Modify MapsActivity.java from last example "Make GoogleMaps marker draggabe and detect moving marker".
package com.blogspot.android_er.androidstudiomapapp;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.InputType;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.GoogleApiAvailability;
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.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback,
GoogleMap.OnMapClickListener, GoogleMap.OnMapLongClickListener,
GoogleMap.OnMarkerDragListener, GoogleMap.InfoWindowAdapter {

private GoogleMap mMap;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);

}

/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setOnMapClickListener(this);
mMap.setOnMapLongClickListener(this);
mMap.setOnMarkerDragListener(this);
mMap.setInfoWindowAdapter(this);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_addmarkers:
addMarker();
return true;
case R.id.maptypeHYBRID:
if(mMap != null){
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
return true;
}
case R.id.maptypeNONE:
if(mMap != null){
mMap.setMapType(GoogleMap.MAP_TYPE_NONE);
return true;
}
case R.id.maptypeNORMAL:
if(mMap != null){
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
return true;
}
case R.id.maptypeSATELLITE:
if(mMap != null){
mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
return true;
}
case R.id.maptypeTERRAIN:
if(mMap != null){
mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
return true;
}
case R.id.menu_legalnotices:
String LicenseInfo = GoogleApiAvailability
.getInstance()
.getOpenSourceSoftwareLicenseInfo(MapsActivity.this);
AlertDialog.Builder LicenseDialog =
new AlertDialog.Builder(MapsActivity.this);
LicenseDialog.setTitle("Legal Notices");
LicenseDialog.setMessage(LicenseInfo);
LicenseDialog.show();
return true;
case R.id.menu_about:
AlertDialog.Builder aboutDialogBuilder =
new AlertDialog.Builder(MapsActivity.this);
aboutDialogBuilder.setTitle("About Me")
.setMessage("http://android-er.blogspot.com");

aboutDialogBuilder.setPositiveButton("visit",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String url = "http://android-er.blogspot.com";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
});

aboutDialogBuilder.setNegativeButton("Dismiss",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});

AlertDialog aboutDialog = aboutDialogBuilder.create();
aboutDialog.show();

return true;
}
return super.onOptionsItemSelected(item);
}

private void addMarker(){
if(mMap != null){

//create custom LinearLayout programmatically
LinearLayout layout = new LinearLayout(MapsActivity.this);
layout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
layout.setOrientation(LinearLayout.VERTICAL);

final EditText titleField = new EditText(MapsActivity.this);
titleField.setHint("Title");

final EditText latField = new EditText(MapsActivity.this);
latField.setHint("Latitude");
latField.setInputType(InputType.TYPE_CLASS_NUMBER
| InputType.TYPE_NUMBER_FLAG_DECIMAL
| InputType.TYPE_NUMBER_FLAG_SIGNED);

final EditText lonField = new EditText(MapsActivity.this);
lonField.setHint("Longitude");
lonField.setInputType(InputType.TYPE_CLASS_NUMBER
| InputType.TYPE_NUMBER_FLAG_DECIMAL
| InputType.TYPE_NUMBER_FLAG_SIGNED);

layout.addView(titleField);
layout.addView(latField);
layout.addView(lonField);

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Add Marker");
builder.setView(layout);
AlertDialog alertDialog = builder.create();

builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
boolean parsable = true;
Double lat = null, lon = null;

String strLat = latField.getText().toString();
String strLon = lonField.getText().toString();
String strTitle = titleField.getText().toString();

try{
lat = Double.parseDouble(strLat);
}catch (NumberFormatException ex){
parsable = false;
Toast.makeText(MapsActivity.this,
"Latitude does not contain a parsable double",
Toast.LENGTH_LONG).show();
}

try{
lon = Double.parseDouble(strLon);
}catch (NumberFormatException ex){
parsable = false;
Toast.makeText(MapsActivity.this,
"Longitude does not contain a parsable double",
Toast.LENGTH_LONG).show();
}

if(parsable){

LatLng targetLatLng = new LatLng(lat, lon);
MarkerOptions markerOptions =
new MarkerOptions().position(targetLatLng).title(strTitle);

markerOptions.draggable(true);

mMap.addMarker(markerOptions);
mMap.moveCamera(CameraUpdateFactory.newLatLng(targetLatLng));

}
}
});
builder.setNegativeButton("Cancel", null);

builder.show();
}else{
Toast.makeText(MapsActivity.this, "Map not ready", Toast.LENGTH_LONG).show();
}
}

@Override
public void onMapClick(LatLng latLng) {
Toast.makeText(MapsActivity.this,
"onMapClick: " + latLng.latitude + " : " + latLng.longitude,
Toast.LENGTH_LONG).show();
}

@Override
public void onMapLongClick(LatLng latLng) {
Toast.makeText(MapsActivity.this,
"onMapLongClick: " + latLng.latitude + " : " + latLng.longitude,
Toast.LENGTH_LONG).show();

//Add marker on LongClick position
MarkerOptions markerOptions =
new MarkerOptions().position(latLng).title(latLng.toString());
markerOptions.draggable(true);

mMap.addMarker(markerOptions);
}


@Override
public void onMarkerDragStart(Marker marker) {
marker.setTitle(marker.getPosition().toString());
marker.showInfoWindow();
marker.setAlpha(0.5f);
}

@Override
public void onMarkerDrag(Marker marker) {
marker.setTitle(marker.getPosition().toString());
marker.showInfoWindow();
marker.setAlpha(0.5f);
}

@Override
public void onMarkerDragEnd(Marker marker) {
marker.setTitle(marker.getPosition().toString());
marker.showInfoWindow();
marker.setAlpha(1.0f);
}

@Override
public View getInfoWindow(Marker marker) {
return null;
//return prepareInfoView(marker);
}


@Override
public View getInfoContents(Marker marker) {
//return null;
return prepareInfoView(marker);

}


private View prepareInfoView(Marker marker){
//prepare InfoView programmatically
LinearLayout infoView = new LinearLayout(MapsActivity.this);
LinearLayout.LayoutParams infoViewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
infoView.setOrientation(LinearLayout.HORIZONTAL);
infoView.setLayoutParams(infoViewParams);

ImageView infoImageView = new ImageView(MapsActivity.this);
//Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher);
Drawable drawable = getResources().getDrawable(android.R.drawable.ic_dialog_map);
infoImageView.setImageDrawable(drawable);
infoView.addView(infoImageView);

LinearLayout subInfoView = new LinearLayout(MapsActivity.this);
LinearLayout.LayoutParams subInfoViewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
subInfoView.setOrientation(LinearLayout.VERTICAL);
subInfoView.setLayoutParams(subInfoViewParams);

TextView subInfoLat = new TextView(MapsActivity.this);
subInfoLat.setText("Lat: " + marker.getPosition().latitude);
TextView subInfoLnt = new TextView(MapsActivity.this);
subInfoLnt.setText("Lnt: " + marker.getPosition().longitude);
subInfoView.addView(subInfoLat);
subInfoView.addView(subInfoLnt);
infoView.addView(subInfoView);

return infoView;
}

}


Reference: https://developers.google.com/maps/documentation/android-api/infowindows

Next:
- Detect user click on InfoWindow, by implementing GoogleMap.OnInfoWindowClickListener()


~ Step-by-step of Android Google Maps Activity using Google Maps Android API v2, on Android Studio

Read More..

Friday, February 19, 2016

Hilton helps guests book the perfect room with Google Maps APIs

Posted by Virginia Suliman, Vice President of Digital Design and Development, Hilton Worldwide

(Cross-posted on the Google Geo Developers Blog.)

Editor’s note: Today’s guest blogger is Virginia Suliman, Vice President of Digital Design and Development, Hilton Worldwide. Read how Hilton is experimenting with Google APIs to take the guess work out of the hotel booking and room selection process. Hilton is just one of many customers sharing their story as part of our cross-country road trip, Code the Road.

No one likes surprises when they reserve hotel rooms, so it’s crucial for Hilton that people see exactly what they’ll be getting before they arrive. Currently, Hilton’s HHonors guests can use the HHonors website and app as a one-stop tool to control their on-property experience – from finding the best hotels in the right neighborhoods and booking the most suitable one, to soon, using the app as a room key.
couple_sitting.jpg

With a spirit of constant innovation, we’re always looking for new ways to enhance the guest experience. One way we’re doing so is by experimenting with the Google Maps APIs through proof of concept iPhone app functionality we built to enhance the room selection process during digital check-in. The concept tests a the Street View panoramas, part of the Google Maps SDK for iOS, letting users see on the app the exact view they’ll experience when they get to their hotel room. For example, they could virtually look out their window on the app and select the room that overlooks a park or a quiet street corner.
Businesswoman2.jpg

People care not just about the hotel they stay in, but also about the neighborhood, including what kinds of food, entertainment and amenities are nearby. So in our concept, we also tested a controlled list of businesses and points of interest from the Google Maps Places API for IOS to highlight nearby destinations via the HHonors app, like Lincoln Center in New York City, a great fish restaurant in Boston, or the Centennial Olympic Park in Atlanta.

The full potential of Google APIs sets in when you combine them. If successful, the Maps and Street View panorama concepts could one day fully integrate into our HHonors app or global web portal, which already uses Google Maps Business View to offer panoramic virtual tours of our properties to guests.

We believe that happy travelers are repeat customers who become loyalists. If you feel connected to the experience you’ve had with us, you’re more likely to return and to tell others about it. Through technology, we’re hoping to make it easier for people to find the perfect room, have an unforgettable stay and come back for another adventure.

We were delighted to participate in the Code the Road trip. We hosted the Code the Road bus at our Hilton Chicago property on June 10 and at Hilton Headquarters in McLean, Virginia on June 22. You can also see the Hilton HHonors app window-view proof of concept demo on the bus.
Read More..