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

【android 蓝牙开发——蓝牙耳机】

【android 蓝牙开发——传统蓝牙】

【android 蓝牙开发——BLE(低功耗)蓝牙 2021-10-09更新】

总结一下蓝牙开发的基本使用以及蓝牙耳机的断开和链接。

所以需权限:

  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- Android12 的蓝牙权限 如果您的应用与已配对的蓝牙设备通信或者获取当前手机蓝牙是否打开 --><uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- Android12 的蓝牙权限 如果您的应用查找蓝牙设备(如蓝牙低功耗 (BLE) 外围设备) --><uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <!-- Android12 的蓝牙权限 如果您的应用使当前设备可被其他蓝牙设备检测到 --><uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

注意这里需要位置权限。

开启权限:

 ActivityResultLauncher<Intent> bluetoothOpenLaunch;private void startBluetooth() {bluetoothOpenLaunch = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {@Overridepublic void onActivityResult(ActivityResult result) {System.out.println("MainActivity.onActivityResult" + result.getResultCode());if (Activity.RESULT_OK == result.getResultCode()) {getPermission();}}});Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {ArrayList<String> arrayListOf = new ArrayList<>();arrayListOf.add(Manifest.permission.BLUETOOTH_CONNECT);PermissionUtils.permission(String.valueOf(arrayListOf)).callback(new PermissionUtils.SimpleCallback() {@Overridepublic void onGranted() {System.out.println("MainActivity.onGranted");bluetoothOpenLaunch.launch(intent);}@Overridepublic void onDenied() {System.out.println("MainActivity.onDenied");ToastUtils.showLong("请开启蓝牙权限");}}).request();} else {bluetoothOpenLaunch.launch(intent);}}private void getPermission() {ArrayList<String> arrayListOf = new ArrayList<>();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {arrayListOf.add(Manifest.permission.BLUETOOTH_SCAN);arrayListOf.add(Manifest.permission.BLUETOOTH_CONNECT);arrayListOf.add(Manifest.permission.BLUETOOTH_ADVERTISE);}arrayListOf.add(Manifest.permission.BLUETOOTH);arrayListOf.add(Manifest.permission.BLUETOOTH_ADMIN);arrayListOf.add(Manifest.permission.ACCESS_FINE_LOCATION);arrayListOf.add(Manifest.permission.ACCESS_COARSE_LOCATION);PermissionUtils.permission(String.valueOf(arrayListOf)).callback(new PermissionUtils.SimpleCallback() {@Overridepublic void onGranted() {ToastUtils.showLong("蓝牙相关权限已成功授权");BluetoothManager blueManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);//mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()mBluetoothAdapter = blueManager.getAdapter();}@Overridepublic void onDenied() {ToastUtils.showLong("请开启蓝牙权限");}}).request();}

监听蓝牙连接配对等相关广播,建议直接采用以下方式:(也有其他方法,搜索低功耗蓝牙的方式 startLeScan )

 //注册BoradcasrReceiverprivate void registerReceiver() {IntentFilter discoveryFilter = new IntentFilter();discoveryFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);discoveryFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);discoveryFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);discoveryFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);discoveryFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);discoveryFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);discoveryFilter.addAction(BluetoothDevice.ACTION_FOUND);registerReceiver(discoveryReceiver, discoveryFilter);}//蓝牙搜索广播的接收器@SuppressLint("MissingPermission")private BroadcastReceiver discoveryReceiver = new BroadcastReceiver() {String pin = "0000";  //此处为你要连接的蓝牙设备的初始密钥,一般为 1234 或 0000@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);  //获取设备,发现远程蓝牙设备if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {Log.i(TAG, "onReceive: 开始搜索");} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {Log.i(TAG, "onReceive:  搜索结束");} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {// //获取扫描到的设备String name = bluetoothDevice.getName();String address = bluetoothDevice.getAddress();Log.i(TAG, "onReceive: name=" + name + " address=" + address);/*if (bluetoothDevice.getBondState() == BluetoothDevice.BOND_BONDED) {Log.i(TAG, "已配对 onReceive: name=" + name + " address=" + address);} else {}*///已经配对boolean isExist = false;for (DeviceBean device : bluetoothDevices) {if (device.getAddress().equals(address)) {isExist = true;}}if (!isExist) {bluetoothDevices.add(new DeviceBean(name, address));mAdapter.notifyDataSetChanged();}} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {//Log.i(TAG, "onReceive:  绑定状态改变");int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);Log.i(TAG, "onReceive:  绑定状态改变 state=" + state);if (state == 12) {Log.i(TAG, "onReceive:  绑定成功 ");ToastUtils.showLong("绑定成功");String name = bluetoothDevice.getName();String address = bluetoothDevice.getAddress();boolean isExist = false;for (DeviceBean device : pairedDevices) {if (device.getAddress().equals(address)) {isExist = true;}}if (!isExist) {/*for (DeviceBean device : pairedDevices) {device.setStatus(false);}*/DeviceBean deviceBean = new DeviceBean(name, address);deviceBean.setStatus(true);pairedDevices.add(0, deviceBean);mDevicePairedAdapter.notifyDataSetChanged();} else {for (DeviceBean device : pairedDevices) {if (device.getAddress().equals(address)) {device.setStatus(true);mDevicePairedAdapter.notifyDataSetChanged();break;}}}}} else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {//Log.i(TAG, "onReceive:  连接状态改变");int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, BluetoothAdapter.ERROR);String name = bluetoothDevice.getName();String address = bluetoothDevice.getAddress();Log.i(TAG, "onReceive:  连接状态改变 state=" + state);switch (state) {case 0://断开成功for (DeviceBean device : pairedDevices) {if (device.getAddress().equals(address)) {device.setStatus(false);mDevicePairedAdapter.notifyDataSetChanged();break;}}break;//case 1: break;case 2://连接成功Log.i(TAG, "onReceive:  连接成功 address=" + address);ToastUtils.showLong("连接成功");for (DeviceBean device : pairedDevices) {if (device.getAddress().equals(address)) {device.setStatus(true);mDevicePairedAdapter.notifyDataSetChanged();break;}}break;default:break;}} else if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {Log.i(TAG, "onReceive:  配对");try {// bluetoothDevice.setPairingConfirmation(true);// abortBroadcast();// bluetoothDevice.setPin(pin.getBytes());//1:/*  ClsUtils.setPairingConfirmation(bluetoothDevice.getClass(),bluetoothDevice,true);//2:如果没有将广播终止,则会出现一个一闪而过的配对框。abortBroadcast();//3.调用setPin方法进行配对..boolean ret = ClsUtils.setPin(bluetoothDevice.getClass(), bluetoothDevice, pin);System.out.println("ConnectingDevicesActivity.onReceive ret="+ret);*/} catch (Exception e) {throw new RuntimeException(e);}} else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {Log.i(TAG, "onReceive:   蓝牙开关状态改变");int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);switch (state) {case BluetoothAdapter.STATE_OFF:break;case BluetoothAdapter.STATE_ON:break;}} else {Log.i(TAG, "onReceive:   else action=" + action);}}};

我们也可以获取已配对蓝牙列表:

private void initData() {Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();if (bondedDevices != null && bondedDevices.size() > 0) {for (BluetoothDevice bondedDevice : bondedDevices) {System.out.println("ConnectingDevicesActivity.initData name==" + bondedDevice.getName());DeviceBean deviceBean = new DeviceBean(bondedDevice.getName(), bondedDevice.getAddress());pairedDevices.add(deviceBean);}mDevicePairedAdapter.notifyDataSetChanged();}}

蓝牙耳机断开和连接的具体方法:

  public boolean isDisconnected = false;/*** 断开蓝牙设备连接** @param bluetoothDevice BluetoothDevice*/public void disconnect(BluetoothDevice bluetoothDevice) {currentBluetoothDevice = bluetoothDevice;//获取A2DP代理对象mBluetoothAdapter.getProfileProxy(this, disconnectProfileServiceListener, BluetoothProfile.HEADSET);//获取HEADSET代理对象mBluetoothAdapter.getProfileProxy(this, disconnectProfileServiceListener, BluetoothProfile.A2DP);}private final BluetoothProfile.ServiceListener disconnectProfileServiceListener = new BluetoothProfile.ServiceListener() {@Overridepublic void onServiceDisconnected(int profile) {System.out.println("ConnectingDevicesActivity.onServiceDisconnected profile="+profile);}@Overridepublic void onServiceConnected(int profile, BluetoothProfile proxy) {try {if (profile == BluetoothProfile.HEADSET) {//使用HEADSET的协议断开蓝牙设备(使用了反射技术调用断开的方法)BluetoothHeadset bluetoothHeadset = (BluetoothHeadset) proxy;boolean isDisConnect = false;try {Method connect = null;if (isDisconnected) {connect = bluetoothHeadset.getClass().getDeclaredMethod("disconnect", BluetoothDevice.class); //disconnect connect} else {connect = bluetoothHeadset.getClass().getDeclaredMethod("connect", BluetoothDevice.class); //disconnect connect}connect.setAccessible(true);isDisConnect = (boolean) connect.invoke(bluetoothHeadset, currentBluetoothDevice);if (isDisconnected) {Log.d(TAG, "isDisConnect:" + (isDisConnect ? "断开通话成功" : "断开通话失败") + currentBluetoothDevice.getName());} else {Log.d(TAG, "isDisConnect:" + (isDisConnect ? "链接通话成功" : "链接通话失败") + currentBluetoothDevice.getName());}} catch (Exception e) {e.printStackTrace();}}if (profile == BluetoothProfile.A2DP) {//使用A2DP的协议断开蓝牙设备(使用了反射技术调用断开的方法)BluetoothA2dp bluetoothA2dp = (BluetoothA2dp) proxy;boolean isDisConnect = false;try {Method connect = null;if (isDisconnected) {connect = bluetoothA2dp.getClass().getDeclaredMethod("disconnect", BluetoothDevice.class);} else {connect = bluetoothA2dp.getClass().getDeclaredMethod("connect", BluetoothDevice.class);}connect.setAccessible(true);isDisConnect = (boolean) connect.invoke(bluetoothA2dp, currentBluetoothDevice);if (isDisconnected) {Log.d(TAG, "isDisConnect:" + (isDisConnect ? "断开音频成功" : "断开音频失败") + currentBluetoothDevice.getName());} else {Log.d(TAG, "isDisConnect:" + (isDisConnect ? "链接音频成功" : "链接音频失败") + currentBluetoothDevice.getName());}} catch (Exception e) {e.printStackTrace();}if (isDisConnect) {for (DeviceBean device : pairedDevices) {if (device.getAddress().equals(currentBluetoothDevice.getAddress())) {device.setStatus(!isDisconnected);mDevicePairedAdapter.notifyDataSetChanged();break;}}}}} catch (Exception e) {e.printStackTrace();}}};

源码

相关文章:

【android 蓝牙开发——蓝牙耳机】

【android 蓝牙开发——传统蓝牙】 【android 蓝牙开发——BLE&#xff08;低功耗&#xff09;蓝牙 2021-10-09更新】 总结一下蓝牙开发的基本使用以及蓝牙耳机的断开和链接。 所以需权限&#xff1a; <uses-permission android:name"android.permission.ACCESS_FIN…...

Golang goroutine 进程、线程、并发、并行

goroutine 看一个需求 需求&#xff1a;要求统计1-200000000000的数字中&#xff0c;哪些是素数? 分析思路&#xff1a; 1)传统的方法&#xff0c;就是使用一个循环&#xff0c;循环的判断各个数是不是素数&#xff08;一个任务就分配给一个cpu去做&#xff0c;这样很不划算…...

如何做到安全上网

随着信息化的发展&#xff0c;企业日常办公越来越依赖互联网&#xff0c;而访问互联网过程中&#xff0c;会遇到各种各样不容忽视的风险&#xff0c;例如员工主动故意的数据泄漏&#xff0c;后台应用程序偷偷向外部发信息&#xff0c;木马间谍软件的外联&#xff0c;以及各种挖…...

优维低代码实践:菜单

优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。 优维…...

git merge 如何撤销

如果只是 git merge 未进行其他 git 操作&#xff0c;可以使用 git merge --abort 撤销如果 git merge 之后&#xff0c;再 git add&#xff0c;可以使用 git reset HEAD 或 git reset HEAD file (前者多个文件&#xff0c;后者单个文件)如果 git merge 之后&#xff0c;再 git…...

解读package.json 中的功能

使用 npm init 比较全 一步一步的走,用于完成 package.json 中的各个声明 npm init -y 生成简易的模板下面解读下 package.json 中的功能"version": "1.0.0", //版本号1. 主版本号&#xff1a;非常大的改动 vue2 和 vue3 的改变 2. 功能的升级&#xff0c;…...

UMA 2 - Unity Multipurpose Avatar☀️四.UMA人物部位的默认颜色和自定义(共享)颜色

文章目录 🟥 人物颜色介绍1️⃣ 使用默认颜色2️⃣ 使用自定义颜色🟧 UMA自定义颜色的作用🟨 自定义颜色还可作为共享颜色🟥 人物颜色介绍 UMA不同部位的颜色分为默认的内置颜色和我们新定义的颜色. 1️⃣ 使用默认颜色 比如不勾选UseSharedColor时,使用的眼睛的默认…...

phpstorm配置php运行环境

1&#xff0c;首先安装phpstrom&#xff0c;按照提示的步骤一步一步来就行 2&#xff0c;新建一个项目然后在里面找到这个位置 3&#xff0c;找到php所在的位置&#xff0c;找不到就直接在搜索框中搜索 4&#xff0c;这里要配置php的运行环境&#xff0c;一定要记得自己安装软…...

算法训练营day49|动态规划 part10:(LeetCode 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II)

121. 买卖股票的最佳时机 题目链接&#x1f525; 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大…...

Swagger 使用教程

Swagger 官网&#xff1a; API Documentation & Design Tools for Teams | Swagger 整合swagger 依赖&#xff1a; springfox-swagger2 springfox-swagger-ui <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</a…...

单例模式-饿汉模式、懒汉模式

单例模式&#xff0c;是设计模式的一种。 在计算机这个圈子中&#xff0c;大佬们针对一些典型的场景&#xff0c;给出了一些典型的解决方案。 目录 单例模式 饿汉模式 懒汉模式 线程安全 单例模式 单例模式又可以理解为是单个实例&#xff08;对象&#xff09; 在有些场…...

UG\NX二次开发 复制3元素的double数组到另一个数组 UF_VEC3_copy

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 简介: UG\NX二次开发 复制3元素的double数组到另一个数组 UF_VEC3_copy。仔细看第二段代码 。 效果: 代码: #include "me.hpp"void ufusr(char* param, …...

骨传导耳机对人体有危险吗?会损害听力吗?

如果在使用骨传导耳机的时候控制好时间和音量&#xff0c;是不会对人体带来危险和造成伤害的。 下面跟大家解释一下为什么骨传导耳机对人体没有危害&#xff0c;最大的原因就是骨传导耳机不需要空气传导&#xff0c;而是通过颅骨传到听觉中枢&#xff0c;传输过程中几乎没有噪…...

Spring Boot @Value读不到Nacos配置中心的值。(properties配置文件)

读不到配置中心的值&#xff0c; 配置中心的配置文件名字&#xff08;Data ID的值&#xff09;要以.properties结尾。 如果是yaml&#xff0c;就以yaml命名。...

Rocky Linux怎么安装mysql

Rocky Linux怎么安装mysql 在Rocky Linux上安装MySQL可以通过以下步骤实现&#xff1a; 更新软件包列表 ⭐️⭐️⭐️必要的&#xff0c;必须更新&#xff0c;更新会顺利很多&#xff01;&#xff01;&#xff01;⭐️⭐️⭐️ 在安装MySQL之前&#xff0c;建议先更新软件包…...

轻量级软件FastGithub实现稳定访问github

当我们想访问全球最大的“同性交友网站”https://github.com/ 时&#xff0c;总会出现无法访问的界面&#xff0c;令人非常苦恼&#xff1a;幸运的是&#xff0c;有一种轻量级的软件可以帮助我们稳定地访问GitHub&#xff0c;那就是FastGithub。 什么是FastGithub&#xff1f…...

芯科蓝牙BG27开发笔记6-精简第一个程序

1. 这些IO的控制代码在哪里&#xff1f; 还是蓝牙点灯程序&#xff1a; 首先需要对pinout做一些精简&#xff1a; 为了简化工程&#xff0c;去掉了不必要的IO。 至于PTI接口是什么&#xff0c;怎么用&#xff0c;不知道&#xff0c;现在不考虑&#xff1a; 但是提出以下问题…...

Android8.1 hal 加载wifi ko模块流程

Android如果发现wifi没有正常启动&#xff0c;从下面两个方面 1.是否正常编译出wifi ko文件&#xff0c;如果没有&#xff0c;说明编译的有问题&#xff0c;ko文件的地址vendor/lib/module/devices/wifi 2.如果有编译出ko文件&#xff0c;但还提示Wifi HAL start failed之类的…...

Unity SteamVR 开发教程:SteamVR Input 输入系统(2.x 以上版本)

文章目录 &#x1f4d5;前言&#x1f4d5;教程说明&#x1f4d5;导入 SteamVR 插件&#x1f4d5;SteamVR Input 窗口⭐action.json 文件⭐窗口面板⭐SteamVR_Input 目录 &#x1f4d5;SteamVR 动作的类型⭐Boolean⭐Single⭐Vector2⭐Vector3⭐Pose⭐Skeleton⭐Vibration &…...

PyTorch中,卷积层、池化层、转置卷积层输出特征图形状计算公式总结

在PyTorch中&#xff0c;卷积层&#xff08;Convolutional Layer&#xff09;、池化层&#xff08;Pooling Layer&#xff0c;例如最大池化层&#xff09;、以及转置卷积层&#xff08;Transpose Convolutional Layer&#xff0c;也称为反卷积层或上采样层&#xff09;的输出特…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...