You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Beacon Library后台检测iBeacon无响应及实现咨询

Fixing Android Beacon Library Detection & Implementing Background/Foreground Features for HM-10 iBeacon

Hey there! Let's get your HM-10 iBeacon detection working with the Android Beacon Library, and implement the exact features you want: auto-launch the app when a beacon is detected in the background, and show a Toast notification when the app is already open.

First, Fix Critical Missing Permissions & Manifest Setup

Your current AndroidManifest.xml is missing essential BLE permissions and the library's background service declaration—this is likely why you're seeing no response at all. Update it like this:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <!-- Required for background scanning on Android 10+ -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />

<application 
    android:allowBackup="true" 
    android:name=".Background" 
    android:icon="@mipmap/ic_launcher" 
    android:label="@string/app_name" 
    android:roundIcon="@mipmap/ic_launcher_round" 
    android:supportsRtl="true" 
    android:theme="@style/AppTheme">
    
    <!-- Declare the library's background services -->
    <service android:name="org.altbeacon.beacon.service.BeaconService" android:enabled="true"/>
    <service android:name="org.altbeacon.beacon.BeaconIntentProcessor" android:enabled="true"/>

    <activity android:name=".MainActivity" android:launchMode="singleInstance">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
</application>

Verify HM-10 iBeacon Configuration

Double-check your HM-10 module is configured to broadcast standard iBeacon frames. The layout you're using (m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24) is correct for iBeacon, but if your HM-10 is set to a different format (like Eddystone), it won't be detected. Use AT commands to confirm it's sending valid iBeacon packets.

Update the Background Application Class

We'll modify this to only launch MainActivity when the app is in the background, and trigger a Toast if it's already active. We'll also add proper background scanning parameters to balance performance and battery:

import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.startup.BootstrapNotifier;
import org.altbeacon.beacon.startup.RegionBootstrap;
import android.util.Log;

public class Background extends Application implements BootstrapNotifier {
    private static final String TAG = "BeaconBackgroundApp";
    private RegionBootstrap regionBootstrap;
    private boolean isAppInForeground = false;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "Application initialized");

        BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
        // Configure parser for standard iBeacon
        beaconManager.getBeaconParsers().add(new BeaconParser()
                .setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));

        // Set background scan intervals (adjust based on battery needs)
        beaconManager.setBackgroundScanPeriod(1000);
        beaconManager.setBackgroundBetweenScanPeriod(5000);

        // Monitor all iBeacons (filter by UUID/major/minor here if needed)
        Region region = new Region("bootstrapRegion", null, null, null);
        regionBootstrap = new RegionBootstrap(this, region);

        // Track app foreground/background state
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityResumed(@NonNull Activity activity) {
                isAppInForeground = true;
            }

            @Override
            public void onActivityPaused(@NonNull Activity activity) {
                isAppInForeground = false;
            }

            // Unused callbacks can be left empty
            @Override public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {}
            @Override public void onActivityStarted(@NonNull Activity activity) {}
            @Override public void onActivityStopped(@NonNull Activity activity) {}
            @Override public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {}
            @Override public void onActivityDestroyed(@NonNull Activity activity) {}
        });
    }

    @Override
    public void didDetermineStateForRegion(int state, Region region) {
        // Not needed for your use case
    }

    @Override
    public void didEnterRegion(Region region) {
        Log.d(TAG, "Beacon detected!");

        if (isAppInForeground) {
            // App is open: show Toast notification
            Toast.makeText(getApplicationContext(), "A Beacon is nearby!", Toast.LENGTH_LONG).show();
        } else {
            // App is closed: launch MainActivity
            Intent intent = new Intent(this, MainActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(intent);
            Toast.makeText(getApplicationContext(), "Launched app due to Beacon detection", Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void didExitRegion(Region region) {
        // Not needed for your use case
    }
}

Update MainActivity for Foreground Detection

Add code here to listen for beacons while the app is active, and manage the BeaconManager lifecycle to avoid unnecessary battery drain:

import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.widget.Toast;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.MonitorNotifier;
import org.altbeacon.beacon.Region;
import android.os.RemoteException;

public class MainActivity extends Activity implements BeaconConsumer {
    private BeaconManager beaconManager;
    private Region monitoringRegion;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Request runtime permissions for BLE scanning (required on Android 6.0+)
        requestBlePermissions();

        // Initialize BeaconManager for foreground detection
        beaconManager = BeaconManager.getInstanceForApplication(this);
        beaconManager.getBeaconParsers().add(new BeaconParser()
                .setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
        monitoringRegion = new Region("foregroundRegion", null, null, null);
    }

    private void requestBlePermissions() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
                checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 2);
            }
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        // Bind to BeaconManager when activity is visible
        beaconManager.bind(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // Unbind to save battery when activity is hidden
        beaconManager.unbind(this);
    }

    @Override
    public void onBeaconServiceConnect() {
        // Set up monitoring for beacons in foreground
        beaconManager.addMonitorNotifier(new MonitorNotifier() {
            @Override
            public void didEnterRegion(Region region) {
                // Show Toast on the UI thread
                runOnUiThread(() ->
                    Toast.makeText(MainActivity.this, "Beacon detected in foreground!", Toast.LENGTH_LONG).show()
                );
            }

            @Override
            public void didExitRegion(Region region) {}

            @Override
            public void didDetermineStateForRegion(int state, Region region) {}
        });

        try {
            beaconManager.startMonitoringBeaconsInRegion(monitoringRegion);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

Final Tips to Ensure It Works

  1. Test on a Physical Device: BLE scanning doesn't work on most emulators, so use a real Android device for testing.
  2. HM-10 Power: Make sure your HM-10 module has a stable power source—weak batteries can cause inconsistent broadcasting.
  3. Permission Acceptance: When the app launches, make sure to accept all requested location permissions; otherwise, scanning will fail.

内容的提问来源于stack exchange,提问作者Yassine CHOUH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:25:10