2016-04-20 17 views
2

Ich entwickle und app zu senden BLE Advertisement Paket in android. Ich habe AdvertiseData- und AdvertiseSettings-Klassen verwendet, um das Werbepaket zu generieren. Aber wenn ich das StartAdvertising mache, gibt es immer einen Fehler mit Fehlercode "2", "ADVERTISE_FAILED_TOO_MANY_ADVERTISERS", "konnte die Werbung nicht starten, weil keine Werbeinstanz verfügbar ist."BLE Werbung in Android

Unten ist mein Code für 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); 
    } 
} 

-Code für 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> 

Könnten Sie mir bitte mitteilen, was ich tue, falsch und wie kann ich dieses Problem lösen Error?

Dank

Antwort

2

Siehe this question für eine mögliche Antwort, BLE Anzeigen werden auf jedem Gerät nicht unterstützt.

Versuchen Sie auch, den Gerätenamen wie vorgeschlagen here zu vermeiden.

+0

Ich überprüfe das Bluetooth LE Feature und es ist auf meinem Gerät verfügbar. 'PackageManager Manager = getApplicationContext(). GetPackageManager(); boolean featureAvailable = manager.hasSystemFeature (PackageManager.FEATURE_BLUETOOTH_LE); if (! FeatureAvailable) Toast.makeText (das, "Bluetooth LE-Funktion ist nicht verfügbar", Toast.LENGTH_SHORT) .show(); ' – MMJ

+2

Nur die Bluetooth LE-Funktion ist nicht genug. Die Werbung wird nicht auf allen Geräten mit Bluetooth LE unterstützt. Es gibt eine [Liste kompatibler Geräte] (https://altbeacon.github.io/android-beacon-library/beacon-transmitter-devices.html) und Sie testen, ob Ihr Gerät werben kann, wenn Sie [diese App von Radius ausprobieren ] (https://play.google.com/store/apps/details?id=com.radiusnetworks.locate). –

+0

Eigentlich verwende ich Qualcomm Eval Kit für Android, APQ 8084 und es hat Bluetooth 4.1, was bedeutet, dass es den LE-Modus unterstützt. – MMJ

5

Aus meiner Erfahrung gibt es 4 Arten von Android-Geräten in BLE Werbung Hinweis:

  1. Geräte mit Android pre-5.0 - LE Werbung nicht
  2. Geräte mit Android 5+ unterstützt, der Unterstützung LE nicht Anzeige und Rückgabe null von getBluetoothLeAdvertiser(). Diese Geräte geben false von isMultipleAdvertisementSupported() zurück. Sie tun dies sogar mit Bluetooth ON (siehe Hinweis unten).
  3. Geräte mit Android 5+, der die BluetoothLeAdvertiser Objekt zurück, aber jeder Versuch der Werbung endet mit ADVERTISE_FAILED_TOO_MANY_ADVERTISERS Fehler (dies ist der Fall, Sie haben). Diese Geräte geben true von isMultipleAdvertisementSupported() zurück, was, wie Sie sehen, nicht wahr ist. Bisher habe ich nur ein Handy aus dieser Kategorie gesehen: Sony Xperia Z1 Compact, aber wenn es eins gibt, gibt es mehr.
  4. Geräte mit Android 5+, die LE Werbung unterstützen. Diese geben true von isMultipleAdvertisementSupported() zurück, aber nur wenn Bluetooth eingeschaltet ist.

Hinweis: in der 2., 3. und 4. der BluetoothLeAdvertiser Objekt wird nur zurückgegeben, wenn Bluetooth eingeschaltet ist. Ansonsten null wird zurückgegeben, so dass Sie tatsächlich keine Ahnung haben, ob das Gerät LE-Werbung unterstützt oder nicht, bis Bluetooth aktiviert ist.

Überprüfen Sie die nRF Connect App: Deaktivieren Sie Bluetooth, installieren Sie die App, öffnen Sie die Registerkarte Advertiser oder wählen Sie das Navigationsmenü -> Geräteinformation. Sie werden aufgefordert, Bluetooth einzuschalten, bevor der Status angezeigt wird.

Verwandte Themen