改进GPS订阅服务发送框架
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user