How to start a method from MainActivity in a foreground service

Viewed 690

I have got a MainActivity which gets the current location on click of a button. In the activity, and the location is stored with three different methods in

  1. SharedPreferences
  2. An online SQL Database
  3. In a text file on the device

I have another class to start a foreground service (ForegroundService.java) which starts with the click of another button in the MainAcivity and stops with a third button.

My plan is to have regular (1 hour interval) location updates using the ForegroundService and a JobService. So if we click on the StartService-button in the MainActivity the foreground service should start and regularly call the methods from the MainActivity: getCurrentGPSPosition (to get the location), and the three methods to store the information.

The MainActivity works fine. The ForegroundService can be started and stopped bud I do not know how to make it call the methods from the MainActivity. Here is the code - ForegroundService.java:


import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;

import static com.example.currentlocation.App.CHANNEL_ID;

public class ForegroundService extends Service {
    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //String input = intent.getStringExtra("inputExtra");
        Intent notificationIntent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,
                0, notificationIntent, 0);
        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("GPS position tracker")
            //.setContentText(input)
            .setSmallIcon(R.drawable.ic_baseline_gps_fixed_24)
            .setContentIntent(pendingIntent)
            .build();
        startForeground(1, notification);
        return START_NOT_STICKY;

    }

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

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

App.java


import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;

public class App extends Application {
    public static final String CHANNEL_ID = "CurrentLocationServiceChannel";

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

        createNotificationChannel();
    }

    private void createNotificationChannel(){
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                NotificationChannel serviceChannel = new NotificationChannel(
                        CHANNEL_ID,
                        "Current Location Service Channel",
                        NotificationManager.IMPORTANCE_DEFAULT
                );
                NotificationManager manager = getSystemService(NotificationManager.class);
                manager.createNotificationChannel(serviceChannel);
            }



        }
    }

In the MainActivity the following parts:

public class MainActivity extends AppCompatActivity {

........

   //Backgroundservice
    public void startService(View v){
     //   String input = editTextInput.getText().toString();

        Intent serviceIntent = new Intent(this, ForegroundService.class);
      //  serviceIntent.putExtra("inputExtra", input);

        startService(serviceIntent);
    }
    public void stopService(View v){
        Intent serviceIntent = new Intent(this, ForegroundService.class);

        stopService(serviceIntent);
    }
//Method to store in SQL online
public void  OnReg() {.......code....}
//Method to save data in SharedPreferences
public void saveData() {.......code....}
//Method to save data in Internal File
public void saveToFile() {.......code....}

//method for GPS request
getCurrentGPSLocation() {.......code....}
}

Has anybody got an idea how to work that out? Or do you need more details? Thanks for your help!

2 Answers

Don't put those functions in MainActivity. If you need them to be called from both the Activity and a Service, put them in a separate class that can be instantiated as needed. If you can't do that because there's data in MainActivity that both need, rethink your architecture- that data won't be available when the job service fires anyway.

OK, first solution is to make a new class (Functions.java) and using an intent to call this class form the MainActivity and then do the location request there and then give the data back to the MainActivity. Second step would then be to do the same from the foreground service. The Problem is, the functions class does not get the data from the method. If I put hard-coded strings into the intent, they are transmitted to the MainActivity, so the intent works. So this is only part of the full solution. Here's the code:

public class Functions extends AppCompatActivity {

    //initialize variable
    FusedLocationProviderClient fusedLocationProviderClient;
    private double ser_Latitude;
    private double ser_Longitude;
    private String ser_Accuracy;
    private String ser_Altitude;
    private String currentDateandTime;
    private String ser_Location;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Boolean precision = getIntent().getBooleanExtra("precision", true);
        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(
                Functions.this);
        getCurrentGPSLocation();

        Intent intent = new Intent();

        intent.putExtra("latitude", ser_Latitude);
        intent.putExtra("longitude", ser_Longitude);
        intent.putExtra("accuracy", ser_Accuracy);
        intent.putExtra("altitude", ser_Altitude);
        intent.putExtra("location", ser_Location);
        intent.putExtra("currentDateandTime", currentDateandTime);
        setResult(RESULT_OK, intent);
        Functions.this.finish();
    }

    //Force new GPS Location Request
    private void getCurrentGPSLocation() {
        // get the new location from the fused client
        // update the UI - i.e. set all properties in their associated text view items

        //Initialize new location request
        LocationRequest locationRequest = new LocationRequest()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(3000)
                .setFastestInterval(2000)
                .setNumUpdates(1)
                ;

        //Initialize location call back
        LocationCallback locationCallback = new LocationCallback() {
            @Override

            public void onLocationResult(LocationResult locationResult) {

                //Initialize location1
                Location location1 = locationResult.getLastLocation();

                //Set latitude
                ser_Latitude = location1.getLatitude();
                //Set longitude
                ser_Longitude = location1.getLongitude();
                //Set Accuracy
                double ser_accura1 = location1.getAccuracy();
                ser_Accuracy = new DecimalFormat("##.##").format(ser_accura1) + " m";
                //Set Altitude
                double ser_altit1 = location1.getAltitude();
                ser_Altitude = new DecimalFormat("##.##").format(ser_altit1) + " m";

                //Get Adress
              /*  Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
                try {
                    List<Address> listAddresses = geocoder.getFromLocation(ser_Latitude, ser_Longitude, 1);
                    if (null != listAddresses && listAddresses.size() > 0) {
                        String _Location1 = listAddresses.get(0).getAddressLine(0);
                        //Set Location
                        //ser_Location = String.valueOf(_Location1);

                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }*/
                
//Set location as hard-coded string for testing
ser_Location = "London";
                //Set Update Time
                SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy 'um ' HH:mm:ss z");
                currentDateandTime = sdf.format(new Date());

            }

        };
        
        //Request location updates
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        fusedLocationProviderClient.requestLocationUpdates(locationRequest
                , locationCallback, Looper.myLooper());
    }
    
}

The new GPS request is triggered as I can see running the app, but no information is delivered from the method getCurrentGPSLocation() to the intent, which I can see because even the hard-coded location string is not delivered. This needs revision please.

Related