[在Android的前景服务中使用FusedLocationClient请求位置

问题描述 投票:0回答:1

我正在尝试使用Android O中的Fused Location Provider Client在前台服务中获取设备的当前位置。但是,在发出位置请求后,该服务将被终止。我认为服务被终止是因为融合的位置提供程序客户端在另一个后台线程中获取了位置,并且从服务的角度来看,它的任务已经完成。问题是服务销毁后未收到位置更新。在明确停止服务之前,如何使服务保持活动状态?

我的服务类别:

    private val TAG = LocationService::class.java.simpleName

    companion object {
        val STOP_ACTION = "STOP_ACTION"
    }

    private lateinit var mFusedLocationClient: FusedLocationProviderClient
    private lateinit var mLocationCallback: LocationCallback
    private lateinit var notificationManager: NotificationManager
    private val notificationId = 1

    private val UPDATE_INTERVAL_IN_MILLISECONDS = 5000L
    private val FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 500L
    private val CHANNEL_ID = TAG

    override fun onHandleIntent(intent: Intent?) {
        Log.d(TAG, "onHandleIntent start")
        if (intent?.action.equals(STOP_ACTION)) {
            Log.d(TAG, "stop service")
            stopForeground(true)
            stopSelf()
        } else {
            Log.d(TAG, "start location update")
            createNotificationChannel()
            val notificationIntent = Intent(this, OnboardingActivity::class.java)
            val pendingIntent = PendingIntent.getActivity(
                this,
                0, notificationIntent, 0
            )
            val notification = NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("Tracking realtime location")
                .setContentText("Tap to open the application")
                .setSmallIcon(R.drawable.logo)
                .setContentIntent(pendingIntent)
                .setOngoing(true)
                .build()

            startForeground(notificationId , notification)
            startLocationUpdates()
        }
    }

    override fun onCreate() {
        super.onCreate()
        notificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
        mLocationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult?) {
                locationResult ?: return
                for (location in locationResult.locations) {
                    Log.d(TAG, "$location")
                }
            }

            override fun onLocationAvailability(p0: LocationAvailability?) {
                super.onLocationAvailability(p0)
            }
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.e(TAG, "onStartCommand")
        super.onStartCommand(intent, flags, startId)
        return START_STICKY
    }

    override fun onDestroy() {
        super.onDestroy()
        mFusedLocationClient.removeLocationUpdates(mLocationCallback)
        Log.e(TAG, "location service destroyed")
    }

    private fun startLocationUpdates() {
        val mLocationRequest = LocationRequest()
        mLocationRequest.interval = UPDATE_INTERVAL_IN_MILLISECONDS
        mLocationRequest.fastestInterval = FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS
        mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY

        try {
            mFusedLocationClient.requestLocationUpdates(
                mLocationRequest,
                mLocationCallback,
                Looper.myLooper()
            )
        } catch (e: SecurityException) {
            Log.e(TAG, "Lost location permission. Could not request updates. $e")
        }
    }

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val nChannel = notificationManager.getNotificationChannel(CHANNEL_ID)

            if (nChannel == null) {
                val serviceChannel = NotificationChannel(
                    CHANNEL_ID,
                    "Foreground Service Channel",
                    NotificationManager.IMPORTANCE_DEFAULT
                )
                notificationManager.createNotificationChannel(serviceChannel)
            }
        }
    }
}

非常感谢您的帮助。

android kotlin foreground-service fusedlocationproviderclient
1个回答
0
投票

尝试一下

public class BackgroundLocationUpdateService extends Service {

    /**
    * Author:Hardik Talaviya
    * Date:  2019.08.3 2:30 PM
    * Describe:
    */

    private static final String TAG = "BackgroundLocation";
    private Context context;
    private FusedLocationProviderClient client;
    private LocationCallback locationCallback;
    private boolean stopService = false;
    private Handler handler;
    private Runnable runnable;
    private NotificationCompat.Builder builder = null;
    private NotificationManager notificationManager;

    @Override
    public void onCreate() {
        Log.e(TAG, "Background Service onCreate :: ");
        super.onCreate();
        context = this;

        handler = new Handler();
        runnable = new Runnable() {

            @Override
            public void run() {
                try {
                    requestLocationUpdates();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    handler.postDelayed(this, TimeUnit.SECONDS.toMillis(2));
                }
            }
        };
        if (!stopService) {
            handler.postDelayed(runnable, TimeUnit.SECONDS.toMillis(2));
        }
    }

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

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        Log.e(TAG, "onTaskRemoved :: ");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand :: ");
        StartForeground();
        if (client != null) {
            client.removeLocationUpdates(locationCallback);
            Log.e(TAG, "Location Update Callback Removed");
        }
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "BackgroundService onDestroy :: ");
        stopService = true;
        if (handler != null) {
            handler.removeCallbacks(runnable);
        }
        if (client != null) {
            client.removeLocationUpdates(locationCallback);
            Log.e(TAG, "Location Update Callback Removed");
        }
    }

    private void requestLocationUpdates() {
        LocationRequest request = new LocationRequest();
        request.setFastestInterval(100)
                .setInterval(200)
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        client = LocationServices.getFusedLocationProviderClient(this);


        final int[] permission = {ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)};
        if (permission[0] == PackageManager.PERMISSION_GRANTED) {

            final Location[] location = {new Location(LocationManager.GPS_PROVIDER)};
            locationCallback = new LocationCallback() {
                @Override
                public void onLocationResult(LocationResult locationResult) {

                    location[0] = locationResult.getLastLocation();

                    if (location[0] != null) {
                        Log.d(TAG, "location update " + location[0]);
                        Log.d(TAG, "location Latitude " + location[0].getLatitude());
                        Log.d(TAG, "location Longitude " + location[0].getLongitude());
                        Log.d(TAG, "Speed :: " + location[0].getSpeed() * 3.6);

                        if (notificationManager != null && client != null && !stopService) {
                            builder.setContentText("Your current location is " +  location[0].getLatitude() + "," + location[0].getLongitude());
                            notificationManager.notify(101, builder.build());
                        }
                    }
                }
            };
            client.requestLocationUpdates(request, locationCallback, null);
        }
    }

    /*-------- For notification ----------*/
    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";

        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.setColorized(false);
            builder.setChannelId(CHANNEL_ID);
            builder.setColor(ContextCompat.getColor(this, R.color.colorPrimaryDark));
            builder.setBadgeIconType(NotificationCompat.BADGE_ICON_NONE);
        } else {
            builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID);
        }
        builder.setOnlyAlertOnce(true);
        builder.setContentTitle(context.getResources().getString(R.string.app_name));
        builder.setContentText("Your current location is ");
        Uri notificationSound = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_NOTIFICATION);
        builder.setSound(notificationSound);
        builder.setAutoCancel(true);
        builder.setSmallIcon(R.mipmap.ic_notification_app_icon);
        builder.setContentIntent(pendingIntent);
        startForeground(101, builder.build());
    }
} 

我希望这可以帮助您!

© www.soinside.com 2019 - 2024. All rights reserved.