Android 蓝牙4.0 BLE 理解

转载自:http://blog.csdn.net/chaoyue0071/article/details/43450183/ 本文简单结合两篇文章 http://blog.csdn.net/hellogv/article/details/24267685 http://blog.csdn.net/jimoduwu/article/details/21604215 在BLE协议中,有两个角色,周边(Periphery)和中央(Central),一个中央可以同时连接多个周边,但是一个周边某一时刻只能连接一个中央。但是不管是Periphery还是Central都是可以实现 GATT server 和 GATT client去传输数据,但是无法同时都是。 大概了解了概念后,看看Android BLE SDK的四个关键类(class): a) BluetoothGattServer作为周边来提供数据; BluetoothGattServerCallback返回周边的状态。 b) BluetoothGatt作为中央来使用和处理数据;BluetoothGattCallback返回中央的状态和周边提供的数据。 因为我们讨论的是Android的BLE SDK,下面所有的BluetoothGattServer代表周边,BluetoothGatt代表中央。 一.创建一个周边(虽然目前周边API在Android手机上不工作,但还是看看) a)先看看周边用到的class,蓝色椭圆 b)说明: 每一个周边BluetoothGattServer,包含多个服务Service,每一个Service包含多个特征Characteristic。 1.new一个特征:character = new BluetoothGattCharacteristic( UUID.fromString(characteristicUUID), BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ); 2.new一个服务:service = new BluetoothGattService(UUID.fromString(serviceUUID), BluetoothGattService.SERVICE_TYPE_PRIMARY); 3.把特征添加到服务:service.addCharacteristic(character); 4.获取BluetoothManager:manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 5.获取/打开周边:BluetoothGattServer server = manager.openGattServer(this, new BluetoothGattServerCallback(){…}); 6.把service添加到周边:server.addService(service); 7.开始广播service:Google还没有广播Service的API,等吧!!!!!所以目前我们还不能让一个Android手机作为周边来提供数据。 二.创建一个中央(这次不会让你失望,可以成功创建并且连接到周边的) a)先看看中央用到的class,蓝色椭圆 b)说明: 为了拿到中央BluetoothGatt,可要爬山涉水十八弯: 1.先拿到BluetoothManager:bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 2.再拿到BluetoothAdapt:btAdapter = bluetoothManager.getAdapter(); 3.开始扫描:btAdapter.startLeScan( BluetoothAdapter.LeScanCallback); 4.从LeScanCallback中得到BluetoothDevice:public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {…..} 5.用BluetoothDevice得到BluetoothGatt:gatt = device.connectGatt(this, true, gattCallback); 终于拿到中央BluetoothGatt了,它有一堆方法(查API吧),调用这些方法,你就可以通过BluetoothGattCallback和周边BluetoothGattServer交互了。 官方有给出BLE 通信的sample ,下面是牛人简化了代码,简化得简单明了 本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处! 最近穿戴设备发展得很火,把相关技术也带旺了,其中一项是BLE(Bluetooth Low Energy)。BLE是蓝牙4.0的核心Profile,主打功能是快速搜索,快速连接,超低功耗保持连接和传输数据,弱点是数据传输速率低,由于BLE的低功耗特点,因此普遍用于穿戴设备。Android 4.3才开始支持BLE API,所以请各位客官把本文代码运行在蓝牙4.0和Android 4.3及其以上的系统,另外本文所用的BLE终端是一个蓝牙4.0的串口蓝牙模块。 PS:我的i9100刷了4.4系统后,竟然也能跟BLE蓝牙模块通信。 ...

2017年2月25日 · 6 分钟 · 天边的星星

【Android】自定义控件让TextView的drawableLeft与文本一起居中显示

前言 TextView的drawableLeft、drawableRight和drawableTop是一个常用、好用的属性,可以在文本的上下左右放置一个图片,而不使用更加复杂布局就能达到,我也常常喜欢用RadioButton的这几个属性实现很多效果,但是苦于不支持让drawbleLeft与文本一起居中,设置gravity为center也无济于事,终于有空研究了一下,这里与大家一起分享。 声明 欢迎转载,请注明出处! 博客园:http://www.cnblogs.com/ 农民伯伯: http://www.cnblogs.com/over140/ 正文 一、效果图 二、实现代码 自定义控件 ![复制代码](http://common.cnblogs.com/images/copycode.gif) /** * drawableLeft与文本一起居中显示 * * @author 农民伯伯 * @see http://www.cnblogs.com/over140/p/3464348.html * */ public class DrawableCenterTextView extends TextView { public DrawableCenterTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public DrawableCenterTextView(Context context, AttributeSet attrs) { super(context, attrs); } public DrawableCenterTextView(Context context) { super(context); } @Override protected void onDraw(Canvas canvas) { Drawable[] drawables = getCompoundDrawables(); if (drawables != null) { Drawable drawableLeft = drawables[0]; if (drawableLeft != null) { float textWidth = getPaint().measureText(getText().toString()); int drawablePadding = getCompoundDrawablePadding(); int drawableWidth = 0; drawableWidth = drawableLeft.getIntrinsicWidth(); float bodyWidth = textWidth + drawableWidth + drawablePadding; } } super.onDraw(canvas); } } ...

2016年7月19日 · 1 分钟 · 天边的星星

java中byte与 int、short、char、float、double之间的转换

由于java的字节序和网络字节序一致(高位在前),给出换算方法,亲测OK public static void main(String[] args) { byte[] bs=new byte[2]; short dvalue=1; Utils.putShort(bs, dvalue, 0); for (int i = 0; i < bs.length; i++) { System.out.println(bs[i]); } } /** 将32位的int值放到4字节的里 @param num @return */ public static byte[] int2byteArray(int num) { byte[] result = new byte[4]; result[0] = (byte) (num »> 24);// 取最高8位放到0下标 result[1] = (byte) (num »> 16);// 取次高8为放到1下标 result[2] = (byte) (num »> 8); // 取次低8位放到2下标 result[3] = (byte) (num); // 取最低8位放到3下标 return result; } /** ...

2015年3月30日 · 3 分钟 · 天边的星星

android蓝牙

http://wenku.baidu.com/link?url=lAOm_kIF29t-JGoUnKAFSY4BhMP6vv-Cvfx9x1_oVSTZ1QDMm6URT7fhRR8ODX7aBVSX8ffOD0LnI-TX4PaRTqzXPWwJdOhBNXMu0lg214O http://wenku.baidu.com/view/490171b20242a8956bece47d.html?re=view http://wenku.baidu.com/view/cf48328371fe910ef12df827.html http://wenku.baidu.com/view/490171b20242a8956bece47d.html?re=view http://wenku.baidu.com/link?url=lAOm_kIF29t-JGoUnKAFSY4BhMP6vv-Cvfx9x1_oVSTZ1QDMm6URT7fhRR8ODX7aBVSX8ffOD0LnI-TX4PaRTqzXPWwJdOhBNXMu0lg214O android平台包含了蓝牙网络协议栈的支持,允许android设备与其他蓝牙设备相互传输数据。应用层框架提供了API函数来访问蓝牙模块。使用这些API可以让应用程序连接其他蓝牙设备,实现点对点或多点无线传输。 运用蓝牙API,可以实现以下功能: 搜索其他蓝牙设备 查询本地蓝牙适配器中已经配对好的设备 建立RFCOMM协议通道 通过服务端搜索连接到其他设备 与其他设备互相传输数据 管理多个连接 快速阅读 Android蓝牙API可以让应用程序与其他设备传输无线数据。 关键类 BluetoothAdapter BluetoothDevice BluetoothSocket BluetoothServerSocket 相关用例 蓝牙对讲 http://developer.android.com/resources/samples/BluetoothChat/index.html 蓝牙医疗设备(Health Device Profile),比如心率监视器,血压计,温度计等。http://developer.android.com/resources/samples/BluetoothHDP/index.html 目录 [隐藏] 1 基本原理 2 蓝牙权限 3 配置蓝牙 4 获取蓝牙设备 4.1 查询已配对设备 4.2 搜索设备 4.3 开启蓝牙可检测性 5 设备连接 5.1 作为服务端连接 5.2 作为客户端连接 6 连接管理 7 在蓝牙规范协议下工作 7.1 Vendor-specific AT commands 7.2 Health Device Profile 基本原理 本文档描述了如何使用蓝牙API来完成蓝牙通讯的四项必要任务:配置蓝牙、搜索附件未配对或可用的蓝牙设备、连接设备、设备间传输数据。 所有蓝牙API都包含在android.bluetooth包中。以下是建立蓝牙连接需要用到的类和接口的概要: BluetoothAdapter (蓝牙适配器) 表示本地蓝牙适配器(蓝牙收发器). BluetoothAdapter是所有蓝牙活动的起始类. 可用于搜索其他蓝牙设备, 查询已配对设备的列表, 使用MAC地址实例化一个BluetoothDevice对象, 创建BluetoothServerSocket侦听其他设备的连接. BluetoothDevice (蓝牙设备) 表示远程蓝牙设备。可以通过一个BluetoothSocket向它描述的远程设备发起连接,或者该设备的名称、地址、类、连接状态等信息。 BluetoothSocket (蓝牙套接字) 表示一个蓝牙套接字(与TCP Socket类似). 它是设备间的连接点,允许应用程序通过InputStream和OutputStream与其他设备进行数据传输。 BluetoothServerSocket (蓝牙服务端套接字) 表示一个开放的蓝牙服务器, 用于侦听其他设备发过来的连接请求(与TCP ServerSocket类似). 要将两台设备连接起来, 其中一台必须使用这个类开启一个server socket. 当远程蓝牙设备发起对server的连接请求, 如果连接被接受,BluetoothServerSocket将返回一个连接成功的BluetoothSocket对象. BluetoothClass (蓝牙类型) 描述一个蓝牙设备的规格参数和功能。这是一个只读的属性集,定义了该设备的主要和次要设备种类和服务。它不能完全描述该设备的所有特性和服务,常用于判断设备的类型。 BluetoothProfile (蓝牙规范协议) 表示Bluetooth profile的接口. Bluetooth profile是设备间基于蓝牙通讯的接口规范协议。比如Hands-Free(非手持设备) profile。更多关于profiles的说明, 请查看Working with Profiles(在蓝牙规范协议下工作)。 BluetoothHeadset (蓝牙耳机) 提供手机使用蓝牙耳机的支持。同时包含了蓝牙耳机和Hands-Free(v1.5)的profiles. BluetoothA2dp (蓝牙A2dp) 定义高质量音频流如何通过蓝牙连接传输到其他设备。”A2DP”是”Advanced Audio Distribution Profile”的缩写,表示高级音频分发规范协议。 BluetoothHealth (蓝牙医疗设备) 表示为医疗设备提供蓝牙服务的代理类。 BluetoothHealthCallback 这是一个抽象类,用于实现BluetoothHealth的callbacks方法。需要继承此类并实现callback方法才能接收应用程序状态和蓝牙频道状态的变化。 BluetoothHealthAppConfiguration 表示蓝牙医疗第三方应用与远程蓝牙医疗设备连接的配置参数。 BluetoothProfile.ServiceListener (蓝牙规范协议服务侦听) 一个接口类,当服务连接或断开的时候通知BluetoothProfile IPC 客户端。(这是内部服务运行的一个特殊模式)。 蓝牙权限 ...

2015年2月4日 · 13 分钟 · 天边的星星

蓝牙BLE 4.0提供的服务名称列表

保健设备配置文件 https://www.bluetooth.org/zh-cn/specification/assigned-numbers/health-device-profile ** ** ** ** 上面2个Service对应下面2个服务 通用属性配置文件(GATT) ​​​通用属性配置文件(GATT) GATT服务 **记忆码** <td width="61"> **UUID规格** </td> <td width="109"> **UUID** </td> <td width="233"> **参考规格** </td> 《通用访问配置文件》 <td width="61"> uuid16 </td> <td width="109"> 0x1800 </td> <td width="233"> *Bluetooth*®核心规格第3卷C部分第12节 </td> 《通用属性配置文件》 <td width="61"> uuid16 </td> <td width="109"> 0x1801 </td> <td width="233"> 蓝牙核心规格第3卷G部分第7节 </td> <td width="61"> </td> <td width="109"> (最大值0xFFFF) </td> <td width="233"> </td> 表1: GATT服务 GATT属性类型 **记忆码** <td width="61"> **UUID规格** </td> <td width="109"> **UUID** </td> <td width="202"> **参考规格** </td> «主要服务» <td width="61"> uuid16 </td> <td width="109"> 0x2800 </td> <td width="202"> 蓝牙核心规格第3卷G部分第3.1节 </td> «辅助服务» <td width="61"> uuid16 </td> <td width="109"> 0x2801 </td> <td width="202"> 蓝牙核心规格第3卷G部分第3.1节 </td> «包含» <td width="61"> uuid16 </td> <td width="109"> 0x2802 </td> <td width="202"> 蓝牙核心规格第3卷G部分第3.2节 </td> «特征» <td width="61"> uuid16 </td> <td width="109"> 0x2803 </td> <td width="202"> 蓝牙核心规格第3卷G部分第3.3节 </td> <td width="61"> </td> <td width="109"> (最大值0xFFFF) </td> <td width="202"> </td> 表2:GATT属性类型 ...

2015年2月4日 · 5 分钟 · 天边的星星

Android4.3 蓝牙BLE初步

一、关键概念: **Generic Attribute Profile (GATT)** 通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。 **Attribute Protocol (ATT)** GATT是基于ATT Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。 **Characteristic** Characteristic可以理解为一个数据类型,它包括一个value和0至多个对次value的描述(Descriptor)。 **Descriptor** 对Characteristic的描述,例如范围、计量单位等。 **Service** Characteristic的集合。例如一个service叫做“Heart Rate Monitor”,它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement”的Characteristic。 二、角色和职责: Android设备与BLE设备交互有两组角色: 中心设备和外围设备(Central vs. peripheral); GATT server vs. GATT client. Central vs. peripheral: 中心设备和外围设备的概念针对的是BLE连接本身。Central角色负责scan advertisement。而peripheral角色负责make advertisement。 GATT server vs. GATT client: 这两种角色取决于BLE连接成功后,两个设备间通信的方式。 举例说明: 现有一个活动追踪的BLE设备和一个支持BLE的Android设备。Android设备支持Central角色,而BLE设备支持peripheral角色。创建一个BLE连接需要这两个角色都存在,都仅支持Central角色或者都仅支持peripheral角色则无法建立连接。 当连接建立后,它们之间就需要传输GATT数据。谁做server,谁做client,则取决于具体数据传输的情况。例如,如果活动追踪的BLE设备需要向Android设备传输sensor数据,则活动追踪器自然成为了server端;而如果活动追踪器需要从Android设备获取更新信息,则Android设备作为server端可能更合适。 三、权限及feature: 和经典蓝牙一样,应用使用蓝牙,需要声明BLUETOOTH权限,如果需要扫描设备或者操作蓝牙设置,则还需要BLUETOOTH_ADMIN权限: 除了蓝牙权限外,如果需要BLE feature则还需要声明uses-feature: 按时required为true时,则应用只能在支持BLE的Android设备上安装运行;required为false时,Android设备均可正常安装运行,需要在代码运行时判断设备是否支持BLE feature: // Use this check to determine whether BLE is supported on the device. Then // you can selectively disable BLE-related features. if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show(); finish(); } 四、启动蓝牙: 在使用蓝牙BLE之前,需要确认Android设备是否支持BLE feature(required为false时),另外要需要确认蓝牙是否打开。 如果发现不支持BLE,则不能使用BLE相关的功能。如果支持BLE,但是蓝牙没打开,则需要打开蓝牙。 打开蓝牙的步骤: 1、获取BluetoothAdapter BluetoothAdapter是Android系统中所有蓝牙操作都需要的,它对应本地Android设备的蓝牙模块,在整个系统中BluetoothAdapter是单例的。当你获取到它的示例之后,就能进行相关的蓝牙操作了。 获取BluetoothAdapter代码示例如下: // Initializes Bluetooth adapter. final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); 注:这里通过getSystemService获取BluetoothManager,再通过BluetoothManager获取BluetoothAdapter。BluetoothManager在Android4.3以上支持(API level 18)。 2、判断是否支持蓝牙,并打开蓝牙 获取到BluetoothAdapter之后,还需要判断是否支持蓝牙,以及蓝牙是否打开。 如果没打开,需要让用户打开蓝牙: private BluetoothAdapter mBluetoothAdapter; … // Ensures Bluetooth is available on the device and it is enabled. If not, // displays a dialog requesting user permission to enable Bluetooth. if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); } 五、搜索BLE设备: 通过调用BluetoothAdapter的[startLeScan()](http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback))搜索BLE设备。调用此方法时需要传入 `<a href="http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.LeScanCallback.html">BluetoothAdapter.LeScanCallback</a>`参数。 因此你需要实现 `<a href="http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.LeScanCallback.html">BluetoothAdapter.LeScanCallback</a>`接口,BLE设备的搜索结果将通过这个callback返回。 由于搜索需要尽量减少功耗,因此在实际使用时需要注意: 1、当找到对应的设备后,立即停止扫描; 2、不要循环搜索设备,为每次搜索设置适合的时间限制。避免设备不在可用范围的时候持续不停扫描,消耗电量。 搜索的示例代码如下: /** * Activity for scanning and displaying available BLE devices. */ public class DeviceScanActivity extends ListActivity { private BluetoothAdapter mBluetoothAdapter; private boolean mScanning; private Handler mHandler; ...

2015年1月27日 · 2 分钟 · 天边的星星

android 蓝牙

android平台包含了蓝牙网络协议栈的支持,允许android设备与其他蓝牙设备相互传输数据。应用层框架提供了API函数来访问蓝牙模块。使用这些API可以让应用程序连接其他蓝牙设备,实现点对点或多点无线传输。 运用蓝牙API,可以实现以下功能: 搜索其他蓝牙设备 查询本地蓝牙适配器中已经配对好的设备 建立RFCOMM协议通道 通过服务端搜索连接到其他设备 与其他设备互相传输数据 管理多个连接 快速阅读 Android蓝牙API可以让应用程序与其他设备传输无线数据。 关键类 BluetoothAdapter BluetoothDevice BluetoothSocket BluetoothServerSocket 相关用例 蓝牙对讲 http://developer.android.com/resources/samples/BluetoothChat/index.html 蓝牙医疗设备(Health Device Profile),比如心率监视器,血压计,温度计等。http://developer.android.com/resources/samples/BluetoothHDP/index.html 目录 [隐藏] 1 基本原理 2 蓝牙权限 3 配置蓝牙 4 获取蓝牙设备 4.1 查询已配对设备 4.2 搜索设备 4.3 开启蓝牙可检测性 5 设备连接 5.1 作为服务端连接 5.2 作为客户端连接 6 连接管理 7 在蓝牙规范协议下工作 7.1 Vendor-specific AT commands 7.2 Health Device Profile 基本原理 本文档描述了如何使用蓝牙API来完成蓝牙通讯的四项必要任务:配置蓝牙、搜索附件未配对或可用的蓝牙设备、连接设备、设备间传输数据。 所有蓝牙API都包含在android.bluetooth包中。以下是建立蓝牙连接需要用到的类和接口的概要: BluetoothAdapter (蓝牙适配器) 表示本地蓝牙适配器(蓝牙收发器). BluetoothAdapter是所有蓝牙活动的起始类. 可用于搜索其他蓝牙设备, 查询已配对设备的列表, 使用MAC地址实例化一个BluetoothDevice对象, 创建BluetoothServerSocket侦听其他设备的连接. BluetoothDevice (蓝牙设备) 表示远程蓝牙设备。可以通过一个BluetoothSocket向它描述的远程设备发起连接,或者该设备的名称、地址、类、连接状态等信息。 BluetoothSocket (蓝牙套接字) 表示一个蓝牙套接字(与TCP Socket类似). 它是设备间的连接点,允许应用程序通过InputStream和OutputStream与其他设备进行数据传输。 BluetoothServerSocket (蓝牙服务端套接字) 表示一个开放的蓝牙服务器, 用于侦听其他设备发过来的连接请求(与TCP ServerSocket类似). 要将两台设备连接起来, 其中一台必须使用这个类开启一个server socket. 当远程蓝牙设备发起对server的连接请求, 如果连接被接受,BluetoothServerSocket将返回一个连接成功的BluetoothSocket对象. BluetoothClass (蓝牙类型) 描述一个蓝牙设备的规格参数和功能。这是一个只读的属性集,定义了该设备的主要和次要设备种类和服务。它不能完全描述该设备的所有特性和服务,常用于判断设备的类型。 BluetoothProfile (蓝牙规范协议) 表示Bluetooth profile的接口. Bluetooth profile是设备间基于蓝牙通讯的接口规范协议。比如Hands-Free(非手持设备) profile。更多关于profiles的说明, 请查看Working with Profiles(在蓝牙规范协议下工作)。 BluetoothHeadset (蓝牙耳机) 提供手机使用蓝牙耳机的支持。同时包含了蓝牙耳机和Hands-Free(v1.5)的profiles. BluetoothA2dp (蓝牙A2dp) 定义高质量音频流如何通过蓝牙连接传输到其他设备。”A2DP”是”Advanced Audio Distribution Profile”的缩写,表示高级音频分发规范协议。 BluetoothHealth (蓝牙医疗设备) 表示为医疗设备提供蓝牙服务的代理类。 BluetoothHealthCallback 这是一个抽象类,用于实现BluetoothHealth的callbacks方法。需要继承此类并实现callback方法才能接收应用程序状态和蓝牙频道状态的变化。 BluetoothHealthAppConfiguration 表示蓝牙医疗第三方应用与远程蓝牙医疗设备连接的配置参数。 BluetoothProfile.ServiceListener (蓝牙规范协议服务侦听) 一个接口类,当服务连接或断开的时候通知BluetoothProfile IPC 客户端。(这是内部服务运行的一个特殊模式)。 蓝牙权限 ...

2015年1月26日 · 6 分钟 · 天边的星星

file_get_contents()获取https出现这个错误Unable to find the wrapper “https” – did

例如你的原路径是 http://localhost/test/index.php/index/add那么现在的地址是 http://localhost/test/index/add如何去掉index.php呢?1.httpd.conf配置文件中加载了mod_rewrite.so模块 //在APACHE里面去配置#LoadModule rewrite_module modules/mod_rewrite.so把前面的警号去掉2.AllowOverride None 讲None改为 All //在APACHE里面去配置 (注意其他地方的AllowOverride也统统设置为ALL)<Directory “D:/server/apache/cgi-bin”>AllowOverride none 改 AllowOverride ALLOptions NoneOrder allow,denyAllow from all3.确保URL_MODEL设置为2,在项目的配置文件里写return Array( ‘URL_MODEL’ => ‘2’,);4 .htaccess文件必须放到跟目录下这个文件里面加:RewriteEngine onRewriteCond %{REQUEST_FILENAME} !-dRewriteCond %{REQUEST_FILENAME} !-fRewriteRule ^(.*)index.php/1 [QSA,PT,L]补充:在windows下不能建立以点开头的文件,你可以先随便建立一个文件然后在DOS在操作 rename xxxx.xxxx .htaccess ...

2014年9月15日 · 1 分钟 · 天边的星星