From 2ca010959918e42030653b2279b2a5ea77b353f2 Mon Sep 17 00:00:00 2001 From: Charles Plante-Veillette Date: Wed, 4 Mar 2020 19:39:03 -0500 Subject: [PATCH] Add the gps tracking service --- app/build.gradle | 6 +- app/src/main/AndroidManifest.xml | 10 +- .../BackgroundLocationService.java | 122 ++++++++++++++++++ .../mapgears/sharedmemoryen/MainActivity.java | 107 +++++++++++++++ app/src/main/res/layout/activity_main.xml | 29 ++++- app/src/main/res/values/strings.xml | 3 + build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 8 files changed, 272 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/com/mapgears/sharedmemoryen/BackgroundLocationService.java diff --git a/app/build.gradle b/app/build.gradle index 7d2a2ec..183ed89 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,9 +21,9 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test.ext:junit:1.1.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2777bb7..f82a826 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,14 +1,22 @@ + + + android:theme="@style/AppTheme" + tools:ignore="AllowBackup"> + + diff --git a/app/src/main/java/com/mapgears/sharedmemoryen/BackgroundLocationService.java b/app/src/main/java/com/mapgears/sharedmemoryen/BackgroundLocationService.java new file mode 100644 index 0000000..101474e --- /dev/null +++ b/app/src/main/java/com/mapgears/sharedmemoryen/BackgroundLocationService.java @@ -0,0 +1,122 @@ +package com.mapgears.sharedmemoryen; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.location.Location; +import android.location.LocationManager; +import android.os.Binder; +import android.os.Build; +import android.os.Bundle; +import android.os.IBinder; +import android.util.Log; +import android.widget.Toast; + +import androidx.annotation.RequiresApi; + + +public class BackgroundLocationService extends Service { + + private static final String TAG = "SharedMemory"; + private final LocationServiceBinder binder = new LocationServiceBinder(); + private LocationListener mLocationListener; + private LocationManager mLocationManager; + + public BackgroundLocationService() { + } + + @Override + public IBinder onBind(Intent intent) { return binder; } + + private class LocationListener implements android.location.LocationListener { + + LocationListener() { + new Location(LocationManager.GPS_PROVIDER); + } + + @Override + public void onLocationChanged(Location location) { + Log.d(TAG, "LocationChanged: " + location); + Toast.makeText(BackgroundLocationService.this, "LAT: " + location.getLatitude() + "\n LONG: " + location.getLongitude(), Toast.LENGTH_SHORT).show(); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + + } + + @Override + public void onProviderEnabled(String provider) { + + } + + @Override + public void onProviderDisabled(String provider) { + } + } + + @RequiresApi(api = Build.VERSION_CODES.O) + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + super.onStartCommand(intent, flags, startId); + startForeground(12345678, getNotification()); + startTracking(); + return START_STICKY; + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mLocationManager != null) { + try{ + mLocationManager.removeUpdates(mLocationListener); + } catch (Exception ignored) {} + } + + } + + private void startTracking() { + + initializeLocationManager(); + mLocationListener = new LocationListener(); + + try { + mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 300, 1, mLocationListener); + } catch (java.lang.SecurityException ex) { + Log.i("TAG", "fail to request location update, ignore", ex); + } catch (IllegalArgumentException ex) { + Log.d("TAG", "gps provider does not exist " + ex.getMessage()); + } + + } + + private void initializeLocationManager() { + if(mLocationManager == null){ + mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE); + } + } + + public void stopTracking(){ + stopForeground(true); + this.onDestroy(); + } + + @RequiresApi(api = Build.VERSION_CODES.O) + private Notification getNotification() { + + NotificationChannel channel = new NotificationChannel("channel_01", "GPS Status", NotificationManager.IMPORTANCE_DEFAULT); + + NotificationManager notificationManager = getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); + + Notification.Builder builder = new Notification.Builder(getApplicationContext(), "channel_01").setAutoCancel(true); + return builder.build(); + } + + class LocationServiceBinder extends Binder { + public BackgroundLocationService getService(){return BackgroundLocationService.this;} + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mapgears/sharedmemoryen/MainActivity.java b/app/src/main/java/com/mapgears/sharedmemoryen/MainActivity.java index 7c871eb..3b1616c 100644 --- a/app/src/main/java/com/mapgears/sharedmemoryen/MainActivity.java +++ b/app/src/main/java/com/mapgears/sharedmemoryen/MainActivity.java @@ -1,14 +1,121 @@ package com.mapgears.sharedmemoryen; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import android.Manifest; +import android.app.ActivityManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.PackageManager; import android.os.Bundle; +import android.os.IBinder; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; public class MainActivity extends AppCompatActivity { + private static final int ACCES_FINE_LOCATION_REQUEST = 0; + private static final String TAG = "SharedMemory"; + private BackgroundLocationService gpsService; + private boolean isTracking = false; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + Log.d(TAG, "Inside onCreateActivity"); + } + + @Override + protected void onStart() { + super.onStart(); + initializeToggleServiceButton(); + } + + private void initializeToggleServiceButton() { + final Button startService = findViewById(R.id.start_service_button); + if (isServiceRunning()) + startService.setText(R.string.stop_gps); + else + startService.setText(R.string.start_gps); + + startService.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!isTracking) { + startTracking(); + startService.setText(R.string.stop_gps); + } + else{ + startService.setText(R.string.start_gps); + stopTracking(); + } + } + }); + } + + private void startTracking(){ + if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED) { + final Intent intent = new Intent( this.getApplication(), BackgroundLocationService.class); + this.getApplication().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); + this.getApplication().startService(intent); + isTracking = true; + + } else { + ActivityCompat.requestPermissions(MainActivity.this, + new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, + ACCES_FINE_LOCATION_REQUEST); + } } + + private final ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + if( name.getClassName().endsWith("BackgroundLocationService")){ + gpsService = ((BackgroundLocationService.LocationServiceBinder)service).getService(); + TextView gpsStatusLabel = findViewById(R.id.l_appStatus); + gpsStatusLabel.setText(R.string.gps_service_status); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + if (name.getClassName().endsWith("BackgroundLocationService")){ + gpsService = null; + } + } + }; + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == ACCES_FINE_LOCATION_REQUEST){ + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ + startTracking(); + } + } + } + + private void stopTracking(){ + gpsService.stopTracking(); + isTracking = false; + } + private boolean isServiceRunning() { + ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); + for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)){ + if("com.mapgears.sharedmemoryen.BackgroundLocationService".equals(service.service.getClassName())) { + return true; + } + } + return false; + } + } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 4fc2444..71171c5 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -7,12 +7,33 @@ tools:context=".MainActivity"> + + +