【Android App】实战项目之仿微信的附近的人(附源码和演示 超详细)

news2024/11/25 4:35:09

需要全部源码请点赞关注收藏后评论区留言私信~~~

艺术家常说“距离产生美”,其实距离近才是优势,谁不希望自己的工作事少钱多离家近呢?不光是工作,像租房买房、恋爱交友,大家都希望找个近点的,比如58、赶集主打同城交易,微信、陌陌主打同城交友,所谓近水楼台先得月嘛。 正因为位置信息如此重要,所以手机早早支持定位功能,还锲而不舍推进卫星定位、基站定位、WiFi定位等手段。 通过分享自己的位置,人们可以迅速找到附近志同道合的朋友,从而在传统社交之外开辟了新领域——周边社交。

一、需求描述

附近的人除了交友聊天,还存在下列的周边互动场景:

(1)个人有闲置物品,扔了可惜,想送给有需要的乡里乡亲;

(2)家里水电坏了,想临时找个附近的水电工上门修理;

(3)孩子长大了,看看周边有没有美术老师练习绘画、音乐老师练习钢琴之类; 为此需要增加地图导航功能,不仅在地图上标出周围人群的所在地,还需提供导航服务以便用户出行。

二、功能分析

(1)详情对话框:人员详情既包括头像图片,也包括昵称、性别、爱好、地址等文字描述。 (2)地图定位:自己位置和他人位置都用到了定位功能。

(3)地图导航:从当前位置驱车前往对方所在地,需要地图服务提供导航路线以便出行。

(4)网络通信框架:上传人员信息与获取人员列表均需与后端交互。

(5)图片加载框架:利用Glide框架加载人员头像。

(6)移动数据格式JSON:通过JSON结构封装http交互数据。

下面介绍一些代码模块之间的互相关系

(1)ChooseLocationActivity.java:这是选择自身位置的地图界面。

(2)InfoEditActivity.java:这是个人信息的编辑页面。

(3)NearbyActivity.java:这是显示附近人员的地图界面。

(4)NearbyLoadTask.java:这是附近人员列表的加载任务。

(5)PersonDialog.java:这是人员详情对话框,支持打对方电话、去对方那里等功能。

三、效果展示

首先选择自己的位置

点击下一步输入一些自己的基本信息

 

 可以在下拉框中选择查看的人们列表 此处最好用多部手机进行测试并且开启后台服务器

 

四、代码 

部分代码如下 如需要全部源码请点赞关注收藏后评论区留言私信~~~

package com.example.location;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.tencent.lbssearch.TencentSearch;
import com.tencent.lbssearch.object.param.Geo2AddressParam;
import com.tencent.lbssearch.object.result.Geo2AddressResultObject;
import com.tencent.map.geolocation.TencentLocation;
import com.tencent.map.geolocation.TencentLocationListener;
import com.tencent.map.geolocation.TencentLocationManager;
import com.tencent.map.geolocation.TencentLocationRequest;
import com.tencent.map.tools.net.http.HttpResponseListener;
import com.tencent.tencentmap.mapsdk.maps.CameraUpdate;
import com.tencent.tencentmap.mapsdk.maps.CameraUpdateFactory;
import com.tencent.tencentmap.mapsdk.maps.MapView;
import com.tencent.tencentmap.mapsdk.maps.TencentMap;
import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptor;
import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptorFactory;
import com.tencent.tencentmap.mapsdk.maps.model.CameraPosition;
import com.tencent.tencentmap.mapsdk.maps.model.LatLng;
import com.tencent.tencentmap.mapsdk.maps.model.Marker;
import com.tencent.tencentmap.mapsdk.maps.model.MarkerOptions;

public class ChooseLocationActivity extends AppCompatActivity implements
        TencentLocationListener, TencentMap.OnMapClickListener,
        TencentMap.OnMarkerDragListener, TencentMap.OnCameraChangeListener {
    private final static String TAG = "ChooseLocationActivity";
    private TencentLocationManager mLocationManager; // 声明一个腾讯定位管理器对象
    private MapView mMapView; // 声明一个地图视图对象
    private TencentMap mTencentMap; // 声明一个腾讯地图对象
    private boolean isFirstLoc = true; // 是否首次定位
    private float mZoom=12; // 缩放级别
    private LatLng mMyPos; // 当前的经纬度
    private String mAddress; // 详细地址

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_choose_location);
        initLocation(); // 初始化定位服务
        findViewById(R.id.btn_next).setOnClickListener(v -> gotoNext());
    }

    // 初始化定位服务
    private void initLocation() {
        mMapView = findViewById(R.id.mapView);
        mTencentMap = mMapView.getMap(); // 获取腾讯地图对象
        mTencentMap.setOnMapClickListener(this); // 设置地图的点击监听器
        mTencentMap.setOnMarkerDragListener(this); // 设置地图标记的拖动监听器
        mTencentMap.setOnCameraChangeListener(this); // 设置相机视角的变更监听器
        mLocationManager = TencentLocationManager.getInstance(this);
        // 创建腾讯定位请求对象
        TencentLocationRequest request = TencentLocationRequest.create();
        request.setInterval(30000).setAllowGPS(true);
        request.setRequestLevel(TencentLocationRequest.REQUEST_LEVEL_ADMIN_AREA);
        mLocationManager.requestLocationUpdates(request, this); // 开始定位监听
    }

    // 跳到个人信息填写页面
    private void gotoNext() {
        if (mMyPos == null) {
            Toast.makeText(this, "请先选择您的常住地点", Toast.LENGTH_SHORT).show();
            return;
        }
        Intent intent = new Intent(this, InfoEditActivity.class);
        intent.putExtra("latitude", mMyPos.latitude);
        intent.putExtra("longitude", mMyPos.longitude);
        intent.putExtra("address", mAddress);
        startActivity(intent);
    }

    @Override
    public void onLocationChanged(TencentLocation location, int resultCode, String resultDesc) {
        if (resultCode == TencentLocation.ERROR_OK) { // 定位成功
            if (location != null && isFirstLoc) { // 首次定位
                isFirstLoc = false;
                // 创建一个经纬度对象
                LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
                moveLocation(latLng, location.getAddress()); // 将地图移动到当前位置
            }
        } else { // 定位失败
            Log.d(TAG, "定位失败,错误代码为"+resultCode+",错误描述为"+resultDesc);
        }
    }

    @Override
    public void onStatusUpdate(String s, int i, String s1) {}

    // 将地图移动到当前位置
    private void moveLocation(LatLng latLng, String address) {
        mMyPos = latLng;
        mAddress = address;
        CameraUpdate update = CameraUpdateFactory.newLatLngZoom(latLng, mZoom);
        mTencentMap.moveCamera(update); // 把相机视角移动到指定地点
        // 从指定视图中获取位图描述
        BitmapDescriptor bitmapDesc = BitmapDescriptorFactory
                .fromView(getMarkerView(mAddress));
        MarkerOptions marker = new MarkerOptions(latLng).draggable(true) // 可以拖动
                .visible(true).icon(bitmapDesc).snippet("这是您的当前位置");
        mTencentMap.addMarker(marker); // 往地图添加标记
    }

    // 获取标记视图
    private View getMarkerView(String address) {
        View view = getLayoutInflater().inflate(R.layout.marker_me, null);
        TextView tv_address = view.findViewById(R.id.tv_address);
        tv_address.setText(address);
        return view;
    }

    @Override
    public void onMapClick(LatLng latLng) {
        mTencentMap.clearAllOverlays(); // 清除所有覆盖物
        mMyPos = latLng;
        // 创建一个腾讯搜索对象
        TencentSearch tencentSearch = new TencentSearch(this);
        Geo2AddressParam param = new Geo2AddressParam(mMyPos);
        // 根据经纬度查询地图上的详细地址
        tencentSearch.geo2address(param, new HttpResponseListener() {
            @Override
            public void onSuccess(int i, Object o) {
                Geo2AddressResultObject result = (Geo2AddressResultObject) o;
                String address = String.format("%s(%s)",
                        result.result.address, result.result.formatted_addresses.recommend);
                moveLocation(mMyPos, address); // 将地图移动到当前位置
            }

            @Override
            public void onFailure(int i, String s, Throwable throwable) {
                Log.d(TAG, "geo2address onFailure code="+i+", msg="+s);
            }
        });
    }

    @Override
    public void onMarkerDragStart(Marker marker) {}

    @Override
    public void onMarkerDrag(Marker marker) {}

    @Override
    public void onMarkerDragEnd(Marker marker) {
        onMapClick(marker.getPosition()); // 触发该位置的地图点击事件
    }

    @Override
    public void onCameraChange(CameraPosition cameraPosition) {}

    @Override
    public void onCameraChangeFinished(CameraPosition cameraPosition) {
        mZoom = cameraPosition.zoom;
    }

    @Override
    protected void onStart() {
        super.onStart();
        mMapView.onStart();
    }

    @Override
    protected void onStop() {
        super.onStop();
        mMapView.onStop();
    }

    @Override
    public void onPause() {
        super.onPause();
        mMapView.onPause();
    }

    @Override
    public void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLocationManager.removeUpdates(this); // 移除定位监听
        mMapView.onDestroy();
    }
}

编辑自身页面的代码

package com.example.location;

import androidx.appcompat.app.AppCompatActivity;

import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.example.location.bean.JoinResponse;
import com.example.location.constant.UrlConstant;
import com.example.location.util.BitmapUtil;
import com.example.location.util.DateUtil;
import com.example.location.util.SharedUtil;
import com.google.gson.Gson;

import java.io.File;
import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class InfoEditActivity extends AppCompatActivity {
    private final static String TAG = "InfoEditActivity";
    private int CHOOSE_CODE = 3; // 只在相册挑选图片的请求码
    private EditText et_name, et_phone, et_info; // 姓名、手机号、个人信息的编辑框
    private TextView tv_location; // 声明一个文本视图对象
    private ImageView iv_face; // 声明一个图像视图对象
    public boolean isMale = true; // 是否男性
    public int mLoveType=0; // 爱好类型
    public double mLatitude, mLongitude; // 经纬度
    public String mAddress; // 详细地址
    public Bitmap mOriginFace; // 原始的头像位图
    private ProgressDialog mDialog; // 声明一个对话框对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_info_edit);
        et_name = findViewById(R.id.et_name);
        RadioGroup rg_sex = findViewById(R.id.rg_sex);
        rg_sex.setOnCheckedChangeListener((group, checkedId) -> isMale = checkedId == R.id.rb_male);
        et_phone = findViewById(R.id.et_phone);
        tv_location = findViewById(R.id.tv_location);
        iv_face = findViewById(R.id.iv_face);
        et_info = findViewById(R.id.et_info);
        iv_face.setOnClickListener(v -> {
            // 创建一个内容获取动作的意图(准备跳到系统相册)
            Intent albumIntent = new Intent(Intent.ACTION_GET_CONTENT);
            albumIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false); // 是否允许多选
            albumIntent.setType("image/*"); // 类型为图像
            startActivityForResult(albumIntent, CHOOSE_CODE); // 打开系统相册
        });
        findViewById(R.id.btn_confirm).setOnClickListener(v -> saveInfo());
        initIntentData(); // 初始化意图数据
        initLoveSpinner(); // 初始化爱好类型下拉框
    }

    // 初始化意图数据
    private void initIntentData() {
        Bundle bundle = getIntent().getExtras();
        mLatitude = bundle.getDouble("latitude");
        mLongitude = bundle.getDouble("longitude");
        mAddress = bundle.getString("address");
        tv_location.setText(mAddress);
    }

    // 初始化爱好类型下拉框
    private void initLoveSpinner() {
        Spinner sp_love = findViewById(R.id.sp_love);
        ArrayAdapter<String> love_adapter = new ArrayAdapter<>(this,
                R.layout.item_select, loveArray);
        sp_love.setPrompt("请选择兴趣爱好");
        sp_love.setAdapter(love_adapter);
        sp_love.setOnItemSelectedListener(new LoveSelectedListener());
        sp_love.setSelection(0);
    }

    private String[] loveArray = {"唱歌", "跳舞", "绘画", "弹琴", "摄影", "出售闲置物品"};
    class LoveSelectedListener implements AdapterView.OnItemSelectedListener {
        public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
            mLoveType = arg2;
        }

        public void onNothingSelected(AdapterView<?> arg0) {}
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        if (resultCode == RESULT_OK && requestCode == CHOOSE_CODE) { // 从相册返回
            if (intent.getData() != null) { // 从相册选择一张照片
                Uri uri = intent.getData(); // 获得已选择照片的路径对象
                // 根据指定图片的uri,获得自动缩小后的位图对象
                mOriginFace = BitmapUtil.getAutoZoomImage(this, uri, 500);
                iv_face.setImageBitmap(mOriginFace); // 设置图像视图的位图对象
            }
        }
    }

    // 保存个人信息
    private void saveInfo() {
        String name = et_name.getText().toString();
        String phone = et_phone.getText().toString();
        String info = et_info.getText().toString();
        if (TextUtils.isEmpty(name)) {
            Toast.makeText(this, "请先输入您的昵称", Toast.LENGTH_SHORT).show();
            return;
        }
        if (TextUtils.isEmpty(phone)) {
            Toast.makeText(this, "请先输入您的手机号码", Toast.LENGTH_SHORT).show();
            return;
        }
        if (TextUtils.isEmpty(info)) {
            Toast.makeText(this, "请先输入要发布的信息", Toast.LENGTH_SHORT).show();
            return;
        }
        if (mOriginFace == null) {
            Toast.makeText(this, "请先选择您的头像", Toast.LENGTH_SHORT).show();
            return;
        }
        int minScope = Math.min(mOriginFace.getWidth(), mOriginFace.getHeight());
        // 从原始位图裁剪出一个正方形位图
        Bitmap cropFace = Bitmap.createBitmap(mOriginFace, 0, 0, minScope, minScope);
        String path = String.format("%s/%s.jpg",
                getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(),
                DateUtil.getNowDateTime());
        BitmapUtil.saveImage(path, cropFace); // 把位图保存为图片文件
        // 弹出进度对话框
        mDialog = ProgressDialog.show(this, "请稍候", "正在保存位置信息......");
        // 下面把用户信息(包含头像)提交给HTTP服务端
        MultipartBody.Builder builder = new MultipartBody.Builder();
        // 往建造器对象添加文本格式的分段数据
        builder.addFormDataPart("name", name); // 昵称
        builder.addFormDataPart("sex", isMale?"0":"1"); // 性别
        builder.addFormDataPart("phone", phone); // 手机号
        builder.addFormDataPart("love", loveArray[mLoveType]); // 爱好
        builder.addFormDataPart("info", info); // 发布信息
        builder.addFormDataPart("address", mAddress); // 地址
        builder.addFormDataPart("latitude", mLatitude+""); // 纬度
        builder.addFormDataPart("longitude", mLongitude+""); // 经度
        // 往建造器对象添加图像格式的分段数据
        builder.addFormDataPart("image", path.substring(path.lastIndexOf("/")),
                RequestBody.create(new File(path), MediaType.parse("image/*")));
        RequestBody body = builder.build(); // 根据建造器生成请求结构
        OkHttpClient client = new OkHttpClient(); // 创建一个okhttp客户端对象
        // 创建一个POST方式的请求结构
        Request request = new Request.Builder().post(body)
                .url(UrlConstant.HTTP_PREFIX+"joinNearby").build();
        Call call = client.newCall(request); // 根据请求结构创建调用对象
        // 加入HTTP请求队列。异步调用,并设置接口应答的回调方法
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) { // 请求失败
                // 回到主线程操纵界面
                runOnUiThread(() -> {
                    mDialog.dismiss(); // 关闭进度对话框
                    Toast.makeText(InfoEditActivity.this,
                            "保存位置信息出错:"+e.getMessage(), Toast.LENGTH_SHORT).show();
                });
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException { // 请求成功
                String resp = response.body().string();
                JoinResponse joinResponse = new Gson().fromJson(resp, JoinResponse.class);
                // 回到主线程操纵界面
                runOnUiThread(() -> {
                    mDialog.dismiss(); // 关闭进度对话框
                    if ("0".equals(joinResponse.getCode())) {
                        finishSave(); // 结束信息保存动作
                    } else {
                        Toast.makeText(InfoEditActivity.this, "保存位置信息失败:"+joinResponse.getDesc(), Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }

    // 结束信息保存动作
    private void finishSave() {
        Toast.makeText(this, "成功保存您的位置信息", Toast.LENGTH_SHORT).show();
        SharedUtil.getIntance(this).writeString("commitMyInfo", "true");
        Intent intent = new Intent(this, NearbyActivity.class);
        // 设置启动标志:跳转到新页面时,栈中的原有实例都被清空,同时开辟新任务的活动栈
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

}

创作不易 觉得有帮助请点赞关注收藏~~~ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/52478.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【react-笔记】

目录简介基本使用虚拟dom的两种创建方法jsx语法规则模块与组件、模块化和组件化的理解模块组件模块化组件化函数式组件类式组件组件实例三大属性statepropsrefs事件处理包含表单的组件分类非受控组件受控组件高阶函数_函数的柯里化生命周期引出生命周期理解生命周期(旧)总结新的…

Verilog 延迟反标注

延迟反标注&#xff0c; SDF 延迟反标注是设计者根据单元库工艺、门级网表、版图中的电容电阻等信息&#xff0c;借助数字设计工具将延迟信息标注到门级网表中的过程。利用延迟反标注后的网表&#xff0c;就可以进行精确的时序仿真&#xff0c;使仿真更接近实际工作的数字电路…

当MySQL想恋爱,java和navicate抢着做媒婆 ------ java连接MySQL数据库 navicat for MySQL 连接

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 **收录于专栏 数据库 ⭐当MySQL和java通过媒婆navicate谈上了恋爱⭐ 文章目录⭐当MySQL和java通过媒婆navicate谈上了恋爱…

Linux 多线程

目录 一.线程概念 1.什么是线程 2.页表 &#xff08;1&#xff09;页表结构 &#xff08;2&#xff09;好处 3.线程优点 4.线程缺点 5.线程异常 6.线程用途 7.进程和线程的 8.简单使用线程 二.线程控制 1.使用线程 2.线程栈和pthread_t 3.线程的局部存储 4.分离…

[附源码]计算机毕业设计springboot室内设计类网站

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

R语言中的划分聚类模型

划分聚类 是用于基于数据集的相似性将数据集分类为多个组的聚类方法。我们围绕聚类技术进行一些咨询&#xff0c;帮助客户解决独特的业务问题。 【视频】KMEANS均值聚类和层次聚类&#xff1a;R语言分析生活幸福质量系数可视化实例 KMEANS均值聚类和层次聚类&#xff1a;R语言分…

GUI自动化测试工具Sikulix的安装和使用

从程序内部控制对小白来说太难了&#xff0c;所以使用一下自动化测试的工具直接控制按钮达到我的目的 一个比较好的自动化测试工具是Sikulix&#xff0c;这里记录一下安装和基本的使用 下载和安装 官网&#xff1a;http://www.sikulix.com/ 下载对应系统的.jar需要使用java&…

第二证券|A股集体收涨,汽车产业链爆发!房地产延续强势

11月30日早盘&#xff0c;A股三大指数小幅上行。到午间收盘&#xff0c;沪指涨0.21%报3156.50点&#xff0c;深成指涨0.38%&#xff0c;创业板指涨0.20%&#xff1b;两市算计成交5692亿元。 盘面上看&#xff0c;轿车、燃气、地产、油气、煤炭等板块走强&#xff0c;酒店餐饮、…

实验室信息化建设的意义

实验室信息管理系统将实验室的仪器设备、实验人员、实验环境以及相关数据进行集成和管理&#xff0c;使整个实验室形成一个有机整体&#xff0c;规范了业务流程和管理体制&#xff0c;实现各部门之间资源共享协同作业&#xff0c;达到优化配置资源和提高工作效率&#xff0c;不…

欧洲肿瘤生物学博士后申请经历

国外博士后的申请者经常会遇到各种问题&#xff0c;从而感叹申请过程的不易。知识人网小编推荐这篇申请经历&#xff0c;或许会给其他申请者带来一定启示。 作者从今年1月开始申请&#xff0c;5月份获得offer。以下是原文&#xff1a; 背景介绍&#xff1a;国内双非一本生物工…

云开发静态网站H5跳转小程序(记录过程)以及云环境共享(同一主体)

需求&#xff1a;老板要求是在H5网页端&#xff0c;无论是在微信浏览器还是在微信外部浏览器都可以打开这个H5之后&#xff0c;然后跳转到小程序上。 查看了微信相关的文档&#xff0c;发现H5端跳转小程序是有两种方式&#xff1a; 一&#xff1a;微信内网页跳转小程序 官方文档…

【春秋云境】CVE-2022-24124复现

一直不明白updatexml到底要怎么注入 &fieldupdatexml(0,concat(0x7e,(version()),0x7e),0) 确实可以出来版本号 但是如果换成database()还是不行 最后还是靠了大佬 http://eci-2ze625l338u3rfrh3r36.cloudeci1.ichunqiu.com:8000/api/get-organizations?p123&page…

只要让我戴上面具 , 我就会马上逃跑 ! 等下眼镜卡住了

郑重声明 : 本文不包含任何广告 , 不构成任何购买建议 , 我也强烈不建议购买本文这款产品 , 所有图片来自我手机拍照 , 如有侵权 , 通知我 , 马上删除 写在前面 相信各位同学一定都经历过火灾安全知识培训吧 而且肯定有一部分人是那种充当表演对象的上手使用过灭火器的人 除了…

STM32实战总结:HAL之SDIO

在介绍SDIO接口之前先了解一下MMC、SD卡、SD标准等背景知识。 MMC(Multi Media Card)&#xff1a;即多媒体卡&#xff0c;它是一种非易失性存储器件&#xff0c;体积小巧&#xff0c;容量大&#xff0c;耗电量低&#xff0c;传输速度快&#xff0c;主要应用于消费类电子产品中&…

D. Social Network(并查集修改连通块数量)

Problem - D - Codeforces 威廉来到了一个专门讨论加密货币的会议。要想了解加密货币世界的最新消息&#xff0c;建立联系、认识新朋友、利用朋友的关系是必不可少的。 会议有N个参与者&#xff0c;他们最初都不熟悉对方。威廉可以把之前不熟悉的任何两个人a和b介绍给对方。 …

spi驱动数码管

spi是串行全双工同步通信&#xff0c;支持多从机模式&#xff0c;没有应答机制&#xff0c;可靠性方面存在劣势&#xff1b; 采用边沿采样&#xff0c;根据时钟极性和时钟相位&#xff0c;有四种数据传输方式&#xff08;由时钟变化(极性&#xff0c;相位)决定&#xff1b; 因…

Java Tomcat内存马——Listener内存马

目录 &#xff08;一&#xff09;前置知识 0x01 什么是Listener 0x02 Listener的简单案例 0x03 Listener流程分析 &#xff08;二&#xff09;注入分析 (三&#xff09;实现内存马 得到完整的内存马 (四&#xff09;漏洞复现 其他的payload: 总结 &#xff08;一&#…

Observability:从零开始创建 Java 微服务并监控它 (二)

这篇文章是继上一篇文章 “Observability&#xff1a;从零开始创建 Java 微服务并监控它 &#xff08;一&#xff09;” 的续篇。在上一篇文章中&#xff0c;我们讲述了如何创建一个 Java web 应用&#xff0c;并使用 Filebeat 来收集应用所生成的日志。在今天的文章中&#xf…

机器学习3判断机器算法的性能

文章目录一、判断机器算法的性能1基本使用1.目的2.使用pycharm函数封装3.sklearn中的train test split&#xff1a;4.完美调用&#xff1a;二、判断机器算法的性能2分类的准确度&#xff08;accuracy&#xff09;准确度初步计算&#xff1a;完善KNNpy程序如下&#xff1a;一、判…

[附源码]Python计算机毕业设计Django高校社团管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…