Search code examples
androidwakelock

How to lock my screen and my app will continue running


I have an app that records users location and draws a polyline.I want to know how to do that when the user locks his screen.I've implemented a foreground service so the user can do whatever he wants in his phone but it doesn't work if the user turns the screen off.Any ideas?I've seen the wake lock but they are only for not letting the screen turned off.

UPDATE

Here is the foreground service that runs when the user presses a button from the activity

public class MyForeGroundService extends Service implements LocationListener {

private static final String TAG_FOREGROUND_SERVICE = "FOREGROUND_SERVICE";

public static final String ACTION_START_FOREGROUND_SERVICE = "ACTION_START_FOREGROUND_SERVICE";

public static final String ACTION_STOP_FOREGROUND_SERVICE = "ACTION_STOP_FOREGROUND_SERVICE";

public static final String ACTION_PAUSE = "ACTION_PAUSE";

public static final String ACTION_PLAY = "ACTION_PLAY";

public static PolylineOptions line;


private LocationManager locationManager;

public static int steps = 0;


public MyForeGroundService() {
}

@Override
public IBinder onBind(Intent intent) {
    // TODO: Return the communication channel to the service.
    throw new UnsupportedOperationException("Not yet implemented");
}

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

    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
            3000,
            1, this);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if (intent != null) {
        String action = intent.getAction();

        switch (action) {
            case ACTION_START_FOREGROUND_SERVICE:
                startForegroundService();
                break;
            case ACTION_STOP_FOREGROUND_SERVICE:
                stopForegroundService();
                break;
            case ACTION_PLAY:
                Intent openMap= new Intent(this,Map.class);
                startActivity(openMap);
                break;
            case ACTION_PAUSE:
                break;
        }
    }
    return super.onStartCommand(intent, flags, startId);
}

/* Used to build and start foreground service. */
private void startForegroundService() {
    Log.d(TAG_FOREGROUND_SERVICE, "Start foreground service.");

    // Create notification default intent.
    Intent intent = new Intent(this,Map.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

    // Create notification builder.
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this);

    //Go back to Map activity if user press at the notification
    builder.setContentIntent(pendingIntent)
            .setContentTitle("gEKOning...")
            .setContentText("Tap to open gEKOn app");


    builder.setWhen(System.currentTimeMillis());
    builder.setSmallIcon(R.mipmap.ic_launcher);
    Bitmap largeIconBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.strava);
    builder.setLargeIcon(largeIconBitmap);
    // Make the notification max priority.
    builder.setPriority(Notification.PRIORITY_MAX);
    // Make head-up notification.
    builder.setFullScreenIntent(pendingIntent, true);


    // Build the notification.
    Notification notification = builder.build();

    // Start foreground service.
    startForeground(1, notification);
}
private void stopForegroundService() {
    Log.d(TAG_FOREGROUND_SERVICE, "Stop foreground service.");

    // Stop foreground service and remove the notification.
    stopForeground(true);

    // Stop the foreground service.
    stopSelf();
}

@Override
public void onLocationChanged(Location location) {
    String locationProvider = LocationManager.NETWORK_PROVIDER;
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    }
    location = locationManager.getLastKnownLocation(locationProvider);
    try {           

        line.add(new LatLng(location.getLatitude(), location.getLongitude()));
        GMap.addMarker(new MarkerOptions().position(new LatLng(location.getLatitude(), location.getLongitude())).title(""));
        GMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 16.0f));
        steps++;

    } catch (NullPointerException e) {
        //Toast.makeText(this.getBaseContext(), "gyhg" + e.toString(), Toast.LENGTH_LONG).show();
    }

}

@Override
public void onStatusChanged(String s, int i, Bundle bundle) {

}

@Override
public void onProviderEnabled(String s) {

}

@Override
public void onProviderDisabled(String s) {

}
}

Solution

  • you can create a background service that it works when user lock screen or close your app from background you must create service with this way: first create a Service class like this:

    public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks {
    
    
    public static double latitude;
    public static double longitude;
    
    private int retryGPS = 0;
    private int retryNetwork = 0;
    private Handler handler;
    private Runnable runnable;
    private GoogleApiClient mGoogleApiClient;
    private LocationManager mLocationManager;
    private LocationListener[] mLocationListeners = new LocationListener[]{
            new LocationListener(LocationManager.GPS_PROVIDER),
    };
    
    private static final int LOCATION_INTERVAL = 0;
    private static final float LOCATION_DISTANCE = 1;
    
    private static final String TAG = "LocationService";
    
    @Override
    public void onCreate() {
    
        buildGoogleApiClient();
    
        initializeLocationManager();
    
        locationRequest();
    
        handler = new Handler();
        runnable = new Runnable() {
            @Override
            public void run() {
                sendLocation();
            }
        };
    
        sendLocation();
    }
    
    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addApi(LocationServices.API)
                .build();
    }
    
    private void initializeLocationManager() {
    
        if (mLocationManager == null) {
            mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        }
    }
    
    private void locationRequest() {
    
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
    
        mLocationManager.requestLocationUpdates(
                LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
                mLocationListeners[0]);
    }
    
    
    private void sendLocation() {
    
            //TODO: you can use location here
    }
    
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    
    @Override
    public int onStartCommand(final Intent intent, int flags, int startId) {
        if (!mGoogleApiClient.isConnected())
            mGoogleApiClient.connect();
        return START_STICKY;
    }
    
    @Override
    public void onConnected(Bundle bundle) {
    
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    
        if (location != null) {
            latitude = location.getLatitude();
            longitude = location.getLongitude();
        } else {
            try {
                Thread.sleep(3000);
                onConnected(null);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    @Override
    public void onConnectionSuspended(int i) {
    }
    
    @Override
    public void onDestroy() {
    
        handler.removeCallbacks(runnable);
    
        if (mLocationManager != null) {
            for (LocationListener mLocationListener : mLocationListeners) {
                try {
                    mLocationManager.removeUpdates(mLocationListener);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        super.onDestroy();
    }
    
    private class LocationListener implements android.location.LocationListener, ActivityCompat.OnRequestPermissionsResultCallback {
    
        Location mLastLocation;
    
        public LocationListener(String provider) {
    
            Log.d(TAG, "LocationListener: " + provider);
            mLastLocation = new Location(provider);
        }
    
        @Override
        public void onLocationChanged(final Location location) {
    
            mLastLocation.set(location);
            latitude = location.getLatitude();
            longitude = location.getLongitude();
            Log.d(TAG, "onLocationChanged: { latitude: " + latitude + " ,longitude: " + longitude + " , accuracy: " + location.getAccuracy() + " }");
        }
    
        @Override
        public void onProviderDisabled(String provider) {
            Log.d(TAG, "onProviderDisabled: " + provider);
        }
    
        @Override
        public void onProviderEnabled(String provider) {
            Log.d(TAG, "onProviderEnabled: " + provider);
        }
    
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            Log.d(TAG, "onStatusChanged: " + status);
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        }
    
    }
    

    }

    then register service in manifest:

     <service
            android:name=".service.LocationService"
            android:enabled="true"
            android:process=":process" />
    

    then start service from any activity or fragment :

    public static void mStopService(Context context) {
        context.stopService(new Intent(context, LocationService.class));
    }
    
    public static void mStartService(Context context) {
        context.startService(new Intent(context, LocationService.class));
    }