Android Bluetooth BLE相关开发资源汇总

Android开启蓝牙开关

转载自Android:Bluetooth 的打开和关闭

检查系统蓝牙是否开启

BluetoothManager bluetoothManager = (BluetoothManager) this.
getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();
mBluetoothAdapter.isEnabled();

开启系统蓝牙方式:

静默打开:
  • 注册权限:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
  • 开启方式:
mBluetoothAdapter.enable();

以上静默打开 Bluetooth 开关是调用了 BluetoothAdapter.enable() 方法,首先需要获取 BluetoothAdapter 对象,如果这个对象为 null 的话,说明当前设备不支持 Bluetooth 功能。还有以下几点需要注意:
1, 在 Nexus 5 Android 4.4.4 原生系统中,在没有任何其它管理 Bluetooth 权限的应用情况下,调用强制打开 Bluetooth 的方法,没有任何提示就直接打开 Bluetooth 了。
2,在小米手机 MI 2SC / MIUI-4.7.11 (Android 4.1.1 JRO03L) 上系统自带的 “安全中心” – “应用权限管理” – “开启蓝牙” 中,有三种设置:
允许:调用强制打开 Bluetooth 代码,没有任何提示,Bluetooth 被成功打开。
提示:会弹出提示框,提示安全警告 “ ***应用尝试开启蓝牙”,可以选择“拒绝”或“允许”,还有记住此次选择(备注:如果不记住的话,下次还会弹出同样的提示框,除非你自己去修改了应用开启蓝牙的权限)。
拒绝:调用强制打开 Bluetooth 代码,没有任何提示,Bluetooth 强制打开失败。
备注:各种手机自带的权限管理功能或者第三方权限管理应用略有不同。
3,对于 BluetoothAdapter.enable() 这个方法,API 中有以下说明 (备注:初始 API 中,如 Android 2.0 Eclair / API Level 5 中并没有这段提示)
Bluetooth should never be enabled without direct user consent. If you want to turn on Bluetooth in order to create a wireless connection, you should use the ACTION_REQUEST_ENABLE Intent, which will raise a dialog that requests user permission to turn on Bluetooth. The enable() method is provided only for applications that include a user interface for changing system settings, such as a “power manager” app.
没有直接的用户的允许绝不要开启 Bluetooth。如果你想要打开 Bluetooth 创建一个无线连接,你应当使用 ACTION_REQUEST_ENABLE Intent,这样会弹出一个提示框提示用户是否开启 Bluetooth,enable() 方法仅提供给有 UI 、更改系统设置的应用来使用,例如“电源管理”应用。
从以上官方 API 提示可以看出:不建议你调用此方法来打开 Bluetooth,至少是在没有任何用户提醒的前提下!

调用系统弹出框提示用户打开
  • 注册权限:
<uses-permission android:name="android.permission.BLUETOOTH" />
  • 开启方式:
Intent requestBluetoothOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
this.startActivityForResult(requestBluetoothOn, REQUEST_CODE_BLUETOOTH_ON);

对于以上弹出系统弹框提示用户打开 Bluetooth 的代码,有以下几点需要注意:
1,这种调用系统的弹出框提示用户打开 Bluetooth 的方式,一般不会受到系统或者第三方权限管理应用的阻止。只有当你不提示用户的情况下,可以理解为“偷偷摸摸”的打开 Bluetooth ,这个是被认为侵犯用户的知情权,系统或者第三方权限管理应用可能加以阻止:直接禁止不提示用户的情况下打开 Bluetooth,或者提示用户,又或者是让用户自己选择哪些应用可以强制开启 Bluetooth。而在 Nexus 5 / Android 4.4.4 原生系统强制打开 Bluetooth 是没有任何提示,并且可以成功打开。
2,弹出系统的提示框提醒用户打开 Bluetooth 的主要代码:
this.startActivityForResult(requestBluetoothOn, REQUEST_CODE_BLUETOOTH_ON);
注意:这个方法是需要 Activity 的对象来调用的!并且需要在 Activity 中重写 onActivityResult 方法来获取用户操作弹出提示框的结果!
3,这种弹出的系统弹框,根据系统的不同,UI 会有所不同。会导致用户app视觉不统一。

跳转到系统设置中让用户自己打开:
startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));

考虑到涉及用户隐私和用户体验,推荐以下方式开启 Bluetooth :
1,采用强制开启 Bluetooth 的方式打开 Bluetooth ,但是调用强制开启 Bluetooth 代码之前,我们自己在应用中提示用户,我们的应用需要开启 Bluetooth ,让用户自己选择是否开启 Bluetooth 。自己在应用中提示用户我们需要开启 Bluetooth 相对于弹出系统的提示框提示用户当前应用需要开启 Bluetooth 的优势在于我们可以控制提示的内容和提示的方式以及 UI。
2,假若用户选择了开启 Bluetooth,但是强制开启 Bluetooth 失败,比如系统自带的权限管理禁止你的应用开启 Bluetooth ,我们不去提示用户说当前系统禁止了应用开启 Bluetooth,让用户自己去解除禁止。这样显然用户体验很差。这种情况下,我们再去调用弹出系统提示框提醒用户打开 Bluetooth 即可。这种方式一般系统或者第三方应用不会禁止。
3,如果弹出系统提示框提醒用户打开 Bluetooth 有问题的话,最后采用提示用户自己去系统 Bluetooth 设置中打开 Bluetooth,跳转到系统的 Bluetooth 设置界面。

PS:在目前Android手机中,是不支持在飞行模式下开启蓝牙的。如果蓝牙已经开启,那么蓝牙的开关状态会随着飞行模式的状态而发生改变。

BLE广播数据解析

转载自BLE 广播数据解析

BLE中peripheral设备处于被发现状态时会发送广播包,peripheral设备通过广播被中心设备发现,广播中带有peripheral设备自身的相关信息。

广播包有两种: 广播包 (Advertising Data)和 响应包 (Scan Response),其中广播包是每个设备必须广播的,而响应包是可选的。 数据包的格式如下图所示(图片来自官方 Spec):
在这里插入图片描述
每个包都是 31 字节,数据包中分为有效数据(significant)和无效数据(non-significant)两部分。

  • 有效数据部分 :包含若干个广播数据单元,称为 AD Structure 。如图中所示,AD Structure 的组成是:第一个字节是长度值 Len ,表示接下来的 Len 个字节是数据部分。数据部分的第一个字节表示数据的类型 AD Type ,剩下的 Len - 1 个字节是真正的数据 AD data 。其中 AD type 非常关键,决定了 AD Data 的数据代表的是什么和怎么解析,这个在后面会详细讲;
  • 无效数据部分 :因为广播包的长度必须是 31 个 byte,如果有效数据部分不到 31 自己,剩下的就用 0 补全。这部分的数据是无效的,解释的时候,忽略即可。

AD type

所有的 AD type 的定义在文档 Core Specification Supplement 中。 AD Type 包括如下类型:

  • Flags: TYPE = 0x01。这个数据用来标识设备 LE 物理连接的功能。DATA 是 0 到多个字节的 Flag 值,每个 bit 上用 0 或者 1 来表示是否为 True。如果有任何一个 bit 不为 0,并且广播包是可连接的,就必须包含此数据。各 bit 的定义如下:

    • bit 0: LE 有限发现模式
    • bit 1: LE 普通发现模式
    • bit 2: 不支持 BR/EDR
    • bit 3: 对 Same Device Capable(Controller) 同时支持 BLE 和 BR/EDR
    • bit 4: 对 Same Device Capable(Host) 同时支持 BLE 和 BR/EDR
    • bit 5…7: 预留
  • Service UUID: 广播数据中一般都会把设备支持的 GATT Service 广播出来,用来告诉外面本设备所支持的 Service。有三种类型的 UUID:16 bit, 32bit, 128 bit。广播中,每种类型类型有有两个类别:完整和非完整的。这样就共有 6 种 AD Type。

    • 非完整的 16 bit UUID 列表: TYPE = 0x02;
    • 完整的 16 bit UUID 列表: TYPE = 0x03;
    • 非完整的 32 bit UUID 列表: TYPE = 0x04;
    • 完整的 32 bit UUID 列表: TYPE = 0x05;
    • 非完整的 128 bit UUID 列表: TYPE = 0x06;
    • 完整的 128 bit UUID 列表: TYPE = 0x07;
  • Local Name: 设备名字,DATA 是名字的字符串。 Local Name 可以是设备的全名,也可以是设备名字的缩写,其中缩写必须是全名的前面的若干字符。

    • 设备全名: TYPE = 0x08
    • 设备简称: TYPE = 0x09
  • TX Power Level: TYPE = 0x0A,表示设备发送广播包的信号强度。DATA 部分是一个字节,表示 -127 到 + 127 dBm。

  • 带外安全管理(Security Manager Out of Band):TYPE = 0x11。DATA 也是 Flag,每个 bit 表示一个功能:

    • bit 0: OOB Flag,0 表示没有 OOB 数据,1 表示有
    • bit 1: 支持 LE
    • bit 2: 对 Same Device Capable(Host) 同时支持 BLE 和 BR/EDR
    • bit 3: 地址类型,0 表示公开地址,1 表示随机地址
  • 外设(Slave)连接间隔范围:TYPE = 0x12。数据中定义了 Slave 最大和最小连接间隔,数据包含 4 个字节:

    • 前 2 字节:定义最小连接间隔,取值范围:0x0006 ~ 0x0C80,而 0xFFFF 表示未定义;
    • 后 2 字节:定义最大连接间隔,同上,不过需要保证最大连接间隔大于或者等于最小连接间隔。
  • 服务搜寻:外围设备可以要请中心设备提供相应的 Service。其数据定义和前面的 Service UUID 类似:

    • 16 bit UUID 列表: TYPE = 0x14
    • 32 bit UUID 列表: TYPE = 0x??
    • 128 bit UUID 列表: TYPE = 0x15
  • Service Data: Service 对应的数据。

    • 16 bit UUID Service: TYPE = 0x16, 前 2 字节是 UUID,后面是 Service 的数据;
    • 32 bit UUID Service: TYPE = 0x??, 前 4 字节是 UUID,后面是 Service 的数据;
    • 128 bit UUID Service: TYPE = 0x??, 前 16 字节是 UUID,后面是 Service 的数据;
  • 公开目标地址:TYPE = 0x17,表示希望这个广播包被指定的目标设备处理,此设备绑定了公开地址,DATA 是目标地址列表,每个地址 6 字节。

  • 随机目标地址:TYPE = 0x18,定义和前一个类似,表示希望这个广播包被指定的目标设备处理,此设备绑定了随机地址,DATA 是目标地址列表,每个地址 6 字节。

  • Appearance:TYPE = 0x19,DATA 是表示了设备的外观。

  • 厂商自定义数据: TYPE = 0xFF,厂商自定义的数据中,前两个字节表示厂商 ID,剩下的是厂商自己按照需求添加,里面的数据内容自己定义。

还有一些其他的数据,我这里就不一一列举了,有需要的可以从这个文档查阅 Core Specification Supplement 。

GATT

BLE技术是基于GATT进行通信的,GATT是一种属性传输协议,简单的讲可以认为是一种属性传输的应用层协议。它的结构非常简单:
在这里插入图片描述
你可以把他看成xml来理解:

  • 每个GATT由完成不同功能的Service组成;
  • 每个Service由不同的Characteristic组成;
  • 每个Characteristic由一个value和一个或者多个Descriptor组成;
    Service、Characteristic相当于标签(Service相当于他的类别,Characteristic相当于它的名字),而value才真正的包含数据,Descriptor是对这个value进行的说明和描述,当然我们可以从不同角度来描述和说明,因此可以有多个Descriptor.

这样子理解可能不够准确,下面我们来举一个简单的例子进行说明:

常见的小米手环是一个BLE设备,(假设)它包含三个Service,分别是提供设备信息的Service、提供步数的Service、检测心率的Service;
而设备信息的service中包含的characteristic包括厂商信息、硬件信息、版本信息等;而心率Service则包括心率characteristic等,而心率characteristic中的value则真正的包含心率的数据,而descriptor则是对该value的描述说明,比如value的单位啊,描述啊,权限啊等。

作者:小时不识月z
链接:https://www.jianshu.com/p/29a730795294
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

BluetoothAdapter类介绍

摘录自Android中蓝牙的基本使用----BluetoothAdapter类简介

由于网络上关于BluetoothAdapter的一些常用API函数都有了介绍,因此,我着重介绍一些BluetoothAdapter类疏忽的地方。

1,BluetoothAdapter STATE 状态值 , 即开关状态

int STATE_OFF                 蓝牙已经关闭
int STATE_ON                  蓝牙已经打开
int STATE_TURNING_OFF         蓝牙处于关闭过程中 ,关闭ing
int STATE_TURNING_O           蓝牙处于打开过程中 ,打开ing

2,BluetoothAdapter SCAN_MOD状态值 ,即扫描状态

首先说明,可以扫描其他设备的,当然它同时能被其他蓝牙设备扫码。

int  SCAN_MODE_CONNECTABLE               表明该蓝牙可以扫描其他蓝牙设备
int  SCAN_MODE_CONNECTABLE_DISCOVERABLE  表明该蓝牙设备同时可以扫码其他蓝牙设备,并且可以被其他蓝牙设备扫描到。
int  SCAN_MODE_NONE                      该蓝牙不能扫描以及被扫描。

3,获得蓝牙适配器实例

public static synchronized BluetoothAdapter getDefaultAdapter ()
功能:获得本设备的蓝牙适配器实例。
返回值:如果设备具备蓝牙功能,返回BluetoothAdapter 实例;否则,返回null对象。

4,扫描蓝牙设备

public boolean startDiscovery () 
功能: 扫描蓝牙设备
注意: 如果蓝牙没有开启,该方法会返回false,即不会开始扫描过程。public  boolean cancelDiscovery ()
功能: 取消扫描过程。
注意: 如果蓝牙没有开启,该方法会返回false。public boolean isDiscovering ()
功能: 是否正在处于扫描过程中。
注意: 如果蓝牙没有开启,该方法会返回false。

5,获取蓝牙相关信息

public String getName ()
功能:获取蓝牙设备Namepublic String getAddress ()
功能:获取蓝牙设备的硬件地址(MAC地址),例如:00:11:22:AA:BB:CC  public boolean setName (String name)
功能:设置蓝牙设备的Name,public Set<BluetoothDevice> getBondedDevices ()
功能:获取与本机蓝牙所有绑定的远程蓝牙信息,以BluetoothDevice类实例(稍后讲到)返回。
注意:如果蓝牙为开启,该函数会返回一个空集合 。public static boolean checkBluetoothAddress (String address)
功能: 验证蓝牙设备MAC地址是否有效。所有设备地址的英文字母必须大写,48位,形如:00:43:A8:23:10:F1 。
返回值: true 设备地址有效
false 设备地址无效public BluetoothDevice getRemoteDevice (String address)
功能:以给定的MAC地址去创建一个 BluetoothDevice 类实例(代表远程蓝牙实例)。即使该蓝牙地址不可见,也会产生一个BluetoothDevice 类实例。
返回:BluetoothDevice 类实例 。注意,如果该蓝牙设备MAC地址不能被识别,其蓝牙Name为null。
异常:如果MAC  address无效,抛出IllegalArgumentException。

Android Bluetooth Low Energy (BLE) Example

转载自Android Bluetooth Low Energy (BLE) Example

Since BLE was introduced in API 18 and cannot be used on old devices, due to change of Bluetooth specifications. I suggest you to specify the min SDK version to 18 in your app. Next add these permissions and feature tags in the manifest tag of your app manifest:

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

Since I will be printing all the data in logs, there is no need for a layout file, lets have a look at the code for using Bluetooth low energy on Android:

package com.truiton.bleexample;import android.annotation.TargetApi;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.widget.Toast;import java.util.ArrayList;
import java.util.List;@TargetApi(21)
public class MainActivity extends ActionBarActivity {private BluetoothAdapter mBluetoothAdapter;private int REQUEST_ENABLE_BT = 1;private Handler mHandler;private static final long SCAN_PERIOD = 10000;private BluetoothLeScanner mLEScanner;private ScanSettings settings;private List<ScanFilter> filters;private BluetoothGatt mGatt;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mHandler = new Handler();if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {Toast.makeText(this, "BLE Not Supported",Toast.LENGTH_SHORT).show();finish();}final BluetoothManager bluetoothManager =(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);mBluetoothAdapter = bluetoothManager.getAdapter();}@Overrideprotected void onResume() {super.onResume();if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);} else {if (Build.VERSION.SDK_INT >= 21) {mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();filters = new ArrayList<ScanFilter>();}scanLeDevice(true);}}@Overrideprotected void onPause() {super.onPause();if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {scanLeDevice(false);}}@Overrideprotected void onDestroy() {if (mGatt == null) {return;}mGatt.close();mGatt = null;super.onDestroy();}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == REQUEST_ENABLE_BT) {if (resultCode == Activity.RESULT_CANCELED) {//Bluetooth not enabled.finish();return;}}super.onActivityResult(requestCode, resultCode, data);}private void scanLeDevice(final boolean enable) {if (enable) {mHandler.postDelayed(new Runnable() {@Overridepublic void run() {if (Build.VERSION.SDK_INT < 21) {mBluetoothAdapter.stopLeScan(mLeScanCallback);} else {mLEScanner.stopScan(mScanCallback);}}}, SCAN_PERIOD);if (Build.VERSION.SDK_INT < 21) {mBluetoothAdapter.startLeScan(mLeScanCallback);} else {mLEScanner.startScan(filters, settings, mScanCallback);}} else {if (Build.VERSION.SDK_INT < 21) {mBluetoothAdapter.stopLeScan(mLeScanCallback);} else {mLEScanner.stopScan(mScanCallback);}}}private ScanCallback mScanCallback = new ScanCallback() {@Overridepublic void onScanResult(int callbackType, ScanResult result) {Log.i("callbackType", String.valueOf(callbackType));Log.i("result", result.toString());BluetoothDevice btDevice = result.getDevice();connectToDevice(btDevice);}@Overridepublic void onBatchScanResults(List<ScanResult> results) {for (ScanResult sr : results) {Log.i("ScanResult - Results", sr.toString());}}@Overridepublic void onScanFailed(int errorCode) {Log.e("Scan Failed", "Error Code: " + errorCode);}};private BluetoothAdapter.LeScanCallback mLeScanCallback =new BluetoothAdapter.LeScanCallback() {@Overridepublic void onLeScan(final BluetoothDevice device, int rssi,byte[] scanRecord) {runOnUiThread(new Runnable() {@Overridepublic void run() {Log.i("onLeScan", device.toString());connectToDevice(device);}});}};public void connectToDevice(BluetoothDevice device) {if (mGatt == null) {mGatt = device.connectGatt(this, false, gattCallback);scanLeDevice(false);// will stop after first device detection}}private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {Log.i("onConnectionStateChange", "Status: " + status);switch (newState) {case BluetoothProfile.STATE_CONNECTED:Log.i("gattCallback", "STATE_CONNECTED");gatt.discoverServices();break;case BluetoothProfile.STATE_DISCONNECTED:Log.e("gattCallback", "STATE_DISCONNECTED");break;default:Log.e("gattCallback", "STATE_OTHER");}}@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {List<BluetoothGattService> services = gatt.getServices();Log.i("onServicesDiscovered", services.toString());gatt.readCharacteristic(services.get(1).getCharacteristics().get(0));}@Overridepublic void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristiccharacteristic, int status) {Log.i("onCharacteristicRead", characteristic.toString());gatt.disconnect();}};
}
disconnect() 和close()的区别

在进行BLE开发过程中可能会遇到操作失败等情况,这个时候可能需要断开与BLE的连接或者清理相关资源.在BluetoothGatt类中有两个相关的方法 。

  • disconnect()
  • close()

那么这个两个方法有什么区别,又该如何使用呢。
disconnect()方法:如果调用了该方法之后可以调用connect()方法进行重连,这样还可以继续进行断开前的操作。

close()方法:一但调用了该方法, 如果你想再次连接,必须调用BluetoothDevice的connectGatt()方法。 因为close()方法将释放BluetootheGatt的所有资源。

需要注意的问题:
当你需要手动断开时,调用disconnect()方法,此时断开成功后会回调onConnectionStateChange方法,在这个方法中再调用close方法释放资源。
如果在disconnect后立即调用close,会导致无法回调onConnectionStateChange方法。

常见问题:

BLE连接之后onServicesDiscovered不被调用

摘录自ble连接之后onServicesDiscovered 不被调用
问题:onServicesDiscovered never called while connecting to GATT Server

Something that has been really useful for me is to wait for about 600ms after the connection has been established and then start the service discovery.

项目中出现蓝牙连接上之后,始终不进onServicesDiscovered回调,mBluetoothGatt.discoverServices()做如下延时即可

if (newState == BluetoothProfile.STATE_CONNECTED) {intentAction = ACTION_GATT_CONNECTED;broadcastUpdate(intentAction);Log.i(TAG, "Connected to GATT server.");// Attempts to discover services after successful connection.//有时候发现服务不回调,需延时 https://stackoverflow.com/questions/41434555/onservicesdiscovered-never-called-while-connecting-to-gatt-server#comment70285228_41526267try {Thread.sleep(600);Log.i(TAG, "Attempting to start service discovery:"+ mBluetoothGatt.discoverServices());} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}
}

相关资源:

Android低功耗蓝牙的那点事儿

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

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

相关文章

git常用命令及冲突解决

2019独角兽企业重金招聘Python工程师标准>>> git常用命令 git config --global user.name chenhongjiang git config --global user.email 123qq.com git init 建立厂库 git status 查看状态 git add . 添加当前目录 git add a.php 添加文件…

从零开始学习PYTHON3讲义(二)把Python当做计算器

《从零开始PYTHON3》第二讲 上一讲我们说过了如何启动Python IDLE集成开发学习环境&#xff0c;macOS/Linux都可以在命令行执行idle3。Windows则从开始菜单中去寻找IDLE程序的图标。 上一讲我们还见到了Python的两种工作模式&#xff0c;交互模式和程序模式。 通常在一个大型的…

创业者谈:畏惧失败,但也要拥抱失败

摘要&#xff1a;本文作者为Paydirt创始人Tristan Gamilis&#xff0c;他在文中分享了如何面对创业过程中的失败。作为一个创业者&#xff0c;开始的时候并非全才&#xff0c;很多知识都是经历了创业中的失败&#xff0c;摸爬滚打之后才学会的。所以&#xff0c;我们在创业过程…

redis 资料

redis是什么: Redis is an open source, BSD licensed, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets. redis是开源,BSD许可,高级的key-value存储系统. 可以用来存储字…

UnaryOperator函数式接口

2019独角兽企业重金招聘Python工程师标准>>> 这是一个函数式接口&#xff0c;因此可以用作lambda表达式或方法引用的赋值目标。 可以看到UnaryOperator<T>继承了Function<T,T>接口&#xff0c;这里可是两个T,T,还增加了static修饰的identity()方法。 然…

linux--命令rcp和scp

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 rcp代表“remote file copy”&#xff08;远程文件拷贝&#xff09;。该命令用于在计算机之间拷贝文件。rcp命令有两种格式。第一种格式…

Nokia落寞身影下 三星成为全球最大手机厂商

摘要&#xff1a;在诺基亚统治全球最大手机厂商宝座长达14年后&#xff0c;三星今年首次取代诺基亚&#xff0c;成为全球最大手机厂商。据IHS iSuppli的数据显示&#xff0c;三星预计今年手机出货量将占全球29&#xff05;&#xff0c;而落寞的诺基亚市场份额将下降到24&#x…

Django:学习笔记(2)——创建第一个应用

Django&#xff1a;学习笔记(2)——创建第一个应用 创建应用 在 Django 中&#xff0c;每一个应用都是一个 Python 包&#xff0c;并且遵循着相同的约定。Django 自带一个工具&#xff0c;可以帮你生成应用的基础目录结构&#xff0c;这样你就能专心写代码&#xff0c;而不是创…

dubbo源码解析(十)远程通信——Exchange层

远程通讯——Exchange层 目标&#xff1a;介绍Exchange层的相关设计和逻辑、介绍dubbo-remoting-api中的exchange包内的源码解析。前言 上一篇文章我讲的是dubbo框架设计中Transport层&#xff0c;这篇文章我要讲的是它的上一层Exchange层&#xff0c;也就是信息交换层。官方文…

为何获得风险投资的公司多数倒闭了?

北京时间12月12日消息&#xff0c;据国外媒体报道&#xff0c;哈佛商学院的高级讲师施克哈尔高希(Shikhar Ghosh)指出&#xff0c;风险投资领域的失败案例比媒体报道的要多得多。 高希的研究表明&#xff0c;在风险资本支持的公司之中&#xff0c;有75%的公司从未向投资者返回过…

苹果前CEO斯卡利变身创业导师:欲寻下个乔布斯

乔布斯和约翰斯卡利 导语&#xff1a;国外媒体今天撰文称&#xff0c;苹果前CEO约翰斯卡利(John Sculley)虽然早已离开苹果&#xff0c;但仍然活跃在科技行业。他现在将目光转向了医疗科技领域&#xff0c;希望从中挖掘出下一个乔布斯。 以下为文章全文&#xff1a; 下一个乔布…

Linux grep命令、Linux cd命令、Linux pwd命令

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Linux grep命令用于查找文件里符合条件的字符串。 grep指令用于查找内容包含指定的范本样式的文件&#xff0c;如果发现某文件的内容符…

历时四年,给Google提交的Android Framework Bug终于被Fixed了

历时四年&#xff0c;Google终于修复了一个我发现的Android Framework Bug 2014年在做一个Android终端设备开发过程中&#xff0c;发现了一个Android Framework层的Bug&#xff0c;给Google提交了issue和解决方案&#xff0c;和外界传言一致Google一般不太在意个人开发者提交的…

前端布局神器display:flex

2009年&#xff0c;W3C提出了一种新的方案--Flex布局&#xff0c;可以简便、完整、响应式地实现各种页面布局。目前已得到所有现在浏览器的支持。 flex浏览器支持一、Flex布局是什么&#xff1f; Flex是Flexible Box的缩写&#xff0c;翻译成中文就是“弹性盒子”&#xff0c;用…

bind简单转发实验

2019独角兽企业重金招聘Python工程师标准>>> *主配置文件内容// [rootlocalhost /]# cat /etc/named.conf // // named.conf // // Provided by Red Hat bind package to configure the ISC BIND named(8) DNS // server as a caching only nameserver (as a local…

数据结构:块状链表

一、概述 有时候我们需要设计这样一种数据结构&#xff1a;它能快速在要求位置插入或者删除一段数据。先考虑两种简单的数据结构&#xff1a;数组和链表。数组的优点是能够在O(1)的时间内找到所要执行操作的位置&#xff0c;但其缺点是无论是插入或删除都要移动之后的所有数据&…

记账本开发小计(四)

今天处理的是记账本小软件中的查询功能&#xff0c;由于账目的要求就是准确性&#xff0c;所以对于记账本程序来说&#xff0c;模糊查询并不适用&#xff0c;所以在这里只能是按照指定的条件来进行查询所以我做的事按照时间进行查询&#xff0c;为了方便进行处理&#xff0c;这…

4、容器虚拟化网络概述

Docker 网络 Docker 的网络实现其实就是利用了 Linux 上的网络名称空间和虚拟网络设备&#xff08;特别是 veth pair&#xff09;。 Linux 网络命名空间&#xff1a;https://www.jianshu.com/p/369e50201bce Linux虚拟网络设备之veth&#xff1a; https://segmentfault.com/a/1…

大数据计算:如何仅用1.5KB内存为十亿对象计数

摘要&#xff1a;AddThis的数据分析副总监Matt Abrams在High Scalability上发表了一篇文章&#xff0c;介绍了他们公司如何应对大数据。Matt Abrams表示&#xff0c;AddThis仅仅用了1.5KB内存的内存就计算了十亿个不同的对象&#xff0c;这与他们所使用的计算方法分不开的。 A…

详解Nagios配置文件的逻辑关系

1.主配置文件/usr/local/nagios/etc/nagios.cfg a.定义了用户和组 b.定义了某些具体参数 c.定义了配置文件和可以存放配置文件的文件夹 d.通过开头的#号去注释选项以达到关闭配置的效果 e.更改配置后&#xff0c;可以通过命令 /usr/local/nagios/bin/nagios –v /usr/local/na…