当前位置: 首页 > news >正文

面向GIS的Android studio移动开发(二)--在地图上绘制电子围栏

电子围栏,校园跑的常客,也是定位打卡必不可少的东西

主要代码:

创建电子围栏代码

// 添加多边形地理围栏(兼容2023版SDK)private void addPolygon(String fenceName, List<LatLng> points) {if (points == null || points.size() < 3) {Toast.makeText(this, "多边形至少需要3个点", Toast.LENGTH_SHORT).show();return;}// 生成唯一围栏IDString fenceId = "polygon_" + mCustomID++;// 转换坐标点格式List<DPoint> dPoints = new ArrayList<>();for (LatLng point : points) {dPoints.add(new DPoint(point.latitude, point.longitude));}// 正确调用方式(关键修改点)mClientInAndStayAction.addGeoFence(dPoints,               // 参数1: 多边形顶点坐标(必须闭合)fenceId                // 参数2: 自定义围栏ID);// 绘制多边形到地图PolygonOptions options = new PolygonOptions().addAll(points).fillColor(0x5566CCFF)    // 填充色(带透明度).strokeColor(Color.BLUE)  // 边框色.strokeWidth(5);         // 边框宽度(px)Polygon polygon = aMap.addPolygon(options);mCustomEntitys.put(fenceId, polygon);// 设置围栏监听(新增)mClientInAndStayAction.setGeoFenceListener(new GeoFenceListener() {@Overridepublic void onGeoFenceCreateFinished(List<GeoFence> geoFences, int errorCode, String msg) {if (errorCode == GeoFence.ADDGEOFENCE_SUCCESS) {runOnUiThread(() ->Toast.makeText(MapActivity.this, fenceName + "围栏创建成功", Toast.LENGTH_SHORT).show());}}});// 移动视角到围栏中心aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(points.get(0), 15));}//这里通过数据库进行添加电子围栏的多边形private void addTiananmenFence() {List<LatLng> tiananmenArea = new ArrayList<>();// 添加闭合坐标点(示例数据)tiananmenArea.add(new LatLng(39.908722, 116.397499)); // 天安门中心tiananmenArea.add(new LatLng(39.910000, 116.395000)); // 西北角tiananmenArea.add(new LatLng(39.909500, 116.400000));  // 东北角tiananmenArea.add(tiananmenArea.get(0)); // 闭合多边形addPolygon("天安门核心区", tiananmenArea);}

创建广播(当定位在定位外时触发)

// 修改onStart方法中的注册逻辑@Overrideprotected void onStart() {super.onStart();// 创建带安全标志的广播过滤器IntentFilter filter = new IntentFilter(GEOFENCE_BROADCAST_ACTION);// 适配Android 13+广播权限要求if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {registerReceiver(mGeoFenceReceiver,filter,Context.RECEIVER_NOT_EXPORTED // 禁止外部应用访问);} else {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {registerReceiver(mGeoFenceReceiver, filter, Context.RECEIVER_NOT_EXPORTED);}}createNotificationChannel();}@Overrideprotected void onStop() {super.onStop();// 取消注册接收器unregisterReceiver(mGeoFenceReceiver);}private void createNotificationChannel() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {CharSequence name = "地理围栏警报";String description = "电子围栏越界通知";int importance = NotificationManager.IMPORTANCE_HIGH;NotificationChannel channel = new NotificationChannel(ALERT_CHANNEL_ID, name, importance);channel.setDescription(description);NotificationManager notificationManager = getSystemService(NotificationManager.class);notificationManager.createNotificationChannel(channel);}}

发送日志

 // 在MapActivity中private final BroadcastReceiver mGeoFenceReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {if (!isValidBroadcast(intent)) return;Bundle bundle = intent.getExtras();if (bundle == null) return;// 解析基础数据int status = bundle.getInt(GeoFence.BUNDLE_KEY_FENCESTATUS);String fenceId = bundle.getString(GeoFence.BUNDLE_KEY_FENCEID);GeoFence fence = bundle.getParcelable(GeoFence.BUNDLE_KEY_FENCE);// 分发事件处理handleGeoFenceEvent(context, status, fenceId, fence);}private boolean isValidBroadcast(Intent intent) {return intent != null &&GEOFENCE_BROADCAST_ACTION.equals(intent.getAction());}private void handleGeoFenceEvent(Context context, int status,String fenceId, GeoFence fence) {switch (status) {case GeoFence.STATUS_IN:handleEnter(context, fenceId);break;case GeoFence.STATUS_OUT:handleExit(context, fence);break;case GeoFence.STATUS_STAYED:handleStay(fence);break;}}private void handleEnter(Context context, String fenceId) {// 记录日志GeoFenceLogger.logEnter(fenceId);// UI提示Toast.makeText(context, "进入监控区域", Toast.LENGTH_SHORT).show();}private void handleExit(Context context, GeoFence fence) {if (fence == null) return;// 记录日志GeoFenceLogger.logExit(fence.getFenceId());// 触发警报String alertMsg = "⚠️ 已离开安全区域: " + fence.getFenceId();Toast.makeText(context, alertMsg, Toast.LENGTH_LONG).show();sendAlertNotification(context, alertMsg);}private void handleStay(GeoFence fence) {if (fence == null) return;// 记录日志GeoFenceLogger.logStay(fence.getFenceId(), fence.getExpiration());}};private void sendAlertNotification(Context context, String message) {NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);// 构建通知Notification notification = new NotificationCompat.Builder(context, ALERT_CHANNEL_ID).setSmallIcon(R.drawable.ic_alert).setContentTitle("区域越界警告").setContentText(message).setPriority(NotificationCompat.PRIORITY_MAX).setAutoCancel(true).build();// 显示通知if (manager != null) {manager.notify(new Random().nextInt(1000), notification);}}
package com.example.gdmap;import android.util.Log;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;//用来记录学生何时进出入电子围栏
//这部分可将log打印的日志部分写为string放在教师端的文本框中
// GeoFenceLogger.java
public class GeoFenceLogger {private static final String TAG = "GeoFenceTracker";private static final SimpleDateFormat DATE_FORMAT =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault());// 记录进入事件public static void logEnter(String fenceId) {String timestamp = DATE_FORMAT.format(new Date());Log.d(TAG, String.format("[进入] 围栏ID: %s | 时间: %s", fenceId, timestamp));}// 记录离开事件public static void logExit(String fenceId) {String timestamp = DATE_FORMAT.format(new Date());Log.d(TAG, String.format("[离开] 围栏ID: %s | 时间: %s", fenceId, timestamp));}// 记录停留事件public static void logStay(String fenceId, long duration) {String timestamp = DATE_FORMAT.format(new Date());Log.d(TAG, String.format("[停留] 围栏ID: %s | 时间: %s | 持续时间: %dms",fenceId, timestamp, duration));}
}

activity代码

package com.example.gdmap;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;import com.amap.api.fence.GeoFence;
import com.amap.api.fence.GeoFenceListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapView;
import com.amap.api.maps.MapsInitializer;
import com.amap.api.maps.model.CircleOptions;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.fence.GeoFence;
import com.amap.api.fence.GeoFenceClient;
import com.amap.api.maps.model.Polygon;
import com.amap.api.maps.model.PolygonOptions;
import com.amap.api.maps.model.Circle;
import com.amap.api.location.DPoint; // 注意:高德使用DPoint而非LatLng
import android.Manifest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;public class MapActivity extends AppCompatActivity implementsAMap.OnMarkerClickListener,AMap.InfoWindowAdapter {private MapView mMapView;// 地理围栏相关private GeoFenceClient mClientInAndStayAction;private int mCustomID = 1000; // 围栏ID种子值private HashMap<String, Object> mCustomEntitys = new HashMap<>(); // 存储围栏图形对象private static final String GEOFENCE_BROADCAST_ACTION = "com.example.gdmap.geofence";private AMap aMap;private static final int PERMISSION_REQUEST_CODE = 1001;// 在MapActivity类中添加以下代码private static final String TAG = "GeoFenceTracker";// 定义通知渠道IDprivate static final String ALERT_CHANNEL_ID = "geo_fence_alerts";private static final int REQUEST_CODE = 1001;private void requestLocationPermission() {if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_CODE);}}@Overridepublic void onRequestPermissionsResult(int requestCode,@NonNull String[] permissions,@NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults); // 关键调用if (requestCode == REQUEST_CODE) {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {initializeMap();} else {Toast.makeText(this, "权限被拒绝,部分功能受限", Toast.LENGTH_SHORT).show();}}}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_map);// 初始化地图MapsInitializer.updatePrivacyShow(this, true, true);MapsInitializer.updatePrivacyAgree(this, true);mMapView = findViewById(R.id.map);mMapView.onCreate(savedInstanceState);initializeMap();setupLocationStyle();addMarkers();addTiananmenFence();}private void initializeMap() {if (aMap == null) {aMap = mMapView.getMap();mClientInAndStayAction = new GeoFenceClient(getApplicationContext());mClientInAndStayAction.createPendingIntent(GEOFENCE_BROADCAST_ACTION);mClientInAndStayAction.setActivateAction(GeoFenceClient.GEOFENCE_IN | GeoFenceClient.GEOFENCE_STAYED);// 设置信息窗口适配器aMap.setInfoWindowAdapter(this);// 设置Marker点击监听器aMap.setOnMarkerClickListener(this);// 初始地图位置和缩放级别aMap.animateCamera(CameraUpdateFactory.zoomTo(16));aMap.getUiSettings().setScaleControlsEnabled(true);}}private void setupLocationStyle() {MyLocationStyle myLocationStyle = new MyLocationStyle();myLocationStyle.interval(6000);myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);aMap.setMyLocationStyle(myLocationStyle);aMap.setMyLocationEnabled(true);}//这里可以通过数据库进行添加点private void addMarkers() {// 使用自定义方法创建带数据的MarkeraddMarker(28.711666, 115.826600, "AAA水果批发商小王", "苹果");addMarker(28.711667, 115.826750, "AAA水果批发商小李", "芒果");addMarker(28.711680, 115.826450, "AAA水果批发商小张", "草莓");// 东北地区addMarker(45.8038, 126.5340, "哈尔滨水果批发商老刘", "蓝莓"); // 黑龙江哈尔滨addMarker(43.8171, 125.3235, "长春水果批发商孙姐", "人参果"); // 吉林长春addMarker(41.8354, 123.4299, "沈阳水果批发商老金", "南果梨"); // 辽宁沈阳// 华北地区addMarker(39.9042, 116.4074, "北京新发地批发市场", "平谷大桃"); // 北京addMarker(37.8706, 112.5489, "太原水果批发商老陈", "沙金红杏"); // 山西太原addMarker(38.0428, 114.5149, "石家庄水果批发商赵总", "赞皇大枣"); // 河北石家庄// 华东地区addMarker(31.2304, 121.4737, "上海西郊国际批发", "南汇水蜜桃"); // 上海addMarker(30.2595, 120.2194, "杭州水果批发商王姐", "塘栖枇杷"); // 浙江杭州addMarker(32.0603, 118.7969, "南京众彩批发市场", "固城湖螃蟹"); // 江苏南京addMarker(36.6512, 117.1201, "济南堤口批发市场", "烟台樱桃"); // 山东济南// 华中地区addMarker(30.5951, 114.2999, "武汉光霞果批市场", "梁子湖螃蟹"); // 湖北武汉addMarker(28.1941, 112.9723, "长沙红星批发市场", "炎陵黄桃"); // 湖南长沙addMarker(34.7473, 113.6253, "郑州万邦物流城", "灵宝苹果"); // 河南郑州// 华南地区addMarker(23.1291, 113.2644, "广州江南果菜市场", "增城荔枝"); // 广东广州addMarker(20.0444, 110.1999, "海口南北水果市场", "文昌椰子"); // 海南海口addMarker(22.8176, 108.3663, "南宁海吉星市场", "百色芒果"); // 广西南宁// 西北地区addMarker(34.3416, 108.9398, "西安雨润批发市场", "周至猕猴桃"); // 陕西西安addMarker(36.0611, 103.8343, "兰州大青山市场", "白兰瓜"); // 甘肃兰州addMarker(43.8256, 87.6168, "乌鲁木齐九鼎市场", "哈密瓜"); // 新疆乌鲁木齐// 西南地区addMarker(29.6535, 91.1705, "拉萨药王山市场", "林芝苹果"); // 西藏拉萨addMarker(25.0433, 102.7062, "昆明金马正昌市场", "蒙自石榴"); // 云南昆明addMarker(26.6470, 106.6302, "贵阳石板哨市场", "修文猕猴桃"); // 贵州贵阳addMarker(30.5728, 104.0668, "成都濛阳农批市场", "攀枝花芒果"); // 四川成都// 特别行政区addMarker(22.3193, 114.1694, "香港长沙湾市场", "菲律宾香蕉"); // 香港}private void addMarker(double lat, double lng, String title, String phone) {LatLng position = new LatLng(lat, lng);aMap.addMarker(new MarkerOptions().position(position).title(title).snippet("售卖商品: " + phone).draggable(false));}// 实现信息窗口布局@Overridepublic View getInfoWindow(Marker marker) {View infoWindow = getLayoutInflater().inflate(R.layout.custom_info_window, null);renderInfoWindow(marker, infoWindow);return infoWindow;}@Overridepublic View getInfoContents(Marker marker) {return null; // 使用默认信息窗口背景时返回null}private void renderInfoWindow(Marker marker, View view) {TextView title = view.findViewById(R.id.info_window_title);TextView content = view.findViewById(R.id.info_window_content);title.setText(marker.getTitle());content.setText(marker.getSnippet());}// 处理Marker点击事件@Overridepublic boolean onMarkerClick(Marker marker) {// 显示信息窗口(第二个参数为是否强制使用默认布局)marker.showInfoWindow();return true; // 消费点击事件}// 添加多边形地理围栏(兼容2023版SDK)private void addPolygon(String fenceName, List<LatLng> points) {if (points == null || points.size() < 3) {Toast.makeText(this, "多边形至少需要3个点", Toast.LENGTH_SHORT).show();return;}// 生成唯一围栏IDString fenceId = "polygon_" + mCustomID++;// 转换坐标点格式List<DPoint> dPoints = new ArrayList<>();for (LatLng point : points) {dPoints.add(new DPoint(point.latitude, point.longitude));}// 正确调用方式(关键修改点)mClientInAndStayAction.addGeoFence(dPoints,               // 参数1: 多边形顶点坐标(必须闭合)fenceId                // 参数2: 自定义围栏ID);// 绘制多边形到地图PolygonOptions options = new PolygonOptions().addAll(points).fillColor(0x5566CCFF)    // 填充色(带透明度).strokeColor(Color.BLUE)  // 边框色.strokeWidth(5);         // 边框宽度(px)Polygon polygon = aMap.addPolygon(options);mCustomEntitys.put(fenceId, polygon);// 设置围栏监听(新增)mClientInAndStayAction.setGeoFenceListener(new GeoFenceListener() {@Overridepublic void onGeoFenceCreateFinished(List<GeoFence> geoFences, int errorCode, String msg) {if (errorCode == GeoFence.ADDGEOFENCE_SUCCESS) {runOnUiThread(() ->Toast.makeText(MapActivity.this, fenceName + "围栏创建成功", Toast.LENGTH_SHORT).show());}}});// 移动视角到围栏中心aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(points.get(0), 15));}//这里通过数据库进行添加电子围栏的多边形private void addTiananmenFence() {List<LatLng> tiananmenArea = new ArrayList<>();// 添加闭合坐标点(示例数据)tiananmenArea.add(new LatLng(39.908722, 116.397499)); // 天安门中心tiananmenArea.add(new LatLng(39.910000, 116.395000)); // 西北角tiananmenArea.add(new LatLng(39.909500, 116.400000));  // 东北角tiananmenArea.add(tiananmenArea.get(0)); // 闭合多边形addPolygon("天安门核心区", tiananmenArea);}// 修改onStart方法中的注册逻辑@Overrideprotected void onStart() {super.onStart();// 创建带安全标志的广播过滤器IntentFilter filter = new IntentFilter(GEOFENCE_BROADCAST_ACTION);// 适配Android 13+广播权限要求if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {registerReceiver(mGeoFenceReceiver,filter,Context.RECEIVER_NOT_EXPORTED // 禁止外部应用访问);} else {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {registerReceiver(mGeoFenceReceiver, filter, Context.RECEIVER_NOT_EXPORTED);}}createNotificationChannel();}@Overrideprotected void onStop() {super.onStop();// 取消注册接收器unregisterReceiver(mGeoFenceReceiver);}private void createNotificationChannel() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {CharSequence name = "地理围栏警报";String description = "电子围栏越界通知";int importance = NotificationManager.IMPORTANCE_HIGH;NotificationChannel channel = new NotificationChannel(ALERT_CHANNEL_ID, name, importance);channel.setDescription(description);NotificationManager notificationManager = getSystemService(NotificationManager.class);notificationManager.createNotificationChannel(channel);}}// 在MapActivity中private final BroadcastReceiver mGeoFenceReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {if (!isValidBroadcast(intent)) return;Bundle bundle = intent.getExtras();if (bundle == null) return;// 解析基础数据int status = bundle.getInt(GeoFence.BUNDLE_KEY_FENCESTATUS);String fenceId = bundle.getString(GeoFence.BUNDLE_KEY_FENCEID);GeoFence fence = bundle.getParcelable(GeoFence.BUNDLE_KEY_FENCE);// 分发事件处理handleGeoFenceEvent(context, status, fenceId, fence);}private boolean isValidBroadcast(Intent intent) {return intent != null &&GEOFENCE_BROADCAST_ACTION.equals(intent.getAction());}private void handleGeoFenceEvent(Context context, int status,String fenceId, GeoFence fence) {switch (status) {case GeoFence.STATUS_IN:handleEnter(context, fenceId);break;case GeoFence.STATUS_OUT:handleExit(context, fence);break;case GeoFence.STATUS_STAYED:handleStay(fence);break;}}private void handleEnter(Context context, String fenceId) {// 记录日志GeoFenceLogger.logEnter(fenceId);// UI提示Toast.makeText(context, "进入监控区域", Toast.LENGTH_SHORT).show();}private void handleExit(Context context, GeoFence fence) {if (fence == null) return;// 记录日志GeoFenceLogger.logExit(fence.getFenceId());// 触发警报String alertMsg = "⚠️ 已离开安全区域: " + fence.getFenceId();Toast.makeText(context, alertMsg, Toast.LENGTH_LONG).show();sendAlertNotification(context, alertMsg);}private void handleStay(GeoFence fence) {if (fence == null) return;// 记录日志GeoFenceLogger.logStay(fence.getFenceId(), fence.getExpiration());}};private void sendAlertNotification(Context context, String message) {NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);// 构建通知Notification notification = new NotificationCompat.Builder(context, ALERT_CHANNEL_ID).setSmallIcon(R.drawable.ic_alert).setContentTitle("区域越界警告").setContentText(message).setPriority(NotificationCompat.PRIORITY_MAX).setAutoCancel(true).build();// 显示通知if (manager != null) {manager.notify(new Random().nextInt(1000), notification);}}// 生命周期方法@Overrideprotected void onResume() {super.onResume();mMapView.onResume();}@Overrideprotected void onPause() {super.onPause();mMapView.onPause();}@Overrideprotected void onDestroy() {super.onDestroy();mMapView.onDestroy();}@Overrideprotected void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState);mMapView.onSaveInstanceState(outState);}
}

标志.XML

<vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="24dp"android:height="24dp"android:viewportWidth="24"android:viewportHeight="24"><pathandroid:fillColor="#FF0000"android:pathData="M12,2L3,20h18L12,2zM13,16h-2v-2h2v2zm0-4h-2V8h2v4z"/>
</vector>

请添加图片描述

效果图:

请添加图片描述
请添加图片描述

相关文章:

面向GIS的Android studio移动开发(二)--在地图上绘制电子围栏

电子围栏&#xff0c;校园跑的常客&#xff0c;也是定位打卡必不可少的东西 主要代码&#xff1a; 创建电子围栏代码 // 添加多边形地理围栏&#xff08;兼容2023版SDK&#xff09;private void addPolygon(String fenceName, List<LatLng> points) {if (points null…...

《从零开始:Spring Cloud Eureka 配置与服务注册全流程》​

关于Eureka的学习&#xff0c;主要学习如何搭建Eureka&#xff0c;将order-service和product-service都注册到Eureka。 1.为什么使用Eureka? 我在实现一个查询订单功能时&#xff0c;希望可以根据订单中productId去获取对应商品的详细信息&#xff0c;但是产品服务和订单服…...

能力验证及大练兵活动第一期

计算机 请根据计算机检材&#xff0c;回答以下问题&#xff1a; (10道题&#xff0c;共19.0分) 1. 计算机中曾挂载的Bitlocker加密分区的恢复密钥后6位为&#xff1f;&#xff08;答案格式&#xff1a;6位数字&#xff09; (1.0分) 答案&#xff1a;700755 2. 请写出曾远程连…...

TASK03【Datawhale 组队学习】搭建向量知识库

文章目录 向量及向量知识库词向量与向量向量数据库 数据处理数据清洗文档分割 搭建并使用向量数据库 向量及向量知识库 词向量与向量 词向量&#xff08;word embedding&#xff09;是一种以单词为单位将每个单词转化为实数向量的技术。词向量背后的主要想理念是相似或相关的…...

ProfibusDP转ModbusRTU的实用攻略

ProfibusDP转ModbusRTU的实用攻略 在工业自动化领域中&#xff0c;Profibus DP和Modbus RTU是两种常见的通信协议。 Profibus DP是一种广泛应用于过程控制和工厂自动化的现场总线标准&#xff0c;具有高实时性和可靠性。 而Modbus RTU则是一种串行通信协议&#xff0c;常用于…...

基于开源AI智能名片链动2+1模式S2B2C商城小程序源码的去中心化商业扩散研究

摘要&#xff1a;本文探讨在去中心化商业趋势下&#xff0c;开源AI智能名片链动21模式S2B2C商城小程序源码如何助力企业挖掘数据价值、打破信息孤岛&#xff0c;实现商业高效扩散。通过分析该技术组合的架构与功能&#xff0c;结合实际案例&#xff0c;揭示其在用户关系拓展、流…...

iOS 工厂模式

iOS 工厂模式 文章目录 iOS 工厂模式前言工厂模式简单工厂案例场景分析苹果类优点缺点 小结 工厂模式客户端调用**优点****缺点** 抽象工厂模式三个模式对比 前言 笔者之前学习了有关于设计模式的六大原则,之前简单了解过这个工厂模式,今天主要是重新学习一下这个模式,正式系统…...

LaTeX OCR - 数学公式识别系统

文章目录 一、关于 LaTeX OCR1、项目概览架构图2、相关链接资源3、功能特性 二、安装配置基础环境要求Linux 安装Mac 安装 三、使用指南1、快速训练&#xff08;小数据集&#xff09;2、完整训练&#xff08;大数据集&#xff09; 四、可视化功能训练过程可视化预测过程可视化 …...

Go 语言即时通讯系统开发日志-日志day2-5:架构设计与日志封装

Go语言即时通讯系统开发日志day2 计划&#xff1a;学习go中MySQL&#xff0c;Redis的使用&#xff0c;使用MySQL和Redis完成一个单聊demo。 总结&#xff1a;现在每天下午用来开发这个项目&#xff0c;如果有课的话可能学习时间只有3-4个小时&#xff0c;再加上今天的学习效率不…...

@JsonProperty和@JSONField 使用

JsonProperty和JSONField注解的区别 1.底层框架不同 JsonProperty 是Jackson实现的 JSONField 是fastjson实现的 2.用法不同 &#xff08;1&#xff09;bean序列化为Json&#xff1a; JsonProperty&#xff1a; ObjectMapper().writeValueAsString(Object value) JSONField&…...

从代码学习深度学习 - 近似训练 PyTorch版

文章目录 前言负采样 (Negative Sampling)层序Softmax (Hierarchical Softmax)代码示例总结前言 在自然语言处理(NLP)领域,词嵌入(Word Embeddings)技术如Word2Vec(包括Skip-gram和CBOW模型)已经成为一项基础且强大的工具。它们能够将词语映射到低维稠密向量空间,使得…...

代码上传gitte仓库

把代码push上去就行...

系统架构设计(十四):解释器风格

概念 解释器风格是一种将程序的每个语句逐条读取并解释执行的体系结构风格。程序在运行时不会先被编译为机器码&#xff0c;而是动态地由解释器分析并执行其语义。 典型应用&#xff1a;Python 解释器、JavaScript 引擎、Bash Shell、SQL 引擎。 组成结构 解释器风格系统的…...

掌握LINQ:查询语法与方法语法全解析

文章目录 引言1. 查询语法 vs 方法语法1.1 查询语法 (Query Syntax)1.2 方法语法 (Method Syntax)1.3 两种语法的比较 2. 基本的 LINQ 查询结构2.1 数据源2.2 查询操作2.3 查询执行 3. 查询表达式中的关键字3.1 基本关键字fromwhereselectorderbygroup byjoin 3.2 其他常用关键…...

Go 后端中双 token 的实现模板

下面是一个典型的 Go 后端双 Token 认证机制 实现模板&#xff0c;使用 Gin 框架 JWT Redis&#xff0c;结构清晰、可拓展&#xff0c;适合实战开发。 项目结构建议 /utils├── jwt.go // Access & Refresh token 的生成和解析├── claims.go // 从请求…...

GESP编程能力等级认证C++3级1-数组1

1 GESP编程能力等级认证C3级 1.1 GESP简介 GESP是CCF 编程能力等级认证的简称&#xff0c;它为青少年计算机和编程学习者提供学业能力验证的规则和平台。GESP 覆盖中小学阶段&#xff0c;符合年龄条件的青少年均可参加认证。 1.2 GESP的分级 C 编程测试划分为一至八级&…...

FreeRTOS “探究任务调度机制魅力”

引入 现如今随着单片机的资源越来越多&#xff0c;主频越来越高&#xff0c;在面临更复杂的功能实现以及对MCU性能的充分压榨&#xff0c;会RTOS已经成为一个必要的技能&#xff0c;新手刚开始学习的时候就很好奇“为什么代码可以放到两个循环里同时运行&#xff1f;”。接下来…...

BGP策略实验练习

要求&#xff1a; 1、使用PreVal策略&#xff0c;确保R4通过R2到达192.168.10.0/24 2、使用AS_Path策略&#xff0c;确保R4通过R3到达192.168.11.0/24 3、配置MED策略&#xff0c;确保R4到达R3到达192.168.11.0/24 4、使用Local Preference策略&#xff0c;确保R1通过R2到达192…...

Office 中 VBE 的共同特点与区别

1. Excel VBE 核心对象 #mermaid-svg-IklDO11Hu656bdGS {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-IklDO11Hu656bdGS .error-icon{fill:#552222;}#mermaid-svg-IklDO11Hu656bdGS .error-text{fill:#552222;stro…...

Linux虚拟文件系统(1)

1 虚拟文件系统&#xff08;VFS&#xff09; 虚拟文件系统&#xff08;Virtual File System, VFS&#xff09;作为内核的子系统。&#xff0c;它为用户空间的应用程序提供了一个统一的文件系统接口。通过VFS&#xff0c;不同的文件系统可以共存于同一个操作系统中&#xff0c;…...

目标检测评估指标mAP详解:原理与代码

目标检测评估指标mAP详解&#xff1a;原理与代码 目标检测评估指标mAP详解&#xff1a;原理与代码一、前言&#xff1a;为什么需要mAP&#xff1f;二、核心概念解析2.1 PR曲线&#xff08;Precision-Recall Curve&#xff09;2.2 AP计算原理 三、代码实现详解3.1 核心函数ap_pe…...

Linux干货(六)

前言 从B站黑马程序员Linux课程摘选的学习干货&#xff0c;新手友好&#xff01;若有侵权&#xff0c;会第一时间处理。 目录 前言 1.环境变量 1.环境变量的定义 2.env命令的作用 3.$符号的作用 4.PATH的定义和作用 5.修改环境变量的方法 1.临时生效 2.永久生效 2.…...

字符串相乘(43)

43. 字符串相乘 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; class Solution { public:string multiply(string num1, string num2) {string res "0";for (int i 0; i < num2.size(); i) {string str multiplyOneNum(num1, num2[num2.size() -…...

【Vue篇】数据秘语:从watch源码看响应式宇宙的蝴蝶效应

目录 引言 一、watch侦听器&#xff08;监视器&#xff09; 1.作用&#xff1a; 2.语法&#xff1a; 3.侦听器代码准备 4. 配置项 5.总结 二、翻译案例-代码实现 1.需求 2.代码实现 三、综合案例——购物车案例 1. 需求 2. 代码 引言 &#x1f4ac; 欢迎讨论&#…...

esp32课设记录(二)lcd屏显示文字与照片

取模软件链接&#xff1a; 链接: 百度网盘 请输入提取码 提取码: 1234 课设要求如图所示&#xff0c;因此需要在esp32显示文字和照片。在上个文章中我已经写了按键相关内容。这篇主要描述怎么显示文字和照片。我使用的是ESP-IDF库。 本项目使用的是基于ST7789驱动芯片的LCD屏幕…...

Open CASCADE学习|几何体切片处理:OpenMP与OSD_Parallel并行方案深度解析

在三维建模与仿真领域&#xff0c;几何体切片处理是CAE前处理、3D打印路径规划、医学影像分析等场景的关键技术。其核心目标是将三维模型沿特定方向离散为二维截面集合&#xff0c;便于后续分析或制造。OpenCASCADE作为开源几何内核&#xff0c;提供高效的布尔运算与几何算法&a…...

【Android】从Choreographer到UI渲染(二)

【Android】从Choreographer到UI渲染&#xff08;二&#xff09; Google 在 2012 年推出的 Project Butter&#xff08;黄油计划&#xff09;是 Android 系统发展史上的重要里程碑&#xff0c;旨在解决长期存在的 UI 卡顿、响应延迟等问题&#xff0c;提升用户体验。 在 Androi…...

板凳-------Mysql cookbook学习 (三)

1.22 使长输出行更具可读性 mysql> show full columns from limbs; ------------------------------------------------------------------------------------------------------------- | Field | Type | Collation | Null | Key | Default | Extra | Pri…...

济南国网数字化培训班学习笔记-第三组-2-电力通信光缆网认知

电力通信光缆网认知 光缆网架构现状 基础底座 电路系统是高度复杂&#xff0c;实时性、安全性、可靠性要求极高的巨系统&#xff0c;必须建设专用通信网 相伴相生 电力系统是由发电、输电、变电、配电、用电等一次设施&#xff0c;及保障其正常运行的保护、自动化、通信等…...

黑灰产业链深度解析

黑灰产业链深度解析 大家好&#xff0c;欢迎来到「黑产档案」。本频道专注于反诈教育宣传&#xff0c;通过深度拆解黑灰产业链的运作逻辑&#xff0c;帮助公众识别骗局、规避风险。本节课将聚焦产业链的核心环节&#xff0c;揭示其背后的灰色生态。 一、黑灰产的定义与范畴 要…...

golang选项设计模式

选项设计模式 有时候一个函数会有很多参数&#xff0c;为了方便函数的使用&#xff0c;我们会给希望给一些参数设定默认值&#xff0c;调用时只需要传与默认值不同的参数即可&#xff0c;类似于 python 里面的默认参数和字典参数&#xff0c;虽然 golang 里面既没有默认参数也…...

方案精读:104页DeepSeek金融银行核算流程场景部署建设方案【附全文阅读】

DeepSeek,金融银行核算流程的革新方案! 这份方案专为金融银行从业者打造,旨在解决传统核算流程的难题。当下,金融银行核算面临效率低、错误率高、合规压力大等挑战,DeepSeek 方案正是应对之策。 该方案运用人工智能和大数据技术,实现数据采集、清洗自动化,智能核算对账,…...

【MySQL】02.数据库基础

1. 数据库的引入 之前存储数据用文件就可以了&#xff0c;为什么还要弄个数据库? 文件存储存在安全性问题&#xff0c;文件不利于数据查询和管理&#xff0c;文件不利于存储海量数据&#xff0c;文件在程序中控制不方便。而为了解决上述问题&#xff0c;专家们设计出更加利于…...

STM32项目实战:ADC采集

STM32F103C8T6的ADC配置。PB0对应的是ADC1的通道8。在标准库中&#xff0c;需要初始化ADC&#xff0c;设置通道&#xff0c;时钟&#xff0c;转换模式等。需要配置GPIOB的第0脚为模拟输入模式&#xff0c;然后配置ADC1的通道8&#xff0c;设置转换周期和触发方式。 接下来是I2C…...

《AI语音模型:MiniMax Speech-02》

开场&#xff1a;AI 语音界的震撼弹 在 AI 语音技术的激烈竞争赛道上&#xff0c;MiniMax Speech - 02 的出现宛如一颗震撼弹&#xff0c;瞬间引爆了整个行业。不久前&#xff0c;一则消息在全球 AI 领域引起轩然大波&#xff1a;MiniMax 的新一代语音大模型 Speech - 02&#…...

基于LabVIEW的双音多频系统设计

目录 1 系统设计概述 双音多频(Dual-Tone Multi-Frequency, DTMF)信号是一种广泛应用于电话系统中的音频信号,通过不同的频率组合表示不同的按键。每个按键对应两个频率,一个低频和一个高频,共同组成独特的信号。在虚拟仪器技术快速发展的背景下,利用LabVIEW等图形化编程…...

快速生成角色背景设定:基于Next.js的AI辅助工具开发实践

引言 在游戏开发、小说创作和角色扮演&#xff08;RP&#xff09;中&#xff0c;角色背景设定&#xff08;Headcanon&#xff09;的构建往往耗时耗力。传统方法依赖手动编写&#xff0c;容易陷入思维定式。本文将分享如何利用Next.js和Tailwind CSS开发一个高效的AI角色设定生…...

轻量级视频剪辑方案:FFmpeg图形化工具体验

FFmpeg小白助手是基于开源FFmpeg开发的本地化视频处理软件&#xff0c;采用绿色免安装设计&#xff0c;解压后即可直接运行。该工具主要面向普通用户的日常音视频处理需求&#xff0c;通过简洁的图形界面降低了FFmpeg的使用门槛。 功能特性 基础编辑功能 格式转换&#xff1a;…...

主成分分析的应用之sklearn.decomposition模块的PCA函数

主成分分析的应用之sklearn.decomposition模块的PCA函数 一、模型建立整体步骤 二、数据 2297.86 589.62 474.74 164.19 290.91 626.21 295.20 199.03 2262.19 571.69 461.25 185.90 337.83 604.78 354.66 198.96 2303.29 589.99 516.21 236.55 403.92 730.05 438.41 225.80 …...

Java基于数组的阻塞队列实现详解

在多线程编程中&#xff0c;阻塞队列是一种非常有用的工具&#xff0c;它可以在生产者和消费者之间提供一个缓冲区&#xff0c;使得生产者可以往队列中添加数据&#xff0c;而消费者可以从队列中取出数据。当队列满时&#xff0c;生产者会被阻塞直到有空间可用&#xff1b;当队…...

ngx_http_random_index_module 模块概述

一、使用场景 随机内容分发 当同一目录下存放多份等价内容&#xff08;如多张轮播图、不同版本静态页面等&#xff09;时&#xff0c;可通过随机索引实现负载均衡或流量分散。A/B 测试 通过目录请求自动随机分配用户到不同测试组&#xff0c;无需后端逻辑参与。动态“首页”选…...

你引入的lodash充分利用了吗?

#开发中&#xff0c;发现自己只有cloneDeep的时候才想起来用这个库的便利&#xff0c;搜索了项目内代码&#xff0c;发现大家基本也是这样&#xff0c;其实我们错过了很多好东西# cloneDeep 深拷贝 var objects [{ a: 1 }, { b: 2 }];var deep _.cloneDeep(objects); conso…...

Python爬虫基础

本篇内容中&#xff0c;我们主要分享一些爬虫的前置知识&#xff0c;主要知识点有&#xff1a; 爬虫的概念和作用爬虫的流程【重要】http相关的复习 http和https概念和区别浏览器访问一个网址的过程爬虫中常用的请求头、响应头常见的响应状态码 浏览器自带开发者工具的使用 爬…...

飞帆控件:on_post_get 接口配置

在网页中写一个接口是很基础的要求。 今天我们介绍一个工具&#xff0c;不用写代码&#xff0c;配置即可。 先上链接&#xff1a; on_post_gethttps://fvi.cn/798来看看控件的配置&#xff1a; 使用这个控件&#xff0c;在网页中写 post/get 接口可以告别代码。或许能做到初…...

C++笔试题(金山科技新未来训练营):

题目分布&#xff1a; 17道单选&#xff08;每题3分&#xff09;3道多选题&#xff08;全对3分&#xff0c;部分对1分&#xff09;2道编程题&#xff08;每一道20分&#xff09;。 不过题目太多&#xff0c;就记得一部分了&#xff1a; 单选题&#xff1a; static变量的初始…...

Selenium-Java版(css表达式)

css表达式 前言 根据 tag名、id、class 选择元素 tag名 #id .class 选择子元素和后代元素 定义 语法 根据属性选择 验证CSS Selector 组选择 按次序选择子节点 父元素的第n个子节点 父元素的倒数第n个子节点 父元素的第几个某类型的子节点 父元素的…...

19. 结合Selenium和YAML对页面实例化PO对象改造

19. 结合Selenium和YAML对页面实例化PO对象改造 一、架构升级核心思路 1.1 改造核心目标 # 原始PO模式&#xff1a;显式定义元素定位 username (id, ctl00_MainContent_username)# 改造后PO模式&#xff1a;动态属性访问 self.username.send_keys(Tester) # 自动触发元素定…...

MySQL——5、基本查询

表的增删改查 1、Create1.1、单行数据全列插入1.2、多行数据指定列插入1.3、插入否则更新1.4、替换 2、Retrieve2.1、select列2.2、where条件2.3、结果排序2.4、筛选分页结果 3、Update4、Delete4.1、删除数据4.2、截断表 5、插入查询结果6、聚合函数7、group by子句的使用8、实…...

ngx_http_referer_module 模块概述

一、使用场景 防盗链 仅允许本站或特定域名的页面直接引用图片、视频等资源&#xff0c;拒绝第三方网站直接嵌入。流量控制 阻止来自社交媒体、搜索引擎或未知来源的大量自动化抓取。安全审计 简易记录并过滤可疑 Referer&#xff0c;以减少非法请求。 注意 Referer 头可被伪造…...

Go语言--语法基础5--基本数据类型--类型转换

Go 编程语言中 if 条件语句的语法如下&#xff1a; 1、基本形式 if 布尔表达式 { /* 在布尔表达式为 true 时执行 */ } If 在布尔表达式为 true 时&#xff0c;其后紧跟的语句块执行&#xff0c;如果为 false 则 不执行。 package main import "fmt" …...