android蓝牙开发教程(如何使用android原生BLE蓝牙进行操作)
本文目录
- 如何使用android原生BLE蓝牙进行操作
- Android开发 蓝牙连接问题
- android开发SPP经典蓝牙
- Android开发之蓝牙(Bluetooth)
- Android 蓝牙开发(三)-蓝牙的详细介绍
- android开发a2dp怎么实现自动连接蓝牙设备
- 如何使用Android蓝牙开发
- android bluetooth hid协议的开发求助
如何使用android原生BLE蓝牙进行操作
之前的涉及的物联网项目中使用的: BLE 低功耗蓝牙(蓝牙4.0), 支持android 4.3以上的手机 主从关系: BLE低功耗蓝牙只能做从端设备 ,一个蓝牙主端设备,可同时与7个蓝牙从端设备进行通讯
1)低功耗 低功耗的原理: 1\低功耗蓝牙仅使用了3个广播通道,传统蓝牙技术采用 16~32 个频道 2\每次广播开启时间也由传统的 22.5ms 减少到 0.6~1.2ms(毫秒)
2)传输距离极大提高 传统蓝牙传输距离为 2~10m,而蓝牙4.0的有效传输距离可达到 60~100m
3)安全性 使用AES-128 CCM加密算法进行数据包加密和认证。 更多BLE蓝牙的解析参考博客 : BLE4.0教程一 蓝牙协议连接过程与广播分析
添加权限 打开蓝牙 1.先拿到BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 2.再拿到BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter(); 判断是否打开蓝牙 未打开弹出 系统弹框 ,除了 魅族手机 是打开系统设置
设备/手机都是蓝牙信号
在回调方法中:
一般在扫描的过程中,我们还会设置 设备过滤原则 (因为我只想要搜索到我们想要的设备,忽略无关设备) 如:从 scanRecord -- beacon -- beacon.type == 0xFF代表Manufacture,通过与嵌入式软件定义 自己的 Manufacture值即可
用BluetoothDevice得到BluetoothGatt:
断连:
关键问题:连接后一般要做什么事?
( 必须在刚连接成功后2秒内app写一个值给设备,否则会被设备断开连接)
主要是读写 characteristic gatt.wirteCharacteristic(mCurrentcharacteristic);
gatt.readCharacteristic(characteristic);
bluetoothGatt.setCharacteristicNotification(data, true);
真实工作中使用的蓝牙库BlueToothKit请参考我的另一篇博客: android蓝牙入门知识和优秀蓝牙第三方库BluetoothKit的使用
Android开发 蓝牙连接问题
Android 蓝牙编程的基本步骤:1.获取蓝牙适配器BluetoothAdapter blueadapter=BluetoothAdapter.getDefaultAdapter(); 如果BluetoothAdapter 为null,说明android手机没有蓝牙模块。判断蓝牙模块是否开启,blueadapter.isEnabled() true表示已经开启,false表示蓝牙并没启用。2.启动配置蓝牙可见模式,即进入可配对模式Intent in=new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); in.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 200); startActivity(in); ,200就表示200秒。3.获取蓝牙适配器中已经配对的设备Set《BluetoothDevice》 device=blueadapter.getBondedDevices(); 4.还需要在androidManifest.xml中声明蓝牙的权限 《uses-permission android:name="android.permission.BLUETOOTH" /》 《uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /》 接下来就是根据自己的需求对BluetoothAdapter 的操作了。
android开发SPP经典蓝牙
Android 开发SPP经典蓝牙。 1、传统蓝牙采用的是SPP(Serial Port Profile)协议进行数据传输。 2、SPP的UUID:00001101-0000-1000-8000-00805F9B34FB 3、手机一般以客户端的角色主动连接SPP协议设备 概念: BluetoothAdapter: 本地蓝牙适配器,是所有蓝牙交互的入口,表示蓝牙设备自身的一个蓝牙适配器,整个系统只有一个蓝牙适配器,通过他可以发现其他蓝牙设备,查询绑定(配对)设备列表,使用MAC地址实例化BluetoothDevice以及创建BluetoothServerSocket用来侦听来自其他设备的通信。 myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();//获取默认的蓝牙Adapter BluetoothDevice: 远程的蓝牙设备。 private static BluetoothDevice myDevice; myDevice = myBluetoothAdapter.getRemoteDevice(BDAddr);//获取远程设备,通过蓝牙的MAC地址来获取一个远程对象 两种连接方式 BluetoothSocket 客户端:调用BluetoothDevice的createRfcommSocketToServiceRecord()可以获取该对象;调用connect()方法可以建立连接。 private static BluetoothSocket mySocket = null; private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); Method m = myDevice.getClass().getMethod("createRfcommSocket", new Class {int.class});//由BluetoothDevice衍生出BluetoothSocket, createRfcommSocket来选择连接的服务和协议 mySocket = (BluetoothSocket) m.invoke(myDevice, 1); BluetoothServerSocket: 服务端:通过BluetoothServerSocket对象可以创建BluetoothSocket对象,调用BluetoothServerSocket的accept()的方法可以得到改对象。 开发流程: 1:声明权限: 《uses-permission android:name="android.permission.BLUETOOTH"/》 《uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/》 2:启动和关闭蓝牙 获取蓝牙适配器,使用close()接口可以关闭蓝牙适配器 myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();//获取默认的蓝牙Adapter 启动蓝牙 if (!blueadapter.isEnabled()) //判断本机蓝牙是否打开 {//如果没打开,则打开蓝牙 blueadapter.enable(); } 3.使用BlueAdatper搜索 使用bluetoothAdapter搜索设备,bluetoothAdapter.startDiscovery()在搜索过程中,系统会发出三个广播信息: ACTION_DISCOVERY_START:开始搜索 ACTION_DISCOVERY_FINISHED:搜索结束 ACTION_FOUND:找到设备 if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery();//如果蓝牙设备未连接则取消搜索 } bluetoothAdapter.startDiscovery(); } 4:(1)通过注册广播获取搜索到的设备。 IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothDevice.ACTION_FOUND);//找到设备广播 intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索完成广播 registerReceiver(receiver, intentFilter);//注册广播接收器 // receiver private final BroadcastReceiver receiver = new BroadcastReceiver(){ @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // find a device BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (device.getBondState() != BluetoothDevice.BOND_BONDED) { //未配对设备 newDeviceArrayAdapter.add(device.getName() + "\n" + device.getAddress()); }else { //已经配对过的设备 TextView tvPaired = (TextView)findViewById(R.id.tv_paired); tvPaired.setVisibility(View.VISIBLE); lvPairedDevices.setVisibility(View.VISIBLE); pairedDeviceArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } Log.i(TAG,"name:" + device.getName() + " address"+ device.getAddress()); } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action){ // search finish Log.i(TAG, "search finish!"); } } }; (2),直接得到当前的蓝牙设备后,就可用通过遍历pairedDevices ,得到当前手机已经配对过的蓝牙设备。 Set《BluetoothDevice》 pairedDevices = myBluetoothAdapter.getBondedDevices();//获取当前蓝牙设备 if (pairedDevices.size() 《= 0) return false; for (BluetoothDevice device : pairedDevices) { Map《String, String》 map = new HashMap《String, String》(); map.put("DeviceName", device.getName()); map.put("BDAddress", device.getAddress()); list.add(map); 5.建立连接 private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); Method m = myDevice.getClass().getMethod("createRfcommSocket", new Class {int.class});//由BluetoothDevice衍生出BluetoothSocket, createRfcommSocket来选择连接的服务和协议 mySocket = (BluetoothSocket) m.invoke(myDevice, 1); mySocket.connect();//使用BluetoothSocket来连接设备 6.把得到的蓝牙设备给通过点击ListView选择设备。 listView.setOnItemClickListener(new ListView.OnItemClickListener() { public void onItemClick(AdapterView《?》 arg0, View arg1, int arg2, long arg3) { SelectedBDAddress = list.get(arg2).get("BDAddress"); if (((ListView) arg0).getTag() != null) { ((View) ((ListView) arg0).getTag()).setBackgroundDrawable(null); } ((ListView) arg0).setTag(arg1); arg1.setBackgroundColor(Color.BLUE); myDevice = myBluetoothAdapter.getRemoteDevice(SelectedBDAddress); } }); 7.客户端发送数据 当两个设备成功连接之后,双方都会有一个BluetoothSocket对象,这时,就可以在设备之间传送数据了。 1.使用getOutputStream()方法来获取输出流来处理传输。 2.调用write()。 os = socket.getOutputStream();//获取输出流 if (os != null) {//判断输出流是否为空 os.write(message.getBytes("UTF-8")); } os.flush();//将输出流的数据强制提交 os.close();//关闭输出流 } 将输出流中的数据提交后,要记得关闭输出流,否则,可能会造成只能发送一次数据。 8.服务端接收数据 1.使用getInputStream()方法来获取输入流来处理传输。 2.调用read()。 InputStream im=null; im=bluetoothSocket.getInputStream(); byte buf; if (is != null) { is.read(buf, 0, buf.length);//读取发来的数据 String message = new String(buf);//把发来的数据转化为String类型 BuletoothMainActivity.UpdateRevMsg(message);//更新信息在显示文本框 is.close();//关闭输入流 使用服务端接收数据时,要先从客户端向服务端发起连接,只有接收到连接请求之后,才会返回一个BluetoothSocket对象。有BluetoothSocket对象才能获取到输入流。
Android开发之蓝牙(Bluetooth)
在上一篇中有介绍了Wifi与网络连接处理 Android开发之WiFi与网络连接处理 下面,来继续说说Android中蓝牙的基本使用。
Bluetooth是目前使用的最广泛的无线通讯协议之一,主要针对短距离设备通讯(10米),常用于连接耳机、鼠标和移动通讯设备等。
值得一提的是: android4.2新增了部分新功能,但是对于Bluetooth熟悉的人或许开始头疼了,那就是Android4.2引入了一个新的蓝牙协议栈针BLE。谷歌和Broadcom之间的合作,开发新的蓝牙协议栈,取代了基于堆栈的Bluez。因此市场上出现了老设备的兼容问题,很多蓝牙设备在android4.2手机上不能正常使用。
BluetoothAdapter简单点来说就是代表了本设备(手机、电脑等)的蓝牙适配器对象。
first:we need permission 要操作蓝牙,先要在AndroidManifest.xml里加入权限
**下面来看看如何使用蓝牙。 **↓↓↓**** Demo已就绪:
返回值:如果设备具备蓝牙功能,返回BluetoothAdapter 实例;否则,返回null对象。
打开蓝牙设备的方式: 1.直接调用函数enable()去打开蓝牙设备 ; 2.系统API去打开蓝牙设备,该方式会弹出一个对话框样式的Activity供用户选择是否打开蓝牙设备。
注意: 1.如果蓝牙已经开启,不会弹出该Activity界面。2.在目前大多数Android手机中,是不支持在飞行模式下开启蓝牙的。如果蓝牙已经开启,那么蓝牙的开关 ,状态会随着飞行模式的状态而发生改变。
1. 搜索蓝牙设备 使用BluetoothAdapter的startDiscovery()方法来搜索蓝牙设备 startDiscovery()方法是一个异步方法,调用后会立即返回。该方法会进行对其他蓝牙设备的搜索,该过程会持续12秒。该方法调用后,搜索过程实际上是在一个System Service中进行的,所以可以调用cancelDiscovery()方法来停止搜索(该方法可以在未执行discovery请求时调用)。
系统开始搜索蓝牙设备 ^( *  ̄(oo) ̄ ) ^ 系统会发送以下三个广播:
2.扫描设备
3.定义广播接收器接收搜索结果
4.注册广播
获取附近的蓝牙设备
第一步建立连接:首先Android sdk(2.0以上版本)支持的蓝牙连接是通过BluetoothSocket建立连接,服务端BluetoothServerSocket和客户端(BluetoothSocket)需指定同样的UUID,才能建立连接,因为建立连接的方法会阻塞线程,所以服务器端和客户端都应启动新线程连接。
(这里的服务端和客户端是相对来说的) 两个蓝牙设备之间的连接,则必须实现服务端与客户端的机制。 当两个设备在同一个RFCOMM channel下分别拥有一个连接的BluetoothSocket,这两个设备才可以说是建立了连接。
服务端设备与客户端设备获取BluetoothSocket的途径是不同的。 1,服务端设备是通过accepted一个incoming connection来获取的, 2,客户端设备则是通过打开一个到服务端的RFCOMM channel来获取的。
服务端 通过调用BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID)方法来获取BluetoothServerSocket(UUID用于客户端与服务端之间的配对)
客户端 调用BluetoothService的createRfcommSocketToServiceRecord(UUID)方法获取BluetoothSocket(该UUID应该同于服务端的UUID)。 调用BluetoothSocket的connect()方法(该方法为block方法),如果UUID同服务端的UUID匹配,并且连接被服务端accept,则connect()方法返回。
数据传递,通过以上操作,就已经建立的BluetoothSocket连接了,数据传递无非是通过流的形式 获取流
该类就是关于远程蓝牙设备的一个描述。通过它可以和本地蓝牙设备---BluetoothAdapter连接通信。
好多东西我也不知道怎么描述,下面给出Demo: 刚好有刚学习的小伙伴问我ListView怎么用,那我就用ListView。
源码: RairDemo ***隐藏网址******隐藏网址***
Android 蓝牙开发(三)-蓝牙的详细介绍
前面的两篇文章,主要是在 Android 官网关于蓝牙介绍的基础上加上自己的理解完成的。主要针对的是 Android 开发中的一些 API 的使用。 第一篇文章 Android 蓝牙开发(一) 主要是介绍了普通的蓝牙在 Android 开发中的运用。 第二篇文章 Android 蓝牙开发(二) 主要是介绍了低功耗蓝牙的开发。 这篇文章主要介绍的是蓝牙的历史和一些关于蓝牙的通用知识,还有广播包的知识。要想彻底了解蓝牙开发,这些基础的知识也是需要的,就像网络协议一样,这些都是基础的内容。我们的 API 的调用都是以这个为基础的,了解这些,开发过程中遇到问题,才可以知道什么怎么一回事。
下篇文章主要讲的就是实际开发中的一些坑。
蓝牙其实就是一种近距离无线通信技术。
从下到上分别为:控制器(Controller)--》主机(host)--》应用(Application)
详细介绍各个层的含义:
BLE 应用可以分为两大类:基于非连接的和基于连接的
意思就是外设和周边设备不发生连接,主要靠扫描到的广播来获取信息。发送广播的一方叫做 broadcaster 监听广播的一方叫做 oberver 在 GAP 层有对应的角色定义。
网络拓扑图:
这种方式就是广播设备不断的向外发送广播(含有特定的信息),然后观察者接受到广播按照两者之间约定好的协议进行解析拿到有用的信息。例如:iBeacon,通过这种设备我们可以实现室内定位。
其实这些设备的角色可以即使广播者又是观察者。接收到广播后作出了处理,然后又发送广播。这样就形成了双向的网络,类似于因特网,这就是蓝牙 Mesh 组网。
广播数据包格式:
每个广播数据包由 31 byte 组成。分为有效数据和无效数据两部分。
例子:
这里是扫描的数据包(转换成了 16 进制,两个代表一个字节),第一个字节是 02 表示后面的两个字节是数据部分,然后第二个字节是 01 表示了数据的类型。后面一个字节就是真正的数据了。这个广播数据单元就分析完了。下面就是另一个数据单元了。依次类推,关于数据类型的解释,官网有。
这是数据类型对应的含义表。
网络拓扑图:
一个中心设备可连接多个外设,但是一个外设只能连接一个中心(外设连接成功后就会停止对外广播,别人就发现不了它了)。其中一个中心设备的连接外设的数量也是有限的。
***隐藏网址***
android开发a2dp怎么实现自动连接蓝牙设备
在Android程序中可以实现自动扫描蓝牙、配对蓝牙、建立数据通道。 ***隐藏网址***可以入下面方法获取蓝牙设备支持的类型: Java代码 BluetoothDevice device; Arrays.toString(device.getUuids()); 我的蓝牙音箱支持的类型有: Java代码 0000111e-0000-1000-8000-00805f9b34fb:Handsfree 0000110b-0000-1000-8000-00805f9b34fb:AudioSink 0000110e-0000-1000-8000-00805f9b34fb:AVRemoteControl 00001203-0000-1000-8000-00805f9b34fb:GenericFileTransfer
如何使用Android蓝牙开发
Android平台支持蓝牙网络协议栈,实现蓝牙设备之间数据的无线传输。本文档描述了怎样利用android平台提供的蓝牙API去实现蓝压设备之间的通信。蓝牙具有point-to-point 和 multipoint两种连接功能。 使用蓝牙API,可以做到: * 搜索蓝牙设备 * 从本地的Bluetooth adapter中查询已经配对的设备 * 建立RFCOMM通道 * 通过service discovery连接到其它设备 * 在设备之间传输数据 * 管理多个连接 基础知识 本文档介绍了如何使用Android的蓝牙API来完成的四个必要的主要任务,使用蓝牙进行设备通信,主要包含四个部分:蓝牙设置、搜索设备(配对的或可见的)、连接、传输数据。 所有的蓝牙API在android.bluetooth包中。实现这些功能主要需要下面这几个类和接口: BluetoothAdapter 代表本地蓝牙适配器(蓝牙发射器),是所有蓝牙交互的入口。通过它可以搜索其它蓝牙设备,查询已经配对的设备列表,通过已知的MAC地址创建BluetoothDevice,创建BluetoothServerSocket监听来自其它设备的通信。 BluetoothDevice 代表了一个远端的蓝牙设备, 使用它请求远端蓝牙设备连接或者获取 远端蓝牙设备的名称、地址、种类和绑定状态。 (其信息是封装在 bluetoothsocket 中) 。 BluetoothSocket 代表了一个蓝牙套接字的接口(类似于 tcp 中的套接字) ,他是应用程 序通过输入、输出流与其他蓝牙设备通信的连接点。 BluetoothServerSocket 代表打开服务连接来监听可能到来的连接请求 (属于 server 端) , 为了连接两个蓝牙设备必须有一个设备作为服务器打开一个服务套接字。 当远端设备发起连 接连接请求的时候,并且已经连接到了的时候,Blueboothserversocket 类将会返回一个 bluetoothsocket。 BluetoothClass 描述了一个设备的特性(profile)或该设备上的蓝牙大致可以提供哪些服务(service),但不可信。比如,设备是一个电话、计算机或手持设备;设备可以提供audio/telephony服务等。可以用它来进行一些UI上的提示。 BluetoothProfile BluetoothHeadset 提供手机使用蓝牙耳机的支持。这既包括蓝牙耳机和免提(V1.5)模式。 BluetoothA2dp 定义高品质的音频,可以从一个设备传输到另一个蓝牙连接。 “A2DP的”代表高级音频分配模式。 BluetoothHealth 代表了医疗设备配置代理控制的蓝牙服务 BluetoothHealthCallback 一个抽象类,使用实现BluetoothHealth回调。你必须扩展这个类并实现回调方法接收更新应用程序的注册状态和蓝牙通道状态的变化。
android bluetooth hid协议的开发求助
Android Bluetooth HID实现详解
Android 关于蓝牙的部分使用的是BlueZ协议栈。但是直到目前2.3.3都没有扩展HID的profile,只是实现了最基本的Handset和d2dp的profile,所以我们的工作涉及到从应用到jni三层的修改,具体修改文件如图所示,绿色表示新建的类,橙色表示修改的类。
一. 本地层
路径:framework/base/core/jni/
参照android_server_BluetoothA2dpService.cpp新建android_server_bluetoothHidServer.cpp。该类中主要是通过dbus对bluez协议栈的访问,dbus 的通用方法都在android_bluetooth_common.cpp中实现,我们做的仅仅是通过dbus_func_args_async调用到bluez提供的input接口。
主要实现以下两个方法函数:
static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) {
#ifdef HAVE_BLUETOOTH
LOGV(__FUNCTION__);
if (nat) {
const char *c_path = env-》GetStringUTFChars(path, NULL);
bool ret = dbus_func_args_async(env, nat-》conn, -1, NULL, NULL, nat,
c_path, "org.bluez.Input", "Connect",
DBUS_TYPE_INVALID);
env-》ReleaseStringUTFChars(path, c_path);
return ret ? JNI_TRUE : JNI_FALSE;
}
#endif
return JNI_FALSE;
}
static jboolean disconnectSinkNative(JNIEnv *env, jobject object,
jstring path) {
#ifdef HAVE_BLUETOOTH
LOGV(__FUNCTION__);
if (nat) {
const char *c_path = env-》GetStringUTFChars(path, NULL);
bool ret = dbus_func_args_async(env, nat-》conn, -1, NULL, NULL, nat,
c_path, "org.bluez.Input", "Disconnect",
DBUS_TYPE_INVALID);
env-》ReleaseStringUTFChars(path, c_path);
return ret ? JNI_TRUE : JNI_FALSE;
}
#endif
return JNI_FALSE;
}
这里要注意将该文件添加到AndroidRuntime.cpp和Android.mk中,否则不会编译到动态库中。
此部分编译后最终生成libandroid_runtime.so并替换到system/libs下
二.Framework的java部分
路径framework/base/java/android/server/中添加BluetoothHidService.java文件
路径framework/base/java/android/bluetooth/中添加BluetoothHid.java和IBluetoothHid.aidl文件。
interface IBluetoothHid {
boolean connect(in BluetoothDevice device);
boolean disconnect(in BluetoothDevice device);
int getState(in BluetoothDevice device);
boolean setPriority(in BluetoothDevice device, int priority);
int getPriority(in BluetoothDevice device);
}
BluetoothHid.java中主要的两个方法connect和disconnect间接地通过aidl访问BluetoothHidService。这里主要是实现跨进程并为上层提供可直接访问的方法。
由此framework的主要部分打包生成framework.Jar并最终部署到system/framework里。
三.应用(Settings.apk)
最后需要修改应用部分,应用部分的修改点比较分散,不想框架层那样整块模仿A2DP的样子那么方便,但也不是说jni部分有多么容易。反而对于我这种对C语言不熟悉的人来说,修改jni是最头疼得事了。好在蓝牙HID 这部分框架层的修改都是整块进行的,理解上还算比价容易。
总的来说在Settings.apk中要修改的文件主要是这么几个:
LocalBluetoothProfileManager.java 这里主要提供一个HID的profile以便应用层访问。建一个HIDProfile的class调用framework中的BluetoothHID。实际上就是通过bender机制调用了BluetoothHidService。
CashedBluetoothDevice中添加显示蓝牙键盘的图标,BluetoothPairingDialog中则需要添加一段蓝牙配对验证处理的代码,我是参照i9000中先弹出一个随机数,然后在键盘中敲入相同的随机数即配对成功,具体实现如下:
// HID
if (isDeviceKeyboard(mDevice)) {
String pin = String.format("%06d", Long.valueOf(Math
.abs(new Random().nextLong() % 1000000L)));
mPairingView.setVisibility(View.GONE);
messageView.setText(getString(
R.string.bluetooth_enter_keyboard_pin_msg, pin, name));
byte bytePin = BluetoothDevice.convertPinToBytes(pin);
if (bytePin != null) {
mDevice.setPin(bytePin);
}
}
……
}
转载
更多文章:
心灵感应游戏(心灵感应 游戏 一人指物 另一人猜 总是可以猜到围观者指定的物品 没有停顿 没有动作眼神等暗示 没)
2024年6月22日 06:05
有什么好玩的PSP游戏适合女生?PSP里有什么经典的游戏,大家推荐下
2024年5月10日 12:52
ubuntu 中文输入法(怎样才能在 UBUNTU中输入中文)
2024年7月1日 18:03
蘑菇云root下载(手机HTL V11安卓4.0.4怎么获得root权限)
2024年5月1日 18:16