com.example.mapdemo.LiteListDemoActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.example.mapdemo.LiteListDemoActivity.java

Source

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.example.mapdemo;

import com.bumptech.glide.Glide;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
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.MarkerOptions;
import android.net.Uri;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.ListFragment;
import android.text.Html;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import java.util.Collections;

/**
 * This shows to include a map in lite mode in a ListView.
 * Note the use of the view holder pattern with the
 * {@link com.google.android.gms.maps.OnMapReadyCallback}.
 */
public class LiteListDemoActivity extends FragmentActivity implements OnMapReadyCallback {
    private ListFragment mList;
    private MapAdapter mAdapter;
    private SupportMapFragment mapFragment;

    // Places List
    PlacesList nearPlaces = new PlacesList();
    List<Place> places;

    List<NamedLocation> locations = new ArrayList<NamedLocation>();
    ArrayList<HashMap<String, String>> placesList = new ArrayList<HashMap<String, String>>();
    ArrayList<HashMap<String, NamedLocation>> locationmapList = new ArrayList<HashMap<String, NamedLocation>>();
    // Image List Nodes
    // XML node keys
    static final String KEY_THUMB_URL = "thumb_url";
    static final String KEY_SONG = "song"; // parent node
    static final String KEY_ID = "id";
    static final String KEY_NAME = "name";
    static final String KEY_ADDRESS = "address";
    static final String KEY_MAP = "map";
    // GPS Location
    GPSTracker gps;
    ListView list;

    /**
     * A Polygon with five points in the Norther Territory, Australia.
     */

    private com.google.android.gms.maps.model.LatLng LatLng[] = {};

    /**
     * A list of locations to show in this ListView.
     */

    //TODO XMLPullParser Loaded from JSON Object

    private NamedLocation[] LIST_LOCATIONS = new NamedLocation[100];

    Map<String, Place> placelistmap = new HashMap<String, Place>();
    Map<String, NamedLocation> namelocationlistmap = new HashMap<String, NamedLocation>();
    // URL Strings manipulation
    String[] imageUrls;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.lite_list_demo);

        // creating GPS Class object
        // User location
        gps = new GPSTracker(this);
        Bundle b = getIntent().getExtras();

        nearPlaces = (PlacesList) b.getSerializable("near_places");
        places = nearPlaces.results;

        LIST_LOCATIONS = new NamedLocation[nearPlaces.results.size()];
        imageUrls = new String[nearPlaces.results.size()];

        // TODO This i++ resembles C. Can be buggy memory leaks
        int i = 0;
        for (Place place : places) {
            // creating new HashMap
            HashMap<String, String> placesmap = new HashMap<String, String>();
            HashMap<String, NamedLocation> locationsmap = new HashMap<String, NamedLocation>();
            placesmap.put(KEY_ID, place.id);
            placesmap.put(KEY_ID, place.name);
            placesmap.put(KEY_ADDRESS, place.address);
            placesmap.put(KEY_THUMB_URL, place.office_image_url);
            placesList.add(placesmap);
            // Array to sort locations
            LIST_LOCATIONS[i] = new NamedLocation(place.name, new LatLng(place.location.lat, place.location.lng),
                    place.formatted_phone_number, place.address, place.office_image_url, place.vicinity);

            locationmapList.add(locationsmap);
            locations.add(new NamedLocation(place.name, new LatLng(place.location.lat, place.location.lng),
                    place.formatted_phone_number, place.address, place.office_image_url, place.vicinity));

            // Get image URL's
            imageUrls[i] = place.office_image_url;
            i++;
        }

        Collections.sort(locations);

        //  list=(ListView)findViewById(R.id.listview);
        // Getting adapter by passing xml data ArrayList
        //    lAdapter=new LazyAdapter(this.getApplicationContext(), places);
        //   list.setAdapter(lAdapter);
        GoogleType obj = b.getParcelable("GoogleType");

        // Set a custom list adapter for a list of locations
        mAdapter = new MapAdapter(this, R.layout.lite_list_demo_row, locations);

        // Set a custom list adapter for a list of locations
        //     mAdapter = new MapAdapter(this, locations_list);
        mList = (ListFragment) getSupportFragmentManager().findFragmentById(R.id.list);
        mList.setListAdapter(mAdapter);

        mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
        // Set a RecyclerListener to clean up MapView from ListView
        AbsListView lv = mList.getListView();
        lv.setRecyclerListener(mRecycleListener);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        // Notify all MapViews of low memory
        for (MapView m : mAdapter.getMaps()) {
            m.onLowMemory();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        // Pause all instantiated MapViews
        for (MapView m : mAdapter.getMaps()) {
            m.onPause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        // Resume all instantiated MapViews
        for (MapView m : mAdapter.getMaps()) {
            m.onResume();
        }
    }

    @Override
    protected void onDestroy() {
        // Destroy all instantiated MapViews and remove from list
        for (MapView m : mAdapter.getMaps()) {
            m.onResume();
        }
        mAdapter.getMaps().clear();
        super.onDestroy();
    }

    /**
     * Adapter that displays a title and {@link com.google.android.gms.maps.MapView} for each item.
     * The layout is defined in <code>lite_list_demo_row.xml</code>. It contains a MapView
     * that is programatically initialised in
     * {@link #getView(int, android.view.View, android.view.ViewGroup)}
     */
    private class MapAdapter extends ArrayAdapter<NamedLocation> {

        private LayoutInflater inflater = null;
        private List<NamedLocation> items;
        private Context context;
        private Button callButton;
        private final HashSet<MapView> mMaps = new HashSet<MapView>();

        public MapAdapter(Context context, int resource, List<NamedLocation> objects) {
            super(context, resource, objects);
            // TODO Auto-generated constructor stub
            this.context = context;
            this.items = objects;

        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View row = convertView;
            ViewHolder holder;

            // Check if a view can be reused, otherwise inflate a layout and set up the view holder
            if (row == null) {
                // Inflate view from layout file
                row = getLayoutInflater().inflate(R.layout.lite_list_demo_row, null);
                // Set up holder and assign it to the View
                holder = new ViewHolder();
                holder.mapView = (MapView) row.findViewById(R.id.lite_listrow_map);
                holder.title = (TextView) row.findViewById(R.id.lite_listrow_text);
                holder.place_name = (TextView) row.findViewById(R.id.place_name);
                holder.place_image = (ImageView) row.findViewById(R.id.place_image);
                holder.place_distance = (TextView) row.findViewById(R.id.place_distance);
                holder.place_address = (TextView) row.findViewById(R.id.place_address);
                holder.callButton = (Button) row.findViewById(R.id.childButton);
                // Set holder as tag for row for more efficient access.
                row.setTag(holder);
                // Initialise the MapView
                holder.initializeMapView();
                // Keep track of MapView
                mMaps.add(holder.mapView);
            } else {
                // View has already been initialised, get its holder
                holder = (ViewHolder) row.getTag();
            }

            // Get the NamedLocation for this item and attach it to the MapView
            NamedLocation item = getItem(position);
            holder.mapView.setTag(item);
            // Ensure the map has been initialised by the on map ready callback in ViewHolder.
            // If it is not ready yet, it will be initialised with the NamedLocation set as its tag
            // when the callback is received.
            if (holder.map != null) {
                // The map is already ready to be used
                setMapLocation(holder.map, item);
            }
            String url = item.office_image_url;
            // Setting all values in list row
            Glide.with(context.getApplicationContext()).load(url).into(holder.place_image);
            // Set the text label for this item
            holder.title.setText(item.name);
            holder.place_distance.setText(item.distance); /***************************/
            //        holder.place_phone.setText(item.formatted_phone_number);
            holder.place_distance.setText(item.distance);
            holder.place_address.setText(item.address);
            holder.place_name.setText(item.name);
            // Set button listener
            final String formatted_phone = item.formatted_phone_number;
            holder.callButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //TODO
                    Intent callIntent = new Intent(Intent.ACTION_CALL);
                    String uri = "tel:" + formatted_phone.trim();
                    callIntent.setData(Uri.parse(uri));
                    startActivity(callIntent);
                }
            });
            return row;
        }

        /**
         * Retuns the set of all initialised {@link MapView} objects.
         *
         * @return All MapViews that have been initialised programmatically by this adapter
         */
        public HashSet<MapView> getMaps() {
            return mMaps;
        }

        public int getCount() {
            // TODO Auto-generated method stub
            return items.size();
        }

        public long getItemId(int position) {
            // TODO Auto-generated method stub
            return position;
        }

    }

    /**
     * Displays a {@link LiteListDemoActivity.NamedLocation} on a
     * {@link com.google.android.gms.maps.GoogleMap}.
     * Adds a marker and centers the camera on the NamedLocation with the normal map type.
     *
     * @param map
     * @param data
     */
    private static void setMapLocation(GoogleMap map, NamedLocation data) {

        // Add a marker for this item and set the camera
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(data.location, 13f));
        map.addMarker(new MarkerOptions().position(data.location));
        // Set the map type back to normal.
        map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
    }

    /**
     * Holder for Views used in the {@link LiteListDemoActivity.MapAdapter}.
     * Once the  the <code>map</code> field is set, otherwise it is null.
     * When the {@link #onMapReady(com.google.android.gms.maps.GoogleMap)} callback is received and
     * the {@link com.google.android.gms.maps.GoogleMap} is ready, it stored in the {@link #map}
     * field. The map is then initialised with the NamedLocation that is stored as the tag of the
     * MapView. This ensures that the map is initialised with the latest data that it should
     * display.
     */
    class ViewHolder implements OnMapReadyCallback {
        MapView mapView;
        TextView title;
        GoogleMap map;
        ImageView place_image;
        TextView place_distance;
        TextView place_address;
        TextView place_name;
        Button callButton;

        @Override
        public void onMapReady(GoogleMap googleMap) {
            MapsInitializer.initialize(getApplicationContext());
            map = googleMap;
            NamedLocation data = (NamedLocation) mapView.getTag();
            if (data != null) {
                setMapLocation(map, data);
            }
        }

        /**
         * Initialises the MapView by calling its lifecycle methods.
         */
        public void initializeMapView() {
            if (mapView != null) {
                // Initialise the MapView
                mapView.onCreate(null);
                mapView.onResume();
                // Set the map ready callback to receive the GoogleMap object
                mapView.getMapAsync(this);
            }
        }
    }

    /**
     * RecycleListener that completely clears the {@link com.google.android.gms.maps.GoogleMap}
     * attached to a row in the ListView.
     * Sets the map type to {@link com.google.android.gms.maps.GoogleMap#MAP_TYPE_NONE} and clears
     * the map.
     */
    private AbsListView.RecyclerListener mRecycleListener = new AbsListView.RecyclerListener() {
        @Override
        public void onMovedToScrapHeap(View view) {
            ViewHolder holder = (ViewHolder) view.getTag();
            if (holder != null && holder.map != null) {
                // Clear the map and free up resources by changing the map type to none
                holder.map.clear();
                holder.map.setMapType(GoogleMap.MAP_TYPE_NONE);
            }
        }
    };

    /**
     * This is where we can add markers or lines, add listeners or move the camera. In this case, we
     * just add a marker near Africa.
     */
    @Override
    public void onMapReady(GoogleMap map) {
        // TODO his should come from the XMLPullParser, faster render.
        for (Place place : places) {
            map.addMarker(new MarkerOptions().position(new LatLng(place.location.lat, place.location.lng))
                    .title(place.name));
        }

    }

}