Android Open Source - TravelBar Progress Bar Service






From Project

Back to project page TravelBar.

License

The source code is released under:

Apache License

If you think the Android project TravelBar 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.bourke.travelbar;
//from   w w  w.j  a  va2  s  .c  o m
import android.animation.ObjectAnimator;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.view.Gravity;
import android.view.WindowManager;
import android.view.animation.LinearInterpolator;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.squareup.otto.Subscribe;

public class ProgressBarService extends Service implements
        GooglePlayServicesClient.ConnectionCallbacks,
        GooglePlayServicesClient.OnConnectionFailedListener,
        LocationListener {

    private static final String TAG = "TravelBar/ProgressBarService";

    private WindowManager windowManager;
    private ProgressBar mProgressBar;

    private LocationClient mLocationClient;
    private LocationRequest mLocationRequest;

    private Location mStartingPoint;
    private Location mDestination;

    private float mTotalDistance;

    private BroadcastReceiver mStopReceiver;

    private double mRed = 0;
    private double mGreen = 255;
    private double mBlue = 0;

    public static boolean RUNNING = false;

    public static final String STARTING_LAT =
            "com.bourke.travelbar.ProgressBarService.STARTING_LAT";
    public static final String STARTING_LON =
            "com.bourke.travelbar.ProgressBarService.STARTING_LON";

    public static final String DESTINATION_LAT =
            "com.bourke.travelbar.ProgressBarService.DESTINATION_LAT";
    public static final String DESTINATION_LON =
            "com.bourke.travelbar.ProgressBarService.DESTINATION_LON";

    public static final int NOTIFICATION_ID = 0;

    @Override public IBinder onBind(Intent intent) {
        // Not used
        return null;
    }

    @Override public void onCreate() {
        super.onCreate();

        RUNNING = true;

        BusProvider.getInstance().register(this);

        mLocationClient = new LocationClient(this, this, this);
        mLocationClient.connect();

        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(Constants.UPDATE_INTERVAL);
        mLocationRequest.setFastestInterval(Constants.FASTEST_INTERVAL);

        mProgressBar = new ProgressBar(getBaseContext(), null,
                android.R.attr.progressBarStyleHorizontal);
        mProgressBar.getProgressDrawable().setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN);

        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.TOP | Gravity.LEFT;
        params.width = WindowManager.LayoutParams.MATCH_PARENT;
        params.x = 0;
        params.y = 0;

        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        windowManager.addView(mProgressBar, params);

        showRunningNotification("Initialising " + getString(R.string.app_name));
    }

    @Override public int onStartCommand(Intent intent, int flags, int startId) {
        // Parse starting point
        double startingLat = intent.getDoubleExtra(STARTING_LAT, -1);
        double startingLon = intent.getDoubleExtra(STARTING_LON, -1);

        if (startingLat != -1 || startingLon != -1) {
            mStartingPoint = new Location(TAG);
            mStartingPoint.setLatitude(startingLat);
            mStartingPoint.setLongitude(startingLon);

            if (BuildConfig.DEBUG) {
                Log.d(TAG, String.format("Received starting location: %f, %f", startingLat,
                        startingLon));
            }
        } else {
            throw new IllegalStateException("Starting point required to start ProgressBarService");
        }

        // Parse destination
        double destinationLat = intent.getDoubleExtra(DESTINATION_LAT, -1);
        double destinationLon = intent.getDoubleExtra(DESTINATION_LON, -1);

        if (destinationLat != -1 && destinationLon != -1) {
            mDestination = new Location(TAG);
            mDestination.setLatitude(destinationLat);
            mDestination.setLongitude(destinationLon);

            if (BuildConfig.DEBUG) {
                Log.d(TAG, String.format("Received destination: %f, %f", destinationLat,
                        destinationLon));
            }
        } else {
            throw new IllegalStateException("Destination required to start ProgressBarService");
        }

        mTotalDistance = mStartingPoint.distanceTo(mDestination);

        // We want this service to continue running until it is explicitly
        // stopped, so return sticky.
        return START_STICKY;
    }

    @Override public void onDestroy() {
        super.onDestroy();

        if (mLocationClient.isConnected()) {
            mLocationClient.removeLocationUpdates(this);
        }

        // Disconnecting the client invalidates it.
        mLocationClient.disconnect();

        if (mProgressBar != null) {
            windowManager.removeView(mProgressBar);
        }

        if (mStopReceiver != null) {
            try {
                unregisterReceiver(mStopReceiver);
            } catch (IllegalArgumentException e) {
                // http://stackoverflow.com/a/3568906/663370
            }
        }

        // Clear any notifications we've shown
        NotificationManager mNotificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.cancelAll();

        RUNNING = false;
    }

    @Override public void onConnected(Bundle bundle) {
        // TODO: they recommend wrapping a boolean here to disable updates if user requests
        mLocationClient.requestLocationUpdates(mLocationRequest, this);
    }

    @Override public void onDisconnected() {
        Toast.makeText(this, "Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
    }

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

    @Override public void onLocationChanged(Location location) {
        updateProgress(location);
    }

    @Subscribe public void destinationChanged(DestinationChangedEvent event) {
        if (BuildConfig.DEBUG) {
            Log.d(TAG, String.format("Destination changed to: %f,%f", event.lat, event.lon));
        }

        mDestination.setLatitude(event.lat);
        mDestination.setLongitude(event.lon);

        mTotalDistance = mStartingPoint.distanceTo(mDestination);
    }

    private void updateProgress(Location currentLocation) {
        mTotalDistance = mStartingPoint.distanceTo(mDestination);

        float distanceRemaining = currentLocation.distanceTo(mDestination);

        int progressStatus = (int) ((distanceRemaining / mTotalDistance) * 100);
        progressStatus = Math.abs(progressStatus - 100);

        // Set a min > 0 to make the bar more visible when empty
        if (progressStatus <= 3) {
            progressStatus = 3;
        }

        // Update the progress bar smoothly using ObjectAnimator
        ObjectAnimator animation = ObjectAnimator.ofInt(mProgressBar, "progress", progressStatus);
        animation.setDuration(500); // 0.5 second
        animation.setInterpolator(new LinearInterpolator());
        animation.start();

        // Update the ongoing notification
        showRunningNotification(progressStatus + "% journey completed");

        mRed = Math.min(255.0 * 2 * progressStatus / 100, 255);
        if (mRed == 255) {
            mGreen = Math.abs(255 - (255.0 / progressStatus) * 100);
        }
        mProgressBar.getProgressDrawable()
                .setColorFilter(Color.rgb((int) mRed, (int) mGreen, (int) mBlue),
                        PorterDuff.Mode.SRC_IN);

        if (progressStatus >= 90) {
            showArrivalNotification();
            mLocationClient.disconnect();
        }

        if (BuildConfig.DEBUG) {
            Log.d(TAG, "Start: " + mStartingPoint);
            Log.d(TAG, "Destination: " + mDestination);
            Log.d(TAG, "Total distance (metres): " + mTotalDistance);
            Log.d(TAG, "Distance remaining (meters): " + distanceRemaining);
            Log.d(TAG, "Distance complete (percentage): " + progressStatus);
        }
    }

    private PendingIntent getStopServicePendingIntent() {
        PendingIntent stopIntent = PendingIntent.getBroadcast(this, 0,
                new Intent("com.bourke.ProgressBarService.STOP_SERVICE"),
                PendingIntent.FLAG_UPDATE_CURRENT);

        mStopReceiver = new BroadcastReceiver() {
            @Override public void onReceive(Context context, Intent intent) {
                unregisterReceiver(this);
                stopSelf();
            }
        };
        registerReceiver(mStopReceiver,
                new IntentFilter("com.bourke.ProgressBarService.STOP_SERVICE"));

        return stopIntent;
    }

    private void showRunningNotification(String titleText) {
        PendingIntent peStopService = getStopServicePendingIntent();

        PendingIntent peMapsActivity = PendingIntent.getActivity(this, 0,
                new Intent(this, MapsActivity.class), 0);

        NotificationCompat.Builder builder =
                new NotificationCompat.Builder(this)
                        .setSmallIcon(R.drawable.ic_notify)
                        .setContentTitle(titleText)
                        .setAutoCancel(false)
                        .setOngoing(true)
                        .addAction(R.drawable.ic_action_stop_light,
                                getString(R.string.stop_tracking), peStopService)
                        .setContentIntent(peMapsActivity);

        NotificationManager mNotificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(NOTIFICATION_ID, builder.build());
    }

    private void showArrivalNotification() {
        PendingIntent peStopService = getStopServicePendingIntent();

        PendingIntent peMapsActivity = PendingIntent.getActivity(this, 0,
                new Intent(this, MapsActivity.class), 0);

        NotificationCompat.Builder builder =
                new NotificationCompat.Builder(this)
                        .setSmallIcon(R.drawable.ic_notify)
                        .setTicker("Yeehaw!")
                        .setContentTitle("You are arriving at your destination!")
                        .setAutoCancel(true)
                        .setVibrate(new long[]{2000, 2000})
                        .setDefaults(Notification.DEFAULT_ALL)
                        .addAction(R.drawable.ic_action_stop_light,
                                getString(R.string.stop_tracking), peStopService)
                        .setContentIntent(peMapsActivity);

        NotificationManager mNotificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(NOTIFICATION_ID, builder.build());
    }
}




Java Source Code List

com.bourke.travelbar.BusProvider.java
com.bourke.travelbar.Constants.java
com.bourke.travelbar.DestinationChangedEvent.java
com.bourke.travelbar.MapsActivity.java
com.bourke.travelbar.PlaceProvider.java
com.bourke.travelbar.ProgressBarService.java
com.bourke.travelbar.TypefaceSpan.java