在后台服务中获取常规位置更新时如何处理异常?

时间:2014-03-10 07:03:45

标签: android

我必须定期更新用户位置。为此,我创建了一个简单服务,标志设置为START_STICKY。

我正在使用GooglePlayServices LocationClient来定期更新地址。

我通过HomeScreen Activity启动此服务。

以下是此服务的代码

import android.app.Service;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;

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

    private static final String TAG = "GpsLocationUpdatingService";

    public static final int GOOGLE_PLAY_SERVICE_NOT_AVAILABLE = 1;
    public static final int CONN_FAILED_HAS_RESOLUTION = 2;
    public static final int SHOW_GENERAL_LOCATION_DETECT_PROB_DIALOG = 3;

    // Milliseconds per second
    private static final int MILLISECONDS_PER_SECOND = 1000;
    // Update frequency in seconds
    public static final int UPDATE_INTERVAL_IN_SECONDS = 5;
    // Update frequency in milliseconds
    private static final long UPDATE_INTERVAL =
            MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
    // The fastest update frequency, in seconds
    private static final int FASTEST_INTERVAL_IN_SECONDS = 1;
    // A fast frequency ceiling in milliseconds
    private static final long FASTEST_INTERVAL =
            MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;

    private LocationClient mLocationClient = null;
    private LocationRequest mLocationRequest = null;
    private Messenger messenger;


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

        mLocationClient = new LocationClient(this, this, this);
        mLocationRequest = LocationRequest.create();

        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        // Set the update interval to 5 seconds
        mLocationRequest.setInterval(UPDATE_INTERVAL);
        // Set the fastest update interval to 1 second
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        messenger = (Messenger) intent.getExtras().get(MainActivity.INTENT_MESSENGER_EXTRA);

        if(servicesConnected()) {
            mLocationClient.connect();
        }

        return START_STICKY;
    }

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

    @Override
    public void onConnected(Bundle arg0) {
        Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();

        mLocationClient.requestLocationUpdates(mLocationRequest, this);
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        if (connectionResult.hasResolution()) {

            sendMessageObject(CONN_FAILED_HAS_RESOLUTION, connectionResult.getErrorCode());

        } else {

            sendMessageObject(SHOW_GENERAL_LOCATION_DETECT_PROB_DIALOG, 100);

        }

    }

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

    @Override
    public void onLocationChanged(Location location) {
        String msg = "Updated Location: " +
                Double.toString(location.getLatitude()) + "," +
                Double.toString(location.getLongitude());
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    // Method used to check if GPS tracking 
    // Google Play Service is available or not
    private boolean servicesConnected() {
        // Check that Google Play services is available
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        // If Google Play services is available
        if (ConnectionResult.SUCCESS == resultCode) {
            // In debug mode, log the status
            Log.d(TAG, "Google Play services is available.");
            // Continue
            return true;
        // Google Play services was not available for some reason
        } else {
            // Get the error code
            int errorCode = resultCode;
            // Send message to activity with error code.
            // To show the dialog accordingly
            sendMessageObject(GOOGLE_PLAY_SERVICE_NOT_AVAILABLE, errorCode);
            // Stop service

            return false;
        }

    }

    // Send message to handler activity
    private void sendMessageObject(int errorType, int errorCode) {
         Message msg = Message.obtain();
         Bundle bundle = new Bundle();
         bundle.putInt("errortype", errorType);
         bundle.putInt("errorcode", errorCode);
         msg.setData(bundle);

         try {
            messenger.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }




        stopSelf();
    }


}

从代码中你可以看到for handle:

  • Google Play服务不可用例外。
  • 用于连接失败的例外。

我正在将一个消息对象传递给activity(HomeActivity)以处理所有异常。

但不保证在发生异常时活动(HomeActvity)可见。

所以我在这里问你如何在简单后台服务中使用LocationClient时正确处理所有异常。

编辑:添加MainActivity代码

这是我的MainActivity代码

public class MainActivity extends FragmentActivity {

    private static final String TAG = "MainActivity";
    public static final String INTENT_MESSENGER_EXTRA = "messenger";
    private static final int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
    private static Activity activity;

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

        activity = this;

        // Start background Location detecting web-service
        Intent intent = new Intent(this, GpsLocationUpdatingService.class);
        intent.putExtra(INTENT_MESSENGER_EXTRA, new Messenger(handler1));
        startService(intent);
    }

    @Override
    protected void onStart() {
        super.onStart();

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    public static Activity getActvity() {
        return activity;
    }

    // Define a DialogFragment that displays the error dialog
    public static class ErrorDialogFragment extends DialogFragment {
        // Global field to contain the error dialog
        private Dialog mDialog;
        // Default constructor. Sets the dialog field to null
        public ErrorDialogFragment() {
            super();
            mDialog = null;
        }
        // Set the dialog to display
        public void setDialog(Dialog dialog) {
            mDialog = dialog;
        }
        // Return a Dialog to the DialogFragment.
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            return mDialog;
        }
    }

    // Method calls when returning back after updating Google Play Services
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // Decide what to do based on the original request code
        switch (requestCode) {

            case CONNECTION_FAILURE_RESOLUTION_REQUEST:
            /*
             * If the result code is Activity.RESULT_OK, try
             * to connect again
             */
                switch (resultCode) {
                    case Activity.RESULT_OK :
                    /*
                     * Try the request again
                     */
                    break;
                }

        }
     }


    Handler handler1 = new Handler(new Handler.Callback() {

        @Override
        public boolean handleMessage(Message msg) {

            Bundle reply = msg.getData();
            int errorType = reply.getInt("errortype");
            int errorCode;

            switch (errorType) {
            case GpsLocationUpdatingService.GOOGLE_PLAY_SERVICE_NOT_AVAILABLE:
                // Show install google play services dialog
                errorCode = reply.getInt("errorcode");
                showInstallPlayServiceDialog(errorCode);
                break;

            case GpsLocationUpdatingService.CONN_FAILED_HAS_RESOLUTION:
                // Check resolution error code and act accordingly
                errorCode = reply.getInt("errorcode");
                getResoltuinAndShowDialog(errorCode);
                break;

            case GpsLocationUpdatingService.SHOW_GENERAL_LOCATION_DETECT_PROB_DIALOG:
                // Show general dialog of problem
                // detecting location
                showGeneralDialog();
                break;

            default:
                break;
            }

            return false;
        }
    });

    private void showInstallPlayServiceDialog(int errorCode) {
        Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
                errorCode,
                activity,
                CONNECTION_FAILURE_RESOLUTION_REQUEST);
        // If Google Play services can provide an error dialog
        if (errorDialog != null) {
            // Create a new DialogFragment for the error dialog
            ErrorDialogFragment errorFragment =
                    new ErrorDialogFragment();
            // Set the dialog in the DialogFragment
            errorFragment.setDialog(errorDialog);
            // Show the error dialog in the DialogFragment
            errorFragment.show(getSupportFragmentManager(), "Location Updates");
        } else {
            // Show general dialog of problem
            // detecting location
            showGeneralDialog();
        }
    }

    private void getResoltuinAndShowDialog(int errorCode) {
        PendingIntent pendingIntent = PendingIntent.getActivity(getActvity(),
                                                                CONNECTION_FAILURE_RESOLUTION_REQUEST,
                                                                new Intent(this, MainActivity.class),
                                                                PendingIntent.FLAG_UPDATE_CURRENT);

        ConnectionResult connResult = new ConnectionResult(errorCode, pendingIntent);
        try {
            connResult.startResolutionForResult(MainActivity.getActvity(), CONNECTION_FAILURE_RESOLUTION_REQUEST);
        } catch (SendIntentException e) {
            e.printStackTrace();

            Log.d(TAG, "Get resoltuion and show dialog exception");
        }
    }

    private void showGeneralDialog() {
        Toast.makeText(getActvity(), "Show  general dialog is called", Toast.LENGTH_SHORT).show();
    }
}

0 个答案:

没有答案