我正在开发和应用程序在Android中发送BLE广告包。我使用AdvertiseData和AdverstiseSettings类来生成广告包。但是,当我执行StartAdvertising时,它总是给我一个错误,错误代码为“2”,“ADVERTISE_FAILED_TOO_MANY_ADVERTISERS”,“无法开始投放广告,因为没有可用的广告实例。”
以下是我的MainActivity.JAVA
代码package rockwellcollins.blutooth_advertise;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.os.Bundle;
import android.os.ParcelUuid;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
private BluetoothLeScanner mBluetoothLeScanner;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
textView = (TextView) findViewById(R.id.txtv);
mBluetoothLeScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
if( !BluetoothAdapter.getDefaultAdapter().isMultipleAdvertisementSupported() ) {
Toast.makeText(this, "Multiple advertisement not supported", Toast.LENGTH_SHORT).show();
}
advertise();
BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner().startScan(scanCallback);
}
private void advertise() {
BluetoothLeAdvertiser advertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
AdvertiseSettings settings = new AdvertiseSettings.Builder()
.setAdvertiseMode( AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY )
.setTxPowerLevel( AdvertiseSettings.ADVERTISE_TX_POWER_HIGH )
.setConnectable(false)
.build();
Log.i("BLE","start of advertise data after settings");
ParcelUuid pUuid = new ParcelUuid( UUID.fromString("b161c53c-0715-11e6-b512-3e1d05defe78"));
AdvertiseData data = new AdvertiseData.Builder()
.setIncludeDeviceName( true )
.setIncludeTxPowerLevel(true)
.addServiceUuid( pUuid )
//.addServiceData( pUuid, "Data".getBytes(Charset.forName("UTF-8") ) )
.build();
Log.i("BLE","before callback");
AdvertiseCallback advertisingCallback = new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
Log.i("BLE", "LE Advertise success.");
}
@Override
public void onStartFailure(int errorCode) {
Log.e("BLE", "Advertising onStartFailure: " + errorCode);
super.onStartFailure(errorCode);
}
};
advertiser.startAdvertising( settings, data, advertisingCallback );
Log.i("BLE", "start advertising");
}
private final ScanCallback scanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
printScanResult(result);
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
textView.append("Received " + results.size() + " batch results:\n");
for (ScanResult r : results) {
printScanResult(r);
}
}
@Override
public void onScanFailed(int errorCode) {
switch (errorCode) {
case ScanCallback.SCAN_FAILED_ALREADY_STARTED:
textView.append("Scan failed: already started.\n");
break;
case ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED:
textView.append("Scan failed: app registration failed.\n");
break;
case ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED:
textView.append("Scan failed: feature unsupported.\n");
break;
case ScanCallback.SCAN_FAILED_INTERNAL_ERROR:
textView.append("Scan failed: internal error.\n");
break;
}
}
private void printScanResult(ScanResult result) {
String id = result.getDevice() != null ? result.getDevice().getAddress() : "unknown";
int tx = result.getScanRecord() != null ? result.getScanRecord().getTxPowerLevel() : 0;
textView.append("TX: " + tx + " RX: " + result.getRssi() + " from " + id+ ".\n");
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Android Manifest.xml代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="rockwellcollins.blutooth_advertise">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
您能告诉我我的错误吗?如何解决此错误?
由于
答案 0 :(得分:7)
根据我的经验,BLE广告有4种类型的Android设备:
注意:在2.,3和4.中,仅当蓝牙处于开启状态时,才会返回 BluetoothLeAdvertiser 对象。否则返回 null ,因此您实际上不知道设备是否支持LE广告,直到启用蓝牙。
检查nRF Connect应用:禁用蓝牙,安装应用,打开并选择广告商标签或导航菜单 - &gt;设备信息。在显示状态之前,它会要求您打开蓝牙。
答案 1 :(得分:2)
有关可能的答案,请参阅this question,每个设备都不支持BLE广告。
还尝试按建议here省略设备名称。
答案 2 :(得分:1)
您只需要在此方法上添加以下代码:@TargetApi(Build.VERSION_CODES.M)