Я использую некоторый нативный код Android для сканирования устройств BLE.Код работает нормально при использовании в автономном приложении Android, но не работает при использовании в родном плагине Android Unity.
У меня есть все авторизации в моем файле манифеста, особенно Bluetooth и Coarse Location:
android:name="android.permission.BLUETOOTH"
android:required="false" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:required="false" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
и телефон Samsung A5 2017 с Android 8 имеют Bluetooth и точную локализацию.Этот код сделан для версии 5 Android.(Цель в Unity и Eclipse).
Следующая функция вызывается из Unity без каких-либо проблем:
startBLEScan();
Но функция
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord)
никогда не вызывается даже при 3 активных маяках BLE рядом с телефоном..
Чего мне не хватает?
Собственный подключаемый модуль Unity:
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
public class MainActivity extends UnityPlayerActivity {
protected static final String LOG_TAG = "Blutooth";
private BluetoothManager btManager;
private BluetoothAdapter btAdapter;
private Handler scanHandler = new Handler();
private int scan_interval_ms = 6000;
private boolean isScanning = false;
public static Context ctx;
private boolean AllowedScanning = false;
public String UUID = null;
public String BLEUUID = null;
public String Major = null;
public String Minor = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
// init BLE
btManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
btAdapter = btManager.getAdapter();
//scanHandler.post(scanRunnable);
}
public void startBLEScan(){
Log.i("test","-----------------test_from_Android_PlugIn");
AllowedScanning = true;
scanHandler.post(scanRunnable);
Toast.makeText(MainActivity.this,
"startBLEScan", Toast.LENGTH_LONG).show();
}
private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback()
{
@Override
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord)
{
Toast.makeText(MainActivity.this, "leScanCallback... ", Toast.LENGTH_LONG).show();
int startByte = 2;
boolean patternFound = false;
while (startByte <= 5)
{
if ( ((int) scanRecord[startByte + 2] & 0xff) == 0x02 && //Identifies an iBeacon
((int) scanRecord[startByte + 3] & 0xff) == 0x15)
{ //Identifies correct data length
patternFound = true;
break;
}
startByte++;
}
if (patternFound)
{
//Convert to hex String
byte[] uuidBytes = new byte[16];
System.arraycopy(scanRecord, startByte + 4, uuidBytes, 0, 16);
String hexString = bytesToHex(uuidBytes);
//UUID detection
String uuid = hexString.substring(0,8) + "-" +
hexString.substring(8,12) + "-" +
hexString.substring(12,16) + "-" +
hexString.substring(16,20) + "-" +
hexString.substring(20,32);
// major
final int major = (scanRecord[startByte + 20] & 0xff) * 0x100 + (scanRecord[startByte + 21] & 0xff);
// minor
final int minor = (scanRecord[startByte + 22] & 0xff) * 0x100 + (scanRecord[startByte + 23] & 0xff);
Log.i(LOG_TAG,"UUID: " +uuid + "\\nmajor: " +major +"\\nminor" +minor);
UUID = uuid.toString();
BLEUUID = uuid.toString();
Major = String.valueOf(major);
Minor = String.valueOf(minor);
Toast.makeText(MainActivity.this,
"UUID " + UUID, Toast.LENGTH_LONG).show();
}
}
};
static final char[] hexArray = "0123456789ABCDEF".toCharArray();
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
private Runnable scanRunnable = new Runnable()
{
@SuppressWarnings("deprecation")
@Override
public void run() {
if (isScanning)
{
if (btAdapter != null)
{
btAdapter.stopLeScan(leScanCallback);
}
}
else
{
if (btAdapter != null)
{
btAdapter.startLeScan(leScanCallback);
Toast.makeText(MainActivity.this, "Scanning... ", Toast.LENGTH_LONG).show();
}
}
isScanning = !isScanning;
scanHandler.postDelayed(this, scan_interval_ms);
if (UUID != null) {
onStop();
Toast.makeText(MainActivity.this, "UUID " + UUID, Toast.LENGTH_LONG).show();
//BLEReturn(UUID);
} else { Toast.makeText(MainActivity.this,"No beacon found ", Toast.LENGTH_LONG).show();
}
}
};
protected void onStop() {
super.onStop();
scanHandler.removeCallbacks(scanRunnable);
}
}
Автономная версия, которая работает нормально, показывает 3 UUID 3 BLEмаяки возле телефона:
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity extends Activity {
protected static final String LOG_TAG = "Blutooth";
private BluetoothManager btManager;
private BluetoothAdapter btAdapter;
private Handler scanHandler = new Handler();
private int scan_interval_ms = 5000;
private boolean isScanning = false;
private TextView txtDisplay1;
public String UUID = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtDisplay1 = (TextView) findViewById(R.id.textView1);
// init BLE
btManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
btAdapter = btManager.getAdapter();
scanHandler.post(scanRunnable);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback()
{
@Override
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord)
{
int startByte = 2;
boolean patternFound = false;
while (startByte <= 5)
{
if ( ((int) scanRecord[startByte + 2] & 0xff) == 0x02 && //Identifies an iBeacon
((int) scanRecord[startByte + 3] & 0xff) == 0x15)
{ //Identifies correct data length
patternFound = true;
break;
}
startByte++;
}
if (patternFound)
{
//Convert to hex String
byte[] uuidBytes = new byte[16];
System.arraycopy(scanRecord, startByte + 4, uuidBytes, 0, 16);
String hexString = bytesToHex(uuidBytes);
//UUID detection
String uuid = hexString.substring(0,8) + "-" +
hexString.substring(8,12) + "-" +
hexString.substring(12,16) + "-" +
hexString.substring(16,20) + "-" +
hexString.substring(20,32);
// major
final int major = (scanRecord[startByte + 20] & 0xff) * 0x100 + (scanRecord[startByte + 21] & 0xff);
// minor
final int minor = (scanRecord[startByte + 22] & 0xff) * 0x100 + (scanRecord[startByte + 23] & 0xff);
Log.i(LOG_TAG,"UUID: " +uuid + "\\nmajor: " +major +"\\nminor" +minor);
txtDisplay1.setText("UUID: " +uuid + "\\nmajor: " +major +"\\nminor" +minor);
UUID = uuid.toString();
}
}
};
static final char[] hexArray = "0123456789ABCDEF".toCharArray();
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
private Runnable scanRunnable = new Runnable()
{
@SuppressWarnings("deprecation")
@Override
public void run() {
if (isScanning)
{
if (btAdapter != null)
{
btAdapter.stopLeScan(leScanCallback);
}
}
else
{
if (btAdapter != null)
{
btAdapter.startLeScan(leScanCallback);
}
}
isScanning = !isScanning;
scanHandler.postDelayed(this, scan_interval_ms);
if (UUID != null) {
onStop();
txtDisplay1.setText("Terminated, beacon found !");
} else { txtDisplay1.setText("Beacon not found");}
}
};
protected void onStop() {
super.onStop();
scanHandler.removeCallbacks(scanRunnable);
}
}