【Andoird开发】android获取蓝牙权限,beacon,android-beacon-library

iBeacon 最先是苹果的技术,使用android-beacon-library包可以在android上开发iBeacon 技术。

iBeacon的发明意义重大。它是一种基于蓝牙低功耗(Bluetooth Low Energy, BLE)技术的定位系统,通过向周围发送信号来标识其位置。这项技术的意义体现在以下几个方面:

  1. 室内定位与导航: iBeacon可用于在室内环境中提供定位和导航服务。传统的GPS技术在室内环境下往往效果不佳,而iBeacon通过布置在建筑物内部的信标,可以实现更精准的室内定位。

  2. 增强零售体验: 零售业是iBeacon应用的一个重要领域。商店可以利用iBeacon技术向顾客发送特定的优惠信息、促销活动或产品推荐,从而提升顾客体验并促进销售。

  3. 实时定位服务: iBeacon可以实现对移动设备的实时追踪,为企业和组织提供更有效的资产管理、人员定位和安全监控等服务。

  4. 交互式体验: 利用iBeacon技术,可以为用户提供更加个性化和交互式的体验。比如,在博物馆、展览或游乐园等场所,可以通过iBeacon向游客提供相关的解说信息或互动体验。

  5. 开发者创新: iBeacon开放的开发平台为开发者提供了广阔的创新空间,他们可以基于iBeacon技术开发各种各样的应用,从而为用户带来更丰富的体验和功能。

iBeacon的发明为室内定位和个性化服务领域带来了革命性的变革,极大地丰富了移动应用的功能和体验。

先加这句:implementation group: ‘org.altbeacon’, name: ‘android-beacon-library’, version: ‘2.20.6’
在这里插入图片描述
然后sync之后就能使用,xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">


    <!-- Android 12以下才需要定位权限, Android 9以下官方建议申请ACCESS_COARSE_LOCATION -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <!-- Android 12在不申请定位权限时,必须加上android:usesPermissionFlags="neverForLocation",否则搜不到设备 -->
    <uses-permission
        android:name="android.permission.BLUETOOTH_SCAN"
        android:usesPermissionFlags="neverForLocation"
        tools:targetApi="s" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />


    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

主java【搜不到我想要的设备,没有android自带的搜设备兼容性好,或许我用错了,但可以搜到设备!】:

package com.example.myapplication;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.material.bottomnavigation.BottomNavigationView;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.MonitorNotifier;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;


public class MainActivity extends AppCompatActivity {
    private static final int PERMISSION_REQUEST_CODE = 100;
    private static final long SCAN_PERIOD = 10000;

    private static final String TAG = "TimeAttendantFast";

    private BluetoothLeScanner mLEScanner;
    private BluetoothManager btManager;
    private BluetoothAdapter btAdapter;
    private Handler scanHandler;
    private Handler mHandler;
    private Button checkInBtn;
    private TextView tvEmpID;

    private boolean isShowDialog;

    private ScanSettings settings;
    private ArrayList<ScanFilter> filters;
    private String employeeID;

    private List<String> beaconDeviceList = new ArrayList<>();

    private static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
    private static final int REQUEST_CHECK_SETTINGS = 14;


    private static final String TAGx = "BluetoothSearch";
    private BluetoothAdapter bluetoothAdapter;
    private BroadcastReceiver bluetoothReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 请求权限
        requestPermissions();

        settingBlueTooth();
        scanLeDevice(true);


        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 停止蓝牙设备搜索并注销广播接收器
        if (bluetoothAdapter != null) {
            if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            bluetoothAdapter.cancelDiscovery();
        }
        unregisterReceiver(bluetoothReceiver);
    }

    private void settingBlueTooth() {
        // init BLE
        btManager = (BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE);
        btAdapter = btManager.getAdapter();

        if (Build.VERSION.SDK_INT >= 21) {
            mLEScanner = btAdapter.getBluetoothLeScanner();
            settings = new ScanSettings.Builder()
                    .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                    .build();
            filters = new ArrayList<>();
        }
    }

    /**
     * bytesToHex method
     */
    static final char[] hexArray = "0123456789ABCDEF".toCharArray();

    private static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }


    private void foundBeacon(String uuid, int major, int minor) {
        //LOG
        Log.i(TAG, "UUID: " + uuid + "\\nmajor: " + major + "\\nminor" + minor);
    }


    private void findBeaconPattern(byte[] scanRecord) {
        int startByte = 2;
        boolean patternFound = false;
        while (startByte <= 5) {
            if (((int) scanRecord[startByte + 2] & 0xff) == 0x02 && //Identifies an iBeacon
                    ((int) scanRecord[startByte + 3] & 0xff) == 0x15) { //Identifies correct data length
                patternFound = true;
                break;
            }
            startByte++;
        }
        if (patternFound) {
            //Convert to hex String
            byte[] uuidBytes = new byte[16];
            System.arraycopy(scanRecord, startByte + 4, uuidBytes, 0, 16);
            String hexString = bytesToHex(uuidBytes);

            //UUID detection
            String uuid = hexString.substring(0, 8) + "-" +
                    hexString.substring(8, 12) + "-" +
                    hexString.substring(12, 16) + "-" +
                    hexString.substring(16, 20) + "-" +
                    hexString.substring(20, 32);

            // major
            final int major = (scanRecord[startByte + 20] & 0xff) * 0x100 + (scanRecord[startByte + 21] & 0xff);

            // minor
            final int minor = (scanRecord[startByte + 22] & 0xff) * 0x100 + (scanRecord[startByte + 23] & 0xff);

            Log.i(TAG, "UUID: " + uuid + "\\nmajor: " + major + "\\nminor" + minor);
            foundBeacon(uuid, major, minor);
        }

    }

    private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            findBeaconPattern(scanRecord);
        }


    };

    private ScanCallback mScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            Log.i(TAG, "callbackType " + callbackType);
            // 获取ScanRecord对象
            ScanRecord scanRecord = result.getScanRecord();

            String MAC = result.getDevice().getAddress();

            // 如果字符是以A4开头的,就是我们的设备
            if (MAC.startsWith("A4")) {
                Log.i(TAG, "MAC: " + MAC);
            }

            // 尝试直接从ScanRecord中获取设备名称
            if (scanRecord != null) {
                String deviceName = scanRecord.getDeviceName();


                if (deviceName != null && !deviceName.isEmpty()) {
                    Log.i(TAG, "Device Name: " + deviceName);
                } else {
                    // 如果getDeviceName返回null,可能需要从scanRecord的bytes中手动解析(虽然不常见)
                    // 但大多数情况下,直接使用getDeviceName应该足够
                    byte[] scanRecordBytes = scanRecord.getBytes();
                    // 这里可以调用您自定义的方法findBeaconPattern来进一步解析数据,如果需要的话
                    findBeaconPattern(scanRecordBytes);
                    Log.i(TAG, "Device Name not directly available, parsing scan record...");
                }
            }

        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            for (ScanResult sr : results) {
                Log.i(TAG, "ScanResult - Results" + sr.toString());
            }
        }

        @Override
        public void onScanFailed(int errorCode) {
            Log.e(TAG, "Scan Failed Error Code: " + errorCode);
        }
    };


    private void scanLeDevice(final boolean enable) {

        Log.i(TAG, "BLE start scan");
        if (Build.VERSION.SDK_INT < 21) {
            Log.i(TAG, "start SDK_INT < 21");
            if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            btAdapter.startLeScan(leScanCallback);
        } else {
            Log.i(TAG, "start SDK_INT >= 21");
            mLEScanner.startScan(filters, settings, mScanCallback);
        }
    }


    private void requestPermissions() {

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
            if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_ADMIN) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
            ) {
                // 如果没有获取到权限,请求权限
                ActivityCompat.requestPermissions(this, new String[]{
                        android.Manifest.permission.BLUETOOTH,
                        android.Manifest.permission.BLUETOOTH_ADMIN,
                        android.Manifest.permission.ACCESS_FINE_LOCATION,
                        android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                }, PERMISSION_REQUEST_CODE);
            }


        } else {
            if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_ADVERTISE) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
            ) {
                // 如果没有获取到权限,请求权限
                ActivityCompat.requestPermissions(this, new String[]{
                        android.Manifest.permission.BLUETOOTH_SCAN,
                        android.Manifest.permission.BLUETOOTH_ADVERTISE,
                        android.Manifest.permission.BLUETOOTH_CONNECT,
                        android.Manifest.permission.ACCESS_FINE_LOCATION,
                        android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                }, PERMISSION_REQUEST_CODE);
            }

        }
        // 如果权限已经被授予,直接进行蓝牙功能检查和定位功能检查
        checkBluetoothSupport();

    }

    private void checkBluetoothSupport() {
        // 检查手机蓝牙是否打开
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {
            Toast.makeText(this, "本机不支持蓝牙功能, 无法蓝牙打卡", Toast.LENGTH_SHORT).show();
            finish();
        } else if (!bluetoothAdapter.isEnabled()) {
            Toast.makeText(this, "蓝牙未打开, 请先打开蓝牙", Toast.LENGTH_SHORT).show();
            finish();
        }

        // 检查定位是否打开
        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            Toast.makeText(this, "定位未打开, 请先打开定位", Toast.LENGTH_SHORT).show();
            finish();
        }

        // 检查是否联网network
        if (!locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
            Toast.makeText(this, "网络未打开, 请先打开网络", Toast.LENGTH_SHORT).show();
            finish();
        }


        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, "本机不支持蓝牙功能, 无法蓝牙打卡", Toast.LENGTH_SHORT).show();
            finish();
        } else {
            BluetoothManager bm = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            BluetoothAdapter bleAdapter = bm.getAdapter();
            if (bleAdapter == null || !bleAdapter.isEnabled()) {
                Toast.makeText(this, "本机不支持低功耗蓝牙功能, 无法蓝牙打卡", Toast.LENGTH_SHORT).show();
                finish();
            } else {
                Toast.makeText(this, "手机支持蓝牙定位打卡", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

这个代码就完全没反应搜不到了:

import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;

public class MainActivity extends AppCompatActivity implements BeaconConsumer {
    private BeaconManager beaconManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化 BeaconManager
        beaconManager = BeaconManager.getInstanceForApplication(this);
        beaconManager.bind(this);
    }

    @Override
    public void onBeaconServiceConnect() {
        // 监听 iBeacon 的信号
        beaconManager.addRangeNotifier(new RangeNotifier() {
            @Override
            public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
                if (beacons.size() > 0) {
                    for (Beacon beacon : beacons) {
                        String uuid = beacon.getId1().toString(); // 获取 iBeacon 的 UUID
                        Log.d("Beacon", "UUID: " + uuid);
                    }
                }
            }
        });

        try {
            // 开始监测所有的 iBeacon
            beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        beaconManager.unbind(this);
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker 容器间通讯

1、虚拟ip/访问 同一网络 安装docker时&#xff0c;docker会默认创建一个内部的桥接网络docker0&#xff0c;每创建一个容器分配一个虚拟网卡&#xff0c;容器之间(包括宿主机)可以根据分配的ip互相访问(ps:其他主机(包括其他主机的容器)无法ping通docker容器ip无法访问&#…

22个C语言小白常见问题总结

一.语言使用错误 在打代码的过程中&#xff0c;经常需要在中文与英文中进行转换&#xff0c;因此常出现一些符号一不小心就用错&#xff0c;用成中文。例如&#xff1a;“&#xff1b;”中文中的分号占用了两个字节&#xff0c;而英文中“;”分号只占用一个字节。编译器只能识…

mysql数据库主从复制,搭建从库

1 期望效果 假设我们现在有两个服务器&#xff0c;两个服务器都有数据库&#xff0c;然后我们命名一个叫主数据库&#xff08;Master&#xff09;&#xff0c;一个叫从数据库&#xff08;Slave&#xff09; 数据备份和容灾&#xff1a;通过主从复制&#xff0c;可以将主数据库…

计算机操作系统核心组件

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天给大家讲讲操作系统。 操作系统核心组件 用户借助于一个或多个应用程序与操作系统进行交互&#xff0c;常常是通过一个称为shell的特殊应用程序进行的&#xff0c;shell也叫作命令解释器。105今天的大多…

SQL——SELECT相关的题目

目录 197、上升的温度 577、员工奖金 586、订单最多的客户 596、超过5名学生的课 610、判断三角形 620、有趣的电影 181、超过经理收入的员工 1179、重新格式化部门表 1280、学生参加各科测试的次数 1068、产品销售分析I 1075、项目员工I 1084、销售分析III 1327、列出指…

Qt 报错总结 No suitable kits found

目录 “No suitable kits found” 解决 解决方法参考&#xff1a; chatGPT辅助解决QT构建报错error: multiple target patterns 我的解决方法&#xff1a;把语言设置为空 “No suitable kits found” 解决 没有找到合适的kits套件&#xff0c;在安装Qt Creator时没有安装Min…

程序员做推广?我劝你别干

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 这是卢松松会员专区&#xff0c;一位会员朋友的咨询&#xff0c;如果你也有自研产品&#xff0c;但不知道如何推广&#xff0c;一定要阅读本文!强烈建议收藏关注&#xff0c;因为你关注的人&#xff0c;决定你看到的…

Ubuntu切换内核版本

#安装内核安装工具 sudo apt-get install software-properties-common sudo add-apt-repository ppa:cappelikan/ppa sudo apt-get update sudo apt-get install mainline#安装指定内核版本(有些版本并不能安装成功) mainline install 5.14.10#更新GRUB配置 sudo update-grub#查…

Linux 软件包管理器 yum的下载、功能介绍及使用

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;青果大战linux 总有光环在陨落&#xff0c;总有新星在闪烁 Linux下的三种软件安装方…

burpsuite抓包响应报文乱码

1、响应报文中的中文信息乱码 2、解决办法 3、设置成功后重新发起请求

储油罐智控:ThingsBoard网关实现液位温度精准监测

储油罐是采油、炼油企业储存油品的重要设备&#xff0c;对储油罐液位、温度的实时数据监测对企业的库存和安全管理有着重大意义。 场景 对于企业&#xff0c;尤其是加油站来说&#xff0c;高效的罐体液位、温度监测对于优化燃油库存、防止短缺或过剩至关重要。不准确的燃油液位…

05Django项目--前端公共文件和其他html文件的适配

对应视频链接点击直达 Django项目--前端公共文件和其他html文件的适配 对应视频链接点击直达前端页面准备Pubilc页面设置 OVER&#xff0c;不会有人不会吧不会的加Q1394006513结语 接着上一节 前端页面准备 为了方便大家更好的复制&#xff0c;我把整个项目及templates文件夹和…

RabbitMQ(一)概述第一个应用程序

文章目录 概述AMQP和JMS官网安装开始第一个程序 概述 消息队列是实现应用程序和应用程序之间通信的中间件产品 AMQP和JMS 工作体系 官网 https://www.rabbitmq.com/ RabbitMQ是一款基于AMQP、由Erlang语言开发的消息队列产品 安装 # 拉取镜像 docker pull rabbitmq:3.13-m…

运营抖音小店,这件事情每天都需要去做!一个都不能少!

大家好&#xff0c;我是电商小V 咱们的店铺开好之后&#xff0c;然后运营自己的店铺每天需要做好什么事情呢&#xff1f;这个问题是很多新手小伙伴开通抖店之后最关心的问题&#xff0c;咱们今天就来详细的说一下运营抖音小店每天需要做什么呢&#xff1f; 第一点&#xff1a;奖…

commvault学习(8):备份与恢复sql server

1.安装sql server2008r2 安装sql server 2.在客户端添加cv代理mssql server 如果此前的cv代理中没有sql server&#xff0c;那么可以手动再补充 点击setup 添加MSSQL Server 将程序添加到windows防火墙排除表 勾选自动探寻实例 3.备份sql server 3.1配置数据库内容 右击默…

Python操作MySQL实战

文章导读 本文用于巩固Pymysql操作MySQL与MySQL操作的知识点&#xff0c;实现一个简易的音乐播放器&#xff0c;拟实现的功能包括&#xff1a;用户登录&#xff0c;窗口显示&#xff0c;加载本地音乐&#xff0c;加入和删除播放列表&#xff0c;播放音乐。 点击此处获取参考源…

three.js能实现啥效果?看过来,这里都是它的菜(08)

在Three.js中实现旋转动画的原理是通过修改对象的旋转属性来实现的&#xff0c;通常使用渲染循环&#xff08;render loop&#xff09;来更新对象的旋转状态&#xff0c;从而实现动画效果。 具体的原理包括以下几个步骤&#xff1a; 创建对象&#xff1a;首先创建一个需要旋转…

东软联合福建省大数据集团打造“数据要素×医疗健康”服务新模式

5月23日&#xff0c;东软集团与福建省大数据集团有限公司在福州签订战略合作协议。 据「TMT星球」了解&#xff0c;双方将在健康医疗数据要素价值领域展开合作&#xff0c;通过大数据服务&#xff0c;赋能商业保险公司的产品设计和保险两核&#xff0c;打造“数据要素医疗健康…

Superset二次开发之柱状图自定义初始化时Data Zoom数据缩放值

Superset项目柱状图来自Echarts 首先Echarts实现柱状图数据缩放初始化默认值的效果 核心代码 设置Datazoom 的start 和end myChart.showLoading(); $.get(ROOT_PATH + /data/asset/data/obama_budget_proposal_2012.list.json,function (obama_budget_2012) {myChart.hideLo…

工业4.0 企业级云MES全套源码,支持app、小程序、H5、台后管理端

工业4.0 企业级云MES全套源码&#xff0c;支持app、小程序、H5、台后管理端 采用javaspringboot-vue.jsuniapp开发 随着工业4.0的快速发展&#xff0c;制造执行系统&#xff08;MES&#xff09;成为了智能制造的核心。今天&#xff0c;将为大家介绍一款开源的MES系统——MES管…