2016-04-20 8 views
2

Я разрабатываю и приложение, чтобы отправить пакет рекламы BLE в Android. У меня есть классы AdvertisingData и AdverstiseSettings для создания рекламного пакета. Но когда я делаю StartAdvertising, он всегда дает мне ошибку с кодом ошибки «2», «ADVERTISE_FAILED_TOO_MANY_ADVERTISERS», «Не удалось начать рекламу, потому что нет рекламного экземпляра».BLE Реклама в Android

Ниже мой код 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> 

Не могли бы вы, пожалуйста, дайте мне знать, что я делаю неправильно и как я могу решить эту проблему ошибка?

Благодаря

ответ

2

См this question для возможного ответа, BLE объявления о не поддерживаются на каждом устройстве.

Также попробуйте опустить название устройства, как предлагается here.

+0

Я проверяю функцию Bluetooth LE, и она доступна на моем устройстве. 'PackageManager manager = getApplicationContext(). GetPackageManager(); boolean featureAvailable = manager.hasSystemFeature (PackageManager.FEATURE_BLUETOOTH_LE); если (! ОсобенностьAvailable) Toast.makeText (это означает, что функция Bluetooth LE недоступна), Toast.LENGTH_SHORT) .show(); ' – MMJ

+2

Только функция Bluetooth LE недостаточно. Реклама не поддерживается на всех устройствах с Bluetooth LE. Существует [список совместимых устройств] (https://altbeac.g.gub.io/android-beacon-library/beacon-transmitter-devices.html), и вы проверяете, может ли ваше устройство рекламировать, если вы попробуете [это приложение из Radius ] (https://play.google.com/store/apps/details?id=com.radiusnetworks.locate). –

+0

На самом деле, я использую Qualcomm eval kit для Android, APQ 8084 и имеет Bluetooth 4.1, что означает, что он поддерживает режим LE. – MMJ

5

Из моего опыта есть 4 типа Android устройств по отношению BLE рекламы:

  1. Устройства с Android до 5,0 - LE Реклама не поддерживается
  2. устройств с Android 5+, которые не поддерживают LE Реклама и возврат null из getBluetoothLeAdvertiser(). Эти устройства возвращают false от isMultipleAdvertisementSupported(). Они делают это даже при включенном Bluetooth (см. Примечание ниже).
  3. Устройства с Android 5+, что вернуть BluetoothLeAdvertiser объекта, но каждая попытка рекламы заканчивается ADVERTISE_FAILED_TOO_MANY_ADVERTISERS ошибки (это так у вас есть). Эти устройства возвращают true от isMultipleAdvertisementSupported() которые, как вы видите, не соответствуют действительности. До сих пор я видел только один телефон из этой категории: Sony xperia z1 compact, но если есть один, их больше.
  4. Устройства с Android 5+, которые поддерживают LE. Те возвращают true от isMultipleAdvertisementSupported(), но ТОЛЬКО, когда Bluetooth включен.

Примечание: в 2, 3 и 4. BluetoothLeAdvertiser объект возвращается только когда Bluetooth включен. В противном случае возвращается null, поэтому вы фактически не знаете, поддерживает ли устройство LE-объявление или нет, пока Bluetooth не будет включен.

Проверьте приложение nRF Connect: отключите Bluetooth, установите приложение, откройте и выберите вкладку Рекламодатель или Меню навигации -> Информация об устройстве. Он попросит вас включить Bluetooth, прежде чем статус будет показан.