Android Open Source - loopback-android-getting-started Lesson Three Fragment






From Project

Back to project page loopback-android-getting-started.

License

The source code is released under:

MIT License

If you think the Android project loopback-android-getting-started listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.strongloop.android.loopback.guide.lessons;
/*from  www . ja  v  a  2  s .c o  m*/
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.common.collect.ImmutableMap;
import com.strongloop.android.loopback.Model;
import com.strongloop.android.loopback.ModelRepository;
import com.strongloop.android.loopback.RestAdapter;
import com.strongloop.android.loopback.guide.GuideApplication;
import com.strongloop.android.loopback.guide.R;
import com.strongloop.android.loopback.guide.util.HtmlFragment;
import com.strongloop.android.remoting.adapters.Adapter;

/**
 * Implementation for Lesson Three: Don't Outgrow, Outbuild.
 */
public class LessonThreeFragment extends HtmlFragment {
    final LatLng MY_POSITION = new LatLng(37.56572191237293, -122.32357978820802);

    /**
     * Loads all Locations from the server, passing them to our MapView
     * to be displayed as pins.
     */
    private void sendRequest() {
        // 1. Grab the shared RestAdapter instance.
        final GuideApplication app = (GuideApplication)getActivity().getApplication();
        final RestAdapter adapter = app.getLoopBackAdapter();

        // 2. Instantiate our ModelRepository. Rather than create a subclass
        // this time, we'll use the base classes to show off their off-the-shelf
        // super-powers.
        final ModelRepository<Model> repository = adapter.createRepository("location");

        // 3. The meat of the lesson: custom behaviour. Here, we're invoking
        // a custom, static method on the Location model type called "nearby".
        // As you might expect, it does a geo-based query ordered by the closeness
        // to the provided latitude and longitude. Rather than go through
        // LocationClient, we've plugged in the coordinates of our favorite noodle
        // shop here in San Mateo, California.
        //
        // Once we've successfully loaded the models, we pass them to our
        // `displayLocations` method to be converted to MarkerOptions and
        // added to the map as clickable pins!
        final Map<String,?> parameters = ImmutableMap.of(
                "here[lat]", MY_POSITION.latitude,
                "here[lng]", MY_POSITION.longitude);

        repository.invokeStaticMethod(
                "nearby",
                parameters,
                new Adapter.JsonArrayCallback() {
                    @Override
                    public void onSuccess(final JSONArray response) {
                        displayLocations(response);
                    }

                    @Override
                    public void onError(final Throwable t) {
                        Log.e(getTag(), "Cannot list locations.", t);
                        showResult("Failed.");
                    }
                });
    }

    private void showResult(final String message) {
        Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();
    }

    /**
     * Display a list of locations in the GUI.
     */
    private void displayLocations(final JSONArray response) {
        // Convert JSON response to MarkerOptions
        final List<MarkerOptions> locations = convertLocationsToMarkerOptions(response);

        if (canDisplayMap) {
            // If we have a map, then display these markers as pins
            final GoogleMap map = mapFragment.getMap();

            // remove previous markers
            map.clear();

            // add markers for locations returned by the server
            for (final MarkerOptions loc: locations) {
                map.addMarker(loc);
            }

            // Move the camera to our location
            map.moveCamera(CameraUpdateFactory.newLatLngZoom(MY_POSITION, 4));
        } else {
            // Otherwise show a list of locations
            final ListView list = listFragment.getList();
            list.setAdapter(new LocationListAdapter(
                    getActivity(), locations, MY_POSITION));
        }
    }

    private List<MarkerOptions> convertLocationsToMarkerOptions(
            final JSONArray locations) {

        final List<MarkerOptions> result =
                new ArrayList<MarkerOptions>(locations.length());

        for (int ix = 0; ix < locations.length(); ix++) {
            try {
                final JSONObject loc = locations.getJSONObject(ix);
                result.add(createMarkerOptionsForLocation(loc));
            } catch (final JSONException e) {
                Log.w("LessonThreeFragment", "Skipping invalid location object.", e);
            }
        }

        return result;
    }

    private MarkerOptions createMarkerOptionsForLocation(final JSONObject location)
            throws JSONException {
        final JSONObject posJson = location.getJSONObject("geo");
        final LatLng geoPos = new LatLng(
                posJson.getDouble("lat"),
                posJson.getDouble("lng"));

        return new MarkerOptions()
        .position(geoPos)
        .title(location.getString("name"))
        .snippet(location.getString("city"));
    }

    /**
     * Custom ListAdapter for displaying locations.
     */
    private static class LocationListAdapter extends ArrayAdapter<MarkerOptions> {
        private final LatLng myPosition;

        public LocationListAdapter(final Context context, final List<MarkerOptions> list, final LatLng myPosition) {
            super(context, 0, list);
            this.myPosition = myPosition;
        }

        @Override
        public View getView(final int position, View convertView, final ViewGroup parent) {
            if (convertView == null) {
                convertView = LayoutInflater.from(getContext()).inflate(
                        android.R.layout.simple_list_item_2, null);
            }

            final MarkerOptions model = getItem(position);
            if (model == null) return convertView;

            final TextView textView1 = (TextView)convertView.findViewById(
                    android.R.id.text1);
            textView1.setText(model.getTitle());

            final TextView textView2 = (TextView)convertView.findViewById(
                    android.R.id.text2);
            textView2.setText(
                    model.getSnippet() +
                    " (" + getDistanceString(model.getPosition()) + ")");

            return convertView;
        }

        @SuppressLint("DefaultLocale")
        private String getDistanceString(final LatLng position) {
            final float[] distanceResult = new float[1];
            Location.distanceBetween(
                    myPosition.latitude, myPosition.longitude,
                    position.latitude, position.longitude,
                    distanceResult);
            final float distance = distanceResult[0];

            return distance < 1000
                    ? String.format("%dm", Math.round(distance))
                            : String.format("%.1fkm", distance/1000);
        }
    }

    //
    // GUI glue
    //

    private boolean canDisplayMap;
    private SupportMapFragment mapFragment;
    private LocationListFragment listFragment;

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
            final Bundle savedInstanceState) {

        setRootView((ViewGroup) inflater.inflate(
                R.layout.fragment_lesson_three, container, false));

        setHtmlText(R.id.content, R.string.lessonThree_content);

        installButtonClickHandler();

        setUpMapIfNeeded();

        return getRootView();
    }

    @Override
    public void onResume() {
        super.onResume();
        setUpMapIfNeeded();
    }

    private void installButtonClickHandler() {
        final Button button = (Button) getRootView().findViewById(R.id.sendRequest);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {
                sendRequest();
            }
        });
    }

    /**
     * Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly
     * installed) and the map has not already been instantiated.
     * <p>
     * If it isn't installed {@link SupportMapFragment} (and
     * {@link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to
     * install/update the Google Play services APK on their device.
     * <p>
     * A user can return to this FragmentActivity after following the prompt and correctly
     * installing/updating/enabling the Google Play services. Since the FragmentActivity may not
     * have been completely destroyed during this process (it is likely that it would only be
     * stopped or paused), {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}
     * may not be called again so we should call this method in {@link #onResume()}
     * to guarantee that it will be called.
     */
    private void setUpMapIfNeeded() {
        canDisplayMap = detectGoogleMapsSupport();

        if (!canDisplayMap) {
            setupAlternateView();
            return;
        }

        setupMapView();
    }

    private void setupMapView() {
        // Do a null check to confirm that we have not already
        // instantiated the fragment.
        if (mapFragment == null)
            mapFragment = new SupportMapFragment();
        replaceMapFrame(mapFragment);
    }

    private void setupAlternateView() {
        // Do a null check to confirm that we have not already
        // instantiated the fragment.
        if (listFragment == null)
            listFragment = new LocationListFragment();
        replaceMapFrame(listFragment);
    }

    private void replaceMapFrame(final Fragment newFragment) {
        final FragmentManager fragmentManager = getChildFragmentManager();
        final FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.map_frame, newFragment);
        transaction.commit();
    }


    boolean detectGoogleMapsSupport() {
        // 1. Check for OpenGL ES 2.0
        final ActivityManager activityManager =
                (ActivityManager)getActivity().getSystemService(Context.ACTIVITY_SERVICE);
        final ConfigurationInfo configurationInfo =
                activityManager.getDeviceConfigurationInfo();
        if (configurationInfo.reqGlEsVersion < 0x20000) {
            Log.w("LessonThreeFragment", "Device does not support OpenGL ES 2.0");
            return false;
        }

        // 2. Check for Google Play Services availability
        final int playServicesStatus =
                GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity());
        if (playServicesStatus != ConnectionResult.SUCCESS
                && Build.HARDWARE.contains("golfdish")) {
            // It's not possible to install or update Google Play on an emulator
            Log.w("LessonThreeFragment",
                    "Detected an emulator with missing or outdated Play Services.");
            return false;
        }

        Log.i("LessonThreeFragment", "Locations will be displayed in Google Maps.");
        return true;
    }

    public static class LocationListFragment extends Fragment {
        ViewGroup rootView;

        @Override
        public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
                final Bundle savedInstanceState) {

            rootView = (ViewGroup) inflater.inflate(
                    R.layout.fragment_location_list, container, false);
            return rootView;
        }

        public ListView getList() {
            return (ListView) rootView.findViewById(R.id.list);
        }
    }
}




Java Source Code List

com.strongloop.android.loopback.guide.BackFragment.java
com.strongloop.android.loopback.guide.BackFragment.java
com.strongloop.android.loopback.guide.CoverFragment.java
com.strongloop.android.loopback.guide.CoverFragment.java
com.strongloop.android.loopback.guide.FinaleFragment.java
com.strongloop.android.loopback.guide.FinaleFragment.java
com.strongloop.android.loopback.guide.GuideApplication.java
com.strongloop.android.loopback.guide.GuideApplication.java
com.strongloop.android.loopback.guide.IntroductionFragment.java
com.strongloop.android.loopback.guide.IntroductionFragment.java
com.strongloop.android.loopback.guide.SlidePresenterActivity.java
com.strongloop.android.loopback.guide.SlidePresenterActivity.java
com.strongloop.android.loopback.guide.lessons.LessonOneFragment.java
com.strongloop.android.loopback.guide.lessons.LessonOneFragment.java
com.strongloop.android.loopback.guide.lessons.LessonThreeFragment.java
com.strongloop.android.loopback.guide.lessons.LessonThreeFragment.java
com.strongloop.android.loopback.guide.lessons.LessonTwoFragment.java
com.strongloop.android.loopback.guide.lessons.LessonTwoFragment.java
com.strongloop.android.loopback.guide.util.HtmlFragment.java
com.strongloop.android.loopback.guide.util.HtmlFragment.java