改进GPS订阅服务发送框架

This commit is contained in:
2026-05-07 14:37:07 +08:00
parent 9c16685c1f
commit e24c9bdce3
4 changed files with 301 additions and 340 deletions

View File

@@ -1,10 +1,5 @@
package cc.winboll.studio.libgpsrelaysentinel.manager; package cc.winboll.studio.libgpsrelaysentinel.manager;
/**
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
* @Date 2026/05/07 10:26
*/
import cc.winboll.studio.libgpsrelaysentinel.model.GpsSubscribeConst; import cc.winboll.studio.libgpsrelaysentinel.model.GpsSubscribeConst;
import cc.winboll.studio.libgpsrelaysentinel.model.GpsSubscribeMsg; import cc.winboll.studio.libgpsrelaysentinel.model.GpsSubscribeMsg;
import cc.winboll.studio.libgpsrelaysentinel.model.LocationPoint; import cc.winboll.studio.libgpsrelaysentinel.model.LocationPoint;
@@ -15,12 +10,18 @@ import java.util.Map;
public final class SubscribeLocationManager { public final class SubscribeLocationManager {
private static SubscribeLocationManager instance; private static SubscribeLocationManager instance;
//订阅配置
private final Map<String,GpsSubscribeMsg> subscribeConfigMap; private final Map<String,GpsSubscribeMsg> subscribeConfigMap;
//基准定点坐标
private final Map<String,LocationPoint> subscriberPointMap; private final Map<String,LocationPoint> subscriberPointMap;
//真实推送计数(精准统计)
private final Map<String,Integer> subscriberPushCountMap;
private SubscribeLocationManager(){ private SubscribeLocationManager(){
subscribeConfigMap = new HashMap<String, GpsSubscribeMsg>(); subscribeConfigMap = new HashMap<String, GpsSubscribeMsg>();
subscriberPointMap = new HashMap<String, LocationPoint>(); subscriberPointMap = new HashMap<String, LocationPoint>();
subscriberPushCountMap = new HashMap<String, Integer>();
} }
public static SubscribeLocationManager getInstance(){ public static SubscribeLocationManager getInstance(){
@@ -30,48 +31,70 @@ public final class SubscribeLocationManager {
return instance; return instance;
} }
public void putSubscribeConfig(final String sid,final GpsSubscribeMsg msg){ //========= 订阅配置 =========
public void putSubscribeConfig(String sid,GpsSubscribeMsg msg){
subscribeConfigMap.put(sid,msg); subscribeConfigMap.put(sid,msg);
} }
public void initSubscriberPoint(final String sid,double lat,double lng){ public GpsSubscribeMsg getSubscribeConfig(String sid){
subscriberPointMap.put(sid,new LocationPoint(lat,lng,System.currentTimeMillis()));
}
public void updateSubscriberPoint(final String sid,double lat,double lng){
subscriberPointMap.put(sid,new LocationPoint(lat,lng,System.currentTimeMillis()));
}
public LocationPoint getLastPoint(final String sid){
return subscriberPointMap.get(sid);
}
public GpsSubscribeMsg getSubscribeConfig(final String sid){
return subscribeConfigMap.get(sid); return subscribeConfigMap.get(sid);
} }
public boolean isNeedPush(final String sid,double nowLat,double nowLng){ //========= 基准定点坐标 =========
public void initSubscriberPoint(String sid,double lat,double lng){
subscriberPointMap.put(sid,new LocationPoint(lat,lng,System.currentTimeMillis()));
}
public void updateSubscriberPoint(String sid,double lat,double lng){
subscriberPointMap.put(sid,new LocationPoint(lat,lng,System.currentTimeMillis()));
}
public LocationPoint getLastPoint(String sid){
return subscriberPointMap.get(sid);
}
//========= 精准推送计数 =========
public void addPushCount(String sid){
int current = subscriberPushCountMap.get(sid) == null ? 0 : subscriberPushCountMap.get(sid);
subscriberPushCountMap.put(sid,current + 1);
}
public int getPushCount(String sid){
return subscriberPushCountMap.get(sid) == null ? 0 : subscriberPushCountMap.get(sid);
}
public void clearPushCount(String sid){
subscriberPushCountMap.put(sid,0);
}
//========= 步长规则判断 =========
public boolean isNeedPush(String sid,double nowLat,double nowLng){
GpsSubscribeMsg config = getSubscribeConfig(sid); GpsSubscribeMsg config = getSubscribeConfig(sid);
if(config == null){ if(config == null){
return false; return false;
} }
//全量订阅直接放行
if(config.getSubscribeMode() == GpsSubscribeConst.SUB_TYPE_ALL){ if(config.getSubscribeMode() == GpsSubscribeConst.SUB_TYPE_ALL){
return true; return true;
} }
//无初始定点 → 先建立第一个基准点
LocationPoint lastPoint = getLastPoint(sid); LocationPoint lastPoint = getLastPoint(sid);
if(lastPoint == null){ if(lastPoint == null){
return true; return true;
} }
//计算实际移动距离
double distance = calculateDistance( double distance = calculateDistance(
lastPoint.getLatitude(),lastPoint.getLongitude(), lastPoint.getLatitude(),lastPoint.getLongitude(),
nowLat,nowLng nowLat,nowLng
); );
return distance >= config.getStepDistanceM(); return distance >= config.getStepDistanceM();
} }
//两点经纬度距离计算(米)
private double calculateDistance(double lat1,double lng1,double lat2,double lng2){ private double calculateDistance(double lat1,double lng1,double lat2,double lng2){
double radLat1 = Math.toRadians(lat1); double radLat1 = Math.toRadians(lat1);
double radLat2 = Math.toRadians(lat2); double radLat2 = Math.toRadians(lat2);
@@ -81,23 +104,25 @@ public final class SubscribeLocationManager {
double latDiff = radLat1 - radLat2; double latDiff = radLat1 - radLat2;
double lngDiff = radLng1 - radLng2; double lngDiff = radLng1 - radLng2;
double result = 2 * Math.asin(Math.sqrt( double value = 2 * Math.asin(Math.sqrt(
Math.pow(Math.sin(latDiff / 2),2) Math.pow(Math.sin(latDiff / 2),2)
+ Math.cos(radLat1) * Math.cos(radLat2) + Math.cos(radLat1) * Math.cos(radLat2)
* Math.pow(Math.sin(lngDiff / 2),2) * Math.pow(Math.sin(lngDiff / 2),2)
)); ));
result = result * GpsSubscribeConst.EARTH_RADIUS; return value * 6378137;
return result;
} }
public void removeSubscribe(final String sid){ //========= 移除 & 清空 =========
public void removeSubscribe(String sid){
subscribeConfigMap.remove(sid); subscribeConfigMap.remove(sid);
subscriberPointMap.remove(sid); subscriberPointMap.remove(sid);
subscriberPushCountMap.remove(sid);
} }
public void clearAll(){ public void clearAll(){
subscribeConfigMap.clear(); subscribeConfigMap.clear();
subscriberPointMap.clear(); subscriberPointMap.clear();
subscriberPushCountMap.clear();
} }
} }

View File

@@ -4,136 +4,36 @@ import android.app.Service;
import android.content.Intent; import android.content.Intent;
import android.os.IBinder; import android.os.IBinder;
/** import cc.winboll.studio.libappbase.LogUtils;
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
* @Date 2026/05/07 10:46
*/
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import cc.winboll.studio.libgpsrelaysentinel.model.GpsSubscribeConst;
import cc.winboll.studio.libgpsrelaysentinel.model.GpsSubscribeMsg; import cc.winboll.studio.libgpsrelaysentinel.model.GpsSubscribeMsg;
import cc.winboll.studio.libgpsrelaysentinel.model.GpsSubscribeResult;
import cc.winboll.studio.libgpsrelaysentinel.model.LocationPoint; import cc.winboll.studio.libgpsrelaysentinel.model.LocationPoint;
/** /**
* 对外消息接收服务外部App可bind或start * 全局消息接收父类服务
* 收到GPS消息后通过本地广播回调给外部App * 所有应用内接收服务全部继承此类
*/ */
public final class GpsSubscribeReceiverService extends Service { public abstract class GpsSubscribeReceiverService extends Service {
// 外部回调监听 public static final String TAG_PARENT = "GpsSubscribeReceiverService";
public interface GpsMessageListener {
void onGpsLocation(LocationPoint point, GpsSubscribeMsg config); //当前绑定的视图订阅SID
void onSubscribeResult(GpsSubscribeResult result); protected String bindViewSid;
public void bindControlSid(String sid){
this.bindViewSid = sid;
} }
private final List<GpsMessageListener> listeners = new CopyOnWriteArrayList<GpsMessageListener>(); /**
private final IBinder localBinder = new LocalBinder(); * 统一接收GPS推送入口
*/
@Override public void onReceiveGpsData(LocationPoint point, GpsSubscribeMsg config){
public void onCreate() { //父类统一日志溯源
super.onCreate(); LogUtils.d(TAG_PARENT,"【消息溯源】接收视图SID" + bindViewSid);
} }
// 外部App绑定服务
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
return localBinder; return null;
}
// 外部App startService 入口:接收订阅请求
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && intent.getParcelableExtra("req") != null) {
GpsSubscribeMsg msg = intent.getParcelableExtra("req");
handleSubscribeRequest(msg);
}
return START_STICKY;
}
// 处理订阅请求:发送给管理器,并回执
private void handleSubscribeRequest(final GpsSubscribeMsg msg) {
// 加入订阅管理
cc.winboll.studio.libgpsrelaysentinel.manager.GpsSubscribeManager
.getInstance().addSubscribe(msg);
cc.winboll.studio.libgpsrelaysentinel.manager.SubscribeLocationManager
.getInstance().putSubscribeConfig(msg.getSubscribeUniqueId(), msg);
// 回执成功
GpsSubscribeResult result = new GpsSubscribeResult(
msg.getSubscribeUniqueId(),
GpsSubscribeConst.RESULT_SUCCESS,
"subscribe ok",
GpsSubscribeConst.GPS_STATE_LOCATED,
1000,
System.currentTimeMillis()
);
sendSubscribeResultBroadcast(result);
notifySubscribeResult(result);
}
// 供内部GPS服务调用推送定位消息
public void pushLocation(final LocationPoint point, final GpsSubscribeMsg config) {
sendLocationBroadcast(point, config);
notifyGpsLocation(point, config);
}
// ---------- 广播回调(跨进程/外部App接收 ----------
private void sendLocationBroadcast(final LocationPoint point, final GpsSubscribeMsg config) {
Intent intent = new Intent(GpsSubscribeConst.ACTION_GPS_LOCATION);
intent.putExtra("point", point);
intent.putExtra("config", config);
sendBroadcast(intent);
}
private void sendSubscribeResultBroadcast(final GpsSubscribeResult result) {
Intent intent = new Intent(GpsSubscribeConst.ACTION_SUBSCRIBE_CALLBACK);
intent.putExtra("data", result);
sendBroadcast(intent);
}
// ---------- 本地Binder同进程直接回调 ----------
public class LocalBinder extends Binder {
public GpsSubscribeReceiverService getService() {
return GpsSubscribeReceiverService.this;
}
}
public void addListener(final GpsMessageListener l) {
if (l != null && !listeners.contains(l)) {
listeners.add(l);
}
}
public void removeListener(final GpsMessageListener l) {
listeners.remove(l);
}
private void notifyGpsLocation(final LocationPoint point, final GpsSubscribeMsg config) {
for (GpsMessageListener l : listeners) {
l.onGpsLocation(point, config);
}
}
private void notifySubscribeResult(final GpsSubscribeResult result) {
for (GpsMessageListener l : listeners) {
l.onSubscribeResult(result);
}
}
@Override
public void onDestroy() {
listeners.clear();
super.onDestroy();
} }
} }

View File

@@ -1,174 +1,226 @@
package cc.winboll.studio.libgpsrelaysentinel.view; package cc.winboll.studio.libgpsrelaysentinel.view;
/**
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
* @Date 2026/05/07 10:27
*/
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.LayoutInflater;
import android.widget.CompoundButton;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RadioButton; import android.widget.RadioButton;
import android.widget.RadioGroup; import android.widget.RadioGroup;
import android.widget.Switch; import android.widget.Switch;
import android.widget.TextView; import android.widget.TextView;
import cc.winboll.studio.libgpsrelaysentinel.R; import cc.winboll.studio.libgpsrelaysentinel.R;
import cc.winboll.studio.libgpsrelaysentinel.manager.GpsSubscribeManager;
import cc.winboll.studio.libgpsrelaysentinel.manager.SubscribeLocationManager;
import cc.winboll.studio.libgpsrelaysentinel.model.GpsSubscribeConst;
import cc.winboll.studio.libgpsrelaysentinel.model.GpsSubscribeMsg;
import cc.winboll.studio.libgpsrelaysentinel.model.LocationPoint;
import java.util.UUID; import java.util.UUID;
import cc.winboll.studio.libgpsrelaysentinel.model.GpsSubscribeConst;
import cc.winboll.studio.libgpsrelaysentinel.model.GpsSubscribeMsg;
import cc.winboll.studio.libgpsrelaysentinel.model.GpsSubscribeResult;
import cc.winboll.studio.libgpsrelaysentinel.receiver.GpsSubscribeObserverReceiver;
import cc.winboll.studio.libgpsrelaysentinel.util.TimeCountUtil;
public final class GpsSubscribeControlView extends LinearLayout { public final class GpsSubscribeControlView extends LinearLayout {
private RadioGroup rgSubMode; //常量抽取
private RadioButton rbAll; private static final long REFRESH_INTERVAL = 600;
private RadioButton rbStep;
private LinearLayout layoutStepSetting; private RadioGroup rgSubscribeMode;
private RadioButton rbModeAll;
private RadioButton rbModeStep;
private EditText etStepMeter; private EditText etStepMeter;
private Switch switchSubscribe;
private TextView tvSubscribeSid;
private TextView tvSubscribeRecord;
private Switch mSwitchSubscribe;
private TextView mTvCountTip;
private TimeCountUtil mTimeCountUtil;
private GpsSubscribeObserverReceiver mResultReceiver;
private String currentSubscribeSid; private String currentSubscribeSid;
private boolean isSubscribeSuccess; //一对一专属绑定的接收服务
private Class<?> mBindReceiverServiceClazz;
//final管理器 构造器初始化
private final GpsSubscribeManager mSubscribeManager;
private final SubscribeLocationManager mLocationManager;
private final Handler mRefreshHandler = new Handler(Looper.getMainLooper());
public GpsSubscribeControlView(Context context) { public GpsSubscribeControlView(Context context) {
super(context); super(context);
initView(); mSubscribeManager = GpsSubscribeManager.getInstance();
mLocationManager = SubscribeLocationManager.getInstance();
initView(context);
} }
public GpsSubscribeControlView(Context context, AttributeSet attrs) { public GpsSubscribeControlView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
initView(); mSubscribeManager = GpsSubscribeManager.getInstance();
mLocationManager = SubscribeLocationManager.getInstance();
initView(context);
} }
private void initView(){ private void initView(Context context) {
setOrientation(VERTICAL); LayoutInflater.from(context).inflate(R.layout.view_gps_subscribe_control, this, true);
inflate(getContext(),R.layout.view_gps_subscribe_control,this);
rgSubMode = findViewById(R.id.rg_sub_mode); rgSubscribeMode = findViewById(R.id.rg_subscribe_mode);
rbAll = findViewById(R.id.rb_all); rbModeAll = findViewById(R.id.rb_mode_all);
rbStep = findViewById(R.id.rb_step); rbModeStep = findViewById(R.id.rb_mode_step);
layoutStepSetting = findViewById(R.id.layout_step_setting);
etStepMeter = findViewById(R.id.et_step_meter); etStepMeter = findViewById(R.id.et_step_meter);
switchSubscribe = findViewById(R.id.switch_subscribe);
tvSubscribeSid = findViewById(R.id.tv_subscribe_sid);
tvSubscribeRecord = findViewById(R.id.tv_subscribe_record);
mSwitchSubscribe = findViewById(R.id.switch_subscribe); initDefaultConfig();
mTvCountTip = findViewById(R.id.tv_count_tip);
initModeSwitch(); initModeSwitch();
initCountUtil(); initSubscribeSwitch();
initReceiver(); startAutoRefreshRecord();
initSwitchEvent();
} }
private void initModeSwitch(){ private void initDefaultConfig() {
rgSubMode.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { currentSubscribeSid = UUID.randomUUID().toString().substring(0, 16);
tvSubscribeSid.setText("订阅SID" + currentSubscribeSid);
rbModeAll.setChecked(true);
etStepMeter.setText("10");
}
/**
* 外部绑定当前视图专属的接收服务Class
*/
public void bindReceiverService(Class<?> serviceClazz){
this.mBindReceiverServiceClazz = serviceClazz;
}
private void initModeSwitch() {
rgSubscribeMode.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override @Override
public void onCheckedChanged(RadioGroup group, int checkedId) { public void onCheckedChanged(RadioGroup group, int checkedId) {
layoutStepSetting.setVisibility(checkedId == R.id.rb_step ? View.VISIBLE : View.GONE); etStepMeter.setVisibility(checkedId == R.id.rb_mode_step ? VISIBLE : GONE);
} }
}); });
} }
private void initCountUtil(){ private void initSubscribeSwitch() {
mTimeCountUtil = new TimeCountUtil(new TimeCountUtil.OnCountListener() { switchSubscribe.setOnCheckedChangeListener(new android.widget.CompoundButton.OnCheckedChangeListener() {
@Override @Override
public void onTimeOut() { public void onCheckedChanged(android.widget.CompoundButton buttonView, boolean isChecked) {
if(!isSubscribeSuccess){ if (isChecked) {
mSwitchSubscribe.setChecked(false);
mTvCountTip.setText("订阅超时,已自动关闭");
}
}
});
}
private void initReceiver(){
mResultReceiver = new GpsSubscribeObserverReceiver();
mResultReceiver.setOnSubscribeResultListener(new GpsSubscribeObserverReceiver.OnSubscribeResultListener() {
@Override
public void onResultBack(GpsSubscribeResult result) {
if(currentSubscribeSid.equals(result.getSubscribeUniqueId())){
isSubscribeSuccess = true;
mTimeCountUtil.cancel();
mTvCountTip.setText("订阅已生效,通讯正常");
}
}
});
IntentFilter filter = new IntentFilter();
filter.addAction(GpsSubscribeConst.ACTION_SUBSCRIBE_CALLBACK);
getContext().registerReceiver(mResultReceiver,filter);
}
private void initSwitchEvent(){
mSwitchSubscribe.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
startSubscribe(); startSubscribe();
}else{ } else {
stopSubscribe(); stopSubscribe();
} }
} }
}); });
} }
private void startSubscribe(){ private void startSubscribe() {
isSubscribeSuccess = false;
currentSubscribeSid = UUID.randomUUID().toString();
mTvCountTip.setText("等待订阅返回中...");
int subMode = GpsSubscribeConst.SUB_TYPE_ALL; int subMode = GpsSubscribeConst.SUB_TYPE_ALL;
float stepMeter = 10.0f; float stepVal = 10f;
if(rbStep.isChecked()){ if (rbModeStep.isChecked()) {
subMode = GpsSubscribeConst.SUB_TYPE_STEP_DISTANCE; subMode = GpsSubscribeConst.SUB_TYPE_STEP_DISTANCE;
try{ try {
stepMeter = Float.parseFloat(etStepMeter.getText().toString().trim()); stepVal = Float.parseFloat(etStepMeter.getText().toString().trim());
}catch (Exception e){ } catch (Exception ignored) {}
stepMeter = 10.0f;
}
} }
GpsSubscribeMsg msg = new GpsSubscribeMsg( GpsSubscribeMsg subscribeMsg = new GpsSubscribeMsg(
getContext().getPackageName(), getContext().getPackageName(),
subMode, subMode,
stepMeter, stepVal,
GpsSubscribeConst.SUBSCRIBE_TYPE_LOCATION, GpsSubscribeConst.SUBSCRIBE_TYPE_LOCATION,
1000, 1000,
1.0f, 1f,
true, true,
currentSubscribeSid currentSubscribeSid
); );
Intent intent = new Intent(GpsSubscribeConst.ACTION_SUBSCRIBE_REQUEST); mSubscribeManager.addSubscribe(subscribeMsg);
intent.putExtra("req",msg); mLocationManager.putSubscribeConfig(currentSubscribeSid, subscribeMsg);
getContext().sendBroadcast(intent); mLocationManager.clearPushCount(currentSubscribeSid);
mTimeCountUtil.start(GpsSubscribeConst.SUBSCRIBE_TIME_OUT); //开启订阅自动启动专属接收服务
} if(mBindReceiverServiceClazz != null){
Intent startServiceIntent = new Intent(getContext(), mBindReceiverServiceClazz);
private void stopSubscribe(){ getContext().startService(startServiceIntent);
mTimeCountUtil.cancel();
isSubscribeSuccess = false;
mTvCountTip.setText("订阅已关闭");
}
public void release(){
mTimeCountUtil.cancel();
if(mResultReceiver != null){
getContext().unregisterReceiver(mResultReceiver);
} }
} }
private void stopSubscribe() {
mSubscribeManager.removeSubscribe(currentSubscribeSid);
mLocationManager.removeSubscribe(currentSubscribeSid);
tvSubscribeRecord.setText("状态:未订阅");
//关闭订阅 同步停止专属接收服务
if(mBindReceiverServiceClazz != null){
Intent stopServiceIntent = new Intent(getContext(), mBindReceiverServiceClazz);
getContext().stopService(stopServiceIntent);
}
}
private void startAutoRefreshRecord() {
mRefreshHandler.postDelayed(new Runnable() {
@Override
public void run() {
refreshRecordInfo();
mRefreshHandler.postDelayed(this, REFRESH_INTERVAL);
}
}, REFRESH_INTERVAL);
}
private void refreshRecordInfo() {
if (!switchSubscribe.isChecked()) {
tvSubscribeRecord.setText("状态:空闲未订阅");
return;
}
GpsSubscribeMsg config = mLocationManager.getSubscribeConfig(currentSubscribeSid);
LocationPoint lastPoint = mLocationManager.getLastPoint(currentSubscribeSid);
if (config == null) {
tvSubscribeRecord.setText("状态:已订阅|等待管理器加载");
return;
}
String modeText = config.getSubscribeMode() == GpsSubscribeConst.SUB_TYPE_ALL
? "全量订阅" : "步长订阅";
int realPushCount = mLocationManager.getPushCount(currentSubscribeSid);
StringBuilder record = new StringBuilder();
record.append("【订阅实时数据表】\n");
record.append("订阅模式:").append(modeText).append("\n");
record.append("步长阈值:").append(config.getStepDistanceM()).append("\n");
if(lastPoint != null){
record.append("基准定点:").append(lastPoint.getLatitude()).append(" , ").append(lastPoint.getLongitude()).append("\n");
}else{
record.append("基准定点:等待首次定位建立\n");
}
record.append("真实推送次数:").append(realPushCount).append("");
tvSubscribeRecord.setText(record);
}
public String getCurrentSid() {
return currentSubscribeSid;
}
public boolean isSubscribeOpen() {
return switchSubscribe.isChecked();
}
/**
* 视图销毁:强制停止订阅 + 停止服务 + 清空刷新任务
*/
@Override
protected void onDetachedFromWindow() {
if(switchSubscribe.isChecked()){
switchSubscribe.setChecked(false);
}
mRefreshHandler.removeCallbacksAndMessages(null);
super.onDetachedFromWindow();
}
} }

View File

@@ -3,97 +3,81 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp"> android:padding="14dp"
android:layout_marginVertical="6dp"
<LinearLayout android:background="#282828"
android:layout_width="match_parent" android:clipToPadding="false">
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="订阅模式:"
android:textSize="14sp"/>
<RadioGroup
android:id="@+id/rg_sub_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="全消息订阅"
android:checked="true"/>
<RadioButton
android:id="@+id/rb_step"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="步长订阅"/>
</RadioGroup>
</LinearLayout>
<LinearLayout
android:id="@+id/layout_step_setting"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="移动步长阈值(米)"
android:textSize="14sp"/>
<EditText
android:id="@+id/et_step_meter"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:text="10"
android:gravity="center"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginTop="12dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="GPS订阅总开关"
android:textSize="14sp"/>
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"/>
<Switch
android:id="@+id/switch_subscribe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<!-- SID标识 -->
<TextView <TextView
android:id="@+id/tv_count_tip" android:id="@+id/tv_subscribe_sid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#999999"
android:textSize="11sp"/>
<!-- 订阅模式选择 -->
<RadioGroup
android:id="@+id/rg_subscribe_mode"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:orientation="horizontal"
android:text="未订阅" android:layout_marginTop="8dp">
android:textSize="12sp"
android:textColor="#666666"/> <RadioButton
android:id="@+id/rb_mode_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="全量订阅"
android:textColor="#FFFFFF"/>
<RadioButton
android:id="@+id/rb_mode_step"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="步长订阅"
android:layout_marginStart="18dp"
android:textColor="#FFFFFF"/>
</RadioGroup>
<!-- 步长输入 -->
<EditText
android:id="@+id/et_step_meter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="移动阈值(米)"
android:inputType="numberDecimal"
android:text="10"
android:visibility="gone"
android:textColor="#ffffff"
android:textColorHint="#666666"
android:layout_marginTop="8dp"/>
<!-- 订阅开关 -->
<Switch
android:id="@+id/switch_subscribe"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开启独立订阅"
android:textColor="#EEEEEE"
android:layout_marginTop="10dp"/>
<!-- 分割线 -->
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#444444"
android:layout_marginTop="12dp"/>
<!-- 订阅数据记录表【ID完全对应源码 tv_subscribe_record】 -->
<TextView
android:id="@+id/tv_subscribe_record"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#88EE88"
android:textSize="10sp"
android:layout_marginTop="10dp"
android:gravity="start"/>
</LinearLayout> </LinearLayout>