Android Beacon Library后台检测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
- Test on a Physical Device: BLE scanning doesn't work on most emulators, so use a real Android device for testing.
- HM-10 Power: Make sure your HM-10 module has a stable power source—weak batteries can cause inconsistent broadcasting.
- Permission Acceptance: When the app launches, make sure to accept all requested location permissions; otherwise, scanning will fail.
内容的提问来源于stack exchange,提问作者Yassine CHOUH

