サービス開始後に必要な権限ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATIONを付与
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.location.Location;
import android.location.LocationListener;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.tasks.OnCanceledListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import java.util.concurrent.TimeUnit;
/**
* Created by Ketan Ramani on 05/11/18.
*/
public class BackgroundLocationUpdateService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
/* Declare in manifest
<service android:name=".BackgroundLocationUpdateService"/>
*/
private final String TAG = "BackgroundLocationUpdateService";
private final String TAG_LOCATION = "TAG_LOCATION";
private Context context;
private boolean stopService = false;
/* For Google Fused API */
protected GoogleApiClient mGoogleApiClient;
protected LocationSettingsRequest mLocationSettingsRequest;
private String latitude = "0.0", longitude = "0.0";
private FusedLocationProviderClient mFusedLocationClient;
private SettingsClient mSettingsClient;
private LocationCallback mLocationCallback;
private LocationRequest mLocationRequest;
private Location mCurrentLocation;
/* For Google Fused API */
@Override
public void onCreate() {
super.onCreate();
context = this;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
StartForeground();
final Handler handler = new Handler();
final Runnable runnable = new Runnable() {
@Override
public void run() {
try {
if (!stopService) {
//Perform your task here
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (!stopService) {
handler.postDelayed(this, TimeUnit.SECONDS.toMillis(10));
}
}
}
};
handler.postDelayed(runnable, 2000);
buildGoogleApiClient();
return START_STICKY;
}
@Override
public void onDestroy() {
Log.e(TAG, "Service Stopped");
stopService = true;
if (mFusedLocationClient != null) {
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
Log.e(TAG_LOCATION, "Location Update Callback Removed");
}
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void StartForeground() {
Intent intent = new Intent(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT);
String CHANNEL_ID = "channel_location";
String CHANNEL_NAME = "channel_location";
NotificationCompat.Builder builder = null;
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
notificationManager.createNotificationChannel(channel);
builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID);
builder.setChannelId(CHANNEL_ID);
builder.setBadgeIconType(NotificationCompat.BADGE_ICON_NONE);
} else {
builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID);
}
builder.setContentTitle("Your title");
builder.setContentText("You are now online");
Uri notificationSound = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_NOTIFICATION);
builder.setSound(notificationSound);
builder.setAutoCancel(true);
builder.setSmallIcon(R.drawable.ic_logo);
builder.setContentIntent(pendingIntent);
Notification notification = builder.build();
startForeground(101, notification);
}
@Override
public void onLocationChanged(Location location) {
Log.e(TAG_LOCATION, "Location Changed Latitude : " + location.getLatitude() + "\tLongitude : " + location.getLongitude());
latitude = String.valueOf(location.getLatitude());
longitude = String.valueOf(location.getLongitude());
if (latitude.equalsIgnoreCase("0.0") && longitude.equalsIgnoreCase("0.0")) {
requestLocationUpdate();
} else {
Log.e(TAG_LOCATION, "Latitude : " + location.getLatitude() + "\tLongitude : " + location.getLongitude());
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onConnected(@Nullable Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10 * 1000);
mLocationRequest.setFastestInterval(5 * 1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
mLocationSettingsRequest = builder.build();
mSettingsClient
.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
Log.e(TAG_LOCATION, "GPS Success");
requestLocationUpdate();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
int statusCode = ((ApiException) e).getStatusCode();
switch (statusCode) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
int REQUEST_CHECK_SETTINGS = 214;
ResolvableApiException rae = (ResolvableApiException) e;
rae.startResolutionForResult((AppCompatActivity) context, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sie) {
Log.e(TAG_LOCATION, "Unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Log.e(TAG_LOCATION, "Location settings are inadequate, and cannot be fixed here. Fix in Settings.");
}
}
}).addOnCanceledListener(new OnCanceledListener() {
@Override
public void onCanceled() {
Log.e(TAG_LOCATION, "checkLocationSettings -> onCanceled");
}
});
}
@Override
public void onConnectionSuspended(int i) {
connectGoogleClient();
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
mSettingsClient = LocationServices.getSettingsClient(context);
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
connectGoogleClient();
mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
Log.e(TAG_LOCATION, "Location Received");
mCurrentLocation = locationResult.getLastLocation();
onLocationChanged(mCurrentLocation);
}
};
}
private void connectGoogleClient() {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int resultCode = googleAPI.isGooglePlayServicesAvailable(context);
if (resultCode == ConnectionResult.SUCCESS) {
mGoogleApiClient.connect();
}
}
@SuppressLint("MissingPermission")
private void requestLocationUpdate() {
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}
}
活動中
サービス開始:startService(new Intent(this, BackgroundLocationUpdateService.class));
サービス停止:stopService(new Intent(this, BackgroundLocationUpdateService.class));
フラグメント内
サービス開始:getActivity().startService(new Intent(getActivity().getBaseContext(), BackgroundLocationUpdateService.class));
サービス停止:getActivity().stopService(new Intent(getActivity(), BackgroundLocationUpdateService.class));