feat(gpsrelaysentinel): 实现前台服务通知并通过Switch控制服务启停

- 添加FOREGROUND_SERVICE权限支持前台服务
- 使用startForegroundService替代startService启动服务
- 实现前台服务通知,实时显示GPS经纬度数据
- 在MainActivity添加Switch开关控制服务启停
- GPS位置更新时通过updateNotification实时更新通知内容
- 创建通知渠道适配Android O及以上版本
This commit is contained in:
2026-05-07 02:15:19 +08:00
parent 11aee7e373
commit 0e90f40f0f
4 changed files with 71 additions and 1 deletions

View File

@@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:allowBackup="true"

View File

@@ -3,6 +3,8 @@ package cc.winboll.studio.gpsrelaysentinel;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.Switch;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libappbase.LogView;
@@ -11,6 +13,7 @@ import cc.winboll.studio.libappbase.ToastUtils;
public class MainActivity extends AppCompatActivity {
LogView mLogView;
Switch mSwitchService;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -21,6 +24,21 @@ public class MainActivity extends AppCompatActivity {
setSupportActionBar(toolbar);
mLogView = findViewById(R.id.logview);
mSwitchService = findViewById(R.id.switch_service);
mSwitchService.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Intent intent = new Intent(MainActivity.this, MainService.class);
if (isChecked) {
startForegroundService(intent);
ToastUtils.show("GPS Service started");
} else {
stopService(intent);
ToastUtils.show("GPS Service stopped");
}
}
});
ToastUtils.show("onCreate");
}

View File

@@ -1,13 +1,19 @@
package cc.winboll.studio.gpsrelaysentinel;
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.LocationListener;
import android.location.LocationManager;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import androidx.core.app.NotificationCompat;
import cc.winboll.studio.libappbase.LogUtils;
public class MainService extends Service {
@@ -16,11 +22,17 @@ public class MainService extends Service {
private LocationManager mLocationManager;
private LocationListener mLocationListener;
private boolean mIsRunning = false;
private NotificationManager mNotificationManager;
private NotificationCompat.Builder mNotificationBuilder;
private static final String CHANNEL_ID = "gps_relay_channel";
private static final int NOTIFICATION_ID = 1;
@Override
public void onCreate() {
super.onCreate();
LogUtils.d(TAG, "Service onCreate");
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
createNotificationChannel();
}
@Override
@@ -39,7 +51,9 @@ public class MainService extends Service {
mLocationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
LogUtils.d(TAG, "Location changed: " + location.getLatitude() + ", " + location.getLongitude());
String gpsInfo = "Lat: " + location.getLatitude() + ", Lng: " + location.getLongitude();
LogUtils.d(TAG, "Location changed: " + gpsInfo);
updateNotification(gpsInfo);
}
@Override
@@ -68,12 +82,42 @@ public class MainService extends Service {
);
LogUtils.d(TAG, "GPS location updates requested");
mIsRunning = true;
startForegroundNotification();
}
} catch (SecurityException e) {
LogUtils.e(TAG, "Permission denied: " + e.getMessage());
}
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
"GPS Relay Service",
NotificationManager.IMPORTANCE_LOW
);
channel.setDescription("GPS Relay Sentinel service channel");
mNotificationManager.createNotificationChannel(channel);
}
}
private void startForegroundNotification() {
mNotificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("GPS Relay Service")
.setContentText("Waiting for GPS data...")
.setSmallIcon(android.R.drawable.ic_menu_mylocation)
.setOngoing(true);
Notification notification = mNotificationBuilder.build();
startForeground(NOTIFICATION_ID, notification);
}
private void updateNotification(String gpsInfo) {
if (mNotificationBuilder != null) {
mNotificationBuilder.setContentText(gpsInfo);
mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build());
}
}
@Override
public IBinder onBind(Intent intent) {
return null;

View File

@@ -32,6 +32,13 @@
android:text="GPSRelaySentinel"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<Switch
android:id="@+id/switch_service"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="GPS Service"
android:checked="false"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"